During my project for an Ansible Security Audit I needed to use loops and if statements. This for me is a weakness and so I have written this to be used a quick reference guide on how to use Ansible “when “and “with_items”.
Both of these have been used in my SNMP checking playbook. The post can be found here, and GitHub can be found here.
Base Playbook Example
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
--- - name: Cisco ios Find IP hosts: lab_core gather_facts: false connection: network_cli vars: snmp_string: snmp-server community COM_STRING RO tasks: - name: Show SNMP ios_command: commands: - "show snmp" register: pre_snmp_output # Do not run if SNMP is not Configured - name: Show Running SNMP when: pre_snmp_output is not search("%SNMP agent not enabled") ios_command: commands: - "show run | i snmp" register: misconfigured_SNMP - name: Configure SNMP ios_config: lines: - "{{ snmp_string }}" when: pre_snmp_output is search("%SNMP agent not enabled") register: snmp_changed |
When – If Like
The when is and if like statement in Python. My examples will be: When something, run task.
If the “when” condition is not met then the task will be skipped.
When there is output from the task named Show Running SNMP using the registered variable misconfigured_SNMP, then run the task below.
0 1 2 3 4 5 6 7 8 |
- name: Remove Misconfigured SNMP when: - misconfigured_SNMP.stdout_lines is defined ios_config: lines: - "no snmp-server community COM_STRING2 RO" register: |
“When” conditions can also be a list of items that you want to match. Each item in a list is denoted with a hyphen – .
There are three conditions to be matched here.
When;
– There is output from the task named Show Running SNMP using the registered variable misconfigured_SNMP
– And the length of that list is greater than 1
– And the second element of that list is not “snmp-server community COM_STRING RO”
0 1 2 3 4 5 6 7 8 9 10 |
- name: Remove Misconfigured SNMP when: - misconfigured_SNMP.stdout_lines is defined - misconfigured_SNMP.stdout_lines[0] | length > 1 - misconfigured_SNMP.stdout_lines[0][1] is not search ("snmp-server community COM_STRING RO") ios_config: lines: - "no {{ misconfigured_SNMP.stdout_lines[0][1] }}" register: |
With_Items – Loop
In my opinion Ansible loops read upside down. You can reference the item in the loop in the lines above the loop. I’m used to Python so being out of order won’t work.
In the below task there is a single loop to remove the snmp-server configuration.
0 1 2 3 4 5 6 7 8 |
- name: Remove Misconfigured SNMP ios_config: lines: - "no {{ item }}" with_items: - "no snmp-server community WRONG_WRONG1 RO" register: |
with_items can be a list of items denoted by a hyphen – .
0 1 2 3 4 5 6 7 8 9 10 |
- name: Remove Misconfigured SNMP ios_config: lines: - "no {{ item }}" with_items: - "no snmp-server community WRONG_WRONG1 RO" - "no snmp-server community WRONG_WRONG2 RO" - "no snmp-server community WRONG_WRONG3 RO" register: |
with_items can also be a list containing multiple elements. In the example below I have a task that is using the output from a previous task which contains a list of SNMP community string configuration lines.
Just passing in the list to the loop Ansible will iterate over each element of that list and evaluate each element as if it were its own.
0 1 2 3 4 5 6 7 8 |
- name: Remove Misconfigured SNMP ios_config: lines: - "no {{ item }}" with_items: - "{{ misconfigured_SNMP.stdout_lines[0] }}" register: snmp_misconfigure_fix |
Putting When and With_items Together
This is the example from my SNMP Playbook. It combines “when” and “with_items”.
This doesn’t read from top to bottom.
So what is happening is;
– If there is a variable defined named misconfigured_SNMP then proceed.
– That variable is a list, for each item in that list, check if it does not match the snmp_string variable which is defined at the top of the playbook.
– If the list element does not match then execute the ios_config line to remove it.
– If the list element does match then skip that particular line.
0 1 2 3 4 5 6 7 8 9 10 11 |
- name: Remove Misconfigured SNMP when: - misconfigured_SNMP.stdout_lines is defined - item != "{{ snmp_string }}" ios_config: lines: - "no {{ item }}" with_items: - "{{ misconfigured_SNMP.stdout_lines[0] }}" register: snmp_misconfigure_fix |