Commit 94b76036 authored by Mitchell Hashimoto's avatar Mitchell Hashimoto

builder/digitalocean: new multistep API

parent 0b830c92
...@@ -189,11 +189,11 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe ...@@ -189,11 +189,11 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
client := DigitalOceanClient{}.New(b.config.ClientID, b.config.APIKey) client := DigitalOceanClient{}.New(b.config.ClientID, b.config.APIKey)
// Set up the state // Set up the state
state := make(map[string]interface{}) state := new(multistep.BasicStateBag)
state["config"] = b.config state.Put("config", b.config)
state["client"] = client state.Put("client", client)
state["hook"] = hook state.Put("hook", hook)
state["ui"] = ui state.Put("ui", ui)
// Build the steps // Build the steps
steps := []multistep.Step{ steps := []multistep.Step{
...@@ -224,18 +224,18 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe ...@@ -224,18 +224,18 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
b.runner.Run(state) b.runner.Run(state)
// If there was an error, return that // If there was an error, return that
if rawErr, ok := state["error"]; ok { if rawErr, ok := state.GetOk("error"); ok {
return nil, rawErr.(error) return nil, rawErr.(error)
} }
if _, ok := state["snapshot_name"]; !ok { if _, ok := state.GetOk("snapshot_name"); !ok {
log.Println("Failed to find snapshot_name in state. Bug?") log.Println("Failed to find snapshot_name in state. Bug?")
return nil, nil return nil, nil
} }
artifact := &Artifact{ artifact := &Artifact{
snapshotName: state["snapshot_name"].(string), snapshotName: state.Get("snapshot_name").(string),
snapshotId: state["snapshot_image_id"].(uint), snapshotId: state.Get("snapshot_image_id").(uint),
client: client, client: client,
} }
......
...@@ -3,18 +3,19 @@ package digitalocean ...@@ -3,18 +3,19 @@ package digitalocean
import ( import (
gossh "code.google.com/p/go.crypto/ssh" gossh "code.google.com/p/go.crypto/ssh"
"fmt" "fmt"
"github.com/mitchellh/multistep"
"github.com/mitchellh/packer/communicator/ssh" "github.com/mitchellh/packer/communicator/ssh"
) )
func sshAddress(state map[string]interface{}) (string, error) { func sshAddress(state multistep.StateBag) (string, error) {
config := state["config"].(config) config := state.Get("config").(config)
ipAddress := state["droplet_ip"].(string) ipAddress := state.Get("droplet_ip").(string)
return fmt.Sprintf("%s:%d", ipAddress, config.SSHPort), nil return fmt.Sprintf("%s:%d", ipAddress, config.SSHPort), nil
} }
func sshConfig(state map[string]interface{}) (*gossh.ClientConfig, error) { func sshConfig(state multistep.StateBag) (*gossh.ClientConfig, error) {
config := state["config"].(config) config := state.Get("config").(config)
privateKey := state["privateKey"].(string) privateKey := state.Get("privateKey").(string)
keyring := new(ssh.SimpleKeychain) keyring := new(ssh.SimpleKeychain)
if err := keyring.AddPEMKey(privateKey); err != nil { if err := keyring.AddPEMKey(privateKey); err != nil {
......
...@@ -14,11 +14,11 @@ type stepCreateDroplet struct { ...@@ -14,11 +14,11 @@ type stepCreateDroplet struct {
dropletId uint dropletId uint
} }
func (s *stepCreateDroplet) Run(state map[string]interface{}) multistep.StepAction { func (s *stepCreateDroplet) Run(state multistep.StateBag) multistep.StepAction {
client := state["client"].(*DigitalOceanClient) client := state.Get("client").(*DigitalOceanClient)
ui := state["ui"].(packer.Ui) ui := state.Get("ui").(packer.Ui)
c := state["config"].(config) c := state.Get("config").(config)
sshKeyId := state["ssh_key_id"].(uint) sshKeyId := state.Get("ssh_key_id").(uint)
ui.Say("Creating droplet...") ui.Say("Creating droplet...")
...@@ -29,7 +29,7 @@ func (s *stepCreateDroplet) Run(state map[string]interface{}) multistep.StepActi ...@@ -29,7 +29,7 @@ func (s *stepCreateDroplet) Run(state map[string]interface{}) multistep.StepActi
dropletId, err := client.CreateDroplet(name, c.SizeID, c.ImageID, c.RegionID, sshKeyId) dropletId, err := client.CreateDroplet(name, c.SizeID, c.ImageID, c.RegionID, sshKeyId)
if err != nil { if err != nil {
err := fmt.Errorf("Error creating droplet: %s", err) err := fmt.Errorf("Error creating droplet: %s", err)
state["error"] = err state.Put("error", err)
ui.Error(err.Error()) ui.Error(err.Error())
return multistep.ActionHalt return multistep.ActionHalt
} }
...@@ -38,20 +38,20 @@ func (s *stepCreateDroplet) Run(state map[string]interface{}) multistep.StepActi ...@@ -38,20 +38,20 @@ func (s *stepCreateDroplet) Run(state map[string]interface{}) multistep.StepActi
s.dropletId = dropletId s.dropletId = dropletId
// Store the droplet id for later // Store the droplet id for later
state["droplet_id"] = dropletId state.Put("droplet_id", dropletId)
return multistep.ActionContinue return multistep.ActionContinue
} }
func (s *stepCreateDroplet) Cleanup(state map[string]interface{}) { func (s *stepCreateDroplet) Cleanup(state multistep.StateBag) {
// If the dropletid isn't there, we probably never created it // If the dropletid isn't there, we probably never created it
if s.dropletId == 0 { if s.dropletId == 0 {
return return
} }
client := state["client"].(*DigitalOceanClient) client := state.Get("client").(*DigitalOceanClient)
ui := state["ui"].(packer.Ui) ui := state.Get("ui").(packer.Ui)
c := state["config"].(config) c := state.Get("config").(config)
// Destroy the droplet we just created // Destroy the droplet we just created
ui.Say("Destroying droplet...") ui.Say("Destroying droplet...")
......
...@@ -18,9 +18,9 @@ type stepCreateSSHKey struct { ...@@ -18,9 +18,9 @@ type stepCreateSSHKey struct {
keyId uint keyId uint
} }
func (s *stepCreateSSHKey) Run(state map[string]interface{}) multistep.StepAction { func (s *stepCreateSSHKey) Run(state multistep.StateBag) multistep.StepAction {
client := state["client"].(*DigitalOceanClient) client := state.Get("client").(*DigitalOceanClient)
ui := state["ui"].(packer.Ui) ui := state.Get("ui").(packer.Ui)
ui.Say("Creating temporary ssh key for droplet...") ui.Say("Creating temporary ssh key for droplet...")
...@@ -35,7 +35,7 @@ func (s *stepCreateSSHKey) Run(state map[string]interface{}) multistep.StepActio ...@@ -35,7 +35,7 @@ func (s *stepCreateSSHKey) Run(state map[string]interface{}) multistep.StepActio
} }
// Set the private key in the statebag for later // Set the private key in the statebag for later
state["privateKey"] = string(pem.EncodeToMemory(&priv_blk)) state.Put("privateKey", string(pem.EncodeToMemory(&priv_blk)))
// Marshal the public key into SSH compatible format // Marshal the public key into SSH compatible format
pub := priv.PublicKey pub := priv.PublicKey
...@@ -48,7 +48,7 @@ func (s *stepCreateSSHKey) Run(state map[string]interface{}) multistep.StepActio ...@@ -48,7 +48,7 @@ func (s *stepCreateSSHKey) Run(state map[string]interface{}) multistep.StepActio
keyId, err := client.CreateKey(name, pub_sshformat) keyId, err := client.CreateKey(name, pub_sshformat)
if err != nil { if err != nil {
err := fmt.Errorf("Error creating temporary SSH key: %s", err) err := fmt.Errorf("Error creating temporary SSH key: %s", err)
state["error"] = err state.Put("error", err)
ui.Error(err.Error()) ui.Error(err.Error())
return multistep.ActionHalt return multistep.ActionHalt
} }
...@@ -59,20 +59,20 @@ func (s *stepCreateSSHKey) Run(state map[string]interface{}) multistep.StepActio ...@@ -59,20 +59,20 @@ func (s *stepCreateSSHKey) Run(state map[string]interface{}) multistep.StepActio
log.Printf("temporary ssh key name: %s", name) log.Printf("temporary ssh key name: %s", name)
// Remember some state for the future // Remember some state for the future
state["ssh_key_id"] = keyId state.Put("ssh_key_id", keyId)
return multistep.ActionContinue return multistep.ActionContinue
} }
func (s *stepCreateSSHKey) Cleanup(state map[string]interface{}) { func (s *stepCreateSSHKey) Cleanup(state multistep.StateBag) {
// If no key name is set, then we never created it, so just return // If no key name is set, then we never created it, so just return
if s.keyId == 0 { if s.keyId == 0 {
return return
} }
client := state["client"].(*DigitalOceanClient) client := state.Get("client").(*DigitalOceanClient)
ui := state["ui"].(packer.Ui) ui := state.Get("ui").(packer.Ui)
c := state["config"].(config) c := state.Get("config").(config)
ui.Say("Deleting temporary ssh key...") ui.Say("Deleting temporary ssh key...")
err := client.DestroyKey(s.keyId) err := client.DestroyKey(s.keyId)
......
...@@ -8,18 +8,18 @@ import ( ...@@ -8,18 +8,18 @@ import (
type stepDropletInfo struct{} type stepDropletInfo struct{}
func (s *stepDropletInfo) Run(state map[string]interface{}) multistep.StepAction { func (s *stepDropletInfo) Run(state multistep.StateBag) multistep.StepAction {
client := state["client"].(*DigitalOceanClient) client := state.Get("client").(*DigitalOceanClient)
ui := state["ui"].(packer.Ui) ui := state.Get("ui").(packer.Ui)
c := state["config"].(config) c := state.Get("config").(config)
dropletId := state["droplet_id"].(uint) dropletId := state.Get("droplet_id").(uint)
ui.Say("Waiting for droplet to become active...") ui.Say("Waiting for droplet to become active...")
err := waitForDropletState("active", dropletId, client, c) err := waitForDropletState("active", dropletId, client, c)
if err != nil { if err != nil {
err := fmt.Errorf("Error waiting for droplet to become active: %s", err) err := fmt.Errorf("Error waiting for droplet to become active: %s", err)
state["error"] = err state.Put("error", err)
ui.Error(err.Error()) ui.Error(err.Error())
return multistep.ActionHalt return multistep.ActionHalt
} }
...@@ -28,16 +28,16 @@ func (s *stepDropletInfo) Run(state map[string]interface{}) multistep.StepAction ...@@ -28,16 +28,16 @@ func (s *stepDropletInfo) Run(state map[string]interface{}) multistep.StepAction
ip, _, err := client.DropletStatus(dropletId) ip, _, err := client.DropletStatus(dropletId)
if err != nil { if err != nil {
err := fmt.Errorf("Error retrieving droplet ID: %s", err) err := fmt.Errorf("Error retrieving droplet ID: %s", err)
state["error"] = err state.Put("error", err)
ui.Error(err.Error()) ui.Error(err.Error())
return multistep.ActionHalt return multistep.ActionHalt
} }
state["droplet_ip"] = ip state.Put("droplet_ip", ip)
return multistep.ActionContinue return multistep.ActionContinue
} }
func (s *stepDropletInfo) Cleanup(state map[string]interface{}) { func (s *stepDropletInfo) Cleanup(state multistep.StateBag) {
// no cleanup // no cleanup
} }
...@@ -10,11 +10,11 @@ import ( ...@@ -10,11 +10,11 @@ import (
type stepPowerOff struct{} type stepPowerOff struct{}
func (s *stepPowerOff) Run(state map[string]interface{}) multistep.StepAction { func (s *stepPowerOff) Run(state multistep.StateBag) multistep.StepAction {
client := state["client"].(*DigitalOceanClient) client := state.Get("client").(*DigitalOceanClient)
c := state["config"].(config) c := state.Get("config").(config)
ui := state["ui"].(packer.Ui) ui := state.Get("ui").(packer.Ui)
dropletId := state["droplet_id"].(uint) dropletId := state.Get("droplet_id").(uint)
// Sleep arbitrarily before sending power off request // Sleep arbitrarily before sending power off request
// Otherwise we get "pending event" errors, even though there isn't // Otherwise we get "pending event" errors, even though there isn't
...@@ -27,7 +27,7 @@ func (s *stepPowerOff) Run(state map[string]interface{}) multistep.StepAction { ...@@ -27,7 +27,7 @@ func (s *stepPowerOff) Run(state map[string]interface{}) multistep.StepAction {
if err != nil { if err != nil {
err := fmt.Errorf("Error powering off droplet: %s", err) err := fmt.Errorf("Error powering off droplet: %s", err)
state["error"] = err state.Put("error", err)
ui.Error(err.Error()) ui.Error(err.Error())
return multistep.ActionHalt return multistep.ActionHalt
} }
...@@ -44,6 +44,6 @@ func (s *stepPowerOff) Run(state map[string]interface{}) multistep.StepAction { ...@@ -44,6 +44,6 @@ func (s *stepPowerOff) Run(state map[string]interface{}) multistep.StepAction {
return multistep.ActionContinue return multistep.ActionContinue
} }
func (s *stepPowerOff) Cleanup(state map[string]interface{}) { func (s *stepPowerOff) Cleanup(state multistep.StateBag) {
// no cleanup // no cleanup
} }
...@@ -10,11 +10,11 @@ import ( ...@@ -10,11 +10,11 @@ import (
type stepShutdown struct{} type stepShutdown struct{}
func (s *stepShutdown) Run(state map[string]interface{}) multistep.StepAction { func (s *stepShutdown) Run(state multistep.StateBag) multistep.StepAction {
client := state["client"].(*DigitalOceanClient) client := state.Get("client").(*DigitalOceanClient)
c := state["config"].(config) c := state.Get("config").(config)
ui := state["ui"].(packer.Ui) ui := state.Get("ui").(packer.Ui)
dropletId := state["droplet_id"].(uint) dropletId := state.Get("droplet_id").(uint)
// Sleep arbitrarily before sending the request // Sleep arbitrarily before sending the request
// Otherwise we get "pending event" errors, even though there isn't // Otherwise we get "pending event" errors, even though there isn't
...@@ -26,7 +26,7 @@ func (s *stepShutdown) Run(state map[string]interface{}) multistep.StepAction { ...@@ -26,7 +26,7 @@ func (s *stepShutdown) Run(state map[string]interface{}) multistep.StepAction {
if err != nil { if err != nil {
err := fmt.Errorf("Error shutting down droplet: %s", err) err := fmt.Errorf("Error shutting down droplet: %s", err)
state["error"] = err state.Put("error", err)
ui.Error(err.Error()) ui.Error(err.Error())
return multistep.ActionHalt return multistep.ActionHalt
} }
...@@ -36,7 +36,7 @@ func (s *stepShutdown) Run(state map[string]interface{}) multistep.StepAction { ...@@ -36,7 +36,7 @@ func (s *stepShutdown) Run(state map[string]interface{}) multistep.StepAction {
err = waitForDropletState("off", dropletId, client, c) err = waitForDropletState("off", dropletId, client, c)
if err != nil { if err != nil {
err := fmt.Errorf("Error waiting for droplet to become 'off': %s", err) err := fmt.Errorf("Error waiting for droplet to become 'off': %s", err)
state["error"] = err state.Put("error", err)
ui.Error(err.Error()) ui.Error(err.Error())
return multistep.ActionHalt return multistep.ActionHalt
} }
...@@ -44,6 +44,6 @@ func (s *stepShutdown) Run(state map[string]interface{}) multistep.StepAction { ...@@ -44,6 +44,6 @@ func (s *stepShutdown) Run(state map[string]interface{}) multistep.StepAction {
return multistep.ActionContinue return multistep.ActionContinue
} }
func (s *stepShutdown) Cleanup(state map[string]interface{}) { func (s *stepShutdown) Cleanup(state multistep.StateBag) {
// no cleanup // no cleanup
} }
...@@ -10,17 +10,17 @@ import ( ...@@ -10,17 +10,17 @@ import (
type stepSnapshot struct{} type stepSnapshot struct{}
func (s *stepSnapshot) Run(state map[string]interface{}) multistep.StepAction { func (s *stepSnapshot) Run(state multistep.StateBag) multistep.StepAction {
client := state["client"].(*DigitalOceanClient) client := state.Get("client").(*DigitalOceanClient)
ui := state["ui"].(packer.Ui) ui := state.Get("ui").(packer.Ui)
c := state["config"].(config) c := state.Get("config").(config)
dropletId := state["droplet_id"].(uint) dropletId := state.Get("droplet_id").(uint)
ui.Say(fmt.Sprintf("Creating snapshot: %v", c.SnapshotName)) ui.Say(fmt.Sprintf("Creating snapshot: %v", c.SnapshotName))
err := client.CreateSnapshot(dropletId, c.SnapshotName) err := client.CreateSnapshot(dropletId, c.SnapshotName)
if err != nil { if err != nil {
err := fmt.Errorf("Error creating snapshot: %s", err) err := fmt.Errorf("Error creating snapshot: %s", err)
state["error"] = err state.Put("error", err)
ui.Error(err.Error()) ui.Error(err.Error())
return multistep.ActionHalt return multistep.ActionHalt
} }
...@@ -29,7 +29,7 @@ func (s *stepSnapshot) Run(state map[string]interface{}) multistep.StepAction { ...@@ -29,7 +29,7 @@ func (s *stepSnapshot) Run(state map[string]interface{}) multistep.StepAction {
err = waitForDropletState("active", dropletId, client, c) err = waitForDropletState("active", dropletId, client, c)
if err != nil { if err != nil {
err := fmt.Errorf("Error waiting for snapshot to complete: %s", err) err := fmt.Errorf("Error waiting for snapshot to complete: %s", err)
state["error"] = err state.Put("error", err)
ui.Error(err.Error()) ui.Error(err.Error())
return multistep.ActionHalt return multistep.ActionHalt
} }
...@@ -38,7 +38,7 @@ func (s *stepSnapshot) Run(state map[string]interface{}) multistep.StepAction { ...@@ -38,7 +38,7 @@ func (s *stepSnapshot) Run(state map[string]interface{}) multistep.StepAction {
images, err := client.Images() images, err := client.Images()
if err != nil { if err != nil {
err := fmt.Errorf("Error looking up snapshot ID: %s", err) err := fmt.Errorf("Error looking up snapshot ID: %s", err)
state["error"] = err state.Put("error", err)
ui.Error(err.Error()) ui.Error(err.Error())
return multistep.ActionHalt return multistep.ActionHalt
} }
...@@ -53,19 +53,19 @@ func (s *stepSnapshot) Run(state map[string]interface{}) multistep.StepAction { ...@@ -53,19 +53,19 @@ func (s *stepSnapshot) Run(state map[string]interface{}) multistep.StepAction {
if imageId == 0 { if imageId == 0 {
err := errors.New("Couldn't find snapshot to get the image ID. Bug?") err := errors.New("Couldn't find snapshot to get the image ID. Bug?")
state["error"] = err state.Put("error", err)
ui.Error(err.Error()) ui.Error(err.Error())
return multistep.ActionHalt return multistep.ActionHalt
} }
log.Printf("Snapshot image ID: %d", imageId) log.Printf("Snapshot image ID: %d", imageId)
state["snapshot_image_id"] = imageId state.Put("snapshot_image_id", imageId)
state["snapshot_name"] = c.SnapshotName state.Put("snapshot_name", c.SnapshotName)
return multistep.ActionContinue return multistep.ActionContinue
} }
func (s *stepSnapshot) Cleanup(state map[string]interface{}) { func (s *stepSnapshot) Cleanup(state multistep.StateBag) {
// no cleanup // no cleanup
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment