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  }