예제 #1
0
    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
예제 #2
0
    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
예제 #3
0
 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()
             ])
예제 #4
0
파일: __init__.py 프로젝트: wenlien/ansible
    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()
             ])
예제 #6
0
    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
예제 #7
0
    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
예제 #8
0
 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, [])
예제 #9
0
 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, [])
예제 #10
0
    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, [])