Search code examples
amazon-web-servicesautomationansible

Ansible looping through different item within the same task


I want to apply the specific tag or tags for the ec2 instance to the attached EBS volumes. Form the amazon.aws.ec2_instance_info: I get the all information for the ec2 and then with

"{{ item | flatten |
    map(attribute='block_device_mappings') | flatten |
    map(attribute='ebs') | flatten |
    map(attribute='volume_id') }}"

we can extract the volume IDs, but it returns the list of IDs like below

[
  vol-xxxxxxx,
  vol-zzzzzzz,
]

How to make sure for each loop it chooses one of the volume IDs and passes it to amazon.aws.ec2_tag:

playbook:

---
- name: Ansible Test Playbook
  gather_facts: false
  hosts: localhost
  vars_files:
    - vars/regions.yaml

  tasks:
    - name: Gather information about all instances
      amazon.aws.ec2_instance_info:
        region: "{{ item }}"
      register: instance_info
      loop: "{{ region }}"

    - name: Copy tags from EC2 to EBS
      amazon.aws.ec2_tag:
        region: us-east-1
        resource: "{{ item | flatten |
                      map(attribute='block_device_mappings') | flatten |
                      map(attribute='ebs') | flatten |
                      map(attribute='volume_id') }}"
        state: present
        tags:
          "team": "{{ item | flatten |
                      map(attribute='tags') | flatten |
                      map(attribute='team') | join }}"
      loop: "{{ instance_info.results | map(attribute='instances') }}"

In addition to this, I want to iterate the list of regions

region: 
 - us-east-1 
 - us-east-2 

Solution

  • Q: "Each loop passes one of the volume ids to amazon.aws.ec2_tag"

    A: Declare volume_ids and teams (the same way you do it in the loop) and use them in the task

        - amazon.aws.ec2_tag:
            region: "{{ item.1 }}"
            resource: "{{ item.0 }}"
            state: present
            tags:
              team: "{{ teams }}"
          loop: "{{ volume_ids|product(region) }}"
          vars:
            volume_ids: "{{ instance_info.results|
                            map(attribute='instances')|flatten|
                            map(attribute='block_device_mappings')|flatten|
                            map(attribute='ebs')|flatten|
                            map(attribute='volume_id') }}"
            teams: "{{ instance_info.results|
                       map(attribute='instances')|flatten|
                       map(attribute='tags')|flatten|
                       map(attribute='team')|join }}"
    

    (not tested)


    Example of a complete playbook for testing

    shell> cat pb.yml
    - hosts: all
    
      vars:
    
        region: 
          - us-east-1
          - us-east-2
    
        instance_info:
          results:
            - instances:
                - tags:
                    team: tag_X
                  block_device_mappings:
                    - ebs:
                        - volume_id: vol-xxxxxxx
                - tags:
                    team: tag_Z
                  block_device_mappings:
                    - ebs:
                        - volume_id: vol-zzzzzzz
    
      tasks:
    
        - debug:
            msg: |
              amazon.aws.ec2_tag:
                region: "{{ item.1 }}"
                resource: "{{ item.0 }}"
                state: present
                tags:
                  team: "{{ teams }}"
          loop: "{{ volume_ids|product(region) }}"
          vars:
            volume_ids: "{{ instance_info.results|
                            map(attribute='instances')|flatten|
                            map(attribute='block_device_mappings')|flatten|
                            map(attribute='ebs')|flatten|
                            map(attribute='volume_id') }}"
            teams: "{{ instance_info.results|
                       map(attribute='instances')|flatten|
                       map(attribute='tags')|flatten|
                       map(attribute='team')|join }}"
    

    gives

    shell> ansible-playbook pb.yml -l test_01
    
    PLAY [all] ***********************************************************************************
    
    TASK [debug] *********************************************************************************
    ok: [test_01] => (item=['vol-xxxxxxx', 'us-east-1']) => 
      msg: |-
        amazon.aws.ec2_tag:
          region: "us-east-1"
          resource: "vol-xxxxxxx"
          state: present
          tags:
            team: "tag_Xtag_Z"
    ok: [test_01] => (item=['vol-xxxxxxx', 'us-east-2']) => 
      msg: |-
        amazon.aws.ec2_tag:
          region: "us-east-2"
          resource: "vol-xxxxxxx"
          state: present
          tags:
            team: "tag_Xtag_Z"
    ok: [test_01] => (item=['vol-zzzzzzz', 'us-east-1']) => 
      msg: |-
        amazon.aws.ec2_tag:
          region: "us-east-1"
          resource: "vol-zzzzzzz"
          state: present
          tags:
            team: "tag_Xtag_Z"
    ok: [test_01] => (item=['vol-zzzzzzz', 'us-east-2']) => 
      msg: |-
        amazon.aws.ec2_tag:
          region: "us-east-2"
          resource: "vol-zzzzzzz"
          state: present
          tags:
            team: "tag_Xtag_Z"
    
    PLAY RECAP ***********************************************************************************
    test_01                    : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0