Neil H Watson
Neil H Watson

Reputation: 1070

Ansible querying AWS AMIs

I'm trying to query AWS EC2 AMIs from Ansible but keep running into an error when looping through the results:

- hosts: localhost

  tasks:
   - name: Get AMI
     ec2_ami_facts:
        owner: amazon
        filters:
           architecture: x86_64
           root-device-type: ebs
     register: amis

   - name: return filtered data
     debug:
        msg: "{{ item }}"
     loop: " {{ amis \
        | json_query( 'Images[?Description!=`null`] \
        | [?starts_with(Description,`Amazon Linux`)]' ) \
        }} "

The idea is to return the image documents, and later just the image IDs with more filtering (end goal is to get the most recent ami id for a given description). But with the current example, and anything else I try I get this error:

TASK [return filtered data] ****************************************************
fatal: [localhost]: FAILED! => {"msg": "Invalid data passed to 'loop',
 it requires a list, got this instead:   . Hint: If you passed a
 list/dict of just one element, try adding wantlist=True to your lookup
 invocation or use q/query instead of lookup."}

I can look at the 'amis' in its entirety and it looks good, but any filtering I try fails. What is the correct method?

Upvotes: 1

Views: 1653

Answers (2)

sudheerchamarthi
sudheerchamarthi

Reputation: 1241

Use following to dynamically fetch the latest AMI.

---
- name: Find latest AMI  
  ec2_ami_facts:
    owners: 099720109477
    region: "{{ AWS_REGION }}"
    filters:
      name: "ubuntu/images/hvm-ssd/ubuntu-bionic-18.04-amd64-server-*"
  register: findami  
- name: Sort the latest AMI 
  set_fact:
    latest_ami: >
      {{ findami.images | sort(attribute='creation_date') | last }} 
      
- name: Launch Instance with latest AMI
  ec2:
    instance_type: "{{ INSTANCE_TYPE }}"
    image: "{{ latest_ami.image_id }}"
    key_name: "{{ KEY_NAME }}"
    region: "{{ AWS_REGION }}"    
    group_id: "{{ sg.group_id }}"
    wait: yes
    count: "{{ INSTANCES_COUNT }}"
    vpc_subnet_id: "{{ subnet.subnet.id }}"
    assign_public_ip: no

Upvotes: 0

Neil H Watson
Neil H Watson

Reputation: 1070

This works, thanks for the folks at #ansible on freenode.

- hosts: localhost

  tasks:
   - name: Get AMI
     ec2_ami_facts:
        owner: amazon
        filters:
           architecture: x86_64
           root-device-type: ebs
     register: amis

   - name: return latest AMI
     set_fact:
        my_ami: "{{ amis.images \
            | selectattr('description', 'defined') \
            | selectattr('description', 'match', '^Amazon Linux.*GP2$') \
            | selectattr('description', 'match', '[^(Candidate)]') \
            | sort(attribute='creation_date') \
            | last }} "

   - debug:
        msg: "ami = {{ my_ami | to_nice_yaml }}"

Also see here: https://bitbucket.org/its-application-delivery/ansible-aws/src/master/ansible/task_find_ami.yml?fileviewer=file-view-default

Upvotes: 1

Related Questions