github.com/homburg/packer@v0.6.1-0.20140528012651-1dcaf1716848/builder/amazon/common/run_config.go (about)

     1  package common
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"github.com/mitchellh/packer/packer"
     7  	"os"
     8  	"time"
     9  )
    10  
    11  // RunConfig contains configuration for running an instance from a source
    12  // AMI and details on how to access that launched image.
    13  type RunConfig struct {
    14  	AssociatePublicIpAddress bool              `mapstructure:"associate_public_ip_address"`
    15  	AvailabilityZone         string            `mapstructure:"availability_zone"`
    16  	IamInstanceProfile       string            `mapstructure:"iam_instance_profile"`
    17  	InstanceType             string            `mapstructure:"instance_type"`
    18  	RunTags                  map[string]string `mapstructure:"run_tags"`
    19  	SourceAmi                string            `mapstructure:"source_ami"`
    20  	RawSSHTimeout            string            `mapstructure:"ssh_timeout"`
    21  	SSHUsername              string            `mapstructure:"ssh_username"`
    22  	SSHPrivateKeyFile        string            `mapstructure:"ssh_private_key_file"`
    23  	SSHPort                  int               `mapstructure:"ssh_port"`
    24  	SecurityGroupId          string            `mapstructure:"security_group_id"`
    25  	SecurityGroupIds         []string          `mapstructure:"security_group_ids"`
    26  	SubnetId                 string            `mapstructure:"subnet_id"`
    27  	TemporaryKeyPairName     string            `mapstructure:"temporary_key_pair_name"`
    28  	UserData                 string            `mapstructure:"user_data"`
    29  	UserDataFile             string            `mapstructure:"user_data_file"`
    30  	VpcId                    string            `mapstructure:"vpc_id"`
    31  
    32  	// Unexported fields that are calculated from others
    33  	sshTimeout time.Duration
    34  }
    35  
    36  func (c *RunConfig) Prepare(t *packer.ConfigTemplate) []error {
    37  	if t == nil {
    38  		var err error
    39  		t, err = packer.NewConfigTemplate()
    40  		if err != nil {
    41  			return []error{err}
    42  		}
    43  	}
    44  
    45  	// Defaults
    46  	if c.SSHPort == 0 {
    47  		c.SSHPort = 22
    48  	}
    49  
    50  	if c.RawSSHTimeout == "" {
    51  		c.RawSSHTimeout = "5m"
    52  	}
    53  
    54  	if c.TemporaryKeyPairName == "" {
    55  		c.TemporaryKeyPairName = "packer {{uuid}}"
    56  	}
    57  
    58  	// Validation
    59  	var err error
    60  	errs := make([]error, 0)
    61  	if c.SourceAmi == "" {
    62  		errs = append(errs, errors.New("A source_ami must be specified"))
    63  	}
    64  
    65  	if c.InstanceType == "" {
    66  		errs = append(errs, errors.New("An instance_type must be specified"))
    67  	}
    68  
    69  	if c.SSHUsername == "" {
    70  		errs = append(errs, errors.New("An ssh_username must be specified"))
    71  	}
    72  
    73  	if c.UserData != "" && c.UserDataFile != "" {
    74  		errs = append(errs, fmt.Errorf("Only one of user_data or user_data_file can be specified."))
    75  	} else if c.UserDataFile != "" {
    76  		if _, err := os.Stat(c.UserDataFile); err != nil {
    77  			errs = append(errs, fmt.Errorf("user_data_file not found: %s", c.UserDataFile))
    78  		}
    79  	}
    80  
    81  	if c.SecurityGroupId != "" {
    82  		if len(c.SecurityGroupIds) > 0 {
    83  			errs = append(errs, fmt.Errorf("Only one of security_group_id or security_group_ids can be specified."))
    84  		} else {
    85  			c.SecurityGroupIds = []string{c.SecurityGroupId}
    86  			c.SecurityGroupId = ""
    87  		}
    88  	}
    89  
    90  	templates := map[string]*string{
    91  		"iam_instance_profile":    &c.IamInstanceProfile,
    92  		"instance_type":           &c.InstanceType,
    93  		"ssh_timeout":             &c.RawSSHTimeout,
    94  		"ssh_username":            &c.SSHUsername,
    95  		"ssh_private_key_file":    &c.SSHPrivateKeyFile,
    96  		"source_ami":              &c.SourceAmi,
    97  		"subnet_id":               &c.SubnetId,
    98  		"temporary_key_pair_name": &c.TemporaryKeyPairName,
    99  		"vpc_id":                  &c.VpcId,
   100  		"availability_zone":       &c.AvailabilityZone,
   101  	}
   102  
   103  	for n, ptr := range templates {
   104  		var err error
   105  		*ptr, err = t.Process(*ptr, nil)
   106  		if err != nil {
   107  			errs = append(
   108  				errs, fmt.Errorf("Error processing %s: %s", n, err))
   109  		}
   110  	}
   111  
   112  	sliceTemplates := map[string][]string{
   113  		"security_group_ids": c.SecurityGroupIds,
   114  	}
   115  
   116  	for n, slice := range sliceTemplates {
   117  		for i, elem := range slice {
   118  			var err error
   119  			slice[i], err = t.Process(elem, nil)
   120  			if err != nil {
   121  				errs = append(
   122  					errs, fmt.Errorf("Error processing %s[%d]: %s", n, i, err))
   123  			}
   124  		}
   125  	}
   126  
   127  	newTags := make(map[string]string)
   128  	for k, v := range c.RunTags {
   129  		k, err := t.Process(k, nil)
   130  		if err != nil {
   131  			errs = append(errs,
   132  				fmt.Errorf("Error processing tag key %s: %s", k, err))
   133  			continue
   134  		}
   135  
   136  		v, err := t.Process(v, nil)
   137  		if err != nil {
   138  			errs = append(errs,
   139  				fmt.Errorf("Error processing tag value '%s': %s", v, err))
   140  			continue
   141  		}
   142  
   143  		newTags[k] = v
   144  	}
   145  
   146  	c.RunTags = newTags
   147  
   148  	c.sshTimeout, err = time.ParseDuration(c.RawSSHTimeout)
   149  	if err != nil {
   150  		errs = append(errs, fmt.Errorf("Failed parsing ssh_timeout: %s", err))
   151  	}
   152  
   153  	return errs
   154  }
   155  
   156  func (c *RunConfig) SSHTimeout() time.Duration {
   157  	return c.sshTimeout
   158  }