github.com/emate/packer@v0.8.1-0.20150625195101-fe0fde195dc6/builder/googlecompute/step_create_instance.go (about) 1 package googlecompute 2 3 import ( 4 "errors" 5 "fmt" 6 "time" 7 8 "github.com/mitchellh/multistep" 9 "github.com/mitchellh/packer/packer" 10 ) 11 12 // StepCreateInstance represents a Packer build step that creates GCE instances. 13 type StepCreateInstance struct { 14 Debug bool 15 } 16 17 func (config *Config) getImage() Image { 18 project := config.ProjectId 19 if config.SourceImageProjectId != "" { 20 project = config.SourceImageProjectId 21 } 22 return Image{Name: config.SourceImage, ProjectId: project} 23 } 24 25 func (config *Config) getInstanceMetadata(sshPublicKey string) map[string]string { 26 instanceMetadata := make(map[string]string) 27 28 // Copy metadata from config 29 for k, v := range config.Metadata { 30 instanceMetadata[k] = v 31 } 32 33 // Merge any existing ssh keys with our public key 34 sshMetaKey := "sshKeys" 35 sshKeys := fmt.Sprintf("%s:%s", config.Comm.SSHUsername, sshPublicKey) 36 if confSshKeys, exists := instanceMetadata[sshMetaKey]; exists { 37 sshKeys = fmt.Sprintf("%s\n%s", sshKeys, confSshKeys) 38 } 39 instanceMetadata[sshMetaKey] = sshKeys 40 41 return instanceMetadata 42 } 43 44 // Run executes the Packer build step that creates a GCE instance. 45 func (s *StepCreateInstance) Run(state multistep.StateBag) multistep.StepAction { 46 config := state.Get("config").(*Config) 47 driver := state.Get("driver").(Driver) 48 sshPublicKey := state.Get("ssh_public_key").(string) 49 ui := state.Get("ui").(packer.Ui) 50 51 ui.Say("Creating instance...") 52 name := config.InstanceName 53 54 errCh, err := driver.RunInstance(&InstanceConfig{ 55 Description: "New instance created by Packer", 56 DiskSizeGb: config.DiskSizeGb, 57 Image: config.getImage(), 58 MachineType: config.MachineType, 59 Metadata: config.getInstanceMetadata(sshPublicKey), 60 Name: name, 61 Network: config.Network, 62 Tags: config.Tags, 63 Zone: config.Zone, 64 }) 65 66 if err == nil { 67 ui.Message("Waiting for creation operation to complete...") 68 select { 69 case err = <-errCh: 70 case <-time.After(config.stateTimeout): 71 err = errors.New("time out while waiting for instance to create") 72 } 73 } 74 75 if err != nil { 76 err := fmt.Errorf("Error creating instance: %s", err) 77 state.Put("error", err) 78 ui.Error(err.Error()) 79 return multistep.ActionHalt 80 } 81 82 ui.Message("Instance has been created!") 83 84 if s.Debug { 85 if name != "" { 86 ui.Message(fmt.Sprintf("Instance: %s started in %s", name, config.Zone)) 87 } 88 } 89 90 // Things succeeded, store the name so we can remove it later 91 state.Put("instance_name", name) 92 93 return multistep.ActionContinue 94 } 95 96 // Cleanup destroys the GCE instance created during the image creation process. 97 func (s *StepCreateInstance) Cleanup(state multistep.StateBag) { 98 nameRaw, ok := state.GetOk("instance_name") 99 if !ok { 100 return 101 } 102 name := nameRaw.(string) 103 if name == "" { 104 return 105 } 106 107 config := state.Get("config").(*Config) 108 driver := state.Get("driver").(Driver) 109 ui := state.Get("ui").(packer.Ui) 110 111 ui.Say("Deleting instance...") 112 errCh, err := driver.DeleteInstance(config.Zone, name) 113 if err == nil { 114 select { 115 case err = <-errCh: 116 case <-time.After(config.stateTimeout): 117 err = errors.New("time out while waiting for instance to delete") 118 } 119 } 120 121 if err != nil { 122 ui.Error(fmt.Sprintf( 123 "Error deleting instance. Please delete it manually.\n\n"+ 124 "Name: %s\n"+ 125 "Error: %s", name, err)) 126 } 127 128 ui.Message("Instance has been deleted!") 129 state.Put("instance_name", "") 130 131 // Deleting the instance does not remove the boot disk. This cleanup removes 132 // the disk. 133 ui.Say("Deleting disk...") 134 errCh, err = driver.DeleteDisk(config.Zone, config.DiskName) 135 if err == nil { 136 select { 137 case err = <-errCh: 138 case <-time.After(config.stateTimeout): 139 err = errors.New("time out while waiting for disk to delete") 140 } 141 } 142 143 if err != nil { 144 ui.Error(fmt.Sprintf( 145 "Error deleting disk. Please delete it manually.\n\n"+ 146 "Name: %s\n"+ 147 "Error: %s", config.InstanceName, err)) 148 } 149 150 ui.Message("Disk has been deleted!") 151 152 return 153 }