diff --git a/builder/amazon/common/run_config.go b/builder/amazon/common/run_config.go index 129d4d541..9467d42bd 100644 --- a/builder/amazon/common/run_config.go +++ b/builder/amazon/common/run_config.go @@ -43,6 +43,7 @@ type RunConfig struct { SourceAmiFilter AmiFilterOptions `mapstructure:"source_ami_filter"` SpotPrice string `mapstructure:"spot_price"` SpotPriceAutoProduct string `mapstructure:"spot_price_auto_product"` + SpotTags map[string]string `mapstructure:"spot_tags"` SubnetId string `mapstructure:"subnet_id"` TemporaryKeyPairName string `mapstructure:"temporary_key_pair_name"` TemporarySGSourceCidr string `mapstructure:"temporary_security_group_source_cidr"` @@ -118,6 +119,13 @@ func (c *RunConfig) Prepare(ctx *interpolate.Context) []error { } } + if c.SpotTags != nil { + if c.SpotPrice == "" || c.SpotPrice == "0" { + errs = append(errs, fmt.Errorf( + "spot_tags should not be set when not requesting a spot instance")) + } + } + if c.UserData != "" && c.UserDataFile != "" { errs = append(errs, fmt.Errorf("Only one of user_data or user_data_file can be specified.")) } else if c.UserDataFile != "" { diff --git a/builder/amazon/common/step_run_spot_instance.go b/builder/amazon/common/step_run_spot_instance.go index 9e5678f7f..09d456496 100644 --- a/builder/amazon/common/step_run_spot_instance.go +++ b/builder/amazon/common/step_run_spot_instance.go @@ -32,6 +32,7 @@ type StepRunSpotInstance struct { SourceAMI string SpotPrice string SpotPriceProduct string + SpotTags TagMap SubnetId string Tags TagMap VolumeTags TagMap @@ -221,6 +222,33 @@ func (s *StepRunSpotInstance) Run(ctx context.Context, state multistep.StateBag) } instanceId = *spotResp.SpotInstanceRequests[0].InstanceId + // Tag spot instance request + spotTags, err := s.SpotTags.EC2Tags(s.Ctx, *ec2conn.Config.Region, state) + if err != nil { + err := fmt.Errorf("Error tagging spot request: %s", err) + state.Put("error", err) + ui.Error(err.Error()) + return multistep.ActionHalt + } + spotTags.Report(ui) + + if len(spotTags) > 0 && s.SpotTags.IsSet() { + // Retry creating tags for about 2.5 minutes + err = retry.Retry(0.2, 30, 11, func(_ uint) (bool, error) { + _, err := ec2conn.CreateTags(&ec2.CreateTagsInput{ + Tags: spotTags, + Resources: []*string{spotRequestId}, + }) + return true, err + }) + if err != nil { + err := fmt.Errorf("Error tagging spot request: %s", err) + state.Put("error", err) + ui.Error(err.Error()) + return multistep.ActionHalt + } + } + // Set the instance ID so that the cleanup works properly s.instanceId = instanceId diff --git a/builder/amazon/ebs/builder.go b/builder/amazon/ebs/builder.go index 665bf8098..bd10ad36a 100644 --- a/builder/amazon/ebs/builder.go +++ b/builder/amazon/ebs/builder.go @@ -48,6 +48,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { "ami_description", "run_tags", "run_volume_tags", + "spot_tags", "snapshot_tags", "tags", }, @@ -134,6 +135,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe SourceAMI: b.config.SourceAmi, SpotPrice: b.config.SpotPrice, SpotPriceProduct: b.config.SpotPriceAutoProduct, + SpotTags: b.config.SpotTags, SubnetId: b.config.SubnetId, Tags: b.config.RunTags, UserData: b.config.UserData, diff --git a/builder/amazon/ebssurrogate/builder.go b/builder/amazon/ebssurrogate/builder.go index 52a151b22..9642c1a83 100644 --- a/builder/amazon/ebssurrogate/builder.go +++ b/builder/amazon/ebssurrogate/builder.go @@ -48,6 +48,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { "run_tags", "run_volume_tags", "snapshot_tags", + "spot_tags", "tags", }, }, @@ -148,6 +149,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe SourceAMI: b.config.SourceAmi, SpotPrice: b.config.SpotPrice, SpotPriceProduct: b.config.SpotPriceAutoProduct, + SpotTags: b.config.SpotTags, SubnetId: b.config.SubnetId, Tags: b.config.RunTags, UserData: b.config.UserData, diff --git a/builder/amazon/ebsvolume/builder.go b/builder/amazon/ebsvolume/builder.go index 1a79b964e..222febc56 100644 --- a/builder/amazon/ebsvolume/builder.go +++ b/builder/amazon/ebsvolume/builder.go @@ -44,6 +44,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { InterpolateFilter: &interpolate.RenderFilter{ Exclude: []string{ "run_tags", + "spot_tags", "ebs_volumes", }, }, @@ -132,6 +133,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe SourceAMI: b.config.SourceAmi, SpotPrice: b.config.SpotPrice, SpotPriceProduct: b.config.SpotPriceAutoProduct, + SpotTags: b.config.SpotTags, SubnetId: b.config.SubnetId, Tags: b.config.RunTags, UserData: b.config.UserData, diff --git a/builder/amazon/instance/builder.go b/builder/amazon/instance/builder.go index c197cadeb..fb59fff95 100644 --- a/builder/amazon/instance/builder.go +++ b/builder/amazon/instance/builder.go @@ -69,6 +69,7 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) { "run_volume_tags", "snapshot_tags", "tags", + "spot_tags", }, }, }, configs...) @@ -219,6 +220,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe SpotPriceProduct: b.config.SpotPriceAutoProduct, SubnetId: b.config.SubnetId, Tags: b.config.RunTags, + SpotTags: b.config.SpotTags, UserData: b.config.UserData, UserDataFile: b.config.UserDataFile, } diff --git a/website/source/docs/builders/amazon-ebs.html.md b/website/source/docs/builders/amazon-ebs.html.md index f8d75ebd0..c09591768 100644 --- a/website/source/docs/builders/amazon-ebs.html.md +++ b/website/source/docs/builders/amazon-ebs.html.md @@ -343,6 +343,10 @@ builder. best spot price. This must be one of: `Linux/UNIX`, `SUSE Linux`, `Windows`, `Linux/UNIX (Amazon VPC)`, `SUSE Linux (Amazon VPC)`, `Windows (Amazon VPC)` +- `spot_tags` (object of key/value strings) - Requires `spot_price` to + be set. This tells Packer to apply tags to the spot request that is + issued. + - `sriov_support` (boolean) - Enable enhanced networking (SriovNetSupport but not ENA) on HVM-compatible AMIs. If true, add `ec2:ModifyInstanceAttribute` to your AWS IAM policy. Note: you must make sure enhanced networking is enabled on your instance. See [Amazon's diff --git a/website/source/docs/builders/amazon-ebssurrogate.html.md b/website/source/docs/builders/amazon-ebssurrogate.html.md index eb21c1525..881cce45e 100644 --- a/website/source/docs/builders/amazon-ebssurrogate.html.md +++ b/website/source/docs/builders/amazon-ebssurrogate.html.md @@ -336,6 +336,10 @@ builder. best spot price. This must be one of: `Linux/UNIX`, `SUSE Linux`, `Windows`, `Linux/UNIX (Amazon VPC)`, `SUSE Linux (Amazon VPC)`, `Windows (Amazon VPC)` +- `spot_tags` (object of key/value strings) - Requires `spot_price` to + be set. This tells Packer to apply tags to the spot request that is + issued. + - `sriov_support` (boolean) - Enable enhanced networking (SriovNetSupport but not ENA) on HVM-compatible AMIs. If true, add `ec2:ModifyInstanceAttribute` to your AWS IAM policy. Note: you must make sure enhanced networking is enabled on your instance. See [Amazon's diff --git a/website/source/docs/builders/amazon-ebsvolume.html.md b/website/source/docs/builders/amazon-ebsvolume.html.md index acfa33e84..a3ff74785 100644 --- a/website/source/docs/builders/amazon-ebsvolume.html.md +++ b/website/source/docs/builders/amazon-ebsvolume.html.md @@ -264,6 +264,10 @@ builder. best spot price. This must be one of: `Linux/UNIX`, `SUSE Linux`, `Windows`, `Linux/UNIX (Amazon VPC)`, `SUSE Linux (Amazon VPC)` or `Windows (Amazon VPC)` +- `spot_tags` (object of key/value strings) - Requires `spot_price` to + be set. This tells Packer to apply tags to the spot request that is + issued. + - `sriov_support` (boolean) - Enable enhanced networking (SriovNetSupport but not ENA) on HVM-compatible AMIs. If true, add `ec2:ModifyInstanceAttribute` to your AWS IAM policy. Note: you must make sure enhanced networking is enabled on your instance. See [Amazon's diff --git a/website/source/docs/builders/amazon-instance.html.md b/website/source/docs/builders/amazon-instance.html.md index 52686aeec..00700dfb5 100644 --- a/website/source/docs/builders/amazon-instance.html.md +++ b/website/source/docs/builders/amazon-instance.html.md @@ -339,6 +339,10 @@ builder. best spot price. This must be one of: `Linux/UNIX`, `SUSE Linux`, `Windows`, `Linux/UNIX (Amazon VPC)`, `SUSE Linux (Amazon VPC)`, `Windows (Amazon VPC)` +- `spot_tags` (object of key/value strings) - Requires `spot_price` to + be set. This tells Packer to apply tags to the spot request that is + issued. + - `sriov_support` (boolean) - Enable enhanced networking (SriovNetSupport but not ENA) on HVM-compatible AMIs. If true, add `ec2:ModifyInstanceAttribute` to your AWS IAM policy. Note: you must make sure enhanced networking is enabled on your instance. See [Amazon's