I need to write some lines in a YAML file for a variable number of times:
- name: Retry a task until a certain condition is met
lineinfile:
path: /root/file
insertafter: '^listeners:'
line: 'iteration #iteration_number++'
retries: {{ a_variable }}
delay: 10
I want to write execution number of each iteration to the file also. Similar to the following for loop:
for i in {1..a_variable}
do
echo "i"
done
How to keep track of where you are in a loop?
Q: “Similar to the following for loop.“
Based on the already given idea, a minimal example playbook
---
- hosts: localhost
become: false
gather_facts: false
tasks:
- name: Echo index into file
lineinfile:
path: index.file
create: true
line: '{{ item }}'
loop: "{{ range(1, i + 1, 1) }}"
loop_control:
extended: true
label: "{{ ansible_loop.index }}"
vars:
i: 3
will result into an output of
TASK [Echo index into file] ****
changed: [localhost] => (item=1)
changed: [localhost] => (item=2)
changed: [localhost] => (item=3)
and a file content of
cat index.file
1
2
3
Even if this is technically possible one should keep in mind The Zen of Ansible.
If you’re trying to “write code” in your plays and roles, you’re setting yourself up for failure. Ansible’s YAML-based playbooks were never meant to be for programming.
Documentation
- Jinja2 Template Designer – List of Global Functions –
range()
- Adding controls to
loop
First, retries are not loops as they don’t iterate over anything. They just poll until the condition is met. Instead, you need to put your lineinfile
execution in a loop
that would iterate over a range from 0 to your value. Something like this (I can’t validate right now, just showing the idea):
- name: Retry a task until a certain condition is met
lineinfile:
path: /root/file
insertafter: '^listeners:'
line: 'iteration #iteration_number++'
loop: "{{ lookup('range', 0, a_variable }}"
Then, you can use the default item
variable or set it to another one using the optional loop_var
directive of the loop_control
parameter.
But that’s true for simple cases. In the real world, one iterates over some list of objects, so Ansible provides a special variable just for this case. It’s covered in
Tracking progress through a loop with index_var
:
To keep track of where you are in a loop, use the
index_var
directive withloop_control
. This directive specifies a variable name to contain the current loop index.
- name: Count our fruit
ansible.builtin.debug:
msg: "{{ item }} with index {{ my_idx }}"
loop:
- apple
- banana
- pear
loop_control:
index_var: my_idx
You might also consider templating the file with Jinja2 instead.