Skip to content

Instantly share code, notes, and snippets.

@irgeek
Last active December 10, 2021 16:42
Show Gist options
  • Save irgeek/2f5bb964e3ce298e15b7 to your computer and use it in GitHub Desktop.
Save irgeek/2f5bb964e3ce298e15b7 to your computer and use it in GitHub Desktop.
Finding AMIs after building an image with Packer

Finding Packer-generated AMIs automatically after builds

The basic technique is to have Packer add a tag with a unique value during the build, and use AWS' built-in filtering capabilities to find that specific AMI after the build finishes.

  • template.json - Shows the settings that need to be added to your template
  • build.sh - Shows how to use the template to do a build and retrieve the AMI information
#!/bin/bash
# Generate a unique identified for this build. UUID is the easiest
UUID=$(uuid -v4)
# Pass the unique identifier to packer as a user variable
packer build -var build_uuid=${UUID} template.json
# Use the AWS CLI tools to query for AMIs, using the unique tag value to
# filter for the build we just did
aws ec2 describe-images --filters Name=tag:BuildUUID,Values=${UUID} > build.json
# Assuming you have `jq` installed (and you should if you're dealing with JSON)
AMI_ID=$(jq --raw-output '.Images[0].ImageId' build.json)
# If you don't have `jq` you can accomplish the same thing with python 2.6+
# Thanks to @qualidafial
# AMI_ID=$(python -c 'import json,sys;obj=json.load(sys.stdin);print obj["Images"][0]["ImageId"]' < build.json)
# You can also use the '--query' flag of the AWS CLI tools to find the AMI ID
# without needing any other tools installed. You can comment out line 10 if
# you use this method. If you need to query for multiple values, though, this
# method will be slower because each query hits AWS API again.
# AMI_ID=$(aws ec2 describe-images --filters Name=tag:BuildUUID,Values=${UUID} --output text --query 'Images[0].ImageId')
{
"variables": {
"build_uuid": null
},
"builders": [
{
"type": "amazon-ebs",
"tags": {
"BuildUUID": "{{user `build_uuid`}}"
}
}
]
}
@joescii
Copy link

joescii commented Jan 3, 2015

This works awesome. Just a few tweaks folks may want to consider.

  1. I used a timestamp instead of UUID to make it more meaningful:
timestamp=`date +"%Y%m%d%H%M%S"`
  1. I needed to use --raw-output on jq to avoid quotes around the string:
AMI_ID=`jq --raw-output '.Images[0].ImageId' ami.json`

@irgeek
Copy link
Author

irgeek commented Jan 9, 2015

Oops! Missed the --raw-output flag when I translated this from my overly-complicated build scripts to a gist. I've updated it now. Thanks for pointing that out.

As for using a timestamp -- definitely works. We run this from inside Jenkins, though, so I needed to be able to guarantee that two builds wouldn't collide. Hence the UUID.

@tuxinaut
Copy link

tuxinaut commented Apr 25, 2016

Thanks for the nice script. I found out that you need to specify the aws cli output format because I've as default output format table and the command need json

@jmuenster
Copy link

+1 to @jeff-zohrab, you can get to the same place with --output

$ aws ec2 describe-images --filters Name=tag:zztest,Values=zzzzzz --query 'Images[0].ImageId' --output text
ami-12345678

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment