I have an Ansible role that i call to return the following information on a network switch
"networkSwitch": [
{
"switchName": "some_switch_name_01",
"uplinks": [
"physicalNic-nic0",
"physicalNic-nic3"
],
"uplink_count": 2
}
]
I need to call the role until one of two conditions are met
- the switchName value matches an expected name
- the uplink_count is >= 1
Preferably both of the above would be true and this would break out of the loop successfully
I've discovered that it's not possible to use until/retry/delay with either include_role or retry_role.
I found Looping or repeating a group of tasks until success and attempted to follow it's instruction without success
I've created a file called get_switch_detail.yml It contains
---
- name: repeat until success
block:
- name: increment attempts counter
set_fact:
attempt_number: "{{ attempt_number | d(0) | int + 1 }}"
- name: Get switch details
debug:
msg: "This is a dummy task, it doesn't actually get the switch details"
- name: Print the switch facts
debug: var=item
with_items: "{{switch_facts.results}}"
when: item.ansible_facts is defined
- name: set fact to collect specific Switch attributes
set_fact:
networkSwitch: "{{ networkSwitch | d([]) + [{ 'switchName': item.ansible_facts.config.network.proxySwitch[0].dvsName,
'uplinks': item.ansible_facts.config.network.proxySwitch[0].pnic,
'uplink_count': item.ansible_facts.config.network.proxySwitch[0].pnic|length }] }}"
with_list: "{{lookup('list', switch_facts.results) }}"
when: item.ansible_facts is defined
- name: Print the proxySwitch attributes
debug:
msg:
- "proxySwitch attributes are: {{proxySwitch}}"
- "proxySwitch name is: {{proxySwitch[0].dvsName}}"
- "Number of proxySwitch uplinks is: {{proxySwitch[0].pnic_count}}"
- name: Print
debug: var=proxySwitch
- name: Task to check for success
debug:
msg: success
when:
- proxySwitch[0].switchName == target_switch_name
- proxySwitch[0].uplink_count >= 2
rescue:
- name: "Fail if we reached the max of {{ max_attempts | d(3) }} attempts"
# Default will be 3 attempts if max_attempts is not passed as a parameter
ansible.builtin.fail:
msg: Maximum number of attempts reached
when: attempt_number | int == max_attempts | int | d(3)
- ansible.builtin.debug:
msg: "group of tasks failed on attempt {{ attempt_number }}. Retrying"
- name: add delay if needed
# no delay if retry_delay is not passed as parameter
ansible.builtin.wait_for:
timeout: "{{ retry_delay | int | d(omit) }}"
when: retry_delay is defined
# include ourselves to retry.
- ansible.builtin.include_tasks: ../get_switch_detail.yml
I call the above using
- name: Retrying
include_tasks: ../get_switch_detail.yml
vars:
max_attempts: 4
retry_delay: 5
but it never repeats
Figured it out, probably not correct way of doing things but, in this scenario it gives the desired outcome.
In short, i'm calling the role from within itself when a condition is met. This potentially leads to an infinite loop but, was the best i could come up with.
Main play
The last task within the get_switch_uplinks role calls itself when conditions are right
Again, if the conditions specified are not met, this causes an infinite loop. Definitely not the best solution.
In my scenario though, the conditions will be met, it's just that they are met on some devices earlier than others so, trying to use a static timer at the beginning of the third play task wasn't always successful