diff --git a/lib/ansible/module_utils/basic.py b/lib/ansible/module_utils/basic.py index 19c112577e..1fafd85186 100644 --- a/lib/ansible/module_utils/basic.py +++ b/lib/ansible/module_utils/basic.py @@ -781,6 +781,7 @@ class AnsibleModule(object): self.run_command_environ_update = {} self._warnings = [] self._deprecations = [] + self._clean = {} self.aliases = {} self._legal_inputs = ['_ansible_check_mode', '_ansible_no_log', '_ansible_debug', '_ansible_diff', '_ansible_verbosity', @@ -2538,6 +2539,41 @@ class AnsibleModule(object): return data + def _clean_args(self, args): + + if not self._clean: + # create a printable version of the command for use in reporting later, + # which strips out things like passwords from the args list + to_clean_args = args + if PY2: + if isinstance(args, text_type): + to_clean_args = to_bytes(args) + else: + if isinstance(args, binary_type): + to_clean_args = to_text(args) + if isinstance(args, (text_type, binary_type)): + to_clean_args = shlex.split(to_clean_args) + + clean_args = [] + is_passwd = False + for arg in (to_native(a) for a in to_clean_args): + if is_passwd: + is_passwd = False + clean_args.append('********') + continue + if PASSWD_ARG_RE.match(arg): + sep_idx = arg.find('=') + if sep_idx > -1: + clean_args.append('%s=********' % arg[:sep_idx]) + continue + else: + is_passwd = True + arg = heuristic_log_sanitize(arg, self.no_log_values) + clean_args.append(arg) + self._clean = ' '.join(shlex_quote(arg) for arg in clean_args) + + return self._clean + def run_command(self, args, check_rc=False, close_fds=True, executable=None, data=None, binary_data=False, path_prefix=None, cwd=None, use_unsafe_shell=False, prompt_regex=None, environ_update=None, umask=None, encoding='utf-8', errors='surrogate_or_strict'): ''' @@ -2583,6 +2619,8 @@ class AnsibleModule(object): according to the encoding and errors parameters. If you want byte strings on python3, use encoding=None to turn decoding to text off. ''' + # used by clean args later on + self._clean = None if not isinstance(args, (list, binary_type, text_type)): msg = "Argument 'args' to run_command must be list or string" @@ -2661,37 +2699,6 @@ class AnsibleModule(object): if not os.environ['PYTHONPATH']: del os.environ['PYTHONPATH'] - # create a printable version of the command for use - # in reporting later, which strips out things like - # passwords from the args list - to_clean_args = args - if PY2: - if isinstance(args, text_type): - to_clean_args = to_bytes(args) - else: - if isinstance(args, binary_type): - to_clean_args = to_text(args) - if isinstance(args, (text_type, binary_type)): - to_clean_args = shlex.split(to_clean_args) - - clean_args = [] - is_passwd = False - for arg in (to_native(a) for a in to_clean_args): - if is_passwd: - is_passwd = False - clean_args.append('********') - continue - if PASSWD_ARG_RE.match(arg): - sep_idx = arg.find('=') - if sep_idx > -1: - clean_args.append('%s=********' % arg[:sep_idx]) - continue - else: - is_passwd = True - arg = heuristic_log_sanitize(arg, self.no_log_values) - clean_args.append(arg) - clean_args = ' '.join(shlex_quote(arg) for arg in clean_args) - if data: st_in = subprocess.PIPE @@ -2723,7 +2730,7 @@ class AnsibleModule(object): try: if self._debug: - self.log('Executing: ' + clean_args) + self.log('Executing: ' + self._clean_args(args)) cmd = subprocess.Popen(args, **kwargs) # the communication logic here is essentially taken from that @@ -2772,11 +2779,11 @@ class AnsibleModule(object): rc = cmd.returncode except (OSError, IOError) as e: - self.log("Error Executing CMD:%s Exception:%s" % (clean_args, to_native(e))) - self.fail_json(rc=e.errno, msg=to_native(e), cmd=clean_args) + self.log("Error Executing CMD:%s Exception:%s" % (self._clean_args(args), to_native(e))) + self.fail_json(rc=e.errno, msg=to_native(e), cmd=self._clean_args(args)) except Exception as e: - self.log("Error Executing CMD:%s Exception:%s" % (clean_args, to_native(traceback.format_exc()))) - self.fail_json(rc=257, msg=to_native(e), exception=traceback.format_exc(), cmd=clean_args) + self.log("Error Executing CMD:%s Exception:%s" % (self._clean_args(args), to_native(traceback.format_exc()))) + self.fail_json(rc=257, msg=to_native(e), exception=traceback.format_exc(), cmd=self._clean_args(args)) # Restore env settings for key, val in old_env_vals.items(): @@ -2790,7 +2797,7 @@ class AnsibleModule(object): if rc != 0 and check_rc: msg = heuristic_log_sanitize(stderr.rstrip(), self.no_log_values) - self.fail_json(cmd=clean_args, rc=rc, stdout=stdout, stderr=stderr, msg=msg) + self.fail_json(cmd=self._clean_args(args), rc=rc, stdout=stdout, stderr=stderr, msg=msg) # reset the pwd os.chdir(prev_dir) @@ -2798,6 +2805,7 @@ class AnsibleModule(object): if encoding is not None: return (rc, to_native(stdout, encoding=encoding, errors=errors), to_native(stderr, encoding=encoding, errors=errors)) + return (rc, stdout, stderr) def append_to_file(self, filename, str):