Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Get AMI ID from a packer build
packer build packer.json 2>&1 | sudo tee output.txt
tail -2 output.txt | head -2 | awk 'match($0, /ami-.*/) { print substr($0, RSTART, RLENGTH) }' > sudo ami.txt
@danrigsby
Copy link
Author

danrigsby commented Apr 27, 2014

This will get the AMI ID from a packer build while still outputting stdout to the console to be picked up by a build server (Jenkins, Bamboo, etc)

@solarce
Copy link

solarce commented Sep 29, 2014

Thank you!

@kouk
Copy link

kouk commented Nov 27, 2014

🍻 thanks!

@grayaii
Copy link

grayaii commented Dec 5, 2014

Thanks for finding this! This really helped. It's a bit unfortunate that packer does not provide a way to do this for you. If they change the output, then this will start failing. Thanks for posting here: https://groups.google.com/forum/#!searchin/packer-tool/ami$20id/packer-tool/FjwlZU2lo3g/Hq0Y7l-UwiwJ

@irgeek
Copy link

irgeek commented Dec 10, 2014

I try to avoid output parsing -- and running output through tee also causes Packer to strip colours -- so I came up with a different technique that has been working very well. Basically, have Packer tag the AMI with a unique value you know, then use AWS' built-in filtering to find the correct AMI after the build finishes.

More details in this gist: https://gist.github.com/irgeek/2f5bb964e3ce298e15b7

@rafaelmagu
Copy link

rafaelmagu commented Dec 29, 2014

Why not use packer build -machine-readable and parse that output?

I use:

packer build -machine-readable packer.json | tee build.log
grep 'artifact,0,id' build.log | cut -d, -f6 | cut -d: -f2

@stefanteixeira
Copy link

stefanteixeira commented Oct 2, 2015

Thanks @rafaelmagu, it worked very nicely!

@stefanteixeira
Copy link

stefanteixeira commented Oct 2, 2015

I needed to grep the snapshot-id to delete it via AWS CLI. Based on @rafaelmagu answer, I created a gist that returns the snapshot-id: https://gist.github.com/stefanteixeira/ab91dfacda81bc030148

@rbowlby
Copy link

rbowlby commented Nov 20, 2015

Perfect, thanks for the share.

@sidarta-luizalabs
Copy link

sidarta-luizalabs commented May 3, 2016

Nice!
I've changed a little bit, based on @rafaelmagu :

packer build -machine-readable packer.json | tee build.log
egrep -m1 -oe 'ami-.{8}' build.log

cheers!

@delaman
Copy link

delaman commented Jun 14, 2016

This works good too:

$ packer build -machine-readable packer.json | awk -F, '$0 ~/artifact,0,id/ {print $6}'

@huyanhvn
Copy link

huyanhvn commented Aug 18, 2016

Just adding to @delaman, if you're doing multi-regions, you can do this to parse:

$ packer build -machine-readable packer.json | awk -F, '$0 ~/artifact,0,id/ {print $6}' | sed 's/%!(PACKER_COMMA)/\n/g'

@carlosonunez
Copy link

carlosonunez commented Jan 4, 2017

These are nice solutions. I went with the grep approach below, but the awk approach is just as clean.

packer build -machine-readable ... | egrep 'artifact,0,id' | rev | cut -f1 -d, | rev

@dayer4b
Copy link

dayer4b commented Jan 26, 2017

you might try the manifest post-processor instead.

https://www.packer.io/docs/post-processors/manifest.html

It can produce a JSON file with the relevant data that looks like:

{                                                                  
  "builds": [                                                      
    {                                                              
      "name": "amazon-ebs",                                        
      "builder_type": "amazon-ebs",                                
      "build_time": 1485460577,                                    
      "files": null,                                               
      "artifact_id": "us-west-1:ami-XXXXXXXX",                     
      "packer_run_uuid": "cd66f925-1eb5-c43e-4370-e696a66d53aa"    
    }                                                              
  ],                                                               
  "last_run_uuid": "cd66f925-1eb5-c43e-4370-e696a66d53aa"          
}                                                                  

@rquadling
Copy link

rquadling commented Mar 28, 2017

With regard to the manifest file post-processor, you need to be on at least https://github.com/mitchellh/packer/blob/master/CHANGELOG.md#0110-october-21-2016, but https://github.com/mitchellh/packer/blob/master/CHANGELOG.md#0121-december-15-2016 has changes to the manifest config, so would probably be a better option.

Otherwise, you'll get a message saying that the manifest post-processor cannot be found.

(As I did!)

@mschiessl
Copy link

mschiessl commented Jul 14, 2017

The Manifest output does not work, if you create your own ami (for example with the virtualbox bulder) and use the "amazon-import" post-processor, since it is just treating the build processor :(

@wmbutler
Copy link

wmbutler commented Apr 7, 2018

The manifest postprocessor worked great for me:

  "post-processors": [
    [
      {
        "output": "manifest.json",
        "strip_path": true,
        "type": "manifest"
      }
    ]
  ]

Then this chain of events will capture the ami-XXXXXX as shown by @dayer4b above.

cat manifest.json | jq -r .builds[0].artifact_id |  cut -d':' -f2

@Aagat
Copy link

Aagat commented Jun 8, 2018

I ended up using this along with manifest post processor to get the latest ami

cat manifest.json | jq -r '.builds[-1].artifact_id' |  cut -d':' -f2

@nishadmehendale
Copy link

nishadmehendale commented Dec 7, 2018

How can we directly export the AMI_ID to global variable?

@sfdc-afraley
Copy link

sfdc-afraley commented Feb 11, 2019

This is old, but comes up when you search for how to get the ami id from the amazon-import post-processor. Note that the manifest will contain the AMI id, but you have to wrap the amazon-import post-processor and the manifest post-processor within the same list, or as Packer calls it, a sequence.

"post-processors": [
    [
      {
      "type": "amazon-import",
      "ami_name": "import_test",
      "region": "{{ user `target_region` }}",
      "s3_bucket_name": "{{ user `s3_artifact_bucket` }}",
      "role_name": "{{ user `aws_vmimport_role` }}"
      },
      { "type":"manifest" }
    ]
  ]

More info here: hashicorp/packer#7297

@piedmont01
Copy link

piedmont01 commented Jun 7, 2019

You can omit the cat command and pass the file file to jq directly or jq -r '.builds[-1].artifact_id' manifest.json | cut -d':' -f2

@electrawn
Copy link

electrawn commented Aug 7, 2019

Gist is one of those sites where it pays to read the comments. I was able to take this and combine it with some of the above additional techniques and wrap it together in a modern AWS demonstration. Enjoy: https://gist.github.com/electrawn/be0c239e46517a859e31bf0a2496235e

@dougireton
Copy link

dougireton commented Apr 2, 2020

Using a post-processor with jq works as well.

jq -r '.builds[0].artifact_id|split(":")[1]' ./manifest.json

@CodeForcer
Copy link

CodeForcer commented Jul 2, 2021

Seriously, we shouldn't have to do all this parsing of text. Packer should just have a way to spit out the ami_id in the language itself so we can use it in future build stages without having to parse arrays in json manifest files

@enishalilaj
Copy link

enishalilaj commented Aug 30, 2022

@CodeForcer yes, definitely I agree!!!

@galvarado
Copy link

galvarado commented Dec 2, 2022

Complete example using HCL with a manifest post-processor and the jq command from @dougireton:

packer {
  required_plugins {
    amazon = {
      version = ">= 0.0.2"
      source  = "github.com/hashicorp/amazon"
    }
  }
}

source "amazon-ebs" "ubuntu" {
  ami_name      = "custom-ami-{{timestamp}}"
  instance_type = "t2.micro"
  region        = "eu-west-1"
  source_ami_filter {
    filters = {
      name                = "ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-amd64-server-*"
      root-device-type    = "ebs"
      virtualization-type = "hvm"
    }
    most_recent = true
    owners      = ["099720109477"]
  }
  ssh_username = "ubuntu"
  tags = {
    Name = "my-app"
    Os   = "ubuntu-jammy-22.04-amd64-server"
  }
}

build {
  name = "custom-ami"
  sources = ["source.amazon-ebs.ubuntu"]
    post-processor "manifest" {
        output = "manifest.json"
        strip_path = true
    }
}

Then just:
jq -r '.builds[0].artifact_id|split(":")[1]' ./manifest.json
Expected output:
ami-0dcbaf6794c89f392

But agree with @CodeForcer 2022 and packer still does not have a built-in method to spit out the id.

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