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