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  }