├── .gitignore ├── bin ├── out ├── check └── in ├── Dockerfile ├── ami-resource.sublime-project └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | /*.sublime-workspace 2 | -------------------------------------------------------------------------------- /bin/out: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -eu -o pipefail 3 | exec 3>&1 1>&2 4 | 5 | cat | jq '{version}' <&0 >&3 6 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:latest 2 | 3 | RUN apk --no-cache add py2-pip jq 4 | 5 | RUN pip --no-cache-dir --disable-pip-version-check install awscli 6 | 7 | ADD bin /opt/resource 8 | -------------------------------------------------------------------------------- /ami-resource.sublime-project: -------------------------------------------------------------------------------- 1 | { 2 | "folders": 3 | [ 4 | { 5 | "path": ".", 6 | "follow_symlinks": true, 7 | "file_exclude_patterns": [ "*.sublime-*" ], 8 | "folder_exclude_patterns": [ ] 9 | } 10 | ], 11 | "settings": { 12 | "tab_size": 2, 13 | "translate_tabs_to_spaces": true, 14 | "ensure_newline_at_eof_on_save": true, 15 | "default_line_ending": "unix", 16 | "rulers": [80] 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /bin/check: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -eu -o pipefail 3 | exec 3>&1 1>&2 4 | 5 | cat | jq . <&0 > /tmp/input 6 | 7 | AMI=$(jq -r '.version.ami // empty' /tmp/input) 8 | 9 | export AWS_ACCESS_KEY_ID=$(jq -r '.source.aws_access_key_id // empty' /tmp/input) 10 | export AWS_SECRET_ACCESS_KEY=$(jq -r '.source.aws_secret_access_key // empty' /tmp/input) 11 | export AWS_DEFAULT_REGION=$(jq -r '.source.region // empty' /tmp/input) 12 | 13 | # remove any empty credentials vars so the AWS client will try instance profiles 14 | if [ -z "$AWS_ACCESS_KEY_ID" ]; then 15 | unset AWS_ACCESS_KEY_ID 16 | fi 17 | 18 | if [ -z "$AWS_SECRET_ACCESS_KEY" ]; then 19 | unset AWS_SECRET_ACCESS_KEY 20 | fi 21 | 22 | jq '.source.filters | to_entries | map({"Name": .key, "Values": [(.value|select(type!="array") = [.])|.[]|tostring]})' /tmp/input > /tmp/filters.json 23 | 24 | aws ec2 describe-images \ 25 | --filters file:///tmp/filters.json \ 26 | --query 'sort_by(Images, &CreationDate)' \ 27 | | jq '.[([.[] | .ImageId] | index("'$AMI'") // -2) + 1:] | [.[] | {ami: .ImageId}]' >&3 28 | -------------------------------------------------------------------------------- /bin/in: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -eu -o pipefail 3 | exec 3>&1 1>&2 4 | 5 | cat | jq . <&0 > /tmp/input 6 | 7 | DEST="$1" 8 | 9 | AMI=$(jq -r '.version.ami // empty' /tmp/input) 10 | 11 | export AWS_ACCESS_KEY_ID=$(jq -r '.source.aws_access_key_id // empty' /tmp/input) 12 | export AWS_SECRET_ACCESS_KEY=$(jq -r '.source.aws_secret_access_key // empty' /tmp/input) 13 | export AWS_DEFAULT_REGION=$(jq -r '.source.region // empty' /tmp/input) 14 | 15 | # remove any empty credentials vars so the AWS client will try instance profiles 16 | if [ -z "$AWS_ACCESS_KEY_ID" ]; then 17 | unset AWS_ACCESS_KEY_ID 18 | fi 19 | 20 | if [ -z "$AWS_SECRET_ACCESS_KEY" ]; then 21 | unset AWS_SECRET_ACCESS_KEY 22 | fi 23 | 24 | aws ec2 describe-images --image-ids "$AMI" --query 'Images[0]' \ 25 | | tee "$DEST/output.json" 26 | 27 | jq -r '.ImageId' < "$DEST/output.json" > "$DEST/id" 28 | 29 | jq '{source_ami: .ImageId}' < "$DEST/output.json" > "$DEST/packer.json" 30 | 31 | jq '.ImageId as $image | {Name, CreationDate, VirtualizationType, RootDeviceType} | to_entries | {metadata: map({name:.key, value:.value}), version: {ami: $image}}' < "$DEST/output.json" >&3 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AMI Update Resource 2 | 3 | A Concourse CI resource to check for new Amazon Machine Images (AMI). 4 | 5 | ## Source Configuration 6 | 7 | - `aws_access_key_id`: Your AWS access key ID. 8 | 9 | - `aws_secret_access_key`: Your AWS secret access key. 10 | 11 | - `region`: *Required.* The AWS region to search for AMIs. 12 | 13 | - `filters`: *Required.* A map of named filters to their values. Check the AWS CLI [describe-images](http://docs.aws.amazon.com/cli/latest/reference/ec2/describe-images.html) documentation for a complete list of acceptable filters and values. 14 | 15 | If `aws_access_key_id` and `aws_secret_access_key` are both absent, AWS CLI will fall back to other authentication mechanisms. See [Configuration setting and precedence](http://docs.aws.amazon.com/cli/latest/userguide/cli-chap-getting-started.html#config-settings-and-precedence) 16 | 17 | ## Behaviour 18 | 19 | ### `check`: Check for new AMIs 20 | 21 | Searches for AMIs that match the provided source filters, ordered by their creation date. The AMI ID serves as the resulting version. 22 | 23 | #### Parameters 24 | 25 | *None.* 26 | 27 | ### `in`: Fetch the description of an AMI 28 | 29 | Places the following files in the destination: 30 | 31 | - `output.json`: The complete AMI description object in JSON format. Check the AWS CLI [describe-images](http://docs.aws.amazon.com/cli/latest/reference/ec2/describe-images.html#examples) documentation for examples. 32 | 33 | - `id`: A plain text file containing the AMI ID, e.g. `ami-5731123e` 34 | 35 | - `packer.json`: The AMI ID in Packer `var-file` input format, typically for use with [packer-resource](https://github.com/jdub/packer-resource), e.g. 36 | 37 | ```json 38 | {"source_ami": "ami-5731123e"} 39 | ``` 40 | 41 | #### Parameters 42 | 43 | *None.* 44 | 45 | ## Example 46 | 47 | This pipeline will check for a new Ubuntu 14.04 LTS AMI in the Sydney region every hour, triggering the next step of the build plan if it finds one. 48 | 49 | ```yaml 50 | resource_types: 51 | - name: ami 52 | type: docker-image 53 | source: 54 | repository: jdub/ami-resource 55 | 56 | resources: 57 | - name: ubuntu-ami 58 | type: ami 59 | check_every: 1h 60 | source: 61 | aws_access_key_id: "..." 62 | aws_secret_access_key: "..." 63 | region: ap-southeast-2 64 | filters: 65 | owner-id: "099720109477" 66 | is-public: true 67 | state: available 68 | name: ubuntu/images/hvm-ssd/ubuntu-trusty-*server* 69 | 70 | jobs: 71 | - name: my-ami 72 | plan: 73 | - get: ubuntu-ami 74 | trigger: true 75 | - task: build-fresh-image 76 | ... 77 | ``` 78 | --------------------------------------------------------------------------------