From 8aabe01badb4e91d599626d59e7277811fa93cc4 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Fri, 27 Dec 2013 20:54:35 -0700 Subject: [PATCH] builder/amazon/common: run_tags to apply to launch [GH-722] --- CHANGELOG.md | 2 + builder/amazon/common/run_config.go | 52 +++++++++++++------ .../amazon/common/step_run_source_instance.go | 22 +++++--- builder/amazon/ebs/builder.go | 1 + builder/amazon/instance/builder.go | 1 + .../docs/builders/amazon-ebs.html.markdown | 4 ++ .../builders/amazon-instance.html.markdown | 4 ++ 7 files changed, 63 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6337ee211..fa02033dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,6 +47,8 @@ IMPROVEMENTS: "Packer Builder" so that they are easily recognizable. [GH-642] * builder/amazon/all: Copying AMIs to multiple regions now happens in parallel. [GH-495] +* builder/amazon/all: Ability to specify "run\_tags" to tag the instance + while running. [GH-722] * builder/digitalocean: Private networking support. [GH-698] * builder/docker: A "run\_command" can be specified, configuring how the container is started. [GH-648] diff --git a/builder/amazon/common/run_config.go b/builder/amazon/common/run_config.go index 11530f7e6..0699219c7 100644 --- a/builder/amazon/common/run_config.go +++ b/builder/amazon/common/run_config.go @@ -11,21 +11,22 @@ import ( // RunConfig contains configuration for running an instance from a source // AMI and details on how to access that launched image. type RunConfig struct { - AssociatePublicIpAddress bool `mapstructure:"associate_public_ip_address"` - AvailabilityZone string `mapstructure:"availability_zone"` - IamInstanceProfile string `mapstructure:"iam_instance_profile"` - InstanceType string `mapstructure:"instance_type"` - SourceAmi string `mapstructure:"source_ami"` - RawSSHTimeout string `mapstructure:"ssh_timeout"` - SSHUsername string `mapstructure:"ssh_username"` - SSHPort int `mapstructure:"ssh_port"` - SecurityGroupId string `mapstructure:"security_group_id"` - SecurityGroupIds []string `mapstructure:"security_group_ids"` - SubnetId string `mapstructure:"subnet_id"` - TemporaryKeyPairName string `mapstructure:"temporary_key_pair_name"` - UserData string `mapstructure:"user_data"` - UserDataFile string `mapstructure:"user_data_file"` - VpcId string `mapstructure:"vpc_id"` + AssociatePublicIpAddress bool `mapstructure:"associate_public_ip_address"` + AvailabilityZone string `mapstructure:"availability_zone"` + IamInstanceProfile string `mapstructure:"iam_instance_profile"` + InstanceType string `mapstructure:"instance_type"` + RunTags map[string]string `mapstructure:"run_tags"` + SourceAmi string `mapstructure:"source_ami"` + RawSSHTimeout string `mapstructure:"ssh_timeout"` + SSHUsername string `mapstructure:"ssh_username"` + SSHPort int `mapstructure:"ssh_port"` + SecurityGroupId string `mapstructure:"security_group_id"` + SecurityGroupIds []string `mapstructure:"security_group_ids"` + SubnetId string `mapstructure:"subnet_id"` + TemporaryKeyPairName string `mapstructure:"temporary_key_pair_name"` + UserData string `mapstructure:"user_data"` + UserDataFile string `mapstructure:"user_data_file"` + VpcId string `mapstructure:"vpc_id"` // Unexported fields that are calculated from others sshTimeout time.Duration @@ -121,6 +122,27 @@ func (c *RunConfig) Prepare(t *packer.ConfigTemplate) []error { } } + newTags := make(map[string]string) + for k, v := range c.RunTags { + k, err := t.Process(k, nil) + if err != nil { + errs = append(errs, + fmt.Errorf("Error processing tag key %s: %s", k, err)) + continue + } + + v, err := t.Process(v, nil) + if err != nil { + errs = append(errs, + fmt.Errorf("Error processing tag value '%s': %s", v, err)) + continue + } + + newTags[k] = v + } + + c.RunTags = newTags + c.sshTimeout, err = time.ParseDuration(c.RawSSHTimeout) if err != nil { errs = append(errs, fmt.Errorf("Failed parsing ssh_timeout: %s", err)) diff --git a/builder/amazon/common/step_run_source_instance.go b/builder/amazon/common/step_run_source_instance.go index c5733581e..c9827e589 100644 --- a/builder/amazon/common/step_run_source_instance.go +++ b/builder/amazon/common/step_run_source_instance.go @@ -9,17 +9,18 @@ import ( ) type StepRunSourceInstance struct { + AssociatePublicIpAddress bool + AvailabilityZone string + BlockDevices BlockDevices Debug bool ExpectedRootDevice string InstanceType string - UserData string - UserDataFile string - SourceAMI string IamInstanceProfile string + SourceAMI string SubnetId string - AssociatePublicIpAddress bool - AvailabilityZone string - BlockDevices BlockDevices + Tags map[string]string + UserData string + UserDataFile string instance *ec2.Instance } @@ -92,8 +93,13 @@ func (s *StepRunSourceInstance) Run(state multistep.StateBag) multistep.StepActi s.instance = &runResp.Instances[0] ui.Message(fmt.Sprintf("Instance ID: %s", s.instance.InstanceId)) - _, err = ec2conn.CreateTags( - []string{s.instance.InstanceId}, []ec2.Tag{{"Name", "Packer Builder"}}) + ec2Tags := make([]ec2.Tag, 1, len(s.Tags)+1) + ec2Tags[0] = ec2.Tag{"Name", "Packer Builder"} + for k, v := range s.Tags { + ec2Tags = append(ec2Tags, ec2.Tag{k, v}) + } + + _, err = ec2conn.CreateTags([]string{s.instance.InstanceId}, ec2Tags) if err != nil { ui.Message( fmt.Sprintf("Failed to tag a Name on the builder instance: %s", err)) diff --git a/builder/amazon/ebs/builder.go b/builder/amazon/ebs/builder.go index e58392f84..f17dad4d4 100644 --- a/builder/amazon/ebs/builder.go +++ b/builder/amazon/ebs/builder.go @@ -104,6 +104,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe AssociatePublicIpAddress: b.config.AssociatePublicIpAddress, AvailabilityZone: b.config.AvailabilityZone, BlockDevices: b.config.BlockDevices, + Tags: b.config.RunTags, }, &common.StepConnectSSH{ SSHAddress: awscommon.SSHAddress(ec2conn, b.config.SSHPort), diff --git a/builder/amazon/instance/builder.go b/builder/amazon/instance/builder.go index db1d6c28e..e0c934c16 100644 --- a/builder/amazon/instance/builder.go +++ b/builder/amazon/instance/builder.go @@ -208,6 +208,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe AssociatePublicIpAddress: b.config.AssociatePublicIpAddress, AvailabilityZone: b.config.AvailabilityZone, BlockDevices: b.config.BlockDevices, + Tags: b.config.RunTags, }, &common.StepConnectSSH{ SSHAddress: awscommon.SSHAddress(ec2conn, b.config.SSHPort), diff --git a/website/source/docs/builders/amazon-ebs.html.markdown b/website/source/docs/builders/amazon-ebs.html.markdown index 96177bfb9..855c123ab 100644 --- a/website/source/docs/builders/amazon-ebs.html.markdown +++ b/website/source/docs/builders/amazon-ebs.html.markdown @@ -91,6 +91,10 @@ Optional: block device mappings to the launch instance. The block device mappings are the same as `ami_block_device_mappings` above. +* `run_tags` (object of key/value strings) - Tags to apply to the instance + that is _launched_ to create the AMI. These tags are _not_ applied to + the resulting AMI unless they're duplicated in `tags`. + * `security_group_id` (string) - The ID (_not_ the name) of the security group to assign to the instance. By default this is not set and Packer will automatically create a new temporary security group to allow SSH diff --git a/website/source/docs/builders/amazon-instance.html.markdown b/website/source/docs/builders/amazon-instance.html.markdown index 42e34e48b..5e43e32f2 100644 --- a/website/source/docs/builders/amazon-instance.html.markdown +++ b/website/source/docs/builders/amazon-instance.html.markdown @@ -130,6 +130,10 @@ Optional: block device mappings to the launch instance. The block device mappings are the same as `ami_block_device_mappings` above. +* `run_tags` (object of key/value strings) - Tags to apply to the instance + that is _launched_ to create the AMI. These tags are _not_ applied to + the resulting AMI unless they're duplicated in `tags`. + * `security_group_id` (string) - The ID (_not_ the name) of the security group to assign to the instance. By default this is not set and Packer will automatically create a new temporary security group to allow SSH