Add check mode indicators at the beginning and the end of the playbook, play, and task (#49432)

* Add integration tests for default callback check mode markers
This commit is contained in:
basos g 2019-07-25 19:05:43 +03:00 committed by Sam Doran
parent a5d409a8b2
commit 3c8838f0f7
12 changed files with 492 additions and 9 deletions

View file

@ -0,0 +1,2 @@
minor_changes:
- Add new option to default standard out callback plugin, ``ANSIBLE_CHECK_MODE_MARKERS``, which adds check mode markers (``DRY RUN``, ``CHECK_MODE``) to the output when running in check mode. It is off by default.

View file

@ -16,8 +16,27 @@ DOCUMENTATION = '''
- default_callback
requirements:
- set as stdout in configuration
options:
check_mode_markers:
name: Show markers when running in check mode
description:
- "Toggle to control displaying markers when running in check mode. The markers are C(DRY RUN)
at the beggining and ending of playbook execution (when calling C(ansible-playbook --check))
and C(CHECK MODE) as a suffix at every play and task that is run in check mode."
type: bool
default: no
version_added: 2.9
env:
- name: ANSIBLE_CHECK_MODE_MARKERS
ini:
- key: check_mode_markers
section: defaults
'''
# NOTE: check_mode_markers functionality is also implemented in the following derived plugins:
# debug.py, yaml.py, dense.py. Maybe their documentation needs updating, too.
from ansible import constants as C
from ansible import context
from ansible.playbook.task_include import TaskInclude
@ -33,10 +52,12 @@ from ansible.utils.color import colorize, hostcolor
# these are used to provide backwards compat with old plugins that subclass from default
# but still don't use the new config system and/or fail to document the options
# TODO: Change the default of check_mode_markers to True in a future release (2.13)
COMPAT_OPTIONS = (('display_skipped_hosts', C.DISPLAY_SKIPPED_HOSTS),
('display_ok_hosts', True),
('show_custom_stats', C.SHOW_CUSTOM_STATS),
('display_failed_stderr', False),)
('display_failed_stderr', False),
('check_mode_markers', False),)
class CallbackModule(CallbackBase):
@ -213,7 +234,11 @@ class CallbackModule(CallbackBase):
if task_name is None:
task_name = task.get_name().strip()
self._display.banner(u"%s [%s%s]" % (prefix, task_name, args))
if task.check_mode and self.check_mode_markers:
checkmsg = " [CHECK MODE]"
else:
checkmsg = ""
self._display.banner(u"%s [%s%s]%s" % (prefix, task_name, args, checkmsg))
if self._display.verbosity >= 2:
path = task.get_path()
if path:
@ -233,10 +258,14 @@ class CallbackModule(CallbackBase):
def v2_playbook_on_play_start(self, play):
name = play.get_name().strip()
if not name:
msg = u"PLAY"
if play.check_mode and self.check_mode_markers:
checkmsg = " [CHECK MODE]"
else:
msg = u"PLAY [%s]" % name
checkmsg = ""
if not name:
msg = u"PLAY%s" % checkmsg
else:
msg = u"PLAY [%s]%s" % (name, checkmsg)
self._play = play
@ -378,6 +407,9 @@ class CallbackModule(CallbackBase):
self._display.display('\tRUN: %s' % self._dump_results(stats.custom['_run'], indent=1).replace('\n', ''))
self._display.display("", screen_only=True)
if context.CLIARGS['check'] and self.check_mode_markers:
self._display.banner("DRY RUN")
def v2_playbook_on_start(self, playbook):
if self._display.verbosity > 1:
from os.path import basename
@ -394,6 +426,9 @@ class CallbackModule(CallbackBase):
if val:
self._display.display('%s: %s' % (argument, val), color=C.COLOR_VERBOSE, screen_only=True)
if context.CLIARGS['check'] and self.check_mode_markers:
self._display.banner("DRY RUN")
def v2_runner_retry(self, result):
task_name = result.task_name or result._task
msg = "FAILED - RETRYING: %s (%d retries left)." % (task_name, result._result['retries'] - result._result['attempts'])

View file

@ -0,0 +1,2 @@
+ ansible-playbook -i inventory --check test_dryrun.yml
++ set +x

View file

@ -0,0 +1,78 @@
DRY RUN ************************************************************************
PLAY [A common play] [CHECK MODE] **********************************************
TASK [debug] [CHECK MODE] ******************************************************
ok: [testhost] => {
"msg": "ansible_check_mode: True"
}
TASK [Command] [CHECK MODE] ****************************************************
skipping: [testhost]
TASK [Command with check_mode: false] ******************************************
changed: [testhost]
TASK [Command with check_mode: true] [CHECK MODE] ******************************
skipping: [testhost]
PLAY [Play with check_mode: true (runs always in check_mode)] [CHECK MODE] *****
TASK [debug] [CHECK MODE] ******************************************************
ok: [testhost] => {
"msg": "ansible_check_mode: True"
}
TASK [Command] [CHECK MODE] ****************************************************
skipping: [testhost]
TASK [Command with check_mode: false] ******************************************
changed: [testhost]
TASK [Command with check_mode: true] [CHECK MODE] ******************************
skipping: [testhost]
PLAY [Play with check_mode: false (runs always in wet mode)] *******************
TASK [debug] *******************************************************************
ok: [testhost] => {
"msg": "ansible_check_mode: True"
}
TASK [Command] *****************************************************************
changed: [testhost]
TASK [Command with check_mode: false] ******************************************
changed: [testhost]
TASK [Command with check_mode: true] [CHECK MODE] ******************************
skipping: [testhost]
PLAY [Play with a block with check_mode: true] [CHECK MODE] ********************
TASK [Command] [CHECK MODE] ****************************************************
skipping: [testhost]
TASK [Command with check_mode: false] ******************************************
changed: [testhost]
TASK [Command with check_mode: true] [CHECK MODE] ******************************
skipping: [testhost]
PLAY [Play with a block with check_mode: false] [CHECK MODE] *******************
TASK [Command] *****************************************************************
changed: [testhost]
TASK [Command with check_mode: false] ******************************************
changed: [testhost]
TASK [Command with check_mode: true] [CHECK MODE] ******************************
skipping: [testhost]
PLAY RECAP *********************************************************************
testhost : ok=10 changed=7 unreachable=0 failed=0 skipped=8 rescued=0 ignored=0
DRY RUN ************************************************************************

View file

@ -0,0 +1,2 @@
+ ansible-playbook -i inventory test_dryrun.yml
++ set +x

View file

@ -0,0 +1,74 @@
PLAY [A common play] ***********************************************************
TASK [debug] *******************************************************************
ok: [testhost] => {
"msg": "ansible_check_mode: False"
}
TASK [Command] *****************************************************************
changed: [testhost]
TASK [Command with check_mode: false] ******************************************
changed: [testhost]
TASK [Command with check_mode: true] [CHECK MODE] ******************************
skipping: [testhost]
PLAY [Play with check_mode: true (runs always in check_mode)] [CHECK MODE] *****
TASK [debug] [CHECK MODE] ******************************************************
ok: [testhost] => {
"msg": "ansible_check_mode: False"
}
TASK [Command] [CHECK MODE] ****************************************************
skipping: [testhost]
TASK [Command with check_mode: false] ******************************************
changed: [testhost]
TASK [Command with check_mode: true] [CHECK MODE] ******************************
skipping: [testhost]
PLAY [Play with check_mode: false (runs always in wet mode)] *******************
TASK [debug] *******************************************************************
ok: [testhost] => {
"msg": "ansible_check_mode: False"
}
TASK [Command] *****************************************************************
changed: [testhost]
TASK [Command with check_mode: false] ******************************************
changed: [testhost]
TASK [Command with check_mode: true] [CHECK MODE] ******************************
skipping: [testhost]
PLAY [Play with a block with check_mode: true] *********************************
TASK [Command] [CHECK MODE] ****************************************************
skipping: [testhost]
TASK [Command with check_mode: false] ******************************************
changed: [testhost]
TASK [Command with check_mode: true] [CHECK MODE] ******************************
skipping: [testhost]
PLAY [Play with a block with check_mode: false] ********************************
TASK [Command] *****************************************************************
changed: [testhost]
TASK [Command with check_mode: false] ******************************************
changed: [testhost]
TASK [Command with check_mode: true] [CHECK MODE] ******************************
skipping: [testhost]
PLAY RECAP *********************************************************************
testhost : ok=11 changed=8 unreachable=0 failed=0 skipped=7 rescued=0 ignored=0

View file

@ -0,0 +1,2 @@
+ ansible-playbook -i inventory --check test_dryrun.yml
++ set +x

View file

@ -0,0 +1,74 @@
PLAY [A common play] ***********************************************************
TASK [debug] *******************************************************************
ok: [testhost] => {
"msg": "ansible_check_mode: True"
}
TASK [Command] *****************************************************************
skipping: [testhost]
TASK [Command with check_mode: false] ******************************************
changed: [testhost]
TASK [Command with check_mode: true] *******************************************
skipping: [testhost]
PLAY [Play with check_mode: true (runs always in check_mode)] ******************
TASK [debug] *******************************************************************
ok: [testhost] => {
"msg": "ansible_check_mode: True"
}
TASK [Command] *****************************************************************
skipping: [testhost]
TASK [Command with check_mode: false] ******************************************
changed: [testhost]
TASK [Command with check_mode: true] *******************************************
skipping: [testhost]
PLAY [Play with check_mode: false (runs always in wet mode)] *******************
TASK [debug] *******************************************************************
ok: [testhost] => {
"msg": "ansible_check_mode: True"
}
TASK [Command] *****************************************************************
changed: [testhost]
TASK [Command with check_mode: false] ******************************************
changed: [testhost]
TASK [Command with check_mode: true] *******************************************
skipping: [testhost]
PLAY [Play with a block with check_mode: true] *********************************
TASK [Command] *****************************************************************
skipping: [testhost]
TASK [Command with check_mode: false] ******************************************
changed: [testhost]
TASK [Command with check_mode: true] *******************************************
skipping: [testhost]
PLAY [Play with a block with check_mode: false] ********************************
TASK [Command] *****************************************************************
changed: [testhost]
TASK [Command with check_mode: false] ******************************************
changed: [testhost]
TASK [Command with check_mode: true] *******************************************
skipping: [testhost]
PLAY RECAP *********************************************************************
testhost : ok=10 changed=7 unreachable=0 failed=0 skipped=8 rescued=0 ignored=0

View file

@ -0,0 +1,2 @@
+ ansible-playbook -i inventory test_dryrun.yml
++ set +x

View file

@ -0,0 +1,74 @@
PLAY [A common play] ***********************************************************
TASK [debug] *******************************************************************
ok: [testhost] => {
"msg": "ansible_check_mode: False"
}
TASK [Command] *****************************************************************
changed: [testhost]
TASK [Command with check_mode: false] ******************************************
changed: [testhost]
TASK [Command with check_mode: true] *******************************************
skipping: [testhost]
PLAY [Play with check_mode: true (runs always in check_mode)] ******************
TASK [debug] *******************************************************************
ok: [testhost] => {
"msg": "ansible_check_mode: False"
}
TASK [Command] *****************************************************************
skipping: [testhost]
TASK [Command with check_mode: false] ******************************************
changed: [testhost]
TASK [Command with check_mode: true] *******************************************
skipping: [testhost]
PLAY [Play with check_mode: false (runs always in wet mode)] *******************
TASK [debug] *******************************************************************
ok: [testhost] => {
"msg": "ansible_check_mode: False"
}
TASK [Command] *****************************************************************
changed: [testhost]
TASK [Command with check_mode: false] ******************************************
changed: [testhost]
TASK [Command with check_mode: true] *******************************************
skipping: [testhost]
PLAY [Play with a block with check_mode: true] *********************************
TASK [Command] *****************************************************************
skipping: [testhost]
TASK [Command with check_mode: false] ******************************************
changed: [testhost]
TASK [Command with check_mode: true] *******************************************
skipping: [testhost]
PLAY [Play with a block with check_mode: false] ********************************
TASK [Command] *****************************************************************
changed: [testhost]
TASK [Command with check_mode: false] ******************************************
changed: [testhost]
TASK [Command with check_mode: true] *******************************************
skipping: [testhost]
PLAY RECAP *********************************************************************
testhost : ok=11 changed=8 unreachable=0 failed=0 skipped=7 rescued=0 ignored=0

View file

@ -28,6 +28,26 @@ run_test() {
diff -u "${ORIGFILE}.${testname}.stderr" "${OUTFILE}.${testname}.stderr" || diff_failure
}
run_test_dryrun() {
local testname=$1
# optional, pass --check to run a dry run
local chk=${2:-}
# This needed to satisfy shellcheck that can not accept unquoted variable
cmd="ansible-playbook -i inventory ${chk} test_dryrun.yml"
# The shenanigans with redirection and 'tee' are to capture STDOUT and
# STDERR separately while still displaying both to the console
{ $cmd \
> >(set +x; tee "${OUTFILE}.${testname}.stdout"); } \
2> >(set +x; tee "${OUTFILE}.${testname}.stderr" >&2)
# Scrub deprication warning that shows up in Python 2.6 on CentOS 6
sed -i -e '/RandomPool_DeprecationWarning/d' "${OUTFILE}.${testname}.stderr"
diff -u "${ORIGFILE}.${testname}.stdout" "${OUTFILE}.${testname}.stdout" || diff_failure
diff -u "${ORIGFILE}.${testname}.stderr" "${OUTFILE}.${testname}.stderr" || diff_failure
}
diff_failure() {
if [[ $INIT = 0 ]]; then
echo "FAILURE...diff mismatch!"
@ -91,6 +111,7 @@ export ANSIBLE_NOCOLOR=1
export ANSIBLE_DISPLAY_SKIPPED_HOSTS=1
export ANSIBLE_DISPLAY_OK_HOSTS=1
export ANSIBLE_DISPLAY_FAILED_STDERR=0
export ANSIBLE_CHECK_MODE_MARKERS=0
run_test default
@ -131,3 +152,27 @@ if test "$(grep -c 'UNREACHABLE' "${BASEFILE}.unreachable.stderr")" -ne 1; then
echo "Test failed"
exit 1
fi
## DRY RUN tests
#
# Default settings with dry run tasks
export ANSIBLE_DISPLAY_SKIPPED_HOSTS=1
export ANSIBLE_DISPLAY_OK_HOSTS=1
export ANSIBLE_DISPLAY_FAILED_STDERR=1
# Enable Check mode markers
export ANSIBLE_CHECK_MODE_MARKERS=1
# Test the wet run with check markers
run_test_dryrun check_markers_wet
# Test the dry run with check markers
run_test_dryrun check_markers_dry --check
# Disable Check mode markers
export ANSIBLE_CHECK_MODE_MARKERS=0
# Test the wet run without check markers
run_test_dryrun check_nomarkers_wet
# Test the dry run without check markers
run_test_dryrun check_nomarkers_dry --check

View file

@ -0,0 +1,93 @@
---
- name: A common play
hosts: testhost
gather_facts: no
tasks:
- debug:
msg: 'ansible_check_mode: {{ansible_check_mode}}'
- name: Command
command: ls -l
- name: "Command with check_mode: false"
command: ls -l
check_mode: false
- name: "Command with check_mode: true"
command: ls -l
check_mode: true
- name: "Play with check_mode: true (runs always in check_mode)"
hosts: testhost
gather_facts: no
check_mode: true
tasks:
- debug:
msg: 'ansible_check_mode: {{ansible_check_mode}}'
- name: Command
command: ls -l
- name: "Command with check_mode: false"
command: ls -l
check_mode: false
- name: "Command with check_mode: true"
command: ls -l
check_mode: true
- name: "Play with check_mode: false (runs always in wet mode)"
hosts: testhost
gather_facts: no
check_mode: false
tasks:
- debug:
msg: 'ansible_check_mode: {{ansible_check_mode}}'
- name: Command
command: ls -l
- name: "Command with check_mode: false"
command: ls -l
check_mode: false
- name: "Command with check_mode: true"
command: ls -l
check_mode: true
- name: "Play with a block with check_mode: true"
hosts: testhost
gather_facts: no
tasks:
- block:
- name: Command
command: ls -l
- name: "Command with check_mode: false"
command: ls -l
check_mode: false
- name: "Command with check_mode: true"
command: ls -l
check_mode: true
check_mode: true
- name: "Play with a block with check_mode: false"
hosts: testhost
gather_facts: no
tasks:
- block:
- name: Command
command: ls -l
- name: "Command with check_mode: false"
command: ls -l
check_mode: false
- name: "Command with check_mode: true"
command: ls -l
check_mode: true
check_mode: false