Search code examples
amazon-web-servicesloopsansibleaws-security-group

Create a new array with SecurityGroupIds instead of SecurityGroupNames with Ansible


I am relatively new to Ansible and I am struggling to understand how to perform the following scenario: I have an array with AWS security group names looking like this

['Security-Group-Name1', 'SecurityGroup-Name2', 'SecurityGroup-Name3']

However, what I want is to have an array of SecurityGroupIds. Using Ansible I have the ec2_group_info as an option to retrieve information about a security group. So far so good ...

Now comes my question. I need to loop through the above array using ec2_group_info, set the name of the security group I need and return the retrieved Id into a new array so in the end I have something like this.

['Security-Group-Id1', 'SecurityGroup-Id2', 'SecurityGroup-Id3']

I know I need to use a loop with sort of a dynamic index. But it is not really clear to me how to do this in Ansible.

I am aware of the latest loop section of Ansible Docs and I find them more than confusing... https://docs.ansible.com/ansible/latest/user_guide/playbooks_loops.html

Edit:

This is the current code which works as needed:

- name: Installing pip if not existing on host
  pip:
    name: boto3

- name: Get SecurityGroupId information
  ec2_group_info:
    filters:
      group_name: ['SG-One', 'SG-Two']
      vpc_id: 'vpc-id'
  register: my_groups

- set_fact:
    my_group_ids: '{{ my_groups.security_groups | map(attribute="group_id") | list }}'

- debug:
    msg: "{{ my_groups }}"

- debug:
    msg: "{{ my_group_ids }}"

This is the outcome:

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

TASK [machine-provisioning : Installing pip if not existing on host] ************
ok: [localhost]

TASK [machine-provisioning : Get SecurityGroupId information] ************************* 
ok: [localhost]

TASK [machine-provisioning : set_fact] *********************************
ok: [localhost]

TASK [machine-provisioning : debug] ***********************************************
ok: [localhost] => {
"msg": [
    "sg-00000000",
    "sg-11111111"
]

}


Solution

  • On that linked page about loops, you'll observe the use of register:, which is how you'd capture the result of that ec2_group_info: lookup, then use the map jinja filter to extract map(attribute="group_id") from the resulting list of results; you have to feed the output of map into the list filter, because map and a few others are python generators, and thus need a terminal action to materialize their data. The set_fact: is how ansible does "assignment"

    - ec2_group_info:
        filters:
          group_name: '{{ the_group_names }}'
          vpc_id: '{{ my_vpc_id }}'
      register: my_groups
    - set_fact:
        my_group_ids: '{{ my_groups.security_groups | map(attribute="group_id") | list }}'
    

    yields:

    ok: [localhost] => {"ansible_facts": {"my_group_ids": ["sg-0c5c277ed1edafb54", "sg-7597a123"]}, "changed": false}