This is true about custom iterators, though not all people can write custom iterators and I have personally witnessed some unjustified negativism for accepting in core small improvements for available iterators for everyone’s benefit. To be more specific, I was thinking of a “goback” feature as a very restricted ‘goto’. It would allow to move only backwards and only in the same play and same file. That way all problems of ‘goto’ are gone. That said, now I am thinking of another possible implementation: By default ‘times’ would be 1. If times == 0 it would check that an ‘until’ condition has been set and repeat tagged tasks until that condition becomes true. Other cases: - Stress testing a group of hosts by repeating a group of tasks X times - Run a time-dependent port knocking scheme X times to pass through a firewall - Run X passes of a series of data-destructive tasks on some disk containing your secrets And generally repeating any couple of “run task & check for output” tasks.
we have a do/until already
Hi,
Sorry to reanimate this, but I think I have a “legit” use case for looping over multiple tasks:
This is what I’ve got:
- name: install cq packages
local_action: cqpkg name={{ item.pkg }}
path={{ item.file }}
state=present
admin_user={{ admin_user }}
admin_password={{ admin_pass }}
host={{ ansible_eth1.ipv4.address }}
port={{ listen_port }}
with_items: cq_packages
But really I need (pretend syntax of course):
- name: install cq packages
Install package
- local_action: cqpkg name={{ item.pkg }}
path={{ item.file }}
state=present
admin_user={{ admin_user }}
admin_password={{ admin_pass }}
host={{ ansible_eth1.ipv4.address }}
port={{ listen_port }}
Restart service if package requires it to be done immediately
- service: name={{ service_name }} enabled=yes state=started
when: {{ item.cqrestart }} == immediate
Wait for the port to come up (this can happen a while after restart)
- wait_for: port={{ listen_port }} delay=1
Wait for the darned thing to come back, and this can take AGES
- shell: “{{ aem_check }}”
until: result.stdout.find(“200 OK”) != -1
retries: 180
delay: 10
register: result
changed_when: False
Rinse, repeat
with_items: cq_packages
Because I’m using an ansible module to do actual installation (cqpkg) doing it as a script would require some serious rewriting OR doing all the restarts and waiting and checking within the module. Waiting and checking I’d be reasonably OK with, but not service restart, to be honest. The restart cannot be a handler either, because some packages require immediate restart (application can break beyond recovery if cq is not restarted there and then). As far as I managed to understand flush_handlers this won’t work in a loop either, not to mention unintended consequences, as it’s all or nothing.
This can, and most likely will be, separated out into a parameterised role, but it’ll force fairly non-intuitive "flow.
This really seems to be a simple example of why loop over multiple tasks makes sense: I want to install a package, restart a service and wait for things to settle down before proceeding with installation of next package.
I’ll need to come up with a solution pretty much today, so this is just for general discussion.
Regards,
Daniel
Or is this a role for include + with_items that will be available in 2.0?
Regards,
Daniel
yes
Can you expand on what you mean by “include + with_items”? I have a use case that is almost identical to what Daniel gives above. Need something like this (I’m sure it’s not exactly right):
`
roles/httpd/tasks/main.yml:
- include: file.yml
with_fileglob: - vars/*.yml
file.yml
- include_vars: {{ item }}
- debug: msg=“{{ field1 }} from with list”
- debug: msg=“{{ field2 }} from with list”
- template: src=“templates/site.conf.j2” dest=“site.conf”
Thank you very much! No wonder I hadn’t figured this out earlier! I’m sure there’s just some aspect I never looked into. Just for the next person who comes along what I got to work was
playbook.yml
`
Hi. I think this situation hasn’t changed in ansible v2.7 as well.
There is no way I can find to repeat a particular task or a set of tasks within an existing playbook.
It would have been great if we could use tags to call some “tagged-tasks again” wherever we want in a playbook OR create a new feature like ‘goto or goback’ as discussed in the above threads.
My scenario:
I have to deal with 3 tasks A, B and C. Here C is dependent on A and B’s performance. i.e If C’s output is not as expected, then again A and B have to be repeated again. And somehow I cannot fit this in a ‘block-rescue-always’ structure as its pointless.
Right now, I manage this using ‘include_task’ option along with ‘when’ conditional. I re-enter A and B tasks into a separate ‘.yml’ file and then call it into this playbook using ‘include_task’ wherever I want.
This solved my purpose but is ridiculous especially when we have so many other options to effectively orchestrate things using ansilble.
Any inputs/thoughts on this would be helpful for me to explore more.
If there is some condition that can be tested externally, then why not a simple script that calls ansible-playbook until that condition obtains?