adding quiet option to assert (ansible#27124) (#52032)
* adding quiet option to assert (ansible#27124) * adding doc for quiet to assert.py * fixing PEP8 failure * improving example * improving docs * adding changelog fragment * adding . at end of descriptions * removing trailing blank line * adding integration test for assert * fixing CI complaints * disabling gather_facts in quiet.yml test * rerunning to capture skip * cleaning up python 2 vs 3 * following rebase * fixing CI complaints * fixing CI complaints * fixing CI complaints * fixing CI complaints * fixing CI complaints
This commit is contained in:
parent
0e9a79a589
commit
d2bdbadb03
9 changed files with 134 additions and 7 deletions
|
@ -0,0 +1,3 @@
|
||||||
|
minor_changes:
|
||||||
|
- assert - added ``quiet`` option to the ``assert`` module to avoid verbose
|
||||||
|
output (https://github.com/ansible/ansible/issues/27124).
|
|
@ -24,20 +24,26 @@ version_added: "1.5"
|
||||||
options:
|
options:
|
||||||
that:
|
that:
|
||||||
description:
|
description:
|
||||||
- "A string expression of the same form that can be passed to the 'when' statement"
|
- "A string expression of the same form that can be passed to the 'when' statement."
|
||||||
- "Alternatively, a list of string expressions"
|
- "Alternatively, a list of string expressions."
|
||||||
required: true
|
required: true
|
||||||
fail_msg:
|
fail_msg:
|
||||||
version_added: "2.7"
|
version_added: "2.7"
|
||||||
description:
|
description:
|
||||||
- "The customized message used for a failing assertion"
|
- "The customized message used for a failing assertion."
|
||||||
- "This argument was called 'msg' before version 2.7, now it's renamed to 'fail_msg' with alias 'msg'"
|
- "This argument was called 'msg' before version 2.7, now it's renamed to 'fail_msg' with alias 'msg'."
|
||||||
aliases:
|
aliases:
|
||||||
- msg
|
- msg
|
||||||
success_msg:
|
success_msg:
|
||||||
version_added: "2.7"
|
version_added: "2.7"
|
||||||
description:
|
description:
|
||||||
- "The customized message used for a successful assertion"
|
- "The customized message used for a successful assertion."
|
||||||
|
quiet:
|
||||||
|
version_added: "2.8"
|
||||||
|
description:
|
||||||
|
- "Set this to C(true) to avoid verbose output."
|
||||||
|
type: bool
|
||||||
|
default: false
|
||||||
notes:
|
notes:
|
||||||
- This module is also supported for Windows targets.
|
- This module is also supported for Windows targets.
|
||||||
author:
|
author:
|
||||||
|
@ -67,4 +73,11 @@ EXAMPLES = '''
|
||||||
- "my_param <= 100"
|
- "my_param <= 100"
|
||||||
- "my_param >= 0"
|
- "my_param >= 0"
|
||||||
msg: "'my_param' must be between 0 and 100"
|
msg: "'my_param' must be between 0 and 100"
|
||||||
|
|
||||||
|
- name: use quiet to avoid verbose output
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- "my_param <= 100"
|
||||||
|
- "my_param >= 0"
|
||||||
|
quiet: true
|
||||||
'''
|
'''
|
||||||
|
|
|
@ -21,13 +21,14 @@ from ansible.errors import AnsibleError
|
||||||
from ansible.playbook.conditional import Conditional
|
from ansible.playbook.conditional import Conditional
|
||||||
from ansible.plugins.action import ActionBase
|
from ansible.plugins.action import ActionBase
|
||||||
from ansible.module_utils.six import string_types
|
from ansible.module_utils.six import string_types
|
||||||
|
from ansible.module_utils.parsing.convert_bool import boolean
|
||||||
|
|
||||||
|
|
||||||
class ActionModule(ActionBase):
|
class ActionModule(ActionBase):
|
||||||
''' Fail with custom message '''
|
''' Fail with custom message '''
|
||||||
|
|
||||||
TRANSFERS_FILES = False
|
TRANSFERS_FILES = False
|
||||||
_VALID_ARGS = frozenset(('fail_msg', 'msg', 'success_msg', 'that'))
|
_VALID_ARGS = frozenset(('fail_msg', 'msg', 'quiet', 'success_msg', 'that'))
|
||||||
|
|
||||||
def run(self, tmp=None, task_vars=None):
|
def run(self, tmp=None, task_vars=None):
|
||||||
if task_vars is None:
|
if task_vars is None:
|
||||||
|
@ -54,6 +55,8 @@ class ActionModule(ActionBase):
|
||||||
elif not isinstance(success_msg, string_types):
|
elif not isinstance(success_msg, string_types):
|
||||||
raise AnsibleError('Incorrect type for success_msg, expected string and got %s' % type(success_msg))
|
raise AnsibleError('Incorrect type for success_msg, expected string and got %s' % type(success_msg))
|
||||||
|
|
||||||
|
quiet = boolean(self._task.args.get('quiet', False), strict=False)
|
||||||
|
|
||||||
# make sure the 'that' items are a list
|
# make sure the 'that' items are a list
|
||||||
thats = self._task.args['that']
|
thats = self._task.args['that']
|
||||||
if not isinstance(thats, list):
|
if not isinstance(thats, list):
|
||||||
|
@ -65,7 +68,9 @@ class ActionModule(ActionBase):
|
||||||
# by this point, and is not used again, so we don't care about mangling
|
# by this point, and is not used again, so we don't care about mangling
|
||||||
# that value now
|
# that value now
|
||||||
cond = Conditional(loader=self._loader)
|
cond = Conditional(loader=self._loader)
|
||||||
|
if not quiet:
|
||||||
result['_ansible_verbose_always'] = True
|
result['_ansible_verbose_always'] = True
|
||||||
|
|
||||||
for that in thats:
|
for that in thats:
|
||||||
cond.when = [that]
|
cond.when = [that]
|
||||||
test_result = cond.evaluate_conditional(templar=self._templar, all_vars=task_vars)
|
test_result = cond.evaluate_conditional(templar=self._templar, all_vars=task_vars)
|
||||||
|
|
1
test/integration/targets/assert/aliases
Normal file
1
test/integration/targets/assert/aliases
Normal file
|
@ -0,0 +1 @@
|
||||||
|
shippable/posix/group3
|
|
@ -0,0 +1,2 @@
|
||||||
|
+ ansible-playbook -i localhost, -c local quiet.yml
|
||||||
|
++ set +x
|
|
@ -0,0 +1,16 @@
|
||||||
|
|
||||||
|
PLAY [localhost] ***************************************************************
|
||||||
|
|
||||||
|
TASK [assert] ******************************************************************
|
||||||
|
ok: [localhost] => (item=item_A)
|
||||||
|
|
||||||
|
TASK [assert] ******************************************************************
|
||||||
|
ok: [localhost] => (item=item_A) => {
|
||||||
|
"changed": false,
|
||||||
|
"item": "item_A",
|
||||||
|
"msg": "All assertions passed"
|
||||||
|
}
|
||||||
|
|
||||||
|
PLAY RECAP *********************************************************************
|
||||||
|
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
|
||||||
|
|
3
test/integration/targets/assert/inventory
Normal file
3
test/integration/targets/assert/inventory
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
[all]
|
||||||
|
localhost
|
||||||
|
|
16
test/integration/targets/assert/quiet.yml
Normal file
16
test/integration/targets/assert/quiet.yml
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
---
|
||||||
|
- hosts: localhost
|
||||||
|
gather_facts: False
|
||||||
|
vars:
|
||||||
|
item_A: yes
|
||||||
|
tasks:
|
||||||
|
- assert:
|
||||||
|
that: "{{ item }} is defined"
|
||||||
|
quiet: True
|
||||||
|
with_items:
|
||||||
|
- item_A
|
||||||
|
- assert:
|
||||||
|
that: "{{ item }} is defined"
|
||||||
|
quiet: False
|
||||||
|
with_items:
|
||||||
|
- item_A
|
68
test/integration/targets/assert/runme.sh
Executable file
68
test/integration/targets/assert/runme.sh
Executable file
|
@ -0,0 +1,68 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# This test compares "known good" output with various settings against output
|
||||||
|
# with the current code. It's brittle by nature, but this is probably the
|
||||||
|
# "best" approach possible.
|
||||||
|
#
|
||||||
|
# Notes:
|
||||||
|
# * options passed to this script (such as -v) are ignored, as they would change
|
||||||
|
# the output and break the test
|
||||||
|
# * the number of asterisks after a "banner" differs is forced to 79 by
|
||||||
|
# redirecting stdin from /dev/null
|
||||||
|
|
||||||
|
set -eux
|
||||||
|
|
||||||
|
run_test() {
|
||||||
|
# testname is playbook name
|
||||||
|
local testname=$1
|
||||||
|
|
||||||
|
# The shenanigans with redirection and 'tee' are to capture STDOUT and
|
||||||
|
# STDERR separately while still displaying both to the console
|
||||||
|
{ ansible-playbook -i 'localhost,' -c local "${testname}.yml" \
|
||||||
|
> >(set +x; tee "${OUTFILE}.${testname}.stdout"); } \
|
||||||
|
2> >(set +x; tee "${OUTFILE}.${testname}.stderr" >&2) 0</dev/null
|
||||||
|
|
||||||
|
perl -pi -e 's/ *$//s' "${OUTFILE}.${testname}.stdout"
|
||||||
|
perl -pi -e 's/ *$//s' "${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!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
if [[ $INIT = 0 ]]; then
|
||||||
|
rm -f "${OUTFILE}."*
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
BASEFILE=assert_quiet.out
|
||||||
|
|
||||||
|
ORIGFILE="${BASEFILE}"
|
||||||
|
OUTFILE="${BASEFILE}.new"
|
||||||
|
|
||||||
|
trap 'cleanup' EXIT
|
||||||
|
|
||||||
|
# The --init flag will (re)generate the "good" output files used by the tests
|
||||||
|
INIT=0
|
||||||
|
if [[ ${1:-} == "--init" ]]; then
|
||||||
|
shift
|
||||||
|
OUTFILE=$ORIGFILE
|
||||||
|
INIT=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Force the 'default' callback plugin
|
||||||
|
export ANSIBLE_STDOUT_CALLBACK=default
|
||||||
|
# Disable color in output for consistency
|
||||||
|
export ANSIBLE_FORCE_COLOR=0
|
||||||
|
export ANSIBLE_NOCOLOR=1
|
||||||
|
# Disable retry files
|
||||||
|
export ANSIBLE_RETRY_FILES_ENABLED=0
|
||||||
|
|
||||||
|
run_test quiet
|
Loading…
Reference in a new issue