def _parse_returned_data(self, res): try: filtered_output, warnings = _filter_non_json_lines(res.get('stdout', u'')) for w in warnings: display.warning(w) data = json.loads(filtered_output) if 'ansible_facts' in data and isinstance(data['ansible_facts'], dict): data['ansible_facts'] = wrap_var(data['ansible_facts']) data['_ansible_parsed'] = True except ValueError: # not valid json, lets try to capture error data = dict(failed=True, _ansible_parsed=False) data['module_stdout'] = res.get('stdout', u'') if 'stderr' in res: data['module_stderr'] = res['stderr'] if res['stderr'].startswith(u'Traceback'): data['exception'] = res['stderr'] # The default data['msg'] = "MODULE FAILURE" # try to figure out if we are missing interpreter if self._used_interpreter is not None: match = '%s: No such file or directory' % self._used_interpreter.lstrip('!#') if match in data['module_stderr'] or match in data['module_stdout']: data['msg'] = "The module failed to execute correctly, you probably need to set the interpreter." # always append hint data['msg'] += '\nSee stdout/stderr for the exact error' if 'rc' in res: data['rc'] = res['rc'] return data
def _parse_returned_data(self, res): try: filtered_output, warnings = _filter_non_json_lines( res.get('stdout', u'')) for w in warnings: display.warning(w) data = json.loads(filtered_output) if 'ansible_facts' in data and isinstance(data['ansible_facts'], dict): self._clean_returned_data(data['ansible_facts']) data['ansible_facts'] = wrap_var(data['ansible_facts']) data['_ansible_parsed'] = True except ValueError: # not valid json, lets try to capture error data = dict(failed=True, _ansible_parsed=False) data['msg'] = "MODULE FAILURE" data['module_stdout'] = res.get('stdout', u'') if 'stderr' in res: data['module_stderr'] = res['stderr'] if res['stderr'].startswith(u'Traceback'): data['exception'] = res['stderr'] if 'rc' in res: data['rc'] = res['rc'] return data
def test_trailing_junk(self): for i in self.all_inputs: for j in self.junk: filtered, warnings = _filter_non_json_lines(i + "\n" + j) self.assertEqual(filtered, i) self.assertEqual(warnings, [ u"Module invocation had junk after the JSON data: %s" % j.strip() ])
def _parse_returned_data(self, res): try: filtered_output, warnings = _filter_non_json_lines( res.get('stdout', u'')) for w in warnings: display.warning(w) data = json.loads(filtered_output) data['_ansible_parsed'] = True if 'ansible_facts' in data and isinstance(data['ansible_facts'], dict): remove_keys = set() fact_keys = set(data['ansible_facts'].keys()) # first we add all of our magic variable names to the set of # keys we want to remove from facts for magic_var in MAGIC_VARIABLE_MAPPING: remove_keys.update( fact_keys.intersection( MAGIC_VARIABLE_MAPPING[magic_var])) # next we remove any connection plugin specific vars for conn_path in self._shared_loader_obj.connection_loader.all( path_only=True): try: conn_name = os.path.splitext( os.path.basename(conn_path))[0] re_key = re.compile('^ansible_%s_' % conn_name) for fact_key in fact_keys: if re_key.match(fact_key): remove_keys.add(fact_key) except AttributeError: pass # remove some KNOWN keys for hard in ['ansible_rsync_path', 'ansible_playbook_python']: if hard in fact_keys: remove_keys.add(hard) # finally, we search for interpreter keys to remove re_interp = re.compile('^ansible_.*_interpreter$') for fact_key in fact_keys: if re_interp.match(fact_key): remove_keys.add(fact_key) # then we remove them (except for ssh host keys) for r_key in remove_keys: if not r_key.startswith('ansible_ssh_host_key_'): del data['ansible_facts'][r_key] except ValueError: # not valid json, lets try to capture error data = dict(failed=True, _ansible_parsed=False) data['msg'] = "MODULE FAILURE" data['module_stdout'] = res.get('stdout', u'') if 'stderr' in res: data['module_stderr'] = res['stderr'] if res['stderr'].startswith(u'Traceback'): data['exception'] = res['stderr'] if 'rc' in res: data['rc'] = res['rc'] return data
def test_leading_and_trailing_junk(self): for i in self.all_inputs: for j in self.junk: filtered, warnings = _filter_non_json_lines("\n".join( [j, i, j])) self.assertEquals(filtered, i) self.assertEquals(warnings, [ u"Module invocation had junk after the JSON data: %s" % j.strip() ])
def _parse_returned_data(self, res): try: filtered_output, warnings = _filter_non_json_lines(res.get('stdout', u'')) for w in warnings: display.warning(w) data = json.loads(filtered_output) data['_ansible_parsed'] = True if 'ansible_facts' in data and isinstance(data['ansible_facts'], dict): remove_keys = set() fact_keys = set(data['ansible_facts'].keys()) # first we add all of our magic variable names to the set of # keys we want to remove from facts for magic_var in MAGIC_VARIABLE_MAPPING: remove_keys.update(fact_keys.intersection(MAGIC_VARIABLE_MAPPING[magic_var])) # next we remove any connection plugin specific vars for conn_path in self._shared_loader_obj.connection_loader.all(path_only=True): try: conn_name = os.path.splitext(os.path.basename(conn_path))[0] re_key = re.compile('^ansible_%s_' % conn_name) for fact_key in fact_keys: if re_key.match(fact_key): remove_keys.add(fact_key) except AttributeError: pass # remove some KNOWN keys for hard in ['ansible_rsync_path', 'ansible_playbook_python']: if hard in fact_keys: remove_keys.add(hard) # finally, we search for interpreter keys to remove re_interp = re.compile('^ansible_.*_interpreter$') for fact_key in fact_keys: if re_interp.match(fact_key): remove_keys.add(fact_key) # then we remove them (except for ssh host keys) for r_key in remove_keys: if not r_key.startswith('ansible_ssh_host_key_'): del data['ansible_facts'][r_key] except ValueError: # not valid json, lets try to capture error data = dict(failed=True, _ansible_parsed=False) data['msg'] = "MODULE FAILURE" data['module_stdout'] = res.get('stdout', u'') if 'stderr' in res: data['module_stderr'] = res['stderr'] if res['stderr'].startswith(u'Traceback'): data['exception'] = res['stderr'] return data
def _parse_returned_data(self, res): try: filtered_output, warnings = _filter_non_json_lines(res.get('stdout', u'')) for w in warnings: display.warning(w) data = json.loads(filtered_output) if 'ansible_facts' in data and isinstance(data['ansible_facts'], dict): data['ansible_facts'] = wrap_var(data['ansible_facts']) data['_ansible_parsed'] = True except ValueError: # not valid json, lets try to capture error data = dict(failed=True, _ansible_parsed=False) data['msg'] = "MODULE FAILURE" data['module_stdout'] = res.get('stdout', u'') if 'stderr' in res: data['module_stderr'] = res['stderr'] if res['stderr'].startswith(u'Traceback'): data['exception'] = res['stderr'] if 'rc' in res: data['rc'] = res['rc'] return data
def test_leading_junk(self): for i in self.all_inputs: for j in self.junk: filtered, warnings = _filter_non_json_lines(j + "\n" + i) self.assertEqual(filtered, i) self.assertEqual(warnings, [])
def test_just_json(self): for i in self.all_inputs: filtered, warnings = _filter_non_json_lines(i) self.assertEqual(filtered, i) self.assertEqual(warnings, [])
def _winrm_exec(self, command, args=(), from_exec=False, stdin_iterator=None): if not self.protocol: self.protocol = self._winrm_connect() self._connected = True if from_exec: display.vvvvv("WINRM EXEC %r %r" % (command, args), host=self._winrm_host) else: display.vvvvvv("WINRM EXEC %r %r" % (command, args), host=self._winrm_host) command_id = None try: stdin_push_failed = False command_id = self.protocol.run_command(self.shell_id, to_bytes(command), map(to_bytes, args), console_mode_stdin=(stdin_iterator is None)) try: if stdin_iterator: for (data, is_last) in stdin_iterator: self._winrm_send_input(self.protocol, self.shell_id, command_id, data, eof=is_last) except Exception as ex: display.warning("ERROR DURING WINRM SEND INPUT - attempting to recover: %s %s" % (type(ex).__name__, to_text(ex))) display.debug(traceback.format_exc()) stdin_push_failed = True # NB: this can hang if the receiver is still running (eg, network failed a Send request but the server's still happy). # FUTURE: Consider adding pywinrm status check/abort operations to see if the target is still running after a failure. resptuple = self.protocol.get_command_output(self.shell_id, command_id) # ensure stdout/stderr are text for py3 # FUTURE: this should probably be done internally by pywinrm response = Response(tuple(to_text(v) if isinstance(v, binary_type) else v for v in resptuple)) # TODO: check result from response and set stdin_push_failed if we have nonzero if from_exec: display.vvvvv('WINRM RESULT %r' % to_text(response), host=self._winrm_host) else: display.vvvvvv('WINRM RESULT %r' % to_text(response), host=self._winrm_host) display.vvvvvv('WINRM STDOUT %s' % to_text(response.std_out), host=self._winrm_host) display.vvvvvv('WINRM STDERR %s' % to_text(response.std_err), host=self._winrm_host) if stdin_push_failed: # There are cases where the stdin input failed but the WinRM service still processed it. We attempt to # see if stdout contains a valid json return value so we can ignore this error try: filtered_output, dummy = _filter_non_json_lines(response.std_out) json.loads(filtered_output) except ValueError: # stdout does not contain a return response, stdin input was a fatal error stderr = to_bytes(response.std_err, encoding='utf-8') if stderr.startswith(b"#< CLIXML"): stderr = _parse_clixml(stderr) raise AnsibleError('winrm send_input failed; \nstdout: %s\nstderr %s' % (to_native(response.std_out), to_native(stderr))) return response except requests.exceptions.Timeout as exc: raise AnsibleConnectionFailure('winrm connection error: %s' % to_native(exc)) finally: if command_id: self.protocol.cleanup_command(self.shell_id, command_id)
def test_unparsable_filter_non_json_lines(self): for i in self.unparsable_cases: self.assertRaises(ValueError, lambda data: _filter_non_json_lines(data), data=i)
def test_unparsable_filter_non_json_lines(self): for i in self.unparsable_cases: self.assertRaises(ValueError, lambda data: _filter_non_json_lines(data), data=i )
def test_leading_and_trailing_junk(self): for i in self.all_inputs: for j in self.junk: filtered, warnings = _filter_non_json_lines("\n".join([j, i, j])) self.assertEquals(filtered, i) self.assertEquals(warnings, [u"Module invocation had junk after the JSON data: %s" % j.strip()])
def test_leading_junk(self): for i in self.all_inputs: for j in self.junk: filtered, warnings = _filter_non_json_lines(j + "\n" + i) self.assertEquals(filtered, i) self.assertEquals(warnings, [])
def test_just_json(self): for i in self.all_inputs: filtered, warnings = _filter_non_json_lines(i) self.assertEquals(filtered, i) self.assertEquals(warnings, [])