ansible: raise AnsibleConnectionFailure on connection failure; closes #183

Before:

    $ ANSIBLE_STRATEGY=mitogen ansible -i derp, derp -m setup
    An exception occurred during task execution. To see the full traceback, use -vvv. The error was:     (''.join(bits)[-300:],)
    derp | FAILED! => {
        "msg": "Unexpected failure during module execution.",
        "stdout": ""
    }

After:

    $ ANSIBLE_STRATEGY=mitogen ansible -i derp, derp -m setup
    derp | UNREACHABLE! => {
        "changed": false,
        "msg": "EOF on stream; last 300 bytes received: 'ssh: Could not resolve hostname derp: nodename nor servname provided, or not known\\r\\n'",
        "unreachable": true
    }
pull/193/head
David Wilson 7 years ago
parent b9d4ec57b3
commit 7fd88868a6

@ -37,7 +37,7 @@ import ansible.errors
import ansible.plugins.connection import ansible.plugins.connection
import mitogen.unix import mitogen.unix
from mitogen.utils import cast import mitogen.utils
import ansible_mitogen.helpers import ansible_mitogen.helpers
import ansible_mitogen.process import ansible_mitogen.process
@ -137,25 +137,34 @@ class Connection(ansible.plugins.connection.ConnectionBase):
def connected(self): def connected(self):
return self.broker is not None return self.broker is not None
def _wrap_connect(self, args):
dct = mitogen.service.call(
context=self.parent,
handle=ContextService.handle,
obj=mitogen.utils.cast(args),
)
if dct['msg']:
raise ansible.errors.AnsibleConnectionFailure(dct['msg'])
return dct['context'], dct['home_dir']
def _connect_local(self): def _connect_local(self):
""" """
Fetch a reference to the local() Context from ContextService in the Fetch a reference to the local() Context from ContextService in the
master process. master process.
""" """
return mitogen.service.call(self.parent, ContextService.handle, cast({ return self._wrap_connect({
'method': 'local', 'method': 'local',
'python_path': self.python_path, 'python_path': self.python_path,
})) })
def _connect_ssh(self): def _connect_ssh(self):
""" """
Fetch a reference to an SSH Context matching the play context from Fetch a reference to an SSH Context matching the play context from
ContextService in the master process. ContextService in the master process.
""" """
return mitogen.service.call( return self._wrap_connect({
self.parent,
ContextService.handle,
cast({
'method': 'ssh', 'method': 'ssh',
'check_host_keys': False, # TODO 'check_host_keys': False, # TODO
'hostname': self._play_context.remote_addr, 'hostname': self._play_context.remote_addr,
@ -177,19 +186,14 @@ class Connection(ansible.plugins.connection.ConnectionBase):
for term in shlex.split(s or '') for term in shlex.split(s or '')
] ]
}) })
)
def _connect_docker(self): def _connect_docker(self):
return mitogen.service.call( return self._wrap_connect({
self.parent,
ContextService.handle,
cast({
'method': 'docker', 'method': 'docker',
'container': self._play_context.remote_addr, 'container': self._play_context.remote_addr,
'python_path': self.python_path, 'python_path': self.python_path,
'connect_timeout': self._play_context.timeout, 'connect_timeout': self._play_context.timeout,
}) })
)
def _connect_sudo(self, via=None, python_path=None): def _connect_sudo(self, via=None, python_path=None):
""" """
@ -200,10 +204,7 @@ class Connection(ansible.plugins.connection.ConnectionBase):
Parent Context of the sudo Context. For Ansible, this should always Parent Context of the sudo Context. For Ansible, this should always
be a Context returned by _connect_ssh(). be a Context returned by _connect_ssh().
""" """
return mitogen.service.call( return self._wrap_connect({
self.parent,
ContextService.handle,
cast({
'method': 'sudo', 'method': 'sudo',
'username': self._play_context.become_user, 'username': self._play_context.become_user,
'password': self._play_context.become_pass, 'password': self._play_context.become_pass,
@ -216,7 +217,6 @@ class Connection(ansible.plugins.connection.ConnectionBase):
self._play_context.become_flags or '' self._play_context.become_flags or ''
), ),
}) })
)
def _connect(self): def _connect(self):
""" """
@ -318,8 +318,8 @@ class Connection(ansible.plugins.connection.ConnectionBase):
emulate_tty = (not in_data and sudoable) emulate_tty = (not in_data and sudoable)
rc, stdout, stderr = self.call( rc, stdout, stderr = self.call(
ansible_mitogen.helpers.exec_command, ansible_mitogen.helpers.exec_command,
cmd=cast(cmd), cmd=mitogen.utils.cast(cmd),
in_data=cast(in_data), in_data=mitogen.utils.cast(in_data),
chdir=mitogen_chdir, chdir=mitogen_chdir,
emulate_tty=emulate_tty, emulate_tty=emulate_tty,
) )
@ -341,7 +341,7 @@ class Connection(ansible.plugins.connection.ConnectionBase):
Local filesystem path to write. Local filesystem path to write.
""" """
output = self.call(ansible_mitogen.helpers.read_path, output = self.call(ansible_mitogen.helpers.read_path,
cast(in_path)) mitogen.utils.cast(in_path))
ansible_mitogen.helpers.write_path(out_path, output) ansible_mitogen.helpers.write_path(out_path, output)
def put_data(self, out_path, data): def put_data(self, out_path, data):
@ -355,7 +355,8 @@ class Connection(ansible.plugins.connection.ConnectionBase):
Remote filesystem path to write. Remote filesystem path to write.
""" """
self.call(ansible_mitogen.helpers.write_path, self.call(ansible_mitogen.helpers.write_path,
cast(out_path), cast(data)) mitogen.utils.cast(out_path),
mitogen.utils.cast(data))
def put_file(self, in_path, out_path): def put_file(self, in_path, out_path):
""" """

@ -81,9 +81,21 @@ class ContextService(mitogen.service.DeduplicatingService):
def get_response(self, args): def get_response(self, args):
args.pop('discriminator', None) args.pop('discriminator', None)
method = getattr(self.router, args.pop('method')) method = getattr(self.router, args.pop('method'))
try:
context = method(**args) context = method(**args)
except mitogen.core.StreamError as e:
return {
'context': None,
'home_dir': None,
'msg': str(e),
}
home_dir = context.call(os.path.expanduser, '~') home_dir = context.call(os.path.expanduser, '~')
return context, home_dir return {
'context': context,
'home_dir': home_dir,
'msg': None,
}
class FileService(mitogen.service.Service): class FileService(mitogen.service.Service):

Loading…
Cancel
Save