# issues with ansible looping

**URL:** <https://forum.ansible.com/t/issues-with-ansible-looping/38395>\
**Category:** Ansible Project\
**Tags:** aws\
**Created:** [September 1, 2023, 6:54pm UTC](https://forum.ansible.com/t/issues-with-ansible-looping/38395 "2023-09-01T18:54:20Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![Shivani\_Arora](https://avatars.discourse-cdn.com/v4/letter/s/919ad9/32.png) [@Shivani\_Arora](https://forum.ansible.com/u/Shivani_Arora)\
**Post date:** [September 1, 2023, 6:54pm UTC](https://forum.ansible.com/t/issues-with-ansible-looping/38395/1 "2023-09-01T18:54:20Z")

</div>

Hi Team,

I’m having issues with looping in Ansible. The background of what I’m trying to do is -  
I have 2 regions in aws\_cloud\_regions and their respective waf\_blocked\_accounts list, which looks like the one below.

I want to create regional\_account\_rules in waf for both the regions (as in us-east-1 blocked\_account\_list gets attached to regional\_account\_rules for US East and the same for another region) but facing issues while looping over regions and blocked\_account\_list together.

Also note, that search\_string in “Create statements” accepts a string list, so we have to create one outer loop and one inner loop, an outer loop for regions, and an inner for adding blocked account lists one by one.

-bash-4.2$ cat environment/QAtest/us-east-1/waf\_blocked\_accounts.yml

blocked\_account\_list:

- 5afabfb36d6c356772d8ae02

- 5c46e33273766a3634f91a7c

“aws\_cloud\_regions”: [  
“us-east-1”,  
“eu-central-1”  
]

The playbook which needs modification, it is not region-specific as of now:

- name: Loop over AWS regions

include\_vars:

file: “environment/QAtest/{{ region }}/waf\_blocked\_accounts.yml”

loop: “{{ aws\_cloud\_regions }}”

loop\_control:

loop\_var: region

register: blocked\_accounts

- name: Create statements

set\_fact:

acc\_statements: “{{ acc\_statements + [loop\_statement] }}”

vars:

loop\_statement:

byte\_match\_statement:

search\_string: “{{ acc\_id }}”

positional\_constraint: EXACTLY

field\_to\_match:

single\_header:

name: “accountmoid”

text\_transformations:

- type: NONE

priority: 0

loop: “{{ blocked\_account\_list }}”

loop\_control:

loop\_var: acc\_id

- set\_fact:

regional\_account\_rules:

- name: “BlockedAccounts”

priority: 3

action:

block: {}

visibility\_config:

sampled\_requests\_enabled: yes

cloud\_watch\_metrics\_enabled: yes

metric\_name: “BlockedAccounts”

statement:

or\_statement:

statements: “{{ acc\_statements }}”

- set\_fact:

regional\_account\_rules: “{{ regional\_account\_rules | default() }}”

Any help is appreciated. Thanks in advance.

---

<div class="post-metadata">

**Author:** ![utoddl](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/utoddl/32/249_2.png) [@utoddl](https://forum.ansible.com/u/utoddl)\
**Post date:** [September 1, 2023, 9:08pm UTC](https://forum.ansible.com/t/issues-with-ansible-looping/38395/2 "2023-09-01T21:08:32Z")

</div>

Your first task is replacing blocked\_account\_list each time through the loop, so you end up with only those blocked accounts listed for the last region.

However, you are also registering the results, so you can create a loop that retains all the blocked accounts along with their associated region.

```auto
    - name: Tie region to the blocked accounts
      ansible.builtin.debug:
        msg: "{{ item }}"
      vars:
        ba_query: '[].{region: region, blocked_accounts: ansible_facts.blocked_account_list}'
      loop:
        - "{{ blocked_accounts.results | json_query(ba_query) }}"

```

This result in the following output. (Note, I’m running with  
ANSIBLE\_STDOUT\_CALLBACK=yaml ansible-playbook …  
and I’ve inserted the region into the account numbers so I can tell which accounts came from which region.):

```auto
TASK [Tie region to the blocked accounts] ************************************************************************************************************************************
ok: [localhost] => (item=[{'region': 'us-east-1', 'blocked_accounts': ['20ea8d-us-east-1-bfbafa5', 'c7a19f-us-east-1-33e64c5']}, {'region': 'eu-central-1', 'blocked_accounts': ['5afabf-eu-central-1-ae02', '5c46e3-eu-central-1-1a7c']}]) => 
  msg:
  - blocked_accounts:
    - 20ea8d-us-east-1-bfbafa5
    - c7a19f-us-east-1-33e64c5
    region: us-east-1
  - blocked_accounts:
    - 5afabf-eu-central-1-ae02
    - 5c46e3-eu-central-1-1a7c
    region: eu-central-1

```

After that, it isn’t particularly clear to me how the region is supposed to play into the following tasks. But perhaps this will help get past the first problem.

---

<div class="post-metadata">

**Author:** ![Shivani\_Arora](https://avatars.discourse-cdn.com/v4/letter/s/919ad9/32.png) [@Shivani\_Arora](https://forum.ansible.com/u/Shivani_Arora)\
**Post date:** [September 2, 2023, 4:06pm UTC](https://forum.ansible.com/t/issues-with-ansible-looping/38395/3 "2023-09-02T16:06:47Z")

</div>

Thanks, Todd. I’m majorly facing issues with looping. I want to create regional\_account\_rules for us-east-1 and eu-central-1 and want to make sure correct “acc\_statements” get created for each region with respective blocked accounts. Could you provide some suggestions how to achieve this?

---

<div class="post-metadata">

**Author:** ![Shivani\_Arora](https://avatars.discourse-cdn.com/v4/letter/s/919ad9/32.png) [@Shivani\_Arora](https://forum.ansible.com/u/Shivani_Arora)\
**Post date:** [September 2, 2023, 4:18pm UTC](https://forum.ansible.com/t/issues-with-ansible-looping/38395/4 "2023-09-02T16:18:26Z")

</div>

The code I have written is:

- name: Populate acc\_statements  
set\_fact:  
acc\_statements: “{{ acc\_statements | combine({acc\_id.region: acc\_statements[acc\_id.region] | default() + [loop\_statement]}) }}”  
vars:  
loop\_statement:  
byte\_match\_statement:  
search\_string: “{{ acc\_id.ansible\_facts.blocked\_account\_list }}”  
positional\_constraint: EXACTLY  
field\_to\_match:  
single\_header:  
name: “accountmoid”  
text\_transformations:

- type: NONE  
priority: 0  
loop: “{{ blocked\_accounts.results }}”  
loop\_control:  
loop\_var: acc\_id

- debug:  
var: acc\_statements

**The output I’m getting:**

“acc\_statements”: {  
“eu-central-1”: [  
{  
“byte\_match\_statement”: {  
“field\_to\_match”: {  
“single\_header”: {  
“name”: “accountmoid”  
}  
},  
“positional\_constraint”: “EXACTLY”,  
“search\_string”: [  
“5afabfb36d6c356772d84362”,  
“5c46e33273766a3634f91a8d”  
],  
“text\_transformations”: [  
{  
“priority”: 0,  
“type”: “NONE”  
}  
]  
}  
}  
],  
“us-east-1”: [  
{  
“byte\_match\_statement”: {  
“field\_to\_match”: {  
“single\_header”: {  
“name”: “accountmoid”  
}  
},  
“positional\_constraint”: “EXACTLY”,  
“search\_string”: [  
“5afabfb36d6c356772d8ae02”,  
“5c46e33273766a3634f91a7c”  
],  
“text\_transformations”: [  
{  
“priority”: 0,  
“type”: “NONE”  
}  
]  
}  
}  
]  
}  
}

**And the output I want is, search\_string should be a string instead of a list:**

“acc\_statements”: {  
“eu-central-1”: [  
{  
“byte\_match\_statement”: {  
“field\_to\_match”: {  
“single\_header”: {  
“name”: “accountmoid”  
}  
},  
“positional\_constraint”: “EXACTLY”,  
“search\_string”: “5afabfb36d6c356772d84362”,  
“text\_transformations”: [  
{  
“priority”: 0,  
“type”: “NONE”  
}  
]  
}  
},  
{  
“byte\_match\_statement”: {  
“field\_to\_match”: {  
“single\_header”: {  
“name”: “accountmoid”  
}  
},  
“positional\_constraint”: “EXACTLY”,  
“search\_string”: “5c46e33273766a3634f91a8d”,  
“text\_transformations”: [  
{  
“priority”: 0,  
“type”: “NONE”  
}  
]  
}  
}  
],  
“us-east-1”: [  
{  
“byte\_match\_statement”: {  
“field\_to\_match”: {  
“single\_header”: {  
“name”: “accountmoid”  
}  
},  
“positional\_constraint”: “EXACTLY”,  
“search\_string”: “5afabfb36d6c356772d8ae02”  
“text\_transformations”: [  
{  
“priority”: 0,  
“type”: “NONE”  
}  
]  
}  
}  
]  
}  
}

---

<div class="post-metadata">

**Author:** ![utoddl](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/utoddl/32/249_2.png) [@utoddl](https://forum.ansible.com/u/utoddl)\
**Post date:** [September 2, 2023, 7:08pm UTC](https://forum.ansible.com/t/issues-with-ansible-looping/38395/5 "2023-09-02T19:08:05Z")

</div>

You are close, and your intuition is correct that there’s a way to loop through with one item per (region × account). This is exactly the situation that the subelements filter is designed for. Try this:

```auto
    - name: Populate acc_statements
      ansible.builtin.set_fact:
        acc_statements: "{{ acc_statements | default([]) | combine({acc_id**[0]**.region: acc_statements[acc_id**[0]**.region] | default([]) + [loop_statement]}) }}"
      vars:
        loop_statement:
          byte_match_statement:
            search_string: "{{ acc_id**[1]** }}"
            positional_constraint: EXACTLY
            field_to_match:
              single_header:
                name: "accountmoid"
            text_transformations:
              - type: NONE
                priority: 0
      loop: "{{ blocked_accounts.results **| subelements('ansible_facts.blocked_account_list')** }}"
      loop_control:
        loop_var: acc_id

```

The subelements filter takes a list (blocked\_accounts.results in this case) and duplicates each item once per each subelement of the item as referenced by the given string. Each element of the list it returns (acc\_id) will itself contain two elements: the first (acc\_id[0]) is a copy of an item from the original list (blocked\_accounts.results); the second (acc\_id[1]) is the subelement from acc\_id[0] that this pair corresponds to.

It’s easy to get lost in all the words, but the simple demo is this:

```auto
  orig:
    - alpha: a
      numbers:
        - 1
        - 2
    - alpha: b
      numbers:
        - 3
        - 4
  result: "{{ orig | subelements('numbers') }}"
# result looks like this:
    - - alpha: a
        numbers:
          - **1**
          - 2
      - **1**
    - - alpha: a
        numbers:
          - 1
          - **2**
      - **2**
    - - alpha: b
        numbers:
          - **3**
          - 4
      - **3**
    - - alpha: b
        numbers:
          - 3
          - **4**
      - **4**

```

---

<div class="post-metadata">

**Author:** ![Shivani\_Arora](https://avatars.discourse-cdn.com/v4/letter/s/919ad9/32.png) [@Shivani\_Arora](https://forum.ansible.com/u/Shivani_Arora)\
**Post date:** [September 3, 2023, 4:24pm UTC](https://forum.ansible.com/t/issues-with-ansible-looping/38395/6 "2023-09-03T16:24:10Z")

</div>

Thanks much Todd, the above code works as expected.
