Skip to content

Commit

Permalink
Allow any_errors_fatal to be dynamic
Browse files Browse the repository at this point in the history
This change updates the linear and free strategies to ensure that the
value of any_errors_fatal is properly evaluated if it contains a dynamic
value. Previously if it was not set to a boolean false, it would be
true.

Fixes #61025
  • Loading branch information
mwhahaha committed Jun 4, 2021
1 parent 3d8feed commit 019b5ea
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 6 deletions.
7 changes: 6 additions & 1 deletion lib/ansible/plugins/strategy/free.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,12 @@ def run(self, iterator, play_context):
else:
# handle step if needed, skip meta actions as they are used internally
if not self._step or self._take_step(task, host_name):
if task.any_errors_fatal:
task_any_errors_fatal = task.get_validated_value('any_errors_fatal',
task._valid_attrs['any_errors_fatal'],
templar.template(task.any_errors_fatal),
None)

if task_any_errors_fatal:
display.warning("Using any_errors_fatal with the free strategy is not supported, "
"as tasks are executed independently on each host")
self._tqm.send_callback('v2_playbook_on_task_start', task, is_conditional=False)
Expand Down
9 changes: 7 additions & 2 deletions lib/ansible/plugins/strategy/linear.py
Original file line number Diff line number Diff line change
Expand Up @@ -272,13 +272,18 @@ def run(self, iterator, play_context):
# corresponding action plugin
action = None

task_any_errors_fatal = task.get_validated_value('any_errors_fatal',
task._valid_attrs['any_errors_fatal'],
templar.template(task.any_errors_fatal),
None)

if task.action in C._ACTION_META:
# for the linear strategy, we run meta tasks just once and for
# all hosts currently being iterated over rather than one host
results.extend(self._execute_meta(task, play_context, iterator, host))
if task.args.get('_raw_params', None) not in ('noop', 'reset_connection', 'end_host', 'role_complete'):
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
else:
# handle step if needed, skip meta actions as they are used internally
Expand All @@ -291,7 +296,7 @@ def run(self, iterator, play_context):

run_once = templar.template(task.run_once) or action and getattr(action, 'BYPASS_HOST_LOOP', False)

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

if not callback_sent:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
- hosts: all
gather_facts: false
any_errors_fatal: false
ignore_unreachable: true
vars:
skip_errors: "silliness"
tasks:
- block:
- name: EXPECTED FAILURE any_errors_fatal, simulate failure on one node
shell: exit 1
when: inventory_hostname == "testhost"
- debug:
msg: "any_errors_fatal_dynamic_value_continues"
any_errors_fatal: "{{ skip_errors }}"
14 changes: 14 additions & 0 deletions test/integration/targets/any_errors_fatal/61025-dynamic_block.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
- hosts: all
gather_facts: false
any_errors_fatal: false
ignore_unreachable: true
vars:
skip_errors: true
tasks:
- block:
- name: EXPECTED FAILURE any_errors_fatal, simulate failure on one node
shell: exit 1
when: inventory_hostname == "testhost"
- debug:
msg: "any_errors_fatal_dynamic_value_continues"
any_errors_fatal: "{{ not skip_errors }}"
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- import_playbook: dynamic_playbook.yml
vars:
skip_errors: true
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
- hosts: all
gather_facts: false
any_errors_fatal: "{{ not skip_errors }}"
tasks:
- name: EXPECTED FAILURE any_errors_fatal, simulate failure on one node
shell: exit 1
when: inventory_hostname == "testhost"
- debug:
msg: "any_errors_fatal_dynamic_value_import_playbook_continues"
27 changes: 24 additions & 3 deletions test/integration/targets/any_errors_fatal/runme.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,30 @@ if [ "${res}" -eq 0 ] ; then
exit 1
fi

set -ux

ansible-playbook -i inventory "$@" always_block.yml | tee out.txt | grep 'any_errors_fatal_always_block_start'
res=$?
cat out.txt
exit $res
if [ "${res}" -ne 0 ] ; then
exit 1
fi

ansible-playbook -i inventory "$@" 61025-dynamic_block.yml | tee out.txt | grep 'any_errors_fatal_dynamic_value_continues'
res=$?
cat out.txt
if [ "${res}" -ne 0 ] ; then
exit 1
fi

ansible-playbook -i inventory "$@" 61025-import_playbook.yml | tee out.txt | grep 'any_errors_fatal_dynamic_value_import_playbook_continues'
res=$?
cat out.txt
if [ "${res}" -ne 0 ] ; then
exit 1
fi

ansible-playbook -i inventory "$@" 61025-bad_dynamic_value.yml 2>&1 | tee out.txt | grep 'not a valid boolean.'
res=$?
cat out.txt
if [ "${res}" -ne 0 ] ; then
exit 1
fi

0 comments on commit 019b5ea

Please sign in to comment.