MrChuck
MrChuck

Reputation: 21

Ansible 2.x: ec2_remote_facts

I'm trying to tackle how to list and do something with EC2 stopped instances. ec2_remote_facts is my friend and I can get results from it. But as an ansible noob I cannot for the life of me work out how to get at the 'id' componenent of the returned object. The documentation is sketchy and does not cover what type of thing is returned nor how to use it.

Here is the very basic playbook I'm experimenting with:

---
- name: remote facts
  hosts: localhost

  tasks:

   - ec2_remote_facts:
      region: ap-southeast-2
     register: info

   - name: print
     debug: var=info

This works just fine.

This also works:

---
- name: remote facts
  hosts: localhost

  tasks:

   - ec2_remote_facts:
      region: ap-southeast-2
     register: info

   - name: print
     debug: var=info.instances[0].id

What I can't get my head around is the incantation to give me just the 'id' element for all current instances (3) so I can do something else with all of them--remove, configure, start, whatever. I've had a look at all the looping constructs and with_* options and I can't get any of them to do what I want.

No doubt this will be a 'd'oh!' problem to anyone who knows the answer but I'm afraid at the moment I just don't get it. The returned object looks like this:

ok: [localhost] => {
    "info": {
        "changed": false, 
        "instances": [
            {
                "ami_launch_index": "0", 
                "architecture": "x86_64", 
            "client_token": "vpOGxxxxxxxxxxxxxx", 
            "ebs_optimized": false, 
            "groups": [
                {
                    "id": "sg-xxxxxxxx", 
                    "name": "launch-wizard-3"
                }
            ], 
            "hypervisor": "xen", 
            "id": "i-01xxxxxxxxxxxxxxxx", 

[...]

        "tags": {}, 
        "virtualization_type": "hvm", 
        "vpc_id": "vpc-xxxxxxxx"
    }, 
        {
            "ami_launch_index": "1", 
            "architecture": "x86_64", 

[snip, 2 more instances]

Any thoughts people?

Upvotes: 2

Views: 2299

Answers (6)

zqcolor
zqcolor

Reputation: 330

Thanks @hit3k

I have changed a little of your code to make it working under Ansible 2.7.10

- name: print the variable name
  debug: msg= "{{ item.0 }}"
  with_items: "{{ ec2_metadata.instances|map(attribute='instance_id')|list }}"

Results:

ok: [vpc.prod.dr] => (item=i-0739f6a14abc1e7d9) => {}
ok: [vpc.prod.dr] => (item=i-04dd1eab60bc03488) => {}
ok: [vpc.prod.dr] => (item=i-09702b90ed31cf00f) => {}
ok: [vpc.prod.dr] => (item=i-05bcaf44b1598aadd) => {}
ok: [vpc.prod.dr] => (item=i-085bfe50d2c6e5c88) => {}
ok: [vpc.prod.dr] => (item=i-0237a96d2e8869d13) => {}
ok: [vpc.prod.dr] => (item=i-0769c21225acfac01) => {}
ok: [vpc.prod.dr] => (item=i-09c55f3c6776ff263) => {}
ok: [vpc.prod.dr] => (item=i-0e8faa6ffb085558f) => {}
ok: [vpc.prod.dr] => (item=i-07e68c8c201fc6021) => {}
ok: [vpc.prod.dr] => (item=i-011a94a276e70d92c) => {}
ok: [vpc.prod.dr] => (item=i-05672115214b129bd) => {}
ok: [vpc.prod.dr] => (item=i-0cbe6652ee855f14d) => {}
ok: [vpc.prod.dr] => (item=i-055ff968821cca086) => {}
ok: [vpc.prod.dr] => (item=i-0c9a7db7a8142c240) => {}
ok: [vpc.prod.dr] => (item=i-02ca647fe24ad6c56) => {}
ok: [vpc.prod.dr] => (item=i-054542fcef48629a0) => {}
ok: [vpc.prod.dr] => (item=i-0a095641b04538a73) => {}
ok: [vpc.prod.dr] => (item=i-05434bac67259041c) => {}

Upvotes: 0

Kevin Black
Kevin Black

Reputation: 1

Spent a lot of time looking into this and it is actually very simple using Ansible Jinja2 filters.

this should work:

- name: DEBUG
  debug:
    var: info |json_query('instances[*].id')

Some very usefull Filtering described here: http://docs.ansible.com/ansible/latest/playbooks_filters.html#other-useful-filters

Upvotes: 0

hit3k
hit3k

Reputation: 1493

This should be working:

  tasks:

    - ec2_remote_facts:
        region: ap-southeast-2
      register: thefacts

    - debug: var=item.id
      with_items: "{{thefacts.instances}}"

but produces a lot of unnecessary debug output, for, like, no reason. So let's filter it out:

  tasks:

    - ec2_remote_facts:
        region: ap-southeast-2
      register: thefacts

    - debug: var=item.0
      with_together:
        - "{{ thefacts.instances|map(attribute='id')|list }}"

Upvotes: 1

John Von Neumann
John Von Neumann

Reputation: 925

You had it on your second attempt, funnily enough I had the exact same issue but it took your JSON experience for me to see it.

Your second code snippet:

---
- name: remote facts
  hosts: localhost

  tasks:

   - ec2_remote_facts:
      region: ap-southeast-2
     register: info

   - name: print
     debug: var=info.instances[0].id

My addition:

---
- name: remote facts
  hosts: localhost

  tasks:

   - ec2_remote_facts:
      region: ap-southeast-2
     register: info

   - name: print
     debug: var=info.instances[0].id

   - name: Create AMI from Instance ID
     ec2_ami:
       aws_access_key: "{{ aws_access_key }}"
       aws_secret_key: "{{ aws_secret_key }}"
       region: "{{ region }}"
       instance_id: "{{ ec2_remote_facts.instances[0].id }}"        

Cheers for helping me work this one out haha.

Output from Ansible:

 (ansible27) user@user:/etc/ansible/playbooks$ sudo ansible-playbook ec2_facts.yml
 [WARNING]: Found both group and host with same name: localhost


PLAY [localhost] ***************************************************************

TASK [Gathering Facts] *********************************************************
ok: [localhost]

TASK [EC2 Remote Facts.] *******************************************************
ok: [localhost]

TASK [Display results in JSON format.] *****************************************
ok: [localhost] => {
    "changed": false, 
    "msg": "Most upto date instance is: i-1234567abcdefg "
}

TASK [Create AMI from instance ID.] ********************************************
changed: [localhost]

PLAY RECAP *********************************************************************
localhost                  : ok=4    changed=1    unreachable=0    failed=0   

For your problem of the loop, I assume it will just be a case of passing in the [1] and [2] element specifiers.

Upvotes: 0

Bred Floggs
Bred Floggs

Reputation: 11

It's a bit late, I suspect, but I think that you've simply forgotten to add the "{{ }}" around your with_items variable. Works for me if I do, so:

ec2_remote_facts:
        region: "{{ vpc_region }}"
        filters:
        instance-state-name: running
        vpc-id: "{{ vpc_id }}"         
  register: ec2_info

Then:

set_fact:
  jenkins_master_instances: "{{ jenkins_master_instances|default([]) + [ item.id ]}}"
with_items: "{{ ec2_info.instances }}"

seems to work for me.

Upvotes: 1

Deepali Mittal
Deepali Mittal

Reputation: 1032

Try this it should work :

   - ec2_remote_facts:
      region: ap-southeast-2
     register: info

   - name: print
     debug: var=item.id 
     with_items: info_instances

If doesn't share the complete output of debug: var=info. So that i can tell you the exact code.

Also if you want to use it any task like ec2 for stopping instance use it as a variable {{item.instances.id}} with same loop with_items: info_instances

Upvotes: 0

Related Questions