Co-authored-by: Sam Doran <sdoran@redhat.com>
Sam Doran authored on 2019/10/03 07:04:08... | ... |
@@ -1665,6 +1665,34 @@ class AnsibleModule(object): |
1665 | 1665 |
if no_log_object: |
1666 | 1666 |
self.no_log_values.update(return_values(no_log_object)) |
1667 | 1667 |
|
1668 |
+ # Get no_log values from suboptions |
|
1669 |
+ sub_argument_spec = arg_opts.get('options') |
|
1670 |
+ if sub_argument_spec is not None: |
|
1671 |
+ wanted_type = arg_opts.get('type') |
|
1672 |
+ sub_parameters = param.get(arg_name) |
|
1673 |
+ |
|
1674 |
+ if sub_parameters is not None: |
|
1675 |
+ if wanted_type == 'dict' or (wanted_type == 'list' and arg_opts.get('elements', '') == 'dict'): |
|
1676 |
+ # Sub parameters can be a dict or list of dicts. Ensure parameters are always a list. |
|
1677 |
+ if not isinstance(sub_parameters, list): |
|
1678 |
+ sub_parameters = [sub_parameters] |
|
1679 |
+ |
|
1680 |
+ for sub_param in sub_parameters: |
|
1681 |
+ # Validate dict fields in case they came in as strings |
|
1682 |
+ |
|
1683 |
+ if isinstance(sub_param, string_types): |
|
1684 |
+ sub_param = self._check_type_dict(sub_param) |
|
1685 |
+ |
|
1686 |
+ try: |
|
1687 |
+ if not isinstance(sub_param, Mapping): |
|
1688 |
+ raise TypeError("Value '{1}' in the sub parameter field '{0}' must by a {2}, " |
|
1689 |
+ "not '{1.__class__.__name__}'".format(arg_name, sub_param, wanted_type)) |
|
1690 |
+ except TypeError as te: |
|
1691 |
+ self.fail_json(msg="Failure when processing no_log parameters. Module invocation will be hidden. " |
|
1692 |
+ "%s" % to_native(te), invocation={'module_args': 'HIDDEN DUE TO FAILURE'}) |
|
1693 |
+ |
|
1694 |
+ self._handle_no_log_values(sub_argument_spec, sub_param) |
|
1695 |
+ |
|
1668 | 1696 |
if arg_opts.get('removed_in_version') is not None and arg_name in param: |
1669 | 1697 |
self._deprecations.append({ |
1670 | 1698 |
'msg': "Param '%s' is deprecated. See the module docs for more information" % arg_name, |
... | ... |
@@ -2032,7 +2060,6 @@ class AnsibleModule(object): |
2032 | 2032 |
self._set_fallbacks(spec, param) |
2033 | 2033 |
options_aliases = self._handle_aliases(spec, param) |
2034 | 2034 |
|
2035 |
- self._handle_no_log_values(spec, param) |
|
2036 | 2035 |
options_legal_inputs = list(spec.keys()) + list(options_aliases.keys()) |
2037 | 2036 |
|
2038 | 2037 |
self._check_arguments(self.check_invalid_arguments, spec, param, options_legal_inputs) |
2039 | 2038 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,45 @@ |
0 |
+#!/usr/bin/python |
|
1 |
+# -*- coding: utf-8 -*- |
|
2 |
+# Copyright (c) 2019 Ansible Project |
|
3 |
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) |
|
4 |
+ |
|
5 |
+from __future__ import absolute_import, division, print_function |
|
6 |
+__metaclass__ = type |
|
7 |
+ |
|
8 |
+from ansible.module_utils.basic import AnsibleModule |
|
9 |
+ |
|
10 |
+ |
|
11 |
+def main(): |
|
12 |
+ module = AnsibleModule( |
|
13 |
+ argument_spec={ |
|
14 |
+ 'state': {}, |
|
15 |
+ 'secret': {'no_log': True}, |
|
16 |
+ 'subopt_dict': { |
|
17 |
+ 'type': 'dict', |
|
18 |
+ 'options': { |
|
19 |
+ 'str_sub_opt1': {'no_log': True}, |
|
20 |
+ 'str_sub_opt2': {}, |
|
21 |
+ 'nested_subopt': { |
|
22 |
+ 'type': 'dict', |
|
23 |
+ 'options': { |
|
24 |
+ 'n_subopt1': {'no_log': True}, |
|
25 |
+ } |
|
26 |
+ } |
|
27 |
+ } |
|
28 |
+ }, |
|
29 |
+ 'subopt_list': { |
|
30 |
+ 'type': 'list', |
|
31 |
+ 'elements': 'dict', |
|
32 |
+ 'options': { |
|
33 |
+ 'subopt1': {'no_log': True}, |
|
34 |
+ 'subopt2': {}, |
|
35 |
+ } |
|
36 |
+ } |
|
37 |
+ |
|
38 |
+ } |
|
39 |
+ ) |
|
40 |
+ module.exit_json(msg='done') |
|
41 |
+ |
|
42 |
+ |
|
43 |
+if __name__ == '__main__': |
|
44 |
+ main() |
53 | 54 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,24 @@ |
0 |
+- name: test no log with suboptions |
|
1 |
+ hosts: testhost |
|
2 |
+ gather_facts: no |
|
3 |
+ |
|
4 |
+ tasks: |
|
5 |
+ - name: Task with suboptions |
|
6 |
+ module: |
|
7 |
+ secret: GLAMOROUS |
|
8 |
+ subopt_dict: |
|
9 |
+ str_sub_opt1: AFTERMATH |
|
10 |
+ str_sub_opt2: otherstring |
|
11 |
+ nested_subopt: |
|
12 |
+ n_subopt1: MANPOWER |
|
13 |
+ |
|
14 |
+ subopt_list: |
|
15 |
+ - subopt1: UNTAPPED |
|
16 |
+ subopt2: thridstring |
|
17 |
+ |
|
18 |
+ - subopt1: CONCERNED |
|
19 |
+ |
|
20 |
+ - name: Task with suboptions as string |
|
21 |
+ module: |
|
22 |
+ secret: MARLIN |
|
23 |
+ subopt_dict: str_sub_opt1=FLICK |
0 | 24 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,45 @@ |
0 |
+- name: test no log with suboptions |
|
1 |
+ hosts: testhost |
|
2 |
+ gather_facts: no |
|
3 |
+ ignore_errors: yes |
|
4 |
+ |
|
5 |
+ tasks: |
|
6 |
+ - name: Task with suboptions and invalid parameter |
|
7 |
+ module: |
|
8 |
+ secret: SUPREME |
|
9 |
+ invalid: param |
|
10 |
+ subopt_dict: |
|
11 |
+ str_sub_opt1: IDIOM |
|
12 |
+ str_sub_opt2: otherstring |
|
13 |
+ nested_subopt: |
|
14 |
+ n_subopt1: MOCKUP |
|
15 |
+ |
|
16 |
+ subopt_list: |
|
17 |
+ - subopt1: EDUCATED |
|
18 |
+ subopt2: thridstring |
|
19 |
+ - subopt1: FOOTREST |
|
20 |
+ |
|
21 |
+ - name: Task with suboptions as string with invalid parameter |
|
22 |
+ module: |
|
23 |
+ secret: FOOTREST |
|
24 |
+ invalid: param |
|
25 |
+ subopt_dict: str_sub_opt1=CRAFTY |
|
26 |
+ |
|
27 |
+ - name: Task with suboptions with dict instead of list |
|
28 |
+ module: |
|
29 |
+ secret: FELINE |
|
30 |
+ subopt_dict: |
|
31 |
+ str_sub_opt1: CRYSTAL |
|
32 |
+ str_sub_opt2: otherstring |
|
33 |
+ nested_subopt: |
|
34 |
+ n_subopt1: EXPECTANT |
|
35 |
+ subopt_list: |
|
36 |
+ foo: bar |
|
37 |
+ |
|
38 |
+ - name: Task with suboptions with incorrect data type |
|
39 |
+ module: |
|
40 |
+ secret: AGROUND |
|
41 |
+ subopt_dict: 9068.21361 |
|
42 |
+ subopt_list: |
|
43 |
+ - subopt1: GOLIATH |
|
44 |
+ - subopt1: FREEFALL |
... | ... |
@@ -13,3 +13,9 @@ set -eux |
13 | 13 |
|
14 | 14 |
# no log disabled, should produce 0 censored |
15 | 15 |
[ "$(ansible-playbook dynamic.yml -i ../../inventory -vvvvv "$@" -e unsafe_show_logs=yes|grep -c 'output has been hidden')" = "0" ] |
16 |
+ |
|
17 |
+# test no log for sub options |
|
18 |
+[ "$(ansible-playbook no_log_suboptions.yml -i ../../inventory -vvvvv "$@" | grep -Ec '(MANPOWER|UNTAPPED|CONCERNED|MARLIN|FLICK)')" = "0" ] |
|
19 |
+ |
|
20 |
+# test invalid data passed to a suboption |
|
21 |
+[ "$(ansible-playbook no_log_suboptions_invalid.yml -i ../../inventory -vvvvv "$@" | grep -Ec '(SUPREME|IDIOM|MOCKUP|EDUCATED|FOOTREST|CRAFTY|FELINE|CRYSTAL|EXPECTANT|AGROUND|GOLIATH|FREEFALL)')" = "0" ] |