Exemple #1
0
    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", ))
Exemple #2
0
 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()
Exemple #3
0
    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")
Exemple #4
0
    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()
Exemple #5
0
    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")
Exemple #6
0
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"]
        )