github.com/amanya/packer@v0.12.1-0.20161117214323-902ac5ab2eb6/builder/amazon/common/run_config.go (about)

     1  package common
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"os"
     7  	"regexp"
     8  	"time"
     9  
    10  	"github.com/mitchellh/packer/common/uuid"
    11  	"github.com/mitchellh/packer/helper/communicator"
    12  	"github.com/mitchellh/packer/template/interpolate"
    13  )
    14  
    15  var reShutdownBehavior = regexp.MustCompile("^(stop|terminate)$")
    16  
    17  type AmiFilterOptions struct {
    18  	Filters    map[*string]*string
    19  	Owners     []*string
    20  	MostRecent bool `mapstructure:"most_recent"`
    21  }
    22  
    23  func (d *AmiFilterOptions) Empty() bool {
    24  	return len(d.Owners) == 0 && len(d.Filters) == 0
    25  }
    26  
    27  // RunConfig contains configuration for running an instance from a source
    28  // AMI and details on how to access that launched image.
    29  type RunConfig struct {
    30  	AssociatePublicIpAddress          bool              `mapstructure:"associate_public_ip_address"`
    31  	AvailabilityZone                  string            `mapstructure:"availability_zone"`
    32  	EbsOptimized                      bool              `mapstructure:"ebs_optimized"`
    33  	IamInstanceProfile                string            `mapstructure:"iam_instance_profile"`
    34  	InstanceType                      string            `mapstructure:"instance_type"`
    35  	RunTags                           map[string]string `mapstructure:"run_tags"`
    36  	SourceAmi                         string            `mapstructure:"source_ami"`
    37  	SourceAmiFilter                   AmiFilterOptions  `mapstructure:"source_ami_filter"`
    38  	SpotPrice                         string            `mapstructure:"spot_price"`
    39  	SpotPriceAutoProduct              string            `mapstructure:"spot_price_auto_product"`
    40  	DisableStopInstance               bool              `mapstructure:"disable_stop_instance"`
    41  	SecurityGroupId                   string            `mapstructure:"security_group_id"`
    42  	SecurityGroupIds                  []string          `mapstructure:"security_group_ids"`
    43  	SubnetId                          string            `mapstructure:"subnet_id"`
    44  	TemporaryKeyPairName              string            `mapstructure:"temporary_key_pair_name"`
    45  	UserData                          string            `mapstructure:"user_data"`
    46  	UserDataFile                      string            `mapstructure:"user_data_file"`
    47  	WindowsPasswordTimeout            time.Duration     `mapstructure:"windows_password_timeout"`
    48  	VpcId                             string            `mapstructure:"vpc_id"`
    49  	InstanceInitiatedShutdownBehavior string            `mapstructure:"shutdown_behaviour"`
    50  
    51  	// Communicator settings
    52  	Comm           communicator.Config `mapstructure:",squash"`
    53  	SSHKeyPairName string              `mapstructure:"ssh_keypair_name"`
    54  	SSHPrivateIp   bool                `mapstructure:"ssh_private_ip"`
    55  }
    56  
    57  func (c *RunConfig) Prepare(ctx *interpolate.Context) []error {
    58  	// If we are not given an explicit ssh_keypair_name or
    59  	// ssh_private_key_file, then create a temporary one, but only if the
    60  	// temporary_key_pair_name has not been provided and we are not using
    61  	// ssh_password.
    62  	if c.SSHKeyPairName == "" && c.TemporaryKeyPairName == "" &&
    63  		c.Comm.SSHPrivateKey == "" && c.Comm.SSHPassword == "" {
    64  
    65  		c.TemporaryKeyPairName = fmt.Sprintf("packer_%s", uuid.TimeOrderedUUID())
    66  	}
    67  
    68  	if c.WindowsPasswordTimeout == 0 {
    69  		c.WindowsPasswordTimeout = 10 * time.Minute
    70  	}
    71  
    72  	// Validation
    73  	errs := c.Comm.Prepare(ctx)
    74  	if c.SourceAmi == "" && c.SourceAmiFilter.Empty() {
    75  		errs = append(errs, errors.New("A source_ami or source_ami_filter must be specified"))
    76  	}
    77  
    78  	if c.InstanceType == "" {
    79  		errs = append(errs, errors.New("An instance_type must be specified"))
    80  	}
    81  
    82  	if c.SpotPrice == "auto" {
    83  		if c.SpotPriceAutoProduct == "" {
    84  			errs = append(errs, errors.New(
    85  				"spot_price_auto_product must be specified when spot_price is auto"))
    86  		}
    87  	}
    88  
    89  	if c.UserData != "" && c.UserDataFile != "" {
    90  		errs = append(errs, fmt.Errorf("Only one of user_data or user_data_file can be specified."))
    91  	} else if c.UserDataFile != "" {
    92  		if _, err := os.Stat(c.UserDataFile); err != nil {
    93  			errs = append(errs, fmt.Errorf("user_data_file not found: %s", c.UserDataFile))
    94  		}
    95  	}
    96  
    97  	if c.SecurityGroupId != "" {
    98  		if len(c.SecurityGroupIds) > 0 {
    99  			errs = append(errs, fmt.Errorf("Only one of security_group_id or security_group_ids can be specified."))
   100  		} else {
   101  			c.SecurityGroupIds = []string{c.SecurityGroupId}
   102  			c.SecurityGroupId = ""
   103  		}
   104  	}
   105  
   106  	if c.InstanceInitiatedShutdownBehavior == "" {
   107  		c.InstanceInitiatedShutdownBehavior = "stop"
   108  	} else if !reShutdownBehavior.MatchString(c.InstanceInitiatedShutdownBehavior) {
   109  		errs = append(errs, fmt.Errorf("shutdown_behaviour only accepts 'stop' or 'terminate' values."))
   110  	}
   111  
   112  	return errs
   113  }