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:
parent
a5d409a8b2
commit
3c8838f0f7
12 changed files with 492 additions and 9 deletions
2
changelogs/fragments/check_mode_markers.yml
Normal file
2
changelogs/fragments/check_mode_markers.yml
Normal 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.
|
|
@ -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'])
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
+ ansible-playbook -i inventory --check test_dryrun.yml
|
||||
++ set +x
|
|
@ -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 ************************************************************************
|
|
@ -0,0 +1,2 @@
|
|||
+ ansible-playbook -i inventory test_dryrun.yml
|
||||
++ set +x
|
|
@ -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
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
+ ansible-playbook -i inventory --check test_dryrun.yml
|
||||
++ set +x
|
|
@ -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
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
+ ansible-playbook -i inventory test_dryrun.yml
|
||||
++ set +x
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
93
test/integration/targets/callback_default/test_dryrun.yml
Normal file
93
test/integration/targets/callback_default/test_dryrun.yml
Normal 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
|
Loading…
Reference in a new issue