Add new meta task end_host (#47194)

* Add new meta task  end_host
This commit is contained in:
Martin Krizek 2018-11-14 15:46:25 +01:00 committed by Brian Coca
parent 24593f2ffb
commit 907ff2f26c
8 changed files with 69 additions and 2 deletions

View file

@ -0,0 +1,2 @@
minor_changes:
- Add new meta task end_host - https://github.com/ansible/ansible/issues/40904

View file

@ -39,7 +39,8 @@ options:
- "C(clear_host_errors) (added in 2.1) clears the failed state (if any) from hosts specified in the play's list of hosts." - "C(clear_host_errors) (added in 2.1) clears the failed state (if any) from hosts specified in the play's list of hosts."
- "C(end_play) (added in 2.2) causes the play to end without failing the host(s). Note that this affects all hosts." - "C(end_play) (added in 2.2) causes the play to end without failing the host(s). Note that this affects all hosts."
- "C(reset_connection) (added in 2.3) interrupts a persistent connection (i.e. ssh + control persist)" - "C(reset_connection) (added in 2.3) interrupts a persistent connection (i.e. ssh + control persist)"
choices: ['flush_handlers', 'refresh_inventory', 'noop', 'clear_facts', 'clear_host_errors', 'end_play', 'reset_connection'] - "C(end_host) (added in 2.8) is a per-host variation of C(end_play). Causes the play to end for the current host without failing it."
choices: ['flush_handlers', 'refresh_inventory', 'noop', 'clear_facts', 'clear_host_errors', 'end_play', 'reset_connection', 'end_host']
required: true required: true
notes: notes:
- C(meta) is not really a module nor action_plugin as such it cannot be overwritten. - C(meta) is not really a module nor action_plugin as such it cannot be overwritten.
@ -77,4 +78,10 @@ EXAMPLES = '''
- user: name={{ansible_user}} groups=input - user: name={{ansible_user}} groups=input
- name: reset ssh connection to allow user changes to affect 'current login user' - name: reset ssh connection to allow user changes to affect 'current login user'
meta: reset_connection meta: reset_connection
- name: End the play for hosts that run CentOS 6
meta: end_host
when:
- ansible_distribution == 'CentOS'
- ansible_distribution_major_version == '6'
''' '''

View file

@ -1067,6 +1067,13 @@ class StrategyBase:
if host.name not in self._tqm._unreachable_hosts: if host.name not in self._tqm._unreachable_hosts:
iterator._host_states[host.name].run_state = iterator.ITERATING_COMPLETE iterator._host_states[host.name].run_state = iterator.ITERATING_COMPLETE
msg = "ending play" msg = "ending play"
elif meta_action == 'end_host':
if _evaluate_conditional(target_host):
iterator._host_states[target_host.name].run_state = iterator.ITERATING_COMPLETE
msg = "ending play for %s" % target_host.name
else:
skipped = True
msg = "end_host conditional evaluated to false, continuing execution for %s" % target_host.name
elif meta_action == 'reset_connection': elif meta_action == 'reset_connection':
all_vars = self._variable_manager.get_vars(play=iterator._play, host=target_host, task=task) all_vars = self._variable_manager.get_vars(play=iterator._play, host=target_host, task=task)
templar = Templar(loader=self._loader, variables=all_vars) templar = Templar(loader=self._loader, variables=all_vars)

View file

@ -265,7 +265,7 @@ class StrategyModule(StrategyBase):
# for the linear strategy, we run meta tasks just once and for # for the linear strategy, we run meta tasks just once and for
# all hosts currently being iterated over rather than one host # all hosts currently being iterated over rather than one host
results.extend(self._execute_meta(task, play_context, iterator, host)) results.extend(self._execute_meta(task, play_context, iterator, host))
if task.args.get('_raw_params', None) not in ('noop', 'reset_connection'): if task.args.get('_raw_params', None) not in ('noop', 'reset_connection', 'end_host'):
run_once = True run_once = True
if (task.any_errors_fatal or run_once) and not task.ignore_errors: if (task.any_errors_fatal or run_once) and not task.ignore_errors:
any_errors_fatal = True any_errors_fatal = True

View file

@ -0,0 +1 @@
shippable/posix/group3

View file

@ -0,0 +1,23 @@
#!/usr/bin/env bash
set -eux
# test end_host meta task, with when conditional
for test_strategy in linear free; do
out="$(ansible-playbook test_end_host.yml -i ../../inventory -e test_strategy=$test_strategy -vv "$@")"
grep -q "META: end_host conditional evaluated to false, continuing execution for testhost" <<< "$out"
grep -q "META: ending play for testhost2" <<< "$out"
grep -q "play not ended for testhost" <<< "$out"
grep -qv "play not ended for testhost2" <<< "$out"
done
# test end_host meta task, on all hosts
for test_strategy in linear free; do
out="$(ansible-playbook test_end_host_all.yml -i ../../inventory -e test_strategy=$test_strategy -vv "$@")"
grep -q "META: ending play for testhost" <<< "$out"
grep -q "META: ending play for testhost2" <<< "$out"
grep -qv "play not ended for testhost" <<< "$out"
grep -qv "play not ended for testhost2" <<< "$out"
done

View file

@ -0,0 +1,14 @@
- name: "Testing end_host with strategy={{ test_strategy | default('linear') }}"
hosts:
- testhost
- testhost2
gather_facts: no
strategy: "{{ test_strategy | default('linear') }}"
tasks:
- debug:
- meta: end_host
when: "host_var_role_name == 'role2'" # end play for testhost2, see test/integration/inventory
- debug:
msg: "play not ended for {{ inventory_hostname }}"

View file

@ -0,0 +1,13 @@
- name: "Testing end_host all hosts with strategy={{ test_strategy | default('linear') }}"
hosts:
- testhost
- testhost2
gather_facts: no
strategy: "{{ test_strategy | default('linear') }}"
tasks:
- debug:
- meta: end_host
- debug:
msg: "play not ended {{ inventory_hostname }}"