diff --git a/ansible_mitogen/connection.py b/ansible_mitogen/connection.py index c08df611..06a152b2 100644 --- a/ansible_mitogen/connection.py +++ b/ansible_mitogen/connection.py @@ -950,11 +950,12 @@ class Connection(ansible.plugins.connection.ConnectionBase): :param str out_path: Local filesystem path to write. """ - output = self.get_chain().call( - ansible_mitogen.target.read_path, - mitogen.utils.cast(in_path), + self._connect() + ansible_mitogen.target.transfer_file( + context=self.context, + in_path=in_path, + out_path=out_path ) - ansible_mitogen.target.write_path(out_path, output) def put_data(self, out_path, data, mode=None, utimes=None): """ diff --git a/mitogen/core.py b/mitogen/core.py index a14286f9..8b4f135e 100644 --- a/mitogen/core.py +++ b/mitogen/core.py @@ -395,6 +395,12 @@ else: return _partition(s, sep, s.find) or (s, '', '') +def _has_parent_authority(context_id): + return ( + (context_id == mitogen.context_id) or + (context_id in mitogen.parent_ids) + ) + def has_parent_authority(msg, _stream=None): """ Policy function for use with :class:`Receiver` and @@ -403,8 +409,7 @@ def has_parent_authority(msg, _stream=None): ` has been set to that of a parent context or the current context. """ - return (msg.auth_id == mitogen.context_id or - msg.auth_id in mitogen.parent_ids) + return _has_parent_authority(msg.auth_id) def _signals(obj, signal): diff --git a/mitogen/service.py b/mitogen/service.py index 77a1ae1b..6654fb32 100644 --- a/mitogen/service.py +++ b/mitogen/service.py @@ -1023,7 +1023,11 @@ class FileService(Service): :raises Error: Unregistered path, or Sender did not match requestee context. """ - if path not in self._paths and not self._prefix_is_authorized(path): + if ( + (path not in self._paths) and + (not self._prefix_is_authorized(path)) and + (not mitogen.core._has_parent_authority(msg.auth_id)) + ): msg.reply(mitogen.core.CallError( Error(self.unregistered_msg % (path,)) )) diff --git a/tests/ansible/tests/connection_test.py b/tests/ansible/tests/connection_test.py index e7646716..36d61f09 100644 --- a/tests/ansible/tests/connection_test.py +++ b/tests/ansible/tests/connection_test.py @@ -99,6 +99,21 @@ class OptionalIntTest(testlib.TestCase): self.assertEquals(None, self.func({1:2})) +class FetchFileTest(ConnectionMixin, testlib.TestCase): + def test_success(self): + with tempfile.NamedTemporaryFile(prefix='mitotest') as ifp, \ + tempfile.NamedTemporaryFile(prefix='mitotest') as ofp: + ifp.write('x' * (1048576 * 4)) + ifp.flush() + ifp.seek(0) + + self.conn.fetch_file(ifp.name, ofp.name) + # transfer_file() uses os.rename rather than direct data overwrite, + # so we must reopen. + with open(ofp.name, 'rb') as fp: + self.assertEquals(ifp.read(), fp.read()) + + class PutDataTest(ConnectionMixin, testlib.TestCase): def test_out_path(self): path = tempfile.mktemp(prefix='mitotest')