diff --git a/builder/openstack/builder.go b/builder/openstack/builder.go index 652cb4abb..57caefff9 100644 --- a/builder/openstack/builder.go +++ b/builder/openstack/builder.go @@ -72,11 +72,11 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe } // Setup the state bag and initial state for the steps - state := make(map[string]interface{}) - state["config"] = b.config - state["csp"] = csp - state["hook"] = hook - state["ui"] = ui + state := new(multistep.BasicStateBag) + state.Put("config", b.config) + state.Put("csp", csp) + state.Put("hook", hook) + state.Put("ui", ui) // Build the steps steps := []multistep.Step{ @@ -108,13 +108,13 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe b.runner.Run(state) // If there was an error, return that - if rawErr, ok := state["error"]; ok { + if rawErr, ok := state.GetOk("error"); ok { return nil, rawErr.(error) } // Build the artifact and return it artifact := &Artifact{ - ImageId: state["image"].(string), + ImageId: state.Get("image").(string), BuilderIdValue: BuilderId, Conn: csp, } diff --git a/builder/openstack/server.go b/builder/openstack/server.go index 810c854b7..d62f5a635 100644 --- a/builder/openstack/server.go +++ b/builder/openstack/server.go @@ -25,7 +25,7 @@ type StateRefreshFunc func() (result interface{}, state string, progress int, er type StateChangeConf struct { Pending []string Refresh StateRefreshFunc - StepState map[string]interface{} + StepState multistep.StateBag Target string } @@ -61,7 +61,7 @@ func WaitForState(conf *StateChangeConf) (i interface{}, err error) { } if conf.StepState != nil { - if _, ok := conf.StepState[multistep.StateCancelled]; ok { + if _, ok := conf.StepState.GetOk(multistep.StateCancelled); ok { return nil, errors.New("interrupted") } } diff --git a/builder/openstack/ssh.go b/builder/openstack/ssh.go index 5d4a13d3c..a842c8618 100644 --- a/builder/openstack/ssh.go +++ b/builder/openstack/ssh.go @@ -4,6 +4,7 @@ import ( gossh "code.google.com/p/go.crypto/ssh" "errors" "fmt" + "github.com/mitchellh/multistep" "github.com/mitchellh/packer/communicator/ssh" "github.com/rackspace/gophercloud" "time" @@ -11,10 +12,10 @@ import ( // SSHAddress returns a function that can be given to the SSH communicator // for determining the SSH address based on the server AccessIPv4 setting.. -func SSHAddress(csp gophercloud.CloudServersProvider, port int) func(map[string]interface{}) (string, error) { - return func(state map[string]interface{}) (string, error) { +func SSHAddress(csp gophercloud.CloudServersProvider, port int) func(multistep.StateBag) (string, error) { + return func(state multistep.StateBag) (string, error) { for j := 0; j < 2; j++ { - s := state["server"].(*gophercloud.Server) + s := state.Get("server").(*gophercloud.Server) if s.AccessIPv4 != "" { return fmt.Sprintf("%s:%d", s.AccessIPv4, port), nil } @@ -24,7 +25,7 @@ func SSHAddress(csp gophercloud.CloudServersProvider, port int) func(map[string] return "", err } - state["server"] = serverState + state.Put("server", serverState) time.Sleep(1 * time.Second) } @@ -35,9 +36,9 @@ func SSHAddress(csp gophercloud.CloudServersProvider, port int) func(map[string] // SSHConfig returns a function that can be used for the SSH communicator // config for connecting to the instance created over SSH using the generated // private key. -func SSHConfig(username string) func(map[string]interface{}) (*gossh.ClientConfig, error) { - return func(state map[string]interface{}) (*gossh.ClientConfig, error) { - privateKey := state["privateKey"].(string) +func SSHConfig(username string) func(multistep.StateBag) (*gossh.ClientConfig, error) { + return func(state multistep.StateBag) (*gossh.ClientConfig, error) { + privateKey := state.Get("privateKey").(string) keyring := new(ssh.SimpleKeychain) if err := keyring.AddPEMKey(privateKey); err != nil { diff --git a/builder/openstack/step_create_image.go b/builder/openstack/step_create_image.go index bd98425fc..bed26aea8 100644 --- a/builder/openstack/step_create_image.go +++ b/builder/openstack/step_create_image.go @@ -11,11 +11,11 @@ import ( type stepCreateImage struct{} -func (s *stepCreateImage) Run(state map[string]interface{}) multistep.StepAction { - csp := state["csp"].(gophercloud.CloudServersProvider) - config := state["config"].(config) - server := state["server"].(*gophercloud.Server) - ui := state["ui"].(packer.Ui) +func (s *stepCreateImage) Run(state multistep.StateBag) multistep.StepAction { + csp := state.Get("csp").(gophercloud.CloudServersProvider) + config := state.Get("config").(config) + server := state.Get("server").(*gophercloud.Server) + ui := state.Get("ui").(packer.Ui) // Create the image ui.Say(fmt.Sprintf("Creating the image: %s", config.ImageName)) @@ -25,20 +25,20 @@ func (s *stepCreateImage) Run(state map[string]interface{}) multistep.StepAction imageId, err := csp.CreateImage(server.Id, createOpts) if err != nil { err := fmt.Errorf("Error creating image: %s", err) - state["error"] = err + state.Put("error", err) ui.Error(err.Error()) return multistep.ActionHalt } // Set the Image ID in the state ui.Say(fmt.Sprintf("Image: %s", imageId)) - state["image"] = imageId + state.Put("image", imageId) // Wait for the image to become ready ui.Say("Waiting for image to become ready...") if err := WaitForImage(csp, imageId); err != nil { err := fmt.Errorf("Error waiting for image: %s", err) - state["error"] = err + state.Put("error", err) ui.Error(err.Error()) return multistep.ActionHalt } @@ -46,7 +46,7 @@ func (s *stepCreateImage) Run(state map[string]interface{}) multistep.StepAction return multistep.ActionContinue } -func (s *stepCreateImage) Cleanup(map[string]interface{}) { +func (s *stepCreateImage) Cleanup(multistep.StateBag) { // No cleanup... } diff --git a/builder/openstack/step_key_pair.go b/builder/openstack/step_key_pair.go index 0a1ec7c66..a67579976 100644 --- a/builder/openstack/step_key_pair.go +++ b/builder/openstack/step_key_pair.go @@ -14,16 +14,16 @@ type StepKeyPair struct { keyName string } -func (s *StepKeyPair) Run(state map[string]interface{}) multistep.StepAction { - csp := state["csp"].(gophercloud.CloudServersProvider) - ui := state["ui"].(packer.Ui) +func (s *StepKeyPair) Run(state multistep.StateBag) multistep.StepAction { + csp := state.Get("csp").(gophercloud.CloudServersProvider) + ui := state.Get("ui").(packer.Ui) ui.Say("Creating temporary keypair for this instance...") keyName := fmt.Sprintf("packer %s", hex.EncodeToString(identifier.NewUUID().Raw())) log.Printf("temporary keypair name: %s", keyName) keyResp, err := csp.CreateKeyPair(gophercloud.NewKeyPair{Name: keyName}) if err != nil { - state["error"] = fmt.Errorf("Error creating temporary keypair: %s", err) + state.Put("error", fmt.Errorf("Error creating temporary keypair: %s", err)) return multistep.ActionHalt } @@ -31,20 +31,20 @@ func (s *StepKeyPair) Run(state map[string]interface{}) multistep.StepAction { s.keyName = keyName // Set some state data for use in future steps - state["keyPair"] = keyName - state["privateKey"] = keyResp.PrivateKey + state.Put("keyPair", keyName) + state.Put("privateKey", keyResp.PrivateKey) return multistep.ActionContinue } -func (s *StepKeyPair) Cleanup(state map[string]interface{}) { +func (s *StepKeyPair) Cleanup(state multistep.StateBag) { // If no key name is set, then we never created it, so just return if s.keyName == "" { return } - csp := state["csp"].(gophercloud.CloudServersProvider) - ui := state["ui"].(packer.Ui) + csp := state.Get("csp").(gophercloud.CloudServersProvider) + ui := state.Get("ui").(packer.Ui) ui.Say("Deleting temporary keypair...") err := csp.DeleteKeyPair(s.keyName) diff --git a/builder/openstack/step_run_source_server.go b/builder/openstack/step_run_source_server.go index 7a2b7bc64..c8e121e09 100644 --- a/builder/openstack/step_run_source_server.go +++ b/builder/openstack/step_run_source_server.go @@ -16,10 +16,10 @@ type StepRunSourceServer struct { server *gophercloud.Server } -func (s *StepRunSourceServer) Run(state map[string]interface{}) multistep.StepAction { - csp := state["csp"].(gophercloud.CloudServersProvider) - keyName := state["keyPair"].(string) - ui := state["ui"].(packer.Ui) +func (s *StepRunSourceServer) Run(state multistep.StateBag) multistep.StepAction { + csp := state.Get("csp").(gophercloud.CloudServersProvider) + keyName := state.Get("keyPair").(string) + ui := state.Get("ui").(packer.Ui) // XXX - validate image and flavor is available @@ -33,7 +33,7 @@ func (s *StepRunSourceServer) Run(state map[string]interface{}) multistep.StepAc serverResp, err := csp.CreateServer(server) if err != nil { err := fmt.Errorf("Error launching source server: %s", err) - state["error"] = err + state.Put("error", err) ui.Error(err.Error()) return multistep.ActionHalt } @@ -51,24 +51,24 @@ func (s *StepRunSourceServer) Run(state map[string]interface{}) multistep.StepAc latestServer, err := WaitForState(&stateChange) if err != nil { err := fmt.Errorf("Error waiting for server (%s) to become ready: %s", s.server.Id, err) - state["error"] = err + state.Put("error", err) ui.Error(err.Error()) return multistep.ActionHalt } s.server = latestServer.(*gophercloud.Server) - state["server"] = s.server + state.Put("server", s.server) return multistep.ActionContinue } -func (s *StepRunSourceServer) Cleanup(state map[string]interface{}) { +func (s *StepRunSourceServer) Cleanup(state multistep.StateBag) { if s.server == nil { return } - csp := state["csp"].(gophercloud.CloudServersProvider) - ui := state["ui"].(packer.Ui) + csp := state.Get("csp").(gophercloud.CloudServersProvider) + ui := state.Get("ui").(packer.Ui) ui.Say("Terminating the source server...") if err := csp.DeleteServerById(s.server.Id); err != nil {