I have a system with several hosts for availability. I only need to run my Ansible playbook on one host. However some of these hosts may not be reachable. Let's say I have host1, host2, host3 ... If host1 is not reachable, I want Ansible to try host2. If host2 is reachable and Ansible runs some bash scripts successfully, I want Ansible to skip the rest of hosts. Any suggestions?
3
votes
How do you define "some" in "runs some bash scripts successfully"?
– techraf
And how do you define "unreachable"? Ansible automatically skips hosts unreachable by ssh.
– sm4rk0
@sm4rk0 I'm curious how would it influence the answer? The only determinant whether to continue trying or to stop is a successful execution (of mysterious "some" scripts). What role does the definition of "unreachable" play for the answer, in your opinion?
– techraf
@techraf You're right. I misunderstood the question.
– sm4rk0
2 Answers
2
votes
This is probably not the optimal solution, but I couldn't find a better one.
- (Optionally) Set
gather_facts
toFalse
, to entirely skip the hosts that need to be skipped (if you don't need to gather the host facts). - Set
serial
to 1, so the playbook is played entirely on one host at a time instead of the default 5 hosts in parallel. - Use
set_fact
to set a host fact (nameddone
in example) toTrue
at the end of a play, or useregister
if you need a more specific condition (a command output). - Use
end_play
meta
at the start of the play that would execute when the variable is set toTrue
(or has the expected value, if you usedregister
) for any host. I used the Jinja2 template language to extract the value this way:for
to loop over all thehostvars
(Python dict containing all the variables set for all hosts in the inventory).if
to check whether a host hasdone
variable set toTrue
and return a stringTrue
if it is.default
filter to set the default value ifdone
is not defined for a host (that would cause an error'dict object' has no attribute 'done'
).
For example:
- hosts: all
serial: 1
gather_facts: False
tasks:
- meta: end_play
when: "{% for item in hostvars.values() %}{% if item.done|default(False) %}True{% endif %}{% endfor %}"
# The rest of the play goes here
- set_fact:
done: True