Remove RefStack dependency on Keystone client.

RefStack should use Tempest approach for retrieving Keystone service
Id. For RefStack purpose, raw API call to keystone should be enough
to get necessary information.

Closes-Bug: #1528357

Change-Id: I555308aabb59b638e22249ead882ca5b09043b7b
This commit is contained in:
david liu 2016-01-11 17:58:00 +08:00 committed by David Liu
parent 5e5233c199
commit 0fc224a533
3 changed files with 273 additions and 342 deletions

View File

@ -38,8 +38,6 @@ import time
from Crypto.Hash import SHA256 from Crypto.Hash import SHA256
from Crypto.PublicKey import RSA from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5 from Crypto.Signature import PKCS1_v1_5
from keystoneclient.v2_0 import client as ksclient2
from keystoneclient.v3 import client as ksclient3
import requests import requests
import requests.exceptions import requests.exceptions
import six.moves import six.moves
@ -140,8 +138,9 @@ class RefstackClient:
return os.path.join(tempest_dir, '.testrepository', subunit_file) return os.path.join(tempest_dir, '.testrepository', subunit_file)
def _get_cpid_from_keystone(self, conf_file): def _get_keystone_config(self, conf_file):
'''This will get the Keystone service ID which is used as the CPID.''' '''This will get and return the keystone configs
from config file.'''
try: try:
# Prefer Keystone V3 API if it is enabled # Prefer Keystone V3 API if it is enabled
auth_version = ( auth_version = (
@ -151,7 +150,15 @@ class RefstackClient:
'api_v3') 'api_v3')
and conf_file.has_option('identity', 'uri_v3')) and conf_file.has_option('identity', 'uri_v3'))
else 'v2') else 'v2')
if auth_version == 'v2':
auth_url = '%s/tokens' % (conf_file.get('identity', 'uri')
.rstrip('/'))
elif auth_version == 'v3':
auth_url = '%s/auth/tokens' % (conf_file.get('identity',
'uri_v3').rstrip('/'))
domain_name = 'Default'
if conf_file.has_option('identity', 'domain_name'):
domain_name = conf_file.get('identity', 'domain_name')
if conf_file.has_option('auth', 'test_accounts_file'): if conf_file.has_option('auth', 'test_accounts_file'):
account_file = os.path.expanduser( account_file = os.path.expanduser(
conf_file.get('auth', 'test_accounts_file')) conf_file.get('auth', 'test_accounts_file'))
@ -165,12 +172,17 @@ class RefstackClient:
self.logger.error('Accounts file %s found, ' self.logger.error('Accounts file %s found, '
'but was empty.' % account_file) 'but was empty.' % account_file)
exit(1) exit(1)
account = accounts[0] account = accounts[0]
username = account.get('username') username = account.get('username')
password = account.get('password') password = account.get('password')
tenant_id = account.get('tenant_id') tenant_id = account.get('tenant_id')
tenant_name = account.get('tenant_name') tenant_name = account.get('tenant_name')
return {'auth_version': auth_version,
'auth_url': auth_url,
'domain_name': domain_name,
'username': username, 'password': password,
'tenant_id': tenant_id, 'tenant_name': tenant_name
}
else: else:
username = conf_file.get('identity', 'username') username = conf_file.get('identity', 'username')
password = conf_file.get('identity', 'password') password = conf_file.get('identity', 'password')
@ -179,69 +191,107 @@ class RefstackClient:
tenant_id = conf_file.get('identity', 'tenant_id') tenant_id = conf_file.get('identity', 'tenant_id')
else: else:
tenant_id = None tenant_id = None
tenant_name = conf_file.get('identity', 'tenant_name') tenant_name = conf_file.get('identity', 'tenant_name')
return {'auth_version': auth_version,
args = { 'auth_url': auth_url,
'insecure': self.args.insecure, 'domain_name': domain_name,
'username': username, 'username': username, 'password': password,
'password': password 'tenant_id': tenant_id, 'tenant_name': tenant_name}
}
if tenant_id:
args['tenant_id'] = tenant_id
else:
args['tenant_name'] = tenant_name
try:
if auth_version == 'v2':
args['auth_url'] = conf_file.get('identity', 'uri')
client = ksclient2.Client(**args)
token = client.auth_ref
for service in token['serviceCatalog']:
if service['type'] == 'identity':
if service['endpoints'][0]['id']:
return service['endpoints'][0]['id']
# Raise a key error if 'identity' was not found so that it
# can be caught and have an appropriate error displayed.
raise KeyError
elif auth_version == 'v3':
args['auth_url'] = conf_file.get('identity', 'uri_v3')
if conf_file.has_option('identity', 'domain_name'):
args['project_domain_name'] = \
conf_file.get('identity', 'domain_name')
args['user_domain_name'] = conf_file.get('identity',
'domain_name')
if conf_file.has_option('identity', 'region'):
args['region_name'] = conf_file.get('identity',
'region')
client = ksclient3.Client(**args)
token = client.auth_ref
for service in token['catalog']:
if service['type'] == 'identity' and service['id']:
return service['id']
# Raise a key error if 'identity' was not found. It will
# be caught below as well.
raise KeyError
else:
raise ValueError('Auth_version %s is unsupported'
'' % auth_version)
# If a Key or Index Error was raised, one of the expected keys or
# indices for retrieving the identity service ID was not found.
except (KeyError, IndexError) as e:
self.logger.warning('Unable to retrieve CPID from Keystone %s '
'catalog. The catalog or the identity '
'service endpoint was not '
'found.' % auth_version)
except Exception as e:
self.logger.warning('Problems retrieving CPID from Keystone '
'using %s endpoint (%s)' % (auth_version,
args['auth_url']))
return self._generate_cpid_from_endpoint(args['auth_url'])
except ConfigParser.Error as e: except ConfigParser.Error as e:
# Most likely a missing section or option in the config file. # Most likely a missing section or option in the config file.
self.logger.error("Invalid Config File: %s" % e) self.logger.error("Invalid Config File: %s" % e)
exit(1) exit(1)
def _generate_keystone_data(self, auth_config):
'''This will generate data for http post to keystone
API from auth_config.'''
auth_version = auth_config['auth_version']
auth_url = auth_config['auth_url']
if auth_version == 'v2':
password_credential = {'username': auth_config['username'],
'password': auth_config['password']}
if auth_config['tenant_id']:
data = {
'auth': {
'tenantId': auth_config['tenant_id'],
'passwordCredentials': password_credential
}
}
else:
data = {
'auth': {
'tenantName': auth_config['tenant_name'],
'passwordCredentials': password_credential
}
}
return auth_version, auth_url, data
elif auth_version == 'v3':
identity = {'methods': ['password'], 'password':
{'user': {'name': auth_config['username'],
'domain': {
'name': auth_config['domain_name']
},
'password': auth_config['password']}}}
data = {
'auth': {
'identity': identity,
'scope': {
'project': {
'name': auth_config['username'],
'domain': {'name': auth_config['domain_name']}
}
}
}
}
return auth_version, auth_url, data
def _get_cpid_from_keystone(self, auth_version, auth_url, content):
'''This will get the Keystone service ID which is used as the CPID.'''
try:
headers = {'content-type': 'application/json'}
response = requests.post(auth_url,
data=json.dumps(content),
headers=headers,
verify=not self.args.insecure)
rsp = response.json()
if response.status_code in (200, 203):
# keystone API v2 response.
access = rsp['access']
for service in access['serviceCatalog']:
if service['type'] == 'identity':
if service['endpoints'][0]['id']:
return service['endpoints'][0]['id']
# Raise a key error if 'identity' was not found so that it
# can be caught and have an appropriate error displayed.
raise KeyError
elif response.status_code == 201:
# keystone API v3 response.
token = rsp['token']
for service in token['catalog']:
if service['type'] == 'identity' and service['id']:
return service['id']
# Raise a key error if 'identity' was not found.
# It will be caught below as well.
raise KeyError
else:
message = ('Invalid request with error '
'code: %s. Error message: %s'
'' % (rsp['error']['code'],
rsp['error']['message']))
raise requests.exceptions.HTTPError(message)
# If a Key or Index Error was raised, one of the expected keys or
# indices for retrieving the identity service ID was not found.
except (KeyError, IndexError) as e:
self.logger.warning('Unable to retrieve CPID from Keystone %s '
'catalog. The catalog or the identity '
'service endpoint was not '
'found.' % auth_version)
except Exception as e:
self.logger.warning('Problems retrieving CPID from Keystone '
'using %s endpoint (%s) with error (%s)'
% (auth_version, auth_url, e))
return self._generate_cpid_from_endpoint(auth_url)
def _generate_cpid_from_endpoint(self, endpoint): def _generate_cpid_from_endpoint(self, endpoint):
'''This method will md5 hash the hostname of a Keystone endpoint to '''This method will md5 hash the hostname of a Keystone endpoint to
generate a CPID.''' generate a CPID.'''
@ -333,7 +383,10 @@ class RefstackClient:
self._prep_test() self._prep_test()
results_file = self._get_next_stream_subunit_output_file( results_file = self._get_next_stream_subunit_output_file(
self.tempest_dir) self.tempest_dir)
cpid = self._get_cpid_from_keystone(self.conf) keystone_config = self._get_keystone_config(self.conf)
auth_version, auth_url, content = \
self._generate_keystone_data(keystone_config)
cpid = self._get_cpid_from_keystone(auth_version, auth_url, content)
self.logger.info("Starting Tempest test...") self.logger.info("Starting Tempest test...")
start_time = time.time() start_time = time.time()

View File

@ -24,6 +24,7 @@ import httmock
import mock import mock
from mock import MagicMock from mock import MagicMock
import unittest import unittest
import requests
import refstack_client.refstack_client as rc import refstack_client.refstack_client as rc
@ -68,7 +69,7 @@ class TestRefstackClient(unittest.TestCase):
argv.extend(('--', kwargs.get('test_cases', None))) argv.extend(('--', kwargs.get('test_cases', None)))
return argv return argv
def mock_keystone(self): def mock_data(self):
""" """
Mock the Keystone client methods. Mock the Keystone client methods.
""" """
@ -76,24 +77,13 @@ class TestRefstackClient(unittest.TestCase):
'endpoints': [{'id': 'test-id'}]} 'endpoints': [{'id': 'test-id'}]}
self.mock_identity_service_v3 = {'type': 'identity', self.mock_identity_service_v3 = {'type': 'identity',
'id': 'test-id'} 'id': 'test-id'}
self.mock_ks2_client = MagicMock( self.v2_config = {'auth_url': 'http://0.0.0.0:35357/v2.0/tokens',
name='ks_client', 'auth_version': 'v2',
**{'auth_ref': 'domain_name': 'Default',
{'serviceCatalog': [self.mock_identity_service_v2]}} 'password': 'test',
) 'tenant_id': 'admin_tenant_id',
self.mock_ks3_client = MagicMock( 'tenant_name': 'tenant_name',
name='ks_client', 'username': 'admin'}
**{'auth_ref':
{'catalog': [self.mock_identity_service_v3]}}
)
self.ks2_client_builder = self.patch(
'refstack_client.refstack_client.ksclient2.Client',
return_value=self.mock_ks2_client
)
self.ks3_client_builder = self.patch(
'refstack_client.refstack_client.ksclient3.Client',
return_value=self.mock_ks3_client
)
def setUp(self): def setUp(self):
""" """
@ -163,99 +153,6 @@ class TestRefstackClient(unittest.TestCase):
expected_file = "/tempest/path/.testrepository/0" expected_file = "/tempest/path/.testrepository/0"
self.assertEqual(expected_file, output_file) self.assertEqual(expected_file, output_file)
def test_get_cpid_from_keystone_with_tenant_id(self):
"""
Test getting the CPID from Keystone using an admin tenant ID.
"""
args = rc.parse_cli_args(self.mock_argv())
client = rc.RefstackClient(args)
client.tempest_dir = self.test_path
client._prep_test()
self.mock_keystone()
cpid = client._get_cpid_from_keystone(client.conf)
self.ks2_client_builder.assert_called_with(
username='admin', tenant_id='admin_tenant_id',
password='test', auth_url='http://0.0.0.0:35357/v2.0',
insecure=False
)
self.assertEqual('test-id', cpid)
def test_get_cpid_from_keystone_with_tenant_name(self):
"""
Test getting the CPID from Keystone using an admin tenant name.
"""
args = rc.parse_cli_args(self.mock_argv())
client = rc.RefstackClient(args)
client.tempest_dir = self.test_path
client._prep_test()
client.conf.remove_option('identity', 'tenant_id')
client.conf.set('identity', 'tenant_name', 'tenant_name')
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='http://0.0.0.0:35357/v2.0',
insecure=False
)
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='http://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='http://0.0.0.0:35357/v2.0',
insecure=False
)
self.assertEqual('test-id', cpid)
def test_get_cpid_account_file_not_found(self): def test_get_cpid_account_file_not_found(self):
""" """
Test that the client will exit if an accounts file is specified, Test that the client will exit if an accounts file is specified,
@ -271,11 +168,11 @@ class TestRefstackClient(unittest.TestCase):
'test_accounts_file', 'test_accounts_file',
'%s/some-file.yaml' % self.test_path) '%s/some-file.yaml' % self.test_path)
self.mock_keystone() self.mock_data()
with self.assertRaises(SystemExit): with self.assertRaises(SystemExit):
client._get_cpid_from_keystone(client.conf) client._get_keystone_config(client.conf)
def test_get_cpid_account_file_empty(self): def test_get_keystone_config_account_file_empty(self):
""" """
Test that the client will exit if an accounts file exists, Test that the client will exit if an accounts file exists,
but is empty. but is empty.
@ -294,119 +191,72 @@ class TestRefstackClient(unittest.TestCase):
'test_accounts_file', 'test_accounts_file',
'%s/some-file.yaml' % self.test_path) '%s/some-file.yaml' % self.test_path)
self.mock_keystone() self.mock_data()
with self.assertRaises(SystemExit): with self.assertRaises(SystemExit):
client._get_cpid_from_keystone(client.conf) client._get_keystone_config(client.conf)
def test_get_cpid_from_keystone_insecure(self): def test_get_keystone_config(self):
""" """
Test getting the CPID from Keystone with the insecure arg passed in. Test that keystone configs properly parsed.
"""
argv = self.mock_argv()
argv.append('--insecure')
args = rc.parse_cli_args(argv)
client = rc.RefstackClient(args)
client.tempest_dir = self.test_path
client._prep_test()
self.mock_keystone()
client._get_cpid_from_keystone(client.conf)
self.ks2_client_builder.assert_called_with(
username='admin', tenant_id='admin_tenant_id',
password='test', auth_url='http://0.0.0.0:35357/v2.0',
insecure=True
)
def test_get_cpid_from_keystone_v3(self):
"""
Test getting the CPID from Keystone API v3.
""" """
args = rc.parse_cli_args(self.mock_argv()) args = rc.parse_cli_args(self.mock_argv())
client = rc.RefstackClient(args) client = rc.RefstackClient(args)
client.tempest_dir = self.test_path client.tempest_dir = self.test_path
client._prep_test() client._prep_test()
client.conf.remove_option('identity', 'tenant_id')
client.conf.set('identity', 'tenant_name', 'tenant_name') client.conf.set('identity', 'tenant_name', 'tenant_name')
client.conf.set('identity-feature-enabled', 'api_v3', 'true') self.mock_data()
self.mock_keystone() actual_result = client._get_keystone_config(client.conf)
cpid = client._get_cpid_from_keystone(client.conf) expected_result = self.v2_config
self.ks3_client_builder.assert_called_with( self.assertEqual(expected_result, actual_result)
username='admin', tenant_name='tenant_name',
password='test', auth_url='http://0.0.0.0:35357/v3',
insecure=False
)
self.assertEqual('test-id', cpid)
def test_get_cpid_from_keystone_v2_varying_catalogs(self): def test_get_cpid_from_keystone_by_tenant_name_from_account_file(self):
""" """
Test getting the CPID from keystone API v2 varying catalogs. Test getting a CPID from Keystone using an admin tenant name
from an accounts file.
""" """
argv = self.mock_argv() args = rc.parse_cli_args(self.mock_argv())
args = rc.parse_cli_args(argv)
client = rc.RefstackClient(args) client = rc.RefstackClient(args)
client.tempest_dir = self.test_path client.tempest_dir = self.test_path
client._prep_test() client._prep_test()
client.conf.add_section('auth')
client.conf.set('auth',
'test_accounts_file',
'%s/test-accounts.yaml' % self.test_path)
self.mock_data()
actual_result = client._get_keystone_config(client.conf)
expected_result = None
self.assertEqual(expected_result, actual_result['tenant_id'])
accounts = [
{
'username': 'admin',
'tenant_id': 'tenant_id',
'password': 'test'
}
]
self.patch(
'refstack_client.refstack_client.read_accounts_yaml',
return_value=accounts)
actual_result = client._get_keystone_config(client.conf)
self.assertEqual('tenant_id', actual_result['tenant_id'])
client._generate_cpid_from_endpoint = MagicMock() def test_generate_keystone_data(self):
"""Test that correct data is generated."""
# Test when the identity endpoints is empty args = rc.parse_cli_args(self.mock_argv())
self.mock_ks2_client = MagicMock( client = rc.RefstackClient(args)
name='ks_client', client.tempest_dir = self.test_path
**{'auth_ref': client._prep_test()
{'serviceCatalog': [{'type': 'identity', 'endpoints': []}]}} client.conf.set('identity', 'tenant_name', 'tenant_name')
) self.mock_data()
self.ks2_client_builder = self.patch( configs = client._get_keystone_config(client.conf)
'refstack_client.refstack_client.ksclient2.Client', actual_results = client._generate_keystone_data(configs)
return_value=self.mock_ks2_client expected_results = ('v2', 'http://0.0.0.0:35357/v2.0/tokens',
) {'auth':
client._get_cpid_from_keystone(client.conf) {'passwordCredentials':
# Failover CPID should be generated. {
client._generate_cpid_from_endpoint.assert_called_with( 'username': 'admin', 'password': 'test'
'http://0.0.0.0:35357/v2.0' },
) 'tenantId': 'admin_tenant_id'}})
self.assertEqual(expected_results, actual_results)
# Test when the catalog is empty
self.mock_ks2_client = MagicMock(
name='ks_client',
**{'auth_ref': {'serviceCatalog': []}}
)
self.ks2_client_builder = self.patch(
'refstack_client.refstack_client.ksclient2.Client',
return_value=self.mock_ks2_client
)
client._get_cpid_from_keystone(client.conf)
# Failover CPID should be generated.
client._generate_cpid_from_endpoint.assert_called_with(
'http://0.0.0.0:35357/v2.0'
)
# Test when there is no service catalog
self.mock_ks2_client = MagicMock(name='ks_client', **{'auth_ref': {}})
self.ks2_client_builder = self.patch(
'refstack_client.refstack_client.ksclient2.Client',
return_value=self.mock_ks2_client
)
client._get_cpid_from_keystone(client.conf)
# Failover CPID should be generated.
client._generate_cpid_from_endpoint.assert_called_with(
'http://0.0.0.0:35357/v2.0'
)
# Test when catalog has other non-identity services.
self.mock_ks2_client = MagicMock(
name='ks_client',
**{'auth_ref':
{'serviceCatalog': [{'type': 'compute',
'endpoints': [{'id': 'test-id1'}]},
{'type': 'identity',
'endpoints': [{'id': 'test-id2'}]}]}
}
)
self.ks2_client_builder = self.patch(
'refstack_client.refstack_client.ksclient2.Client',
return_value=self.mock_ks2_client
)
cpid = client._get_cpid_from_keystone(client.conf)
self.assertEqual('test-id2', cpid)
def test_get_cpid_from_keystone_v3_varying_catalogs(self): def test_get_cpid_from_keystone_v3_varying_catalogs(self):
""" """
@ -419,65 +269,79 @@ class TestRefstackClient(unittest.TestCase):
client.conf.remove_option('identity', 'tenant_id') client.conf.remove_option('identity', 'tenant_id')
client.conf.set('identity', 'tenant_name', 'tenant_name') client.conf.set('identity', 'tenant_name', 'tenant_name')
client.conf.set('identity-feature-enabled', 'api_v3', 'true') client.conf.set('identity-feature-enabled', 'api_v3', 'true')
self.mock_data()
configs = client._get_keystone_config(client.conf)
auth_version, auth_url, content = \
client._generate_keystone_data(configs)
client._generate_cpid_from_endpoint = MagicMock() client._generate_cpid_from_endpoint = MagicMock()
requests.post = MagicMock()
# Test when the identity ID is None.
ks3_ID_None = {'auth_ref': {'catalog':
[{'type': 'identity', 'id': None}]}}
# Test when the identity ID is None. @httmock.urlmatch(netloc=r'(.*\.)?127.0.0.1$', path='/v3/auth/tokens')
self.mock_ks3_client = MagicMock( def keystone_api_v3_mock(auth_version, url, request):
name='ks_client', return ks3_ID_None
**{'auth_ref': {'catalog': [{'type': 'identity', 'id': None}]}} with httmock.HTTMock(keystone_api_v3_mock):
) client._get_cpid_from_keystone(auth_version, auth_url, content)
self.ks3_client_builder = self.patch( client._generate_cpid_from_endpoint.assert_called_with(auth_url)
'refstack_client.refstack_client.ksclient3.Client',
return_value=self.mock_ks3_client
)
client._get_cpid_from_keystone(client.conf)
# Failover CPID should be generated.
client._generate_cpid_from_endpoint.assert_called_with(
'http://0.0.0.0:35357/v3'
)
# Test when the catalog is empty. # Test when the catalog is empty.
self.mock_ks3_client = MagicMock( ks3_catalog_empty = {'auth_ref': {'catalog': []}}
name='ks_client',
**{'auth_ref': {'catalog': []}} @httmock.urlmatch(netloc=r'(.*\.)?127.0.0.1$', path='/v3/auth/tokens')
) def keystone_api_v3_mock(auth_version, url, request):
self.ks3_client_builder = self.patch( return ks3_catalog_empty
'refstack_client.refstack_client.ksclient3.Client', with httmock.HTTMock(keystone_api_v3_mock):
return_value=self.mock_ks3_client client._get_cpid_from_keystone(auth_version, auth_url, content)
) client._generate_cpid_from_endpoint.assert_called_with(auth_url)
client._get_cpid_from_keystone(client.conf)
# Failover CPID should be generated.
client._generate_cpid_from_endpoint.assert_called_with(
'http://0.0.0.0:35357/v3'
)
# Test when there is no service catalog. # Test when there is no service catalog.
self.mock_ks3_client = MagicMock(name='ks_client', **{'auth_ref': {}}) ks3_no_catalog = {'auth_ref': {}}
self.ks3_client_builder = self.patch(
'refstack_client.refstack_client.ksclient3.Client', @httmock.urlmatch(netloc=r'(.*\.)?127.0.0.1$', path='/v3/auth/tokens')
return_value=self.mock_ks3_client def keystone_api_v3_mock(auth_version, url, request):
) return ks3_no_catalog
client._get_cpid_from_keystone(client.conf) with httmock.HTTMock(keystone_api_v3_mock):
# Failover CPID should be generated. client._get_cpid_from_keystone(auth_version, auth_url, content)
client._generate_cpid_from_endpoint.assert_called_with( client._generate_cpid_from_endpoint.assert_called_with(auth_url)
'http://0.0.0.0:35357/v3'
)
#Test when catalog has other non-identity services. #Test when catalog has other non-identity services.
self.mock_ks3_client = MagicMock( ks3_other_services = {'token': {'catalog': [{'type': 'compute',
name='ks_client', 'id': 'test-id1'},
**{'auth_ref': {'catalog': [{'type': 'compute',
'id': 'test-id1'},
{'type': 'identity', {'type': 'identity',
'id': 'test-id2'}]}} 'id': 'test-id2'}]}}
) headers = {'content-type': 'application/json'}
self.ks3_client_builder = self.patch(
'refstack_client.refstack_client.ksclient3.Client', @httmock.urlmatch(netloc=r'(.*\.)?127.0.0.1$', path='/v3/auth/tokens')
return_value=self.mock_ks3_client def keystone_api_v3_mock(auth_version, url, request):
) return ks3_other_services
cpid = client._get_cpid_from_keystone(client.conf) with httmock.HTTMock(keystone_api_v3_mock):
self.assertEqual('test-id2', cpid) client._get_cpid_from_keystone(auth_version, auth_url, content)
requests.post.assert_called_with(auth_url,
data=json.dumps(content),
headers=headers,
verify=True)
def test_get_cpid_from_keystone_failure_handled(self):
"""Test that get cpid from keystone API failure handled."""
args = rc.parse_cli_args(self.mock_argv())
client = rc.RefstackClient(args)
client.tempest_dir = self.test_path
client._prep_test()
client.conf.set('identity', 'tenant_name', 'tenant_name')
client.logger.warning = MagicMock()
client._generate_cpid_from_endpoint = MagicMock()
self.mock_data()
configs = client._get_keystone_config(client.conf)
auth_version, url, content = client._generate_keystone_data(configs)
@httmock.urlmatch(netloc=r'(.*\.)?127.0.0.1$', path='/v2/tokens')
def keystone_api_mock(auth_version, url, request):
return None
with httmock.HTTMock(keystone_api_mock):
client._get_cpid_from_keystone(auth_version, url, content)
client._generate_cpid_from_endpoint.assert_called_with(url)
def test_generate_cpid_from_endpoint(self): def test_generate_cpid_from_endpoint(self):
""" """
@ -589,11 +453,9 @@ class TestRefstackClient(unittest.TestCase):
with httmock.HTTMock(refstack_api_mock): with httmock.HTTMock(refstack_api_mock):
client.post_results("http://127.0.0.1", content) client.post_results("http://127.0.0.1", content)
client.logger.info.assert_called_with(
client.logger.info.assert_called_with( 'http://127.0.0.1/v1/results/ Response: '
'http://127.0.0.1/v1/results/ Response: ' '%s' % expected_response)
'%s' % expected_response
)
def test_post_results_with_sign(self): def test_post_results_with_sign(self):
""" """
@ -616,10 +478,9 @@ class TestRefstackClient(unittest.TestCase):
with httmock.HTTMock(refstack_api_mock): with httmock.HTTMock(refstack_api_mock):
client.post_results("http://127.0.0.1", content, client.post_results("http://127.0.0.1", content,
sign_with=self.test_path + '/rsa_key') sign_with=self.test_path + '/rsa_key')
client.logger.info.assert_called_with( client.logger.info.assert_called_with(
'http://127.0.0.1/v1/results/ Response: ' 'http://127.0.0.1/v1/results/ Response: '
'%s' % expected_response '%s' % expected_response)
)
def test_run_tempest(self): def test_run_tempest(self):
""" """
@ -634,11 +495,13 @@ class TestRefstackClient(unittest.TestCase):
'refstack_client.refstack_client.subprocess.Popen', 'refstack_client.refstack_client.subprocess.Popen',
return_value=MagicMock(returncode=0)) return_value=MagicMock(returncode=0))
self.patch("os.path.isfile", return_value=True) self.patch("os.path.isfile", return_value=True)
self.mock_keystone() self.mock_data()
client.get_passed_tests = MagicMock(return_value=[{'name': 'test'}]) client.get_passed_tests = MagicMock(return_value=[{'name': 'test'}])
client.logger.info = MagicMock() client.logger.info = MagicMock()
client._save_json_results = MagicMock() client._save_json_results = MagicMock()
client.post_results = MagicMock() client.post_results = MagicMock()
client._get_keystone_config = MagicMock(
return_value=self.v2_config)
client.test() client.test()
mock_popen.assert_called_with( mock_popen.assert_called_with(
@ -664,10 +527,13 @@ class TestRefstackClient(unittest.TestCase):
'refstack_client.refstack_client.subprocess.Popen', 'refstack_client.refstack_client.subprocess.Popen',
return_value=MagicMock(returncode=0)) return_value=MagicMock(returncode=0))
self.patch("os.path.isfile", return_value=True) self.patch("os.path.isfile", return_value=True)
self.mock_keystone() self.mock_data()
client.get_passed_tests = MagicMock(return_value=['test']) client.get_passed_tests = MagicMock(return_value=['test'])
client.post_results = MagicMock() client.post_results = MagicMock()
client._save_json_results = MagicMock() client._save_json_results = MagicMock()
client._get_keystone_config = MagicMock(
return_value=self.v2_config)
client._get_cpid_from_keystone = MagicMock()
client.test() client.test()
mock_popen.assert_called_with( mock_popen.assert_called_with(
['%s/run_tempest.sh' % self.test_path, '-C', self.conf_file_name, ['%s/run_tempest.sh' % self.test_path, '-C', self.conf_file_name,
@ -693,10 +559,14 @@ class TestRefstackClient(unittest.TestCase):
return_value=MagicMock(returncode=0) return_value=MagicMock(returncode=0)
) )
self.patch("os.path.isfile", return_value=True) self.patch("os.path.isfile", return_value=True)
self.mock_keystone() self.mock_data()
client.get_passed_tests = MagicMock(return_value=['test']) client.get_passed_tests = MagicMock(return_value=['test'])
client.post_results = MagicMock() client.post_results = MagicMock()
client._save_json_results = MagicMock() client._save_json_results = MagicMock()
client._get_keystone_config = MagicMock(
return_value=self.v2_config)
client._get_cpid_from_keystone = MagicMock(
return_value='test-id')
client.test() client.test()
mock_popen.assert_called_with( mock_popen.assert_called_with(
['%s/run_tempest.sh' % self.test_path, '-C', self.conf_file_name, ['%s/run_tempest.sh' % self.test_path, '-C', self.conf_file_name,
@ -724,12 +594,14 @@ class TestRefstackClient(unittest.TestCase):
'refstack_client.refstack_client.subprocess.Popen', 'refstack_client.refstack_client.subprocess.Popen',
return_value=MagicMock(returncode=0)) return_value=MagicMock(returncode=0))
self.patch("os.path.isfile", return_value=True) self.patch("os.path.isfile", return_value=True)
self.mock_keystone() self.mock_data()
client.get_passed_tests = MagicMock(return_value=[{'name': 'test'}]) client.get_passed_tests = MagicMock(return_value=[{'name': 'test'}])
client._save_json_results = MagicMock() client._save_json_results = MagicMock()
client.post_results = MagicMock() client.post_results = MagicMock()
lp.TestListParser.get_normalized_test_list = MagicMock( lp.TestListParser.get_normalized_test_list = MagicMock(
return_value="/tmp/some-list") return_value="/tmp/some-list")
client._get_keystone_config = MagicMock(
return_value=self.v2_config)
client.test() client.test()
lp.TestListParser.get_normalized_test_list.assert_called_with( lp.TestListParser.get_normalized_test_list.assert_called_with(
@ -773,9 +645,13 @@ class TestRefstackClient(unittest.TestCase):
'refstack_client.refstack_client.subprocess.Popen', 'refstack_client.refstack_client.subprocess.Popen',
return_value=MagicMock(returncode=0)) return_value=MagicMock(returncode=0))
self.patch("os.path.isfile", return_value=True) self.patch("os.path.isfile", return_value=True)
self.mock_keystone() self.mock_data()
client.get_passed_tests = MagicMock(return_value=['test']) client.get_passed_tests = MagicMock(return_value=['test'])
client._save_json_results = MagicMock() client._save_json_results = MagicMock()
client._get_keystone_config = MagicMock(
return_value=self.v2_config)
client._get_cpid_from_keystone = MagicMock(
return_value='test-id')
client.test() client.test()
mock_popen.assert_called_with( mock_popen.assert_called_with(
@ -796,11 +672,14 @@ class TestRefstackClient(unittest.TestCase):
""" """
self.patch('refstack_client.refstack_client.subprocess.Popen', self.patch('refstack_client.refstack_client.subprocess.Popen',
return_value=MagicMock(returncode=1)) return_value=MagicMock(returncode=1))
self.mock_keystone()
args = rc.parse_cli_args(self.mock_argv(verbose='-vv')) args = rc.parse_cli_args(self.mock_argv(verbose='-vv'))
client = rc.RefstackClient(args) client = rc.RefstackClient(args)
client.tempest_dir = self.test_path client.tempest_dir = self.test_path
self.mock_data()
client.logger.error = MagicMock() client.logger.error = MagicMock()
client._get_keystone_config = MagicMock(
return_value=self.v2_config)
client._get_cpid_from_keystone = MagicMock()
client.test() client.test()
self.assertTrue(client.logger.error.called) self.assertTrue(client.logger.error.called)

View File

@ -1,4 +1,3 @@
python-keystoneclient>=0.10.0
gitpython>=0.3.2.RC1 gitpython>=0.3.2.RC1
python-subunit>=0.0.18 python-subunit>=0.0.18
pycrypto>=2.6.1 pycrypto>=2.6.1