Merge pull request #6088 from adongy/master

Expose more source ami data in the template
This commit is contained in:
Megan Marsh 2018-04-02 16:32:16 -07:00 committed by GitHub
commit 22608f3efd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 194 additions and 93 deletions

View File

@ -1,6 +1,36 @@
package common
import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/packer/helper/multistep"
)
type BuildInfoTemplate struct {
SourceAMI string
BuildRegion string
SourceAMI string
SourceAMIName string
SourceAMITags map[string]string
}
func extractBuildInfo(region string, state multistep.StateBag) *BuildInfoTemplate {
rawSourceAMI, hasSourceAMI := state.GetOk("source_image")
if !hasSourceAMI {
return &BuildInfoTemplate{
BuildRegion: region,
}
}
sourceAMI := rawSourceAMI.(*ec2.Image)
sourceAMITags := make(map[string]string, len(sourceAMI.Tags))
for _, tag := range sourceAMI.Tags {
sourceAMITags[aws.StringValue(tag.Key)] = aws.StringValue(tag.Value)
}
return &BuildInfoTemplate{
BuildRegion: region,
SourceAMI: aws.StringValue(sourceAMI.ImageId),
SourceAMIName: aws.StringValue(sourceAMI.Name),
SourceAMITags: sourceAMITags,
}
}

View File

@ -0,0 +1,63 @@
package common
import (
"reflect"
"testing"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/packer/helper/multistep"
)
func testImage() *ec2.Image {
return &ec2.Image{
ImageId: aws.String("ami-abcd1234"),
Name: aws.String("ami_test_name"),
Tags: []*ec2.Tag{
{
Key: aws.String("key-1"),
Value: aws.String("value-1"),
},
{
Key: aws.String("key-2"),
Value: aws.String("value-2"),
},
},
}
}
func testState() multistep.StateBag {
state := new(multistep.BasicStateBag)
return state
}
func TestInterpolateBuildInfo_extractBuildInfo_noSourceImage(t *testing.T) {
state := testState()
buildInfo := extractBuildInfo("foo", state)
expected := BuildInfoTemplate{
BuildRegion: "foo",
}
if !reflect.DeepEqual(*buildInfo, expected) {
t.Fatalf("Unexpected BuildInfoTemplate: expected %#v got %#v\n", expected, *buildInfo)
}
}
func TestInterpolateBuildInfo_extractBuildInfo_withSourceImage(t *testing.T) {
state := testState()
state.Put("source_image", testImage())
buildInfo := extractBuildInfo("foo", state)
expected := BuildInfoTemplate{
BuildRegion: "foo",
SourceAMI: "ami-abcd1234",
SourceAMIName: "ami_test_name",
SourceAMITags: map[string]string{
"key-1": "value-1",
"key-2": "value-2",
},
}
if !reflect.DeepEqual(*buildInfo, expected) {
t.Fatalf("Unexpected BuildInfoTemplate: expected %#v got %#v\n", expected, *buildInfo)
}
}

View File

@ -26,13 +26,6 @@ func (s *StepCreateTags) Run(_ context.Context, state multistep.StateBag) multis
ui := state.Get("ui").(packer.Ui)
amis := state.Get("amis").(map[string]string)
var sourceAMI string
if rawSourceAMI, hasSourceAMI := state.GetOk("source_image"); hasSourceAMI {
sourceAMI = *rawSourceAMI.(*ec2.Image).ImageId
} else {
sourceAMI = ""
}
if !s.Tags.IsSet() && !s.SnapshotTags.IsSet() {
return multistep.ActionContinue
}
@ -79,7 +72,7 @@ func (s *StepCreateTags) Run(_ context.Context, state multistep.StateBag) multis
// Convert tags to ec2.Tag format
ui.Say("Creating AMI tags")
amiTags, err := s.Tags.EC2Tags(s.Ctx, *ec2conn.Config.Region, sourceAMI)
amiTags, err := s.Tags.EC2Tags(s.Ctx, *ec2conn.Config.Region, state)
if err != nil {
state.Put("error", err)
ui.Error(err.Error())
@ -88,7 +81,7 @@ func (s *StepCreateTags) Run(_ context.Context, state multistep.StateBag) multis
amiTags.Report(ui)
ui.Say("Creating snapshot tags")
snapshotTags, err := s.SnapshotTags.EC2Tags(s.Ctx, *ec2conn.Config.Region, sourceAMI)
snapshotTags, err := s.SnapshotTags.EC2Tags(s.Ctx, *ec2conn.Config.Region, state)
if err != nil {
state.Put("error", err)
ui.Error(err.Error())

View File

@ -27,13 +27,6 @@ func (s *StepModifyAMIAttributes) Run(_ context.Context, state multistep.StateBa
session := state.Get("awsSession").(*session.Session)
ui := state.Get("ui").(packer.Ui)
amis := state.Get("amis").(map[string]string)
var sourceAMI string
if rawSourceAMI, hasSourceAMI := state.GetOk("source_image"); hasSourceAMI {
sourceAMI = *rawSourceAMI.(*ec2.Image).ImageId
} else {
sourceAMI = ""
}
snapshots := state.Get("snapshots").(map[string][]string)
// Determine if there is any work to do.
@ -50,10 +43,7 @@ func (s *StepModifyAMIAttributes) Run(_ context.Context, state multistep.StateBa
}
var err error
s.Ctx.Data = &BuildInfoTemplate{
SourceAMI: sourceAMI,
BuildRegion: *ec2conn.Config.Region,
}
s.Ctx.Data = extractBuildInfo(*ec2conn.Config.Region, state)
s.Description, err = interpolate.Render(s.Description, &s.Ctx)
if err != nil {
err = fmt.Errorf("Error interpolating AMI description: %s", err)

View File

@ -88,7 +88,7 @@ func (s *StepRunSourceInstance) Run(_ context.Context, state multistep.StateBag)
s.Tags["Name"] = "Packer Builder"
}
ec2Tags, err := s.Tags.EC2Tags(s.Ctx, *ec2conn.Config.Region, s.SourceAMI)
ec2Tags, err := s.Tags.EC2Tags(s.Ctx, *ec2conn.Config.Region, state)
if err != nil {
err := fmt.Errorf("Error tagging source instance: %s", err)
state.Put("error", err)
@ -96,7 +96,7 @@ func (s *StepRunSourceInstance) Run(_ context.Context, state multistep.StateBag)
return multistep.ActionHalt
}
volTags, err := s.VolumeTags.EC2Tags(s.Ctx, *ec2conn.Config.Region, s.SourceAMI)
volTags, err := s.VolumeTags.EC2Tags(s.Ctx, *ec2conn.Config.Region, state)
if err != nil {
err := fmt.Errorf("Error tagging volumes: %s", err)
state.Put("error", err)
@ -259,7 +259,7 @@ func (s *StepRunSourceInstance) Run(_ context.Context, state multistep.StateBag)
if len(volumeIds) > 0 && s.VolumeTags.IsSet() {
ui.Say("Adding tags to source EBS Volumes")
volumeTags, err := s.VolumeTags.EC2Tags(s.Ctx, *ec2conn.Config.Region, s.SourceAMI)
volumeTags, err := s.VolumeTags.EC2Tags(s.Ctx, *ec2conn.Config.Region, state)
if err != nil {
err := fmt.Errorf("Error tagging source EBS Volumes on %s: %s", *instance.InstanceId, err)
state.Put("error", err)

View File

@ -143,7 +143,7 @@ func (s *StepRunSpotInstance) Run(_ context.Context, state multistep.StateBag) m
s.Tags["Name"] = "Packer Builder"
}
ec2Tags, err := s.Tags.EC2Tags(s.Ctx, *ec2conn.Config.Region, s.SourceAMI)
ec2Tags, err := s.Tags.EC2Tags(s.Ctx, *ec2conn.Config.Region, state)
if err != nil {
err := fmt.Errorf("Error tagging source instance: %s", err)
state.Put("error", err)
@ -287,7 +287,7 @@ func (s *StepRunSpotInstance) Run(_ context.Context, state multistep.StateBag) m
if len(volumeIds) > 0 && s.VolumeTags.IsSet() {
ui.Say("Adding tags to source EBS Volumes")
volumeTags, err := s.VolumeTags.EC2Tags(s.Ctx, *ec2conn.Config.Region, s.SourceAMI)
volumeTags, err := s.VolumeTags.EC2Tags(s.Ctx, *ec2conn.Config.Region, state)
if err != nil {
err := fmt.Errorf("Error tagging source EBS Volumes on %s: %s", *instance.InstanceId, err)
state.Put("error", err)

View File

@ -5,6 +5,7 @@ import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/template/interpolate"
)
@ -23,12 +24,10 @@ func (t TagMap) IsSet() bool {
return len(t) > 0
}
func (t TagMap) EC2Tags(ctx interpolate.Context, region, sourceAMIID string) (EC2Tags, error) {
func (t TagMap) EC2Tags(ctx interpolate.Context, region string, state multistep.StateBag) (EC2Tags, error) {
var ec2Tags []*ec2.Tag
ctx.Data = &BuildInfoTemplate{
SourceAMI: sourceAMIID,
BuildRegion: region,
}
ctx.Data = extractBuildInfo(region, state)
for key, value := range t {
interpolatedKey, err := interpolate.Render(key, &ctx)
if err != nil {

View File

@ -18,7 +18,6 @@ type stepTagEBSVolumes struct {
func (s *stepTagEBSVolumes) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
ec2conn := state.Get("ec2").(*ec2.EC2)
instance := state.Get("instance").(*ec2.Instance)
sourceAMI := state.Get("source_image").(*ec2.Image)
ui := state.Get("ui").(packer.Ui)
volumes := make(EbsVolumes)
@ -43,7 +42,7 @@ func (s *stepTagEBSVolumes) Run(_ context.Context, state multistep.StateBag) mul
continue
}
tags, err := mapping.Tags.EC2Tags(s.Ctx, *ec2conn.Config.Region, *sourceAMI.ImageId)
tags, err := mapping.Tags.EC2Tags(s.Ctx, *ec2conn.Config.Region, state)
if err != nil {
err := fmt.Errorf("Error tagging device %s with %s", mapping.DeviceName, err)
state.Put("error", err)

View File

@ -77,10 +77,8 @@ each category, the available configuration keys are alphabetized.
- `ami_description` (string) - The description to set for the
resulting AMI(s). By default this description is empty. This is a
[template engine](/docs/templates/engine.html)
where the `SourceAMI` variable is replaced with the source AMI ID and
`BuildRegion` variable is replaced with name of the region where this
is built.
[template engine](/docs/templates/engine.html),
see [Build template data](#build-template-data) for more information.
- `ami_groups` (array of strings) - A list of groups that have access to
launch the resulting AMI(s). By default no groups have permission to launch
@ -251,10 +249,8 @@ each category, the available configuration keys are alphabetized.
- `snapshot_tags` (object of key/value strings) - Tags to apply to snapshot.
They will override AMI tags if already applied to snapshot. This is a
[template engine](/docs/templates/engine.html)
where the `SourceAMI` variable is replaced with the source AMI ID and
`BuildRegion` variable is replaced with name of the region where this
is built.
[template engine](/docs/templates/engine.html),
see [Build template data](#build-template-data) for more information.
- `snapshot_groups` (array of strings) - A list of groups that have access to
create volumes from the snapshot(s). By default no groups have permission to create
@ -307,10 +303,8 @@ each category, the available configuration keys are alphabetized.
Default `false`.
- `tags` (object of key/value strings) - Tags applied to the AMI. This is a
[template engine](/docs/templates/engine.html)
where the `SourceAMI` variable is replaced with the source AMI ID and
`BuildRegion` variable is replaced with name of the region where this
is built.
[template engine](/docs/templates/engine.html),
see [Build template data](#build-template-data) for more information.
## Basic Example
@ -432,3 +426,12 @@ provisioning commands to install the os and bootloader.
]
}
```
## Build template data
The available variables are:
- `BuildRegion` - The region (for example `eu-central-1`) where Packer is building the AMI.
- `SourceAMI` - The source AMI ID (for example `ami-a2412fcd`) used to build the AMI.
- `SourceAMIName` - The source AMI Name (for example `ubuntu/images/ebs-ssd/ubuntu-xenial-16.04-amd64-server-20180306`) used to build the AMI.
- `SourceAMITags` - The source AMI Tags, as a `map[string]string` object.

View File

@ -114,9 +114,8 @@ builder.
- `ami_description` (string) - The description to set for the
resulting AMI(s). By default this description is empty. This is a
[template engine](/docs/templates/engine.html)
where the `SourceAMI` variable is replaced with the source AMI ID and
`BuildRegion` variable is replaced with the value of `region`.
[template engine](/docs/templates/engine.html),
see [Build template data](#build-template-data) for more information.
- `ami_groups` (array of strings) - A list of groups that have access to
launch the resulting AMI(s). By default no groups have permission to launch
@ -221,16 +220,14 @@ builder.
- `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`. This is a
[template engine](/docs/templates/engine.html)
where the `SourceAMI` variable is replaced with the source AMI ID and
`BuildRegion` variable is replaced with the value of `region`.
[template engine](/docs/templates/engine.html),
see [Build template data](#build-template-data) for more information.
- `run_volume_tags` (object of key/value strings) - Tags to apply to the volumes
that are *launched* to create the AMI. These tags are *not* applied to the
resulting AMI unless they're duplicated in `tags`. This is a
[template engine](/docs/templates/engine.html)
where the `SourceAMI` variable is replaced with the source AMI ID and
`BuildRegion` variable is replaced with the value of `region`.
[template engine](/docs/templates/engine.html),
see [Build template data](#build-template-data) for more information.
- `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
@ -264,9 +261,8 @@ builder.
- `snapshot_tags` (object of key/value strings) - Tags to apply to snapshot.
They will override AMI tags if already applied to snapshot. This is a
[template engine](/docs/templates/engine.html)
where the `SourceAMI` variable is replaced with the source AMI ID and
`BuildRegion` variable is replaced with the value of `region`.
[template engine](/docs/templates/engine.html),
see [Build template data](#build-template-data) for more information.
- `source_ami_filter` (object) - Filters used to populate the `source_ami` field.
Example:
@ -361,9 +357,8 @@ builder.
- `tags` (object of key/value strings) - Tags applied to the AMI and
relevant snapshots. This is a
[template engine](/docs/templates/engine.html)
where the `SourceAMI` variable is replaced with the source AMI ID and
`BuildRegion` variable is replaced with the value of `region`.
[template engine](/docs/templates/engine.html),
see [Build template data](#build-template-data) for more information.
- `temporary_key_pair_name` (string) - The name of the temporary key pair
to generate. By default, Packer generates a name that looks like
@ -462,6 +457,15 @@ configuration of `launch_block_device_mappings` will expand the root volume
}
```
## Build template data
The available variables are:
- `BuildRegion` - The region (for example `eu-central-1`) where Packer is building the AMI.
- `SourceAMI` - The source AMI ID (for example `ami-a2412fcd`) used to build the AMI.
- `SourceAMIName` - The source AMI Name (for example `ubuntu/images/ebs-ssd/ubuntu-xenial-16.04-amd64-server-20180306`) used to build the AMI.
- `SourceAMITags` - The source AMI Tags, as a `map[string]string` object.
## Tag Example
Here is an example using the optional AMI tags. This will add the tags
@ -481,7 +485,9 @@ images exist when this template is run:
"ami_name": "packer-quick-start {{timestamp}}",
"tags": {
"OS_Version": "Ubuntu",
"Release": "Latest"
"Release": "Latest",
"Base_AMI_Name": "{{ .SourceAMIName }}",
"Extra": "{{ .SourceAMITags.TagName }}"
}
}
```

View File

@ -107,9 +107,8 @@ builder.
- `ami_description` (string) - The description to set for the
resulting AMI(s). By default this description is empty. This is a
[template engine](/docs/templates/engine.html)
where the `SourceAMI` variable is replaced with the source AMI ID and
`BuildRegion` variable is replaced with the value of `region`.
[template engine](/docs/templates/engine.html),
see [Build template data](#build-template-data) for more information.
- `ami_groups` (array of strings) - A list of groups that have access to
launch the resulting AMI(s). By default no groups have permission to launch
@ -214,16 +213,14 @@ builder.
- `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`. This is a
[template engine](/docs/templates/engine.html)
where the `SourceAMI` variable is replaced with the source AMI ID and
`BuildRegion` variable is replaced with the value of `region`.
[template engine](/docs/templates/engine.html),
see [Build template data](#build-template-data) for more information.
- `run_volume_tags` (object of key/value strings) - Tags to apply to the volumes
that are *launched* to create the AMI. These tags are *not* applied to the
resulting AMI unless they're duplicated in `tags`. This is a
[template engine](/docs/templates/engine.html)
where the `SourceAMI` variable is replaced with the source AMI ID and
`BuildRegion` variable is replaced with the value of `region`.
[template engine](/docs/templates/engine.html),
see [Build template data](#build-template-data) for more information.
- `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
@ -257,9 +254,8 @@ builder.
- `snapshot_tags` (object of key/value strings) - Tags to apply to snapshot.
They will override AMI tags if already applied to snapshot. This is a
[template engine](/docs/templates/engine.html)
where the `SourceAMI` variable is replaced with the source AMI ID and
`BuildRegion` variable is replaced with the value of `region`.
[template engine](/docs/templates/engine.html),
see [Build template data](#build-template-data) for more information.
- `source_ami_filter` (object) - Filters used to populate the `source_ami` field.
Example:
@ -354,9 +350,8 @@ builder.
- `tags` (object of key/value strings) - Tags applied to the AMI and
relevant snapshots. This is a
[template engine](/docs/templates/engine.html)
where the `SourceAMI` variable is replaced with the source AMI ID and
`BuildRegion` variable is replaced with the value of `region`.
[template engine](/docs/templates/engine.html),
see [Build template data](#build-template-data) for more information.
- `temporary_key_pair_name` (string) - The name of the temporary keypair
to generate. By default, Packer generates a name with a UUID.
@ -426,6 +421,16 @@ with the `-debug` flag. In debug mode, the Amazon builder will save the private
key in the current directory and will output the DNS or IP information as well.
You can use this information to access the instance as it is running.
## Build template data
The available variables are:
- `BuildRegion` - The region (for example `eu-central-1`) where Packer is building the AMI.
- `SourceAMI` - The source AMI ID (for example `ami-a2412fcd`) used to build the AMI.
- `SourceAMIName` - The source AMI Name (for example `ubuntu/images/ebs-ssd/ubuntu-xenial-16.04-amd64-server-20180306`) used to build the AMI.
- `SourceAMITags` - The source AMI Tags, as a `map[string]string` object.
-> **Note:** Packer uses pre-built AMIs as the source for building images.
These source AMIs may include volumes that are not flagged to be destroyed on
termination of the instance building the new image. In addition to those volumes

View File

@ -86,10 +86,9 @@ builder.
volumes, `io1` for Provisioned IOPS (SSD) volumes, and `standard` for Magnetic
volumes
- `tags` (map) - Tags to apply to the volume. These are retained after the
builder completes. This is a \[template engine\]
(/docs/templates/engine.html) where the `SourceAMI`
variable is replaced with the source AMI ID and `BuildRegion` variable
is replaced with the value of `region`.
builder completes. This is a
[template engine](/docs/templates/engine.html),
see [Build template data](#build-template-data) for more information.
- `associate_public_ip_address` (boolean) - If using a non-default VPC, public
IP addresses are not provided by default. If this is toggled, your new
@ -126,9 +125,8 @@ builder.
- `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`. This is a
[template engine](/docs/templates/engine.html)
where the `SourceAMI` variable is replaced with the source AMI ID and
`BuildRegion` variable is replaced with the value of `region`.
[template engine](/docs/templates/engine.html),
see [Build template data](#build-template-data) for more information.
- `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
@ -328,6 +326,15 @@ with the `-debug` flag. In debug mode, the Amazon builder will save the private
key in the current directory and will output the DNS or IP information as well.
You can use this information to access the instance as it is running.
## Build template data
The available variables are:
- `BuildRegion` - The region (for example `eu-central-1`) where Packer is building the AMI.
- `SourceAMI` - The source AMI ID (for example `ami-a2412fcd`) used to build the AMI.
- `SourceAMIName` - The source AMI Name (for example `ubuntu/images/ebs-ssd/ubuntu-xenial-16.04-amd64-server-20180306`) used to build the AMI.
- `SourceAMITags` - The source AMI Tags, as a `map[string]string` object.
-> **Note:** Packer uses pre-built AMIs as the source for building images.
These source AMIs may include volumes that are not flagged to be destroyed on
termination of the instance building the new image. In addition to those volumes

View File

@ -136,9 +136,8 @@ builder.
- `ami_description` (string) - The description to set for the
resulting AMI(s). By default this description is empty. This is a
[template engine](/docs/templates/engine.html)
where the `SourceAMI` variable is replaced with the source AMI ID and
`BuildRegion` variable is replaced with the value of `region`.
[template engine](/docs/templates/engine.html),
see [Build template data](#build-template-data) for more information.
- `ami_groups` (array of strings) - A list of groups that have access to
launch the resulting AMI(s). By default no groups have permission to launch
@ -236,9 +235,8 @@ builder.
- `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`. This is a
[template engine](/docs/templates/engine.html)
where the `SourceAMI` variable is replaced with the source AMI ID and
`BuildRegion` variable is replaced with the value of `region`.
[template engine](/docs/templates/engine.html),
see [Build template data](#build-template-data) for more information.
- `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
@ -361,9 +359,8 @@ builder.
required if you are using an non-default VPC.
- `tags` (object of key/value strings) - Tags applied to the AMI. This is a
[template engine](/docs/templates/engine.html)
where the `SourceAMI` variable is replaced with the source AMI ID and
`BuildRegion` variable is replaced with the value of `region`.
[template engine](/docs/templates/engine.html),
see [Build template data](#build-template-data) for more information.
- `temporary_key_pair_name` (string) - The name of the temporary key pair
to generate. By default, Packer generates a name that looks like
@ -425,6 +422,15 @@ with the `-debug` flag. In debug mode, the Amazon builder will save the private
key in the current directory and will output the DNS or IP information as well.
You can use this information to access the instance as it is running.
## Build template data
The available variables are:
- `BuildRegion` - The region (for example `eu-central-1`) where Packer is building the AMI.
- `SourceAMI` - The source AMI ID (for example `ami-a2412fcd`) used to build the AMI.
- `SourceAMIName` - The source AMI Name (for example `ubuntu/images/ebs-ssd/ubuntu-xenial-16.04-amd64-server-20180306`) used to build the AMI.
- `SourceAMITags` - The source AMI Tags, as a `map[string]string` object.
## Custom Bundle Commands
A lot of the process required for creating an instance-store backed AMI involves