def test_run_command(self): executor = SSHExecutor(host="test_host", username="******", client_keys=["TestKey"]) self.assertIsNone( run_async(executor.run_command, command="Test").stdout) self.mock_asyncssh.connect.assert_called_with(host="test_host", username="******", client_keys=["TestKey"]) self.mock_asyncssh.reset_mock() executor = SSHExecutor(host="test_host", username="******", client_keys=("TestKey", )) self.assertIsNone( run_async(executor.run_command, command="Test").stdout) self.mock_asyncssh.connect.assert_called_with( host="test_host", username="******", client_keys=("TestKey", )) self.mock_asyncssh.reset_mock() executor = SSHExecutor(host="test_host", username="******", client_keys=("TestKey", )) self.assertEqual( run_async(executor.run_command, command="Test", stdin_input="Test").stdout, "Test") self.mock_asyncssh.connect.assert_called_with( host="test_host", username="******", client_keys=("TestKey", ))
def setUp(self) -> None: self.response = AttributeDict(stderr="", exit_status=0) self.mock_asyncssh.connect.return_value = async_return( return_value=MockConnection() ) self.test_asyncssh_params = AttributeDict( host="test_host", username="******", client_keys=["TestKey"] ) self.executor = SSHExecutor(**self.test_asyncssh_params) self.mock_asyncssh.reset_mock()
def test_run_command(self): self.assertIsNone(run_async(self.executor.run_command, command="Test").stdout) self.mock_asyncssh.connect.assert_called_with( host="test_host", username="******", client_keys=["TestKey"] ) self.mock_asyncssh.reset_mock() response = run_async( self.executor.run_command, command="Test", stdin_input="Test" ) self.assertEqual(response.stdout, "Test") self.assertEqual(response.stderr, "TestError") self.assertEqual(response.exit_code, 0) raising_executor = SSHExecutor(**self.test_asyncssh_params) self.mock_asyncssh.connect.return_value = async_return( return_value=MockConnection( exception=ProcessError, env="Test", command="Test", subsystem="Test", exit_status=1, exit_signal=None, returncode=1, stdout="TestError", stderr="TestError", ) ) with self.assertRaises(CommandExecutionFailure): run_async(raising_executor.run_command, command="Test", stdin_input="Test") raising_executor = SSHExecutor(**self.test_asyncssh_params) self.mock_asyncssh.connect.return_value = async_return( return_value=MockConnection( exception=ChannelOpenError, reason="test_reason", code=255 ) ) with self.assertRaises(CommandExecutionFailure): run_async(raising_executor.run_command, command="Test", stdin_input="Test")
def test_run_command(self): response = AttributeDict(stdout="Test", stderr="", exit_status=0) executor = SSHExecutor(host="test_host", username="******", client_keys=["TestKey"]) self.mock_asyncssh.connect.side_effect = generate_connect(response) self.assertEqual( run_async(executor.run_command, command="Test").stdout, "Test") self.mock_asyncssh.connect.assert_called_with(host="test_host", username="******", client_keys=["TestKey"]) self.mock_asyncssh.reset_mock() executor = SSHExecutor(host="test_host", username="******", client_keys=("TestKey", )) self.assertEqual( run_async(executor.run_command, command="Test").stdout, "Test") self.mock_asyncssh.connect.assert_called_with( host="test_host", username="******", client_keys=("TestKey", )) self.mock_asyncssh.connect.side_effect = None self.mock_asyncssh.reset_mock()
def test_run_raises_process_error(self): test_exception = ProcessError(env="Test", command="Test", subsystem="Test", exit_status=1, exit_signal=None, returncode=1, stdout="TestError", stderr="TestError") self.mock_asyncssh.connect.side_effect = generate_connect( self.response, exception=test_exception) executor = SSHExecutor(host="test_host", username="******", client_keys=("TestKey", )) with self.assertRaises(CommandExecutionFailure): run_async(executor.run_command, command="Test", stdin_input="Test")
class TestSSHExecutor(TestCase): mock_asyncssh = None @classmethod def setUpClass(cls): cls.mock_asyncssh_patcher = patch( "tardis.utilities.executors.sshexecutor.asyncssh" ) cls.mock_asyncssh = cls.mock_asyncssh_patcher.start() cls.mock_asyncssh.ChannelOpenError = ChannelOpenError cls.mock_asyncssh.ConnectionLost = ConnectionLost cls.mock_asyncssh.DisconnectError = DisconnectError cls.mock_asyncssh.ProcessError = ProcessError @classmethod def tearDownClass(cls): cls.mock_asyncssh.stop() def setUp(self) -> None: self.response = AttributeDict(stderr="", exit_status=0) self.mock_asyncssh.connect.return_value = async_return( return_value=MockConnection() ) self.test_asyncssh_params = AttributeDict( host="test_host", username="******", client_keys=["TestKey"] ) self.executor = SSHExecutor(**self.test_asyncssh_params) self.mock_asyncssh.reset_mock() @patch("tardis.utilities.executors.sshexecutor.asyncio.sleep", async_return) def test_establish_connection(self): self.assertIsInstance( run_async(self.executor._establish_connection), MockConnection ) self.mock_asyncssh.connect.assert_called_with(**self.test_asyncssh_params) test_exceptions = [ ConnectionResetError(), DisconnectError(reason="test_reason", code=255), ConnectionLost(reason="test_reason"), BrokenPipeError(), ] for exception in test_exceptions: self.mock_asyncssh.reset_mock() self.mock_asyncssh.connect.side_effect = exception with self.assertRaises(type(exception)): run_async(self.executor._establish_connection) self.assertEqual(self.mock_asyncssh.connect.call_count, 10) self.mock_asyncssh.connect.side_effect = None def test_connection_property(self): async def force_connection(): async with self.executor.bounded_connection as connection: return connection self.assertIsNone(self.executor._ssh_connection) run_async(force_connection) self.assertIsInstance(self.executor._ssh_connection, MockConnection) current_ssh_connection = self.executor._ssh_connection run_async(force_connection) # make sure the connection is not needlessly replaced self.assertEqual(self.executor._ssh_connection, current_ssh_connection) def test_lock(self): self.assertIsInstance(self.executor.lock, asyncio.Lock) def test_connection_queueing(self): async def is_queued(n: int): """Check whether the n'th command runs is queued or immediately""" background = [ asyncio.ensure_future(self.executor.run_command("sleep 5")) for _ in range(n - 1) ] # probe can only finish in time if it is not queued probe = asyncio.ensure_future(self.executor.run_command("sleep 0.01")) await asyncio.sleep(0.1) queued = not probe.done() for task in background + [probe]: task.cancel() return queued for sessions in (1, 8, 10, 12, 20): with self.subTest(sessions=sessions): self.assertEqual( sessions > DEFAULT_MAX_SESSIONS, run_async(is_queued, sessions), ) def test_run_command(self): self.assertIsNone(run_async(self.executor.run_command, command="Test").stdout) self.mock_asyncssh.connect.assert_called_with( host="test_host", username="******", client_keys=["TestKey"] ) self.mock_asyncssh.reset_mock() response = run_async( self.executor.run_command, command="Test", stdin_input="Test" ) self.assertEqual(response.stdout, "Test") self.assertEqual(response.stderr, "TestError") self.assertEqual(response.exit_code, 0) raising_executor = SSHExecutor(**self.test_asyncssh_params) self.mock_asyncssh.connect.return_value = async_return( return_value=MockConnection( exception=ProcessError, env="Test", command="Test", subsystem="Test", exit_status=1, exit_signal=None, returncode=1, stdout="TestError", stderr="TestError", ) ) with self.assertRaises(CommandExecutionFailure): run_async(raising_executor.run_command, command="Test", stdin_input="Test") raising_executor = SSHExecutor(**self.test_asyncssh_params) self.mock_asyncssh.connect.return_value = async_return( return_value=MockConnection( exception=ChannelOpenError, reason="test_reason", code=255 ) ) with self.assertRaises(CommandExecutionFailure): run_async(raising_executor.run_command, command="Test", stdin_input="Test") def test_construction_by_yaml(self): executor = yaml.safe_load( """ !SSHExecutor host: test_host username: test client_keys: - TestKey """ ) self.assertEqual( run_async(executor.run_command, command="Test", stdin_input="Test").stdout, "Test", ) self.mock_asyncssh.connect.assert_called_with( host="test_host", username="******", client_keys=["TestKey"] )