def test_key_material_argument(self): path = os.path.join(get_resources_base_path(), "ssh", "dummy_rsa") with open(path, "r") as fp: private_key = fp.read() conn_params = { "hostname": "dummy.host.org", "username": "******", "key_material": private_key, } mock = ParamikoSSHClient(**conn_params) mock.connect() pkey = paramiko.RSAKey.from_private_key(StringIO(private_key)) expected_conn = { "username": "******", "allow_agent": False, "hostname": "dummy.host.org", "look_for_keys": False, "pkey": pkey, "timeout": 30, "port": 22, } mock.client.connect.assert_called_once_with(**expected_conn)
def test_key_material_argument(self): path = os.path.join(get_resources_base_path(), 'ssh', 'dummy_rsa') with open(path, 'r') as fp: private_key = fp.read() conn_params = { 'hostname': 'dummy.host.org', 'username': '******', 'key_material': private_key } mock = ParamikoSSHClient(**conn_params) mock.connect() pkey = paramiko.RSAKey.from_private_key(StringIO(private_key)) expected_conn = { 'username': '******', 'allow_agent': False, 'hostname': 'dummy.host.org', 'look_for_keys': False, 'pkey': pkey, 'timeout': 60, 'port': 22 } mock.client.connect.assert_called_once_with(**expected_conn)
def test_passphrase_not_provided_for_encrypted_key_file(self): path = os.path.join(get_resources_base_path(), 'ssh', 'dummy_rsa_passphrase') conn_params = {'hostname': 'dummy.host.org', 'username': '******', 'key_files': path} mock = ParamikoSSHClient(**conn_params) self.assertRaises(paramiko.ssh_exception.PasswordRequiredException, mock.connect)
def test_put_dir(self, *args): mock = self.ssh_cli mock.connect() local_dir = os.path.join(get_resources_base_path(), "packs") mock.put_dir(local_path=local_dir, remote_path="/tmp") mock_cli = mock.client # The actual mocked object: SSHClient # Assert that expected dirs are created on remote box. calls = [call("/tmp/packs/pythonactions"), call("/tmp/packs/pythonactions/actions")] mock_cli.open_sftp().mkdir.assert_has_calls(calls, any_order=True) # Assert that expected files are copied to remote box. local_file = os.path.join(get_resources_base_path(), "packs/pythonactions/actions/pascal_row.py") remote_file = os.path.join("/tmp", "packs/pythonactions/actions/pascal_row.py") calls = [call(local_file, remote_file)] mock_cli.open_sftp().put.assert_has_calls(calls, any_order=True)
def test_passphrase_not_provided_for_encrypted_key_file(self): path = os.path.join(get_resources_base_path(), "ssh", "dummy_rsa_passphrase") conn_params = { "hostname": "dummy.host.org", "username": "******", "key_files": path, } mock = ParamikoSSHClient(**conn_params) self.assertRaises(paramiko.ssh_exception.PasswordRequiredException, mock.connect)
def test_put_dir(self, *args): mock = self.ssh_cli mock.connect() local_dir = os.path.join(get_resources_base_path(), 'packs') mock.put_dir(local_path=local_dir, remote_path='/tmp') mock_cli = mock.client # The actual mocked object: SSHClient # Assert that expected dirs are created on remote box. calls = [call('/tmp/packs/pythonactions'), call('/tmp/packs/pythonactions/actions')] mock_cli.open_sftp().mkdir.assert_has_calls(calls, any_order=True) # Assert that expected files are copied to remote box. local_file = os.path.join(get_resources_base_path(), 'packs/pythonactions/actions/pascal_row.py') remote_file = os.path.join('/tmp', 'packs/pythonactions/actions/pascal_row.py') calls = [call(local_file, remote_file)] mock_cli.open_sftp().put.assert_has_calls(calls, any_order=True)
def test_key_with_passphrase_success(self): path = os.path.join(get_resources_base_path(), "ssh", "dummy_rsa_passphrase") with open(path, "r") as fp: private_key = fp.read() # Key material provided conn_params = { "hostname": "dummy.host.org", "username": "******", "key_material": private_key, "passphrase": "testphrase", } mock = ParamikoSSHClient(**conn_params) mock.connect() pkey = paramiko.RSAKey.from_private_key(StringIO(private_key), "testphrase") expected_conn = { "username": "******", "allow_agent": False, "hostname": "dummy.host.org", "look_for_keys": False, "pkey": pkey, "timeout": 30, "port": 22, } mock.client.connect.assert_called_once_with(**expected_conn) # Path to private key file provided conn_params = { "hostname": "dummy.host.org", "username": "******", "key_files": path, "passphrase": "testphrase", } mock = ParamikoSSHClient(**conn_params) mock.connect() expected_conn = { "username": "******", "allow_agent": False, "hostname": "dummy.host.org", "look_for_keys": False, "key_filename": path, "password": "******", "timeout": 30, "port": 22, } mock.client.connect.assert_called_once_with(**expected_conn)
def test_key_with_passphrase_success(self): path = os.path.join(get_resources_base_path(), 'ssh', 'dummy_rsa_passphrase') with open(path, 'r') as fp: private_key = fp.read() # Key material provided conn_params = { 'hostname': 'dummy.host.org', 'username': '******', 'key_material': private_key, 'passphrase': 'testphrase' } mock = ParamikoSSHClient(**conn_params) mock.connect() pkey = paramiko.RSAKey.from_private_key(StringIO(private_key), 'testphrase') expected_conn = { 'username': '******', 'allow_agent': False, 'hostname': 'dummy.host.org', 'look_for_keys': False, 'pkey': pkey, 'timeout': 30, 'port': 22 } mock.client.connect.assert_called_once_with(**expected_conn) # Path to private key file provided conn_params = { 'hostname': 'dummy.host.org', 'username': '******', 'key_files': path, 'passphrase': 'testphrase' } mock = ParamikoSSHClient(**conn_params) mock.connect() expected_conn = { 'username': '******', 'allow_agent': False, 'hostname': 'dummy.host.org', 'look_for_keys': False, 'key_filename': path, 'password': '******', 'timeout': 30, 'port': 22 } mock.client.connect.assert_called_once_with(**expected_conn)
def test_key_with_passphrase_success(self): path = os.path.join(get_resources_base_path(), "ssh", "dummy_rsa_passphrase") with open(path, "r") as fp: private_key = fp.read() # Key material provided conn_params = { "hostname": "dummy.host.org", "username": "******", "key_material": private_key, "passphrase": "testphrase", } mock = ParamikoSSHClient(**conn_params) mock.connect() pkey = paramiko.RSAKey.from_private_key(StringIO(private_key), "testphrase") expected_conn = { "username": "******", "allow_agent": False, "hostname": "dummy.host.org", "look_for_keys": False, "pkey": pkey, "timeout": 60, "port": 22, } mock.client.connect.assert_called_once_with(**expected_conn) # Path to private key file provided conn_params = { "hostname": "dummy.host.org", "username": "******", "key_files": path, "passphrase": "testphrase", } mock = ParamikoSSHClient(**conn_params) mock.connect() expected_conn = { "username": "******", "allow_agent": False, "hostname": "dummy.host.org", "look_for_keys": False, "key_filename": path, "password": "******", "timeout": 60, "port": 22, } mock.client.connect.assert_called_once_with(**expected_conn)
def test_fail_set_proxycommand(self, mock_ProxyCommand): """ Loads proxy commands from ssh config file """ ssh_config_file_path = os.path.join(get_resources_base_path(), 'ssh', 'dummy_ssh_config_fail') cfg.CONF.set_override(name='ssh_config_file_path', override=ssh_config_file_path, group='ssh_runner') cfg.CONF.set_override(name='use_ssh_config', override=True, group='ssh_runner') conn_params = {'hostname': 'dummy.host.org'} mock = ParamikoSSHClient(**conn_params) self.assertRaises(Exception, mock.connect) mock_ProxyCommand.assert_not_called()
def test_incorrect_passphrase(self): path = os.path.join(get_resources_base_path(), 'ssh', 'dummy_rsa_passphrase') with open(path, 'r') as fp: private_key = fp.read() conn_params = {'hostname': 'dummy.host.org', 'username': '******', 'key_material': private_key, 'passphrase': 'incorrect'} mock = ParamikoSSHClient(**conn_params) expected_msg = 'Invalid passphrase or invalid/unsupported key type' self.assertRaisesRegexp(paramiko.ssh_exception.SSHException, expected_msg, mock.connect)
def test_set_proxycommand(self, mock_ProxyCommand): """ Loads proxy commands from ssh config file """ ssh_config_file_path = os.path.join(get_resources_base_path(), 'ssh', 'dummy_ssh_config') cfg.CONF.set_override(name='ssh_config_file_path', override=ssh_config_file_path, group='ssh_runner') cfg.CONF.set_override(name='use_ssh_config', override=True, group='ssh_runner') conn_params = {'hostname': 'dummy.host.org', 'username': '******', 'password': '******'} mock = ParamikoSSHClient(**conn_params) mock.connect() mock_ProxyCommand.assert_called_once_with('ssh -q -W dummy.host.org:22 dummy_bastion')
def test_incorrect_passphrase(self): path = os.path.join(get_resources_base_path(), "ssh", "dummy_rsa_passphrase") with open(path, "r") as fp: private_key = fp.read() conn_params = { "hostname": "dummy.host.org", "username": "******", "key_material": private_key, "passphrase": "incorrect", } mock = ParamikoSSHClient(**conn_params) expected_msg = "Invalid passphrase or invalid/unsupported key type" self.assertRaisesRegexp(paramiko.ssh_exception.SSHException, expected_msg, mock.connect)
def test_key_with_passphrase_success(self): path = os.path.join(get_resources_base_path(), 'ssh', 'dummy_rsa_passphrase') with open(path, 'r') as fp: private_key = fp.read() # Key material provided conn_params = {'hostname': 'dummy.host.org', 'username': '******', 'key_material': private_key, 'passphrase': 'testphrase'} mock = ParamikoSSHClient(**conn_params) mock.connect() pkey = paramiko.RSAKey.from_private_key(StringIO(private_key), 'testphrase') expected_conn = {'username': '******', 'allow_agent': False, 'hostname': 'dummy.host.org', 'look_for_keys': False, 'pkey': pkey, 'timeout': 60, 'port': 22} mock.client.connect.assert_called_once_with(**expected_conn) # Path to private key file provided conn_params = {'hostname': 'dummy.host.org', 'username': '******', 'key_files': path, 'passphrase': 'testphrase'} mock = ParamikoSSHClient(**conn_params) mock.connect() expected_conn = {'username': '******', 'allow_agent': False, 'hostname': 'dummy.host.org', 'look_for_keys': False, 'key_filename': path, 'password': '******', 'timeout': 60, 'port': 22} mock.client.connect.assert_called_once_with(**expected_conn)
def test_key_material_argument(self): path = os.path.join(get_resources_base_path(), 'ssh', 'dummy_rsa') with open(path, 'r') as fp: private_key = fp.read() conn_params = {'hostname': 'dummy.host.org', 'username': '******', 'key_material': private_key} mock = ParamikoSSHClient(**conn_params) mock.connect() pkey = paramiko.RSAKey.from_private_key(StringIO(private_key)) expected_conn = {'username': '******', 'allow_agent': False, 'hostname': 'dummy.host.org', 'look_for_keys': False, 'pkey': pkey, 'port': 22} mock.client.connect.assert_called_once_with(**expected_conn)
def test_key_material_argument(self): path = os.path.join(get_resources_base_path(), "ssh", "dummy_rsa") with open(path, "r") as fp: private_key = fp.read() conn_params = {"hostname": "dummy.host.org", "username": "******", "key_material": private_key} mock = ParamikoSSHClient(**conn_params) mock.connect() pkey = paramiko.RSAKey.from_private_key(StringIO(private_key)) expected_conn = { "username": "******", "allow_agent": False, "hostname": "dummy.host.org", "look_for_keys": False, "pkey": pkey, "timeout": 60, "port": 22, } mock.client.connect.assert_called_once_with(**expected_conn)
def test_set_proxycommand(self, mock_ProxyCommand): """ Loads proxy commands from ssh config file """ ssh_config_file_path = os.path.join(get_resources_base_path(), "ssh", "dummy_ssh_config") cfg.CONF.set_override( name="ssh_config_file_path", override=ssh_config_file_path, group="ssh_runner", ) cfg.CONF.set_override(name="use_ssh_config", override=True, group="ssh_runner") conn_params = { "hostname": "dummy.host.org", "username": "******", "password": "******", } mock = ParamikoSSHClient(**conn_params) mock.connect() mock_ProxyCommand.assert_called_once_with( "ssh -q -W dummy.host.org:22 dummy_bastion")
def test_passphrase_not_provided_for_encrypted_key_file(self): path = os.path.join(get_resources_base_path(), "ssh", "dummy_rsa_passphrase") conn_params = {"hostname": "dummy.host.org", "username": "******", "key_files": path} mock = ParamikoSSHClient(**conn_params) self.assertRaises(paramiko.ssh_exception.PasswordRequiredException, mock.connect)
def test_pre_run(self, mock_client): # Test case which verifies that ParamikoSSHClient is instantiated with the correct arguments private_key_path = os.path.join(get_resources_base_path(), 'ssh', 'dummy_rsa') with open(private_key_path, 'r') as fp: private_key = fp.read() # Username and password provided runner = Runner('id') runner.context = {} runner_parameters = { RUNNER_HOSTS: 'localhost', RUNNER_USERNAME: '******', RUNNER_PASSWORD: '******' } runner.runner_parameters = runner_parameters runner.pre_run() expected_kwargs = { 'hosts': ['localhost'], 'user': '******', 'password': '******', 'port': None, 'concurrency': 1, 'bastion_host': None, 'raise_on_any_error': False, 'connect': True } mock_client.assert_called_with(**expected_kwargs) # Private key provided as raw key material runner = Runner('id') runner.context = {} runner_parameters = { RUNNER_HOSTS: 'localhost', RUNNER_USERNAME: '******', RUNNER_PRIVATE_KEY: private_key, RUNNER_SSH_PORT: 22 } runner.runner_parameters = runner_parameters runner.pre_run() expected_kwargs = { 'hosts': ['localhost'], 'user': '******', 'pkey_material': private_key, 'port': 22, 'concurrency': 1, 'bastion_host': None, 'raise_on_any_error': False, 'connect': True } mock_client.assert_called_with(**expected_kwargs) # Private key provided as raw key material + passphrase runner = Runner('id') runner.context = {} runner_parameters = { RUNNER_HOSTS: 'localhost21', RUNNER_USERNAME: '******', RUNNER_PRIVATE_KEY: private_key, RUNNER_PASSPHRASE: 'passphrase21', RUNNER_SSH_PORT: 22 } runner.runner_parameters = runner_parameters runner.pre_run() expected_kwargs = { 'hosts': ['localhost21'], 'user': '******', 'pkey_material': private_key, 'passphrase': 'passphrase21', 'port': 22, 'concurrency': 1, 'bastion_host': None, 'raise_on_any_error': False, 'connect': True } mock_client.assert_called_with(**expected_kwargs) # Private key provided as path to the private key file runner = Runner('id') runner.context = {} runner_parameters = { RUNNER_HOSTS: 'localhost', RUNNER_USERNAME: '******', RUNNER_PRIVATE_KEY: private_key_path, RUNNER_SSH_PORT: 22 } runner.runner_parameters = runner_parameters runner.pre_run() expected_kwargs = { 'hosts': ['localhost'], 'user': '******', 'pkey_file': private_key_path, 'port': 22, 'concurrency': 1, 'bastion_host': None, 'raise_on_any_error': False, 'connect': True } mock_client.assert_called_with(**expected_kwargs) # Private key provided as path to the private key file + passpharse runner = Runner('id') runner.context = {} runner_parameters = { RUNNER_HOSTS: 'localhost31', RUNNER_USERNAME: '******', RUNNER_PRIVATE_KEY: private_key_path, RUNNER_PASSPHRASE: 'passphrase31', RUNNER_SSH_PORT: 22 } runner.runner_parameters = runner_parameters runner.pre_run() expected_kwargs = { 'hosts': ['localhost31'], 'user': '******', 'pkey_file': private_key_path, 'passphrase': 'passphrase31', 'port': 22, 'concurrency': 1, 'bastion_host': None, 'raise_on_any_error': False, 'connect': True } mock_client.assert_called_with(**expected_kwargs) # No password or private key provided, should default to system user private key runner = Runner('id') runner.context = {} runner_parameters = { RUNNER_HOSTS: 'localhost4', RUNNER_SSH_PORT: 22 } runner.runner_parameters = runner_parameters runner.pre_run() expected_kwargs = { 'hosts': ['localhost4'], 'user': None, 'pkey_file': None, 'port': 22, 'concurrency': 1, 'bastion_host': None, 'raise_on_any_error': False, 'connect': True } mock_client.assert_called_with(**expected_kwargs)
def test_pre_run(self, mock_client): # Test case which verifies that ParamikoSSHClient is instantiated with the correct arguments private_key_path = os.path.join(get_resources_base_path(), "ssh", "dummy_rsa") with open(private_key_path, "r") as fp: private_key = fp.read() # Username and password provided runner = Runner("id") runner.context = {} runner_parameters = { RUNNER_HOSTS: "localhost", RUNNER_USERNAME: "******", RUNNER_PASSWORD: "******", } runner.runner_parameters = runner_parameters runner.pre_run() expected_kwargs = { "hosts": ["localhost"], "user": "******", "password": "******", "port": None, "concurrency": 1, "bastion_host": None, "raise_on_any_error": False, "connect": True, "handle_stdout_line_func": mock.ANY, "handle_stderr_line_func": mock.ANY, } mock_client.assert_called_with(**expected_kwargs) # Private key provided as raw key material runner = Runner("id") runner.context = {} runner_parameters = { RUNNER_HOSTS: "localhost", RUNNER_USERNAME: "******", RUNNER_PRIVATE_KEY: private_key, RUNNER_SSH_PORT: 22, } runner.runner_parameters = runner_parameters runner.pre_run() expected_kwargs = { "hosts": ["localhost"], "user": "******", "pkey_material": private_key, "port": 22, "concurrency": 1, "bastion_host": None, "raise_on_any_error": False, "connect": True, "handle_stdout_line_func": mock.ANY, "handle_stderr_line_func": mock.ANY, } mock_client.assert_called_with(**expected_kwargs) # Private key provided as raw key material + passphrase runner = Runner("id") runner.context = {} runner_parameters = { RUNNER_HOSTS: "localhost21", RUNNER_USERNAME: "******", RUNNER_PRIVATE_KEY: private_key, RUNNER_PASSPHRASE: "passphrase21", RUNNER_SSH_PORT: 22, } runner.runner_parameters = runner_parameters runner.pre_run() expected_kwargs = { "hosts": ["localhost21"], "user": "******", "pkey_material": private_key, "passphrase": "passphrase21", "port": 22, "concurrency": 1, "bastion_host": None, "raise_on_any_error": False, "connect": True, "handle_stdout_line_func": mock.ANY, "handle_stderr_line_func": mock.ANY, } mock_client.assert_called_with(**expected_kwargs) # Private key provided as path to the private key file runner = Runner("id") runner.context = {} runner_parameters = { RUNNER_HOSTS: "localhost", RUNNER_USERNAME: "******", RUNNER_PRIVATE_KEY: private_key_path, RUNNER_SSH_PORT: 22, } runner.runner_parameters = runner_parameters runner.pre_run() expected_kwargs = { "hosts": ["localhost"], "user": "******", "pkey_file": private_key_path, "port": 22, "concurrency": 1, "bastion_host": None, "raise_on_any_error": False, "connect": True, "handle_stdout_line_func": mock.ANY, "handle_stderr_line_func": mock.ANY, } mock_client.assert_called_with(**expected_kwargs) # Private key provided as path to the private key file + passphrase runner = Runner("id") runner.context = {} runner_parameters = { RUNNER_HOSTS: "localhost31", RUNNER_USERNAME: "******", RUNNER_PRIVATE_KEY: private_key_path, RUNNER_PASSPHRASE: "passphrase31", RUNNER_SSH_PORT: 22, } runner.runner_parameters = runner_parameters runner.pre_run() expected_kwargs = { "hosts": ["localhost31"], "user": "******", "pkey_file": private_key_path, "passphrase": "passphrase31", "port": 22, "concurrency": 1, "bastion_host": None, "raise_on_any_error": False, "connect": True, "handle_stdout_line_func": mock.ANY, "handle_stderr_line_func": mock.ANY, } mock_client.assert_called_with(**expected_kwargs) # No password or private key provided, should default to system user private key runner = Runner("id") runner.context = {} runner_parameters = {RUNNER_HOSTS: "localhost4", RUNNER_SSH_PORT: 22} runner.runner_parameters = runner_parameters runner.pre_run() expected_kwargs = { "hosts": ["localhost4"], "user": None, "pkey_file": None, "port": 22, "concurrency": 1, "bastion_host": None, "raise_on_any_error": False, "connect": True, "handle_stdout_line_func": mock.ANY, "handle_stderr_line_func": mock.ANY, } mock_client.assert_called_with(**expected_kwargs)
def test_use_ssh_config_port_value_provided_in_the_config( self, mock_sshclient): cfg.CONF.set_override(name='use_ssh_config', override=True, group='ssh_runner') ssh_config_file_path = os.path.join(get_resources_base_path(), 'ssh', 'empty_config') cfg.CONF.set_override(name='ssh_config_file_path', override=ssh_config_file_path, group='ssh_runner') # 1. Default port is used (not explicitly provided) mock_client = mock.Mock() mock_sshclient.return_value = mock_client conn_params = { 'hostname': 'dummy.host.org', 'username': '******', 'password': '******', 'timeout': '600' } ssh_client = ParamikoSSHClient(**conn_params) ssh_client.connect() call_kwargs = mock_client.connect.call_args[1] self.assertEqual(call_kwargs['port'], 22) mock_client = mock.Mock() mock_sshclient.return_value = mock_client conn_params = { 'hostname': 'dummy.host.org', 'username': '******', 'password': '******', 'port': None, 'timeout': '600' } ssh_client = ParamikoSSHClient(**conn_params) ssh_client.connect() call_kwargs = mock_client.connect.call_args[1] self.assertEqual(call_kwargs['port'], 22) # 2. Default port is used (explicitly provided) mock_client = mock.Mock() mock_sshclient.return_value = mock_client conn_params = { 'hostname': 'dummy.host.org', 'username': '******', 'password': '******', 'port': DEFAULT_SSH_PORT, 'timeout': '600' } ssh_client = ParamikoSSHClient(**conn_params) ssh_client.connect() call_kwargs = mock_client.connect.call_args[1] self.assertEqual(call_kwargs['port'], DEFAULT_SSH_PORT) self.assertEqual(call_kwargs['port'], 22) # 3. Custom port is used (explicitly provided) mock_client = mock.Mock() mock_sshclient.return_value = mock_client conn_params = { 'hostname': 'dummy.host.org', 'username': '******', 'password': '******', 'port': 5555, 'timeout': '600' } ssh_client = ParamikoSSHClient(**conn_params) ssh_client.connect() call_kwargs = mock_client.connect.call_args[1] self.assertEqual(call_kwargs['port'], 5555) # 4. Custom port is specified in the ssh config (it has precedence over default port) ssh_config_file_path = os.path.join(get_resources_base_path(), 'ssh', 'ssh_config_custom_port') cfg.CONF.set_override(name='ssh_config_file_path', override=ssh_config_file_path, group='ssh_runner') mock_client = mock.Mock() mock_sshclient.return_value = mock_client conn_params = { 'hostname': 'dummy.host.org', 'username': '******', 'password': '******' } ssh_client = ParamikoSSHClient(**conn_params) ssh_client.connect() call_kwargs = mock_client.connect.call_args[1] self.assertEqual(call_kwargs['port'], 6677) mock_client = mock.Mock() mock_sshclient.return_value = mock_client conn_params = { 'hostname': 'dummy.host.org', 'username': '******', 'password': '******', 'port': DEFAULT_SSH_PORT } ssh_client = ParamikoSSHClient(**conn_params) ssh_client.connect() call_kwargs = mock_client.connect.call_args[1] self.assertEqual(call_kwargs['port'], 6677) # 5. Custom port is specified in ssh config, but one is also provided via runner parameter # (runner parameter one has precedence) ssh_config_file_path = os.path.join(get_resources_base_path(), 'ssh', 'ssh_config_custom_port') cfg.CONF.set_override(name='ssh_config_file_path', override=ssh_config_file_path, group='ssh_runner') mock_client = mock.Mock() mock_sshclient.return_value = mock_client conn_params = { 'hostname': 'dummy.host.org', 'username': '******', 'password': '******', 'port': 9999 } ssh_client = ParamikoSSHClient(**conn_params) ssh_client.connect() call_kwargs = mock_client.connect.call_args[1] self.assertEqual(call_kwargs['port'], 9999)
def test_use_ssh_config_port_value_provided_in_the_config( self, mock_sshclient): cfg.CONF.set_override(name="use_ssh_config", override=True, group="ssh_runner") ssh_config_file_path = os.path.join(get_resources_base_path(), "ssh", "empty_config") cfg.CONF.set_override( name="ssh_config_file_path", override=ssh_config_file_path, group="ssh_runner", ) # 1. Default port is used (not explicitly provided) mock_client = mock.Mock() mock_sshclient.return_value = mock_client conn_params = { "hostname": "dummy.host.org", "username": "******", "password": "******", "timeout": "600", } ssh_client = ParamikoSSHClient(**conn_params) ssh_client.connect() call_kwargs = mock_client.connect.call_args[1] self.assertEqual(call_kwargs["port"], 22) mock_client = mock.Mock() mock_sshclient.return_value = mock_client conn_params = { "hostname": "dummy.host.org", "username": "******", "password": "******", "port": None, "timeout": "600", } ssh_client = ParamikoSSHClient(**conn_params) ssh_client.connect() call_kwargs = mock_client.connect.call_args[1] self.assertEqual(call_kwargs["port"], 22) # 2. Default port is used (explicitly provided) mock_client = mock.Mock() mock_sshclient.return_value = mock_client conn_params = { "hostname": "dummy.host.org", "username": "******", "password": "******", "port": DEFAULT_SSH_PORT, "timeout": "600", } ssh_client = ParamikoSSHClient(**conn_params) ssh_client.connect() call_kwargs = mock_client.connect.call_args[1] self.assertEqual(call_kwargs["port"], DEFAULT_SSH_PORT) self.assertEqual(call_kwargs["port"], 22) # 3. Custom port is used (explicitly provided) mock_client = mock.Mock() mock_sshclient.return_value = mock_client conn_params = { "hostname": "dummy.host.org", "username": "******", "password": "******", "port": 5555, "timeout": "600", } ssh_client = ParamikoSSHClient(**conn_params) ssh_client.connect() call_kwargs = mock_client.connect.call_args[1] self.assertEqual(call_kwargs["port"], 5555) # 4. Custom port is specified in the ssh config (it has precedence over default port) ssh_config_file_path = os.path.join(get_resources_base_path(), "ssh", "ssh_config_custom_port") cfg.CONF.set_override( name="ssh_config_file_path", override=ssh_config_file_path, group="ssh_runner", ) mock_client = mock.Mock() mock_sshclient.return_value = mock_client conn_params = { "hostname": "dummy.host.org", "username": "******", "password": "******", } ssh_client = ParamikoSSHClient(**conn_params) ssh_client.connect() call_kwargs = mock_client.connect.call_args[1] self.assertEqual(call_kwargs["port"], 6677) mock_client = mock.Mock() mock_sshclient.return_value = mock_client conn_params = { "hostname": "dummy.host.org", "username": "******", "password": "******", "port": DEFAULT_SSH_PORT, } ssh_client = ParamikoSSHClient(**conn_params) ssh_client.connect() call_kwargs = mock_client.connect.call_args[1] self.assertEqual(call_kwargs["port"], 6677) # 5. Custom port is specified in ssh config, but one is also provided via runner parameter # (runner parameter one has precedence) ssh_config_file_path = os.path.join(get_resources_base_path(), "ssh", "ssh_config_custom_port") cfg.CONF.set_override( name="ssh_config_file_path", override=ssh_config_file_path, group="ssh_runner", ) mock_client = mock.Mock() mock_sshclient.return_value = mock_client conn_params = { "hostname": "dummy.host.org", "username": "******", "password": "******", "port": 9999, } ssh_client = ParamikoSSHClient(**conn_params) ssh_client.connect() call_kwargs = mock_client.connect.call_args[1] self.assertEqual(call_kwargs["port"], 9999)
def test_pre_run(self, mock_client): # Test case which verifies that ParamikoSSHClient is instantiated with the correct arguments private_key_path = os.path.join(get_resources_base_path(), 'ssh', 'dummy_rsa') with open(private_key_path, 'r') as fp: private_key = fp.read() # Username and password provided runner = Runner('id') runner.context = {} runner_parameters = { RUNNER_HOSTS: 'localhost', RUNNER_USERNAME: '******', RUNNER_PASSWORD: '******' } runner.runner_parameters = runner_parameters runner.pre_run() expected_kwargs = { 'hosts': ['localhost'], 'user': '******', 'password': '******', 'port': None, 'concurrency': 1, 'bastion_host': None, 'raise_on_any_error': False, 'connect': True, 'handle_stdout_line_func': mock.ANY, 'handle_stderr_line_func': mock.ANY } mock_client.assert_called_with(**expected_kwargs) # Private key provided as raw key material runner = Runner('id') runner.context = {} runner_parameters = { RUNNER_HOSTS: 'localhost', RUNNER_USERNAME: '******', RUNNER_PRIVATE_KEY: private_key, RUNNER_SSH_PORT: 22 } runner.runner_parameters = runner_parameters runner.pre_run() expected_kwargs = { 'hosts': ['localhost'], 'user': '******', 'pkey_material': private_key, 'port': 22, 'concurrency': 1, 'bastion_host': None, 'raise_on_any_error': False, 'connect': True, 'handle_stdout_line_func': mock.ANY, 'handle_stderr_line_func': mock.ANY } mock_client.assert_called_with(**expected_kwargs) # Private key provided as raw key material + passphrase runner = Runner('id') runner.context = {} runner_parameters = { RUNNER_HOSTS: 'localhost21', RUNNER_USERNAME: '******', RUNNER_PRIVATE_KEY: private_key, RUNNER_PASSPHRASE: 'passphrase21', RUNNER_SSH_PORT: 22 } runner.runner_parameters = runner_parameters runner.pre_run() expected_kwargs = { 'hosts': ['localhost21'], 'user': '******', 'pkey_material': private_key, 'passphrase': 'passphrase21', 'port': 22, 'concurrency': 1, 'bastion_host': None, 'raise_on_any_error': False, 'connect': True, 'handle_stdout_line_func': mock.ANY, 'handle_stderr_line_func': mock.ANY } mock_client.assert_called_with(**expected_kwargs) # Private key provided as path to the private key file runner = Runner('id') runner.context = {} runner_parameters = { RUNNER_HOSTS: 'localhost', RUNNER_USERNAME: '******', RUNNER_PRIVATE_KEY: private_key_path, RUNNER_SSH_PORT: 22 } runner.runner_parameters = runner_parameters runner.pre_run() expected_kwargs = { 'hosts': ['localhost'], 'user': '******', 'pkey_file': private_key_path, 'port': 22, 'concurrency': 1, 'bastion_host': None, 'raise_on_any_error': False, 'connect': True, 'handle_stdout_line_func': mock.ANY, 'handle_stderr_line_func': mock.ANY } mock_client.assert_called_with(**expected_kwargs) # Private key provided as path to the private key file + passphrase runner = Runner('id') runner.context = {} runner_parameters = { RUNNER_HOSTS: 'localhost31', RUNNER_USERNAME: '******', RUNNER_PRIVATE_KEY: private_key_path, RUNNER_PASSPHRASE: 'passphrase31', RUNNER_SSH_PORT: 22 } runner.runner_parameters = runner_parameters runner.pre_run() expected_kwargs = { 'hosts': ['localhost31'], 'user': '******', 'pkey_file': private_key_path, 'passphrase': 'passphrase31', 'port': 22, 'concurrency': 1, 'bastion_host': None, 'raise_on_any_error': False, 'connect': True, 'handle_stdout_line_func': mock.ANY, 'handle_stderr_line_func': mock.ANY } mock_client.assert_called_with(**expected_kwargs) # No password or private key provided, should default to system user private key runner = Runner('id') runner.context = {} runner_parameters = { RUNNER_HOSTS: 'localhost4', RUNNER_SSH_PORT: 22 } runner.runner_parameters = runner_parameters runner.pre_run() expected_kwargs = { 'hosts': ['localhost4'], 'user': None, 'pkey_file': None, 'port': 22, 'concurrency': 1, 'bastion_host': None, 'raise_on_any_error': False, 'connect': True, 'handle_stdout_line_func': mock.ANY, 'handle_stderr_line_func': mock.ANY } mock_client.assert_called_with(**expected_kwargs)
def test_use_ssh_config_port_value_provided_in_the_config(self, mock_sshclient): cfg.CONF.set_override(name='use_ssh_config', override=True, group='ssh_runner') ssh_config_file_path = os.path.join(get_resources_base_path(), 'ssh', 'empty_config') cfg.CONF.set_override(name='ssh_config_file_path', override=ssh_config_file_path, group='ssh_runner') # 1. Default port is used (not explicitly provided) mock_client = mock.Mock() mock_sshclient.return_value = mock_client conn_params = {'hostname': 'dummy.host.org', 'username': '******', 'password': '******', 'timeout': '600'} ssh_client = ParamikoSSHClient(**conn_params) ssh_client.connect() call_kwargs = mock_client.connect.call_args[1] self.assertEqual(call_kwargs['port'], 22) mock_client = mock.Mock() mock_sshclient.return_value = mock_client conn_params = {'hostname': 'dummy.host.org', 'username': '******', 'password': '******', 'port': None, 'timeout': '600'} ssh_client = ParamikoSSHClient(**conn_params) ssh_client.connect() call_kwargs = mock_client.connect.call_args[1] self.assertEqual(call_kwargs['port'], 22) # 2. Default port is used (explicitly provided) mock_client = mock.Mock() mock_sshclient.return_value = mock_client conn_params = {'hostname': 'dummy.host.org', 'username': '******', 'password': '******', 'port': DEFAULT_SSH_PORT, 'timeout': '600'} ssh_client = ParamikoSSHClient(**conn_params) ssh_client.connect() call_kwargs = mock_client.connect.call_args[1] self.assertEqual(call_kwargs['port'], DEFAULT_SSH_PORT) self.assertEqual(call_kwargs['port'], 22) # 3. Custom port is used (explicitly provided) mock_client = mock.Mock() mock_sshclient.return_value = mock_client conn_params = {'hostname': 'dummy.host.org', 'username': '******', 'password': '******', 'port': 5555, 'timeout': '600'} ssh_client = ParamikoSSHClient(**conn_params) ssh_client.connect() call_kwargs = mock_client.connect.call_args[1] self.assertEqual(call_kwargs['port'], 5555) # 4. Custom port is specified in the ssh config (it has precedence over default port) ssh_config_file_path = os.path.join(get_resources_base_path(), 'ssh', 'ssh_config_custom_port') cfg.CONF.set_override(name='ssh_config_file_path', override=ssh_config_file_path, group='ssh_runner') mock_client = mock.Mock() mock_sshclient.return_value = mock_client conn_params = {'hostname': 'dummy.host.org', 'username': '******', 'password': '******'} ssh_client = ParamikoSSHClient(**conn_params) ssh_client.connect() call_kwargs = mock_client.connect.call_args[1] self.assertEqual(call_kwargs['port'], 6677) mock_client = mock.Mock() mock_sshclient.return_value = mock_client conn_params = {'hostname': 'dummy.host.org', 'username': '******', 'password': '******', 'port': DEFAULT_SSH_PORT} ssh_client = ParamikoSSHClient(**conn_params) ssh_client.connect() call_kwargs = mock_client.connect.call_args[1] self.assertEqual(call_kwargs['port'], 6677) # 5. Custom port is specified in ssh config, but one is also provided via runner parameter # (runner parameter one has precedence) ssh_config_file_path = os.path.join(get_resources_base_path(), 'ssh', 'ssh_config_custom_port') cfg.CONF.set_override(name='ssh_config_file_path', override=ssh_config_file_path, group='ssh_runner') mock_client = mock.Mock() mock_sshclient.return_value = mock_client conn_params = {'hostname': 'dummy.host.org', 'username': '******', 'password': '******', 'port': 9999} ssh_client = ParamikoSSHClient(**conn_params) ssh_client.connect() call_kwargs = mock_client.connect.call_args[1] self.assertEqual(call_kwargs['port'], 9999)