github.com/kikitux/packer@v0.10.1-0.20160322154024-6237df566f9f/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 DiskType: config.DiskType, 58 Image: config.getImage(), 59 MachineType: config.MachineType, 60 Metadata: config.getInstanceMetadata(sshPublicKey), 61 Name: name, 62 Network: config.Network, 63 Subnetwork: config.Subnetwork, 64 Address: config.Address, 65 Preemptible: config.Preemptible, 66 Tags: config.Tags, 67 Region: config.Region, 68 Zone: config.Zone, 69 }) 70 71 if err == nil { 72 ui.Message("Waiting for creation operation to complete...") 73 select { 74 case err = <-errCh: 75 case <-time.After(config.stateTimeout): 76 err = errors.New("time out while waiting for instance to create") 77 } 78 } 79 80 if err != nil { 81 err := fmt.Errorf("Error creating instance: %s", err) 82 state.Put("error", err) 83 ui.Error(err.Error()) 84 return multistep.ActionHalt 85 } 86 87 ui.Message("Instance has been created!") 88 89 if s.Debug { 90 if name != "" { 91 ui.Message(fmt.Sprintf("Instance: %s started in %s", name, config.Zone)) 92 } 93 } 94 95 // Things succeeded, store the name so we can remove it later 96 state.Put("instance_name", name) 97 98 return multistep.ActionContinue 99 } 100 101 // Cleanup destroys the GCE instance created during the image creation process. 102 func (s *StepCreateInstance) Cleanup(state multistep.StateBag) { 103 nameRaw, ok := state.GetOk("instance_name") 104 if !ok { 105 return 106 } 107 name := nameRaw.(string) 108 if name == "" { 109 return 110 } 111 112 config := state.Get("config").(*Config) 113 driver := state.Get("driver").(Driver) 114 ui := state.Get("ui").(packer.Ui) 115 116 ui.Say("Deleting instance...") 117 errCh, err := driver.DeleteInstance(config.Zone, name) 118 if err == nil { 119 select { 120 case err = <-errCh: 121 case <-time.After(config.stateTimeout): 122 err = errors.New("time out while waiting for instance to delete") 123 } 124 } 125 126 if err != nil { 127 ui.Error(fmt.Sprintf( 128 "Error deleting instance. Please delete it manually.\n\n"+ 129 "Name: %s\n"+ 130 "Error: %s", name, err)) 131 } 132 133 ui.Message("Instance has been deleted!") 134 state.Put("instance_name", "") 135 136 // Deleting the instance does not remove the boot disk. This cleanup removes 137 // the disk. 138 ui.Say("Deleting disk...") 139 errCh, err = driver.DeleteDisk(config.Zone, config.DiskName) 140 if err == nil { 141 select { 142 case err = <-errCh: 143 case <-time.After(config.stateTimeout): 144 err = errors.New("time out while waiting for disk to delete") 145 } 146 } 147 148 if err != nil { 149 ui.Error(fmt.Sprintf( 150 "Error deleting disk. Please delete it manually.\n\n"+ 151 "Name: %s\n"+ 152 "Error: %s", config.InstanceName, err)) 153 } 154 155 ui.Message("Disk has been deleted!") 156 157 return 158 }