Skip to content

Ansible Nested Loop with List and Dictionary

Avatar photo

https://www.linkedin.com/in/gineesh/ https://twitter.com/GiniGangadharan

Ansible loops are simple and powerful with mixed data. You will sure say “awesome” when you realize the easiness with loops.

During our technical discussions, we came across a use case for nested loops inside a playbook. Nested loops are easy but we need to be careful when we need some paired values inside the loop.

In below example, user want to update windows registry; 4 values per each port.

HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\<YOUR_PROTOCOL>\<SERVER_OR_CLIENT> -Name <Enabled_OR_DisabledByDefault> -Value <0_or_1> -Type DWord

So the protocol, server/client, Enable/DesabledByDefault and Value will be changed in loops. Let’s say if we have 3 protocols to be changed,

Lets create variables for the same.

     protocol:
       - 'PCT 1.0'
       - 'SSL 2.0'
       - 'SSL 3.0'
     srvtype:
       - 'Server'
       - 'Client'

Since, Enable/DesabledByDefault  coming with value pair, we will put into a dictionary as below.

     regname:
       - myname: 'Enabled'
         type:
           - name: 'Enabled'
             value: 0
       - myname: 'DisabledByDefault'
         type:
           - name: 'DisabledByDefault'
             value: 1

Before I execute, I just want to print the value and see if its working correctly. For that purpose I have created a task with debug module as below.

 tasks:
  - name: check loop1
   debug:
    msg: 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols{{item[0]}}{{item[1]}} -Name {{ item[2]["myname"] }} -Value {{ item.2.type.0.value }} -Type DWord'
   with_nested:
    - '{{ protocol }}'
    - '{{ srvtype }}'
    - '{{ regname }}'

I have just run it to see the output.

$ ansible-playbook usecase-nested-loop-with-dictionary.yml
PLAY [nested] *
TASK [check loop1] ****
ok: [localhost] => (item=None) => {
  "msg": "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\PCT 1.0\Server -Name Enabled -Value 0 -Type DWord"
}
ok: [localhost] => (item=None) => {
  "msg": "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\PCT 1.0\Server -Name DisabledByDefault -Value 1 -Type DWord"
}
ok: [localhost] => (item=None) => {
  "msg": "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\PCT 1.0\Client -Name Enabled -Value 0 -Type DWord"
}
ok: [localhost] => (item=None) => {
  "msg": "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\PCT 1.0\Client -Name DisabledByDefault -Value 1 -Type DWord"
}
ok: [localhost] => (item=None) => {
  "msg": "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 2.0\Server -Name Enabled -Value 0 -Type DWord"
}
ok: [localhost] => (item=None) => {
  "msg": "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 2.0\Server -Name DisabledByDefault -Value 1 -Type DWord"
}
ok: [localhost] => (item=None) => {
  "msg": "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 2.0\Client -Name Enabled -Value 0 -Type DWord"
}
ok: [localhost] => (item=None) => {
  "msg": "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 2.0\Client -Name DisabledByDefault -Value 1 -Type DWord"
}
ok: [localhost] => (item=None) => {
  "msg": "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 3.0\Server -Name Enabled -Value 0 -Type DWord"
}
ok: [localhost] => (item=None) => {
  "msg": "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 3.0\Server -Name DisabledByDefault -Value 1 -Type DWord"
}
ok: [localhost] => (item=None) => {
  "msg": "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 3.0\Client -Name Enabled -Value 0 -Type DWord"
}
ok: [localhost] => (item=None) => {
  "msg": "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\SSL 3.0\Client -Name DisabledByDefault -Value 1 -Type DWord"
}
PLAY RECAP
localhost : ok=1 changed=0 unreachable=0 failed=0

Let’s create the actual task with win_regedit module to update registry.

    - name: Update Windows Reg
      win_regedit:
        path: 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols{{item[0]}}{{item[1]}}'
        name: '{{ item[2]["myname"] }}'
        data: '{{ item.2.type.0.value }}'
        type: dword
      with_nested:
        - '{{ protocol }}'
        - '{{ srvtype }}'
        - '{{ regname }}'

And here see my final playbook.

# Loop to get 3 protocols x 2 servertype x 2 Names&Value (12 combinations)
# We need 12 combinations but Name and Value are pairs, hence used a dictionary
- name: Loop to get 3 protocols x 2 servertype x 2 Names&Value (12 combinations)
  hosts: winteldbservers
  gather_facts: no
  vars:
    regname:
      - myname: 'Enabled'
        type:
          - name: 'Enabled'
            value: 0
      - myname: 'DisabledByDefault'
        type:
          - name: 'DisabledByDefault'
            value: 1
    protocol:
      - 'PCT 1.0'
      - 'SSL 2.0'
      - 'SSL 3.0'
    srvtype:
      - 'Server'
      - 'Client'
  tasks:
    - name: check loop1
      debug:
        msg: 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols{{item[0]}}{{item[1]}}  -Name {{ item[2]["myname"] }} -Value {{ item.2.type.0.value }} -Type DWord'
      with_nested:
        - '{{ protocol }}'
        - '{{ srvtype }}'
        - '{{ regname }}'
        
    - name: Update Windows Reg
      win_regedit:
        path: 'HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols{{item[0]}}{{item[1]}}'
        name: '{{ item[2]["myname"] }}'
        data: '{{ item.2.type.0.value }}'
        type: dword
      with_nested:
        - '{{ protocol }}'
        - '{{ srvtype }}'
        - '{{ regname }}'

You may move these variables to a variable file or create a role for the same for easy handling.

You may find the playbook here.

Disclaimer:

The views expressed and the content shared in all published articles on this website are solely those of the respective authors, and they do not necessarily reflect the views of the author’s employer or the techbeatly platform. We strive to ensure the accuracy and validity of the content published on our website. However, we cannot guarantee the absolute correctness or completeness of the information provided. It is the responsibility of the readers and users of this website to verify the accuracy and appropriateness of any information or opinions expressed within the articles. If you come across any content that you believe to be incorrect or invalid, please contact us immediately so that we can address the issue promptly.

Avatar photo


https://www.linkedin.com/in/gineesh/ https://twitter.com/GiniGangadharan
Gineesh Madapparambath is the founder of techbeatly and he is the author of the book - 𝗔𝗻𝘀𝗶𝗯𝗹𝗲 𝗳𝗼𝗿 𝗥𝗲𝗮𝗹-𝗟𝗶𝗳𝗲 𝗔𝘂𝘁𝗼𝗺𝗮𝘁𝗶𝗼𝗻. He has worked as a Systems Engineer, Automation Specialist, and content author. His primary focus is on Ansible Automation, Containerisation (OpenShift & Kubernetes), and Infrastructure as Code (Terraform). (aka Gini Gangadharan - iamgini.com)

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.