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