github.com/rahart/packer@v0.12.2-0.20161229105310-282bb6ad370f/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_behavior"` 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_behavior only accepts 'stop' or 'terminate' values.")) 110 } 111 112 return errs 113 }