From 02d9ba752959bf91b91306566d7cb226d75a1bc1 Mon Sep 17 00:00:00 2001 From: Daryl Walleck Date: Thu, 1 Oct 2015 15:28:49 -0500 Subject: [PATCH] Provides capability to use a Tempest accounts file refstack-client currently uses the user information provided in the identity section of the Tempest configuration when determining the cpid. The account information from the identity section has now been made optional and a secondary option of using a yaml file with test account information was added. refstack-client currently is not aware of this accounts file and will fail to run if the user is using only the accounts file and has not filled in the user information in the identity section. This change checks to see if the user has specified an accounts file to use and reads the user data from there when applicable. Change-Id: Id5a5a1800febc23a1006b29e58fec05a3aa40af1 Closes-Bug: 1501903 --- refstack_client/refstack_client.py | 49 ++++++++-- refstack_client/tests/unit/test-accounts.yaml | 5 + refstack_client/tests/unit/test_client.py | 97 +++++++++++++++++++ requirements.txt | 1 + 4 files changed, 146 insertions(+), 6 deletions(-) create mode 100644 refstack_client/tests/unit/test-accounts.yaml diff --git a/refstack_client/refstack_client.py b/refstack_client/refstack_client.py index 877e62c..465c213 100755 --- a/refstack_client/refstack_client.py +++ b/refstack_client/refstack_client.py @@ -44,6 +44,7 @@ import requests.exceptions import six.moves from subunit_processor import SubunitProcessor from list_parser import TestListParser +import yaml def get_input(): @@ -53,6 +54,13 @@ def get_input(): return raw_input().lower() # pragma: no cover +def read_accounts_yaml(path): + """Reads a set of accounts from the specified file""" + with open(path, 'r') as yaml_file: + accounts = yaml.load(yaml_file) + return accounts + + class RefstackClient: log_format = "%(asctime)s %(name)s:%(lineno)d %(levelname)s %(message)s" @@ -135,16 +143,45 @@ class RefstackClient: 'api_v3') and conf_file.has_option('identity', 'uri_v3')) else 'v2') + + if conf_file.has_option('auth', 'test_accounts_file'): + account_file = os.path.expanduser( + conf_file.get('auth', 'test_accounts_file')) + if not os.path.isfile(account_file): + self.logger.error( + 'Accounts file not found: %s' % account_file) + exit(1) + + accounts = read_accounts_yaml(account_file) + if not accounts: + self.logger.error('Accounts file %s found, ' + 'but was empty.' % account_file) + exit(1) + + account = accounts[0] + username = account.get('username') + password = account.get('password') + tenant_id = account.get('tenant_id') + tenant_name = account.get('tenant_name') + else: + username = conf_file.get('identity', 'username') + password = conf_file.get('identity', 'password') + + if self.conf.has_option('identity', 'tenant_id'): + tenant_id = conf_file.get('identity', 'tenant_id') + else: + tenant_id = None + tenant_name = conf_file.get('identity', 'tenant_name') + args = { 'insecure': self.args.insecure, - 'username': conf_file.get('identity', 'username'), - 'password': conf_file.get('identity', 'password') + 'username': username, + 'password': password } - - if self.conf.has_option('identity', 'tenant_id'): - args['tenant_id'] = conf_file.get('identity', 'tenant_id') + if tenant_id: + args['tenant_id'] = tenant_id else: - args['tenant_name'] = conf_file.get('identity', 'tenant_name') + args['tenant_name'] = tenant_name if auth_version == 'v2': args['auth_url'] = conf_file.get('identity', 'uri') diff --git a/refstack_client/tests/unit/test-accounts.yaml b/refstack_client/tests/unit/test-accounts.yaml new file mode 100644 index 0000000..b294c6e --- /dev/null +++ b/refstack_client/tests/unit/test-accounts.yaml @@ -0,0 +1,5 @@ +- username: 'admin' + tenant_name: 'tenant_name' + password: 'test' + roles: + - 'Member' diff --git a/refstack_client/tests/unit/test_client.py b/refstack_client/tests/unit/test_client.py index c38dec6..3045454 100755 --- a/refstack_client/tests/unit/test_client.py +++ b/refstack_client/tests/unit/test_client.py @@ -182,6 +182,103 @@ class TestRefstackClient(unittest.TestCase): ) self.assertEqual('test-id', cpid) + def test_get_cpid_from_keystone_by_tenant_name_from_account_file(self): + """ + Test getting a CPID from Keystone using an admin tenant name + from an accounts file. + """ + + args = rc.parse_cli_args(self.mock_argv()) + client = rc.RefstackClient(args) + client.tempest_dir = self.test_path + client._prep_test() + client.conf.add_section('auth') + client.conf.set('auth', + 'test_accounts_file', + '%s/test-accounts.yaml' % self.test_path) + self.mock_keystone() + cpid = client._get_cpid_from_keystone(client.conf) + self.ks2_client_builder.assert_called_with( + username='admin', tenant_name='tenant_name', + password='test', auth_url='0.0.0.0:35357/v2.0', insecure=False + ) + self.assertEqual('test-id', cpid) + + def test_get_cpid_from_keystone_by_tenant_id_from_account_file(self): + """ + Test getting a CPID from Keystone using an admin tenant ID + from an accounts file. + """ + + accounts = [ + { + 'username': 'admin', + 'tenant_id': 'tenant_id', + 'password': 'test' + } + ] + self.patch( + 'refstack_client.refstack_client.read_accounts_yaml', + return_value=accounts) + + args = rc.parse_cli_args(self.mock_argv()) + client = rc.RefstackClient(args) + client.tempest_dir = self.test_path + client._prep_test() + client.conf.add_section('auth') + client.conf.set('auth', + 'test_accounts_file', + '%s/test-accounts.yaml' % self.test_path) + self.mock_keystone() + cpid = client._get_cpid_from_keystone(client.conf) + self.ks2_client_builder.assert_called_with( + username='admin', tenant_id='tenant_id', + password='test', auth_url='0.0.0.0:35357/v2.0', insecure=False + ) + self.assertEqual('test-id', cpid) + + def test_get_cpid_account_file_not_found(self): + """ + Test that the client will exit if an accounts file is specified, + but does not exist. + """ + args = rc.parse_cli_args(self.mock_argv()) + client = rc.RefstackClient(args) + client.tempest_dir = self.test_path + client._prep_test() + + client.conf.add_section('auth') + client.conf.set('auth', + 'test_accounts_file', + '%s/some-file.yaml' % self.test_path) + + self.mock_keystone() + with self.assertRaises(SystemExit): + client._get_cpid_from_keystone(client.conf) + + def test_get_cpid_account_file_empty(self): + """ + Test that the client will exit if an accounts file exists, + but is empty. + """ + self.patch( + 'refstack_client.refstack_client.read_accounts_yaml', + return_value=None) + + args = rc.parse_cli_args(self.mock_argv()) + client = rc.RefstackClient(args) + client.tempest_dir = self.test_path + client._prep_test() + + client.conf.add_section('auth') + client.conf.set('auth', + 'test_accounts_file', + '%s/some-file.yaml' % self.test_path) + + self.mock_keystone() + with self.assertRaises(SystemExit): + client._get_cpid_from_keystone(client.conf) + def test_get_cpid_from_keystone_insecure(self): """ Test getting the CPID from Keystone with the insecure arg passed in. diff --git a/requirements.txt b/requirements.txt index ae29239..2b066f0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,3 +3,4 @@ gitpython>=0.3.2.RC1 python-subunit>=0.0.18 pycrypto>=2.6.1 requests>=2.5.2 +PyYAML>=3.1.0