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  }