Cyber Deals - Get up to 65% off on CKA, CKAD, CKS, KCNA, KCSA exams and courses!

Ansible Nested Loop with List and Dictionary

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.

Gineesh Madapparambath

Gineesh Madapparambath

Gineesh Madapparambath is the founder of techbeatly. He is the co-author of The Kubernetes Bible, Second Edition and the author of Ansible for Real Life Automation. 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). (Read more: iamgini.com)


Disclaimer: Views expressed in articles are those of the respective authors and do not necessarily reflect the views of their employers or this site. While we aim for accuracy, please verify information before relying on it, and let us know if you spot an error.
Share:

Related Posts

Implementing Ansible Roles

Implementing Ansible Roles

In a production environment, we will have hundreds and thousands of different types machines to handle. Hence the type of operations and …

Ansible Deployment

Ansible Deployment

Hope you are clear on the concept and installation of Ansible program. Lets configure our Ansible environment now. See all parts of Automation with …

How to setup SSH key based authentication

How to setup SSH key based authentication

This method is more secure than password-based access since the authentication happens using private and public key pair values.

Play with Ansible Playbooks

Play with Ansible Playbooks

Plays are ordered set of tasks to execute against host selections from your inventory. A playbook is a file containing one or more plays. See...

Ansible

Ansible - Upstream Projects

Note: These are projects related to Ansible and Ansible Automation Platform. This is a living document and I will update the page whenever there is a …

Managing Ansible Inventory

Managing Ansible Inventory

Inventory File An inventory file is a simple and plain text file where we store those host information ansible has to deal with. It can...