Merge branch '2016.11' into 'nitrogen'

Conflicts:
  - tests/unit/states/test_keystone.py
This commit is contained in:
rallytime 2017-05-30 10:16:14 -06:00
commit 675937e0ab
6 changed files with 219 additions and 126 deletions

View File

@ -454,7 +454,7 @@ class Master(SMaster):
os.chdir('/')
except OSError as err:
errors.append(
'Cannot change to root directory ({1})'.format(err)
'Cannot change to root directory ({0})'.format(err)
)
if self.opts.get('fileserver_verify_config', True):

View File

@ -296,7 +296,7 @@ def ec2_credentials_list(user_id=None, name=None, profile=None,
return ret
def endpoint_get(service, profile=None, **connection_args):
def endpoint_get(service, region=None, profile=None, **connection_args):
'''
Return a specific endpoint (keystone endpoint-get)
@ -304,7 +304,7 @@ def endpoint_get(service, profile=None, **connection_args):
.. code-block:: bash
salt '*' keystone.endpoint_get nova
salt '*' keystone.endpoint_get nova [region=RegionOne]
'''
auth(profile, **connection_args)
services = service_list(profile, **connection_args)
@ -312,9 +312,15 @@ def endpoint_get(service, profile=None, **connection_args):
return {'Error': 'Could not find the specified service'}
service_id = services[service]['id']
endpoints = endpoint_list(profile, **connection_args)
for endpoint in endpoints:
if endpoints[endpoint]['service_id'] == service_id:
return endpoints[endpoint]
e = [_f for _f in [e
if e['service_id'] == service_id and
(e['region'] == region if region else True) else None for e in endpoints.values()] if _f]
if len(e) > 1:
return {'Error': 'Multiple endpoints found ({0}) for the {1} service. Please specify region.'.format(e, service)}
if len(e) == 1:
return e[0]
#log.debug('Could not find endpoint for the specified service {0}, service_id: {3} and region {1} in endpoints {2}'.format(service, region, endpoints.values(), service_id))
return {'Error': 'Could not find endpoint for the specified service'}
@ -349,7 +355,7 @@ def endpoint_create(service, publicurl=None, internalurl=None, adminurl=None,
salt 'v2' keystone.endpoint_create nova 'http://public/url' 'http://internal/url' 'http://adminurl/url' region
salt 'v3' keystone.endpoint_create nova url='http://public/url' interface='public'
salt 'v3' keystone.endpoint_create nova url='http://public/url' interface='public' region='RegionOne'
'''
kstone = auth(profile, **connection_args)
keystone_service = service_get(name=service, profile=profile,
@ -368,10 +374,10 @@ def endpoint_create(service, publicurl=None, internalurl=None, adminurl=None,
publicurl=publicurl,
adminurl=adminurl,
internalurl=internalurl)
return endpoint_get(service, profile, **connection_args)
return endpoint_get(service, region, profile, **connection_args)
def endpoint_delete(service, profile=None, **connection_args):
def endpoint_delete(service, region=None, profile=None, **connection_args):
'''
Delete endpoints of an Openstack service
@ -379,14 +385,14 @@ def endpoint_delete(service, profile=None, **connection_args):
.. code-block:: bash
salt '*' keystone.endpoint_delete nova
salt '*' keystone.endpoint_delete nova [region=RegionOne]
'''
kstone = auth(profile, **connection_args)
endpoint = endpoint_get(service, profile, **connection_args)
endpoint = endpoint_get(service, region, profile, **connection_args)
if not endpoint or 'Error' in endpoint:
return {'Error': 'Could not find any endpoints for the service'}
kstone.endpoints.delete(endpoint['id'])
endpoint = endpoint_get(service, profile, **connection_args)
endpoint = endpoint_get(service, region, profile, **connection_args)
if not endpoint or 'Error' in endpoint:
return True
@ -414,6 +420,7 @@ def role_delete(role_id=None, name=None, profile=None,
'''
Delete a role (keystone role-delete)
CLI Examples:
.. code-block:: bash

View File

@ -617,7 +617,7 @@ def endpoint_present(name,
publicurl=None,
internalurl=None,
adminurl=None,
region='RegionOne',
region=None,
profile=None,
url=None,
interface=None, **connection_args):
@ -650,101 +650,19 @@ def endpoint_present(name,
ret = {'name': name,
'changes': {},
'result': True,
'comment': 'Endpoint for service "{0}" already exists'.format(name)}
'comment': ''}
_api_version(profile=profile, **connection_args)
endpoint = __salt__['keystone.endpoint_get'](name,
endpoint = __salt__['keystone.endpoint_get'](name, region,
profile=profile,
**connection_args)
if endpoint and 'Error' not in endpoint:
if endpoint.get('region', None) != region:
if __opts__.get('test'):
ret['result'] = None
ret['comment'] = 'Endpoint for service "{0}" will be updated'.format(name)
ret['changes']['Endpoint'] = 'Will be updated'
return ret
ret['comment'] = 'Endpoint for service "{0}" will be updated'.format(name)
ret['changes']['Region'] = region
def _changes(desc):
return ret.get('comment', '') + desc + '\n'
def _createEndpoint():
if _OS_IDENTITY_API_VERSION > 2:
change_url = False
change_interface = False
if endpoint.get('url', None) != url:
change_url = True
if endpoint.get('interface', None) != interface:
change_interface = True
if __opts__.get('test') and (change_url or change_interface):
ret['result'] = None
ret['changes']['Endpoint'] = 'Will be updated'
ret['comment'] = 'Endpoint for service "{0}" will be updated'.format(name)
return ret
if change_url:
ret['comment'] = 'Endpoint for service "{0}" will be updated'.format(name)
ret['changes']['Endpoint'] = 'Will be updated'
ret['changes']['url'] = url
if change_interface:
ret['comment'] = 'Endpoint for service "{0}" will be updated'.format(name)
ret['changes']['Endpoint'] = 'Will be updated'
ret['changes']['interface'] = interface
else:
change_publicurl = False
change_adminurl = False
change_internalurl = False
if endpoint.get('publicurl', None) != publicurl:
change_publicurl = True
if endpoint.get('adminurl', None) != adminurl:
change_adminurl = True
if endpoint.get('internalurl', None) != internalurl:
change_internalurl = True
if __opts__.get('test') and (change_publicurl or change_adminurl or change_internalurl):
ret['result'] = None
ret['comment'] = 'Endpoint for service "{0}" will be updated'.format(name)
ret['changes']['Endpoint'] = 'Will be updated'
return ret
if endpoint.get('publicurl', None) != publicurl:
ret['comment'] = 'Endpoint for service "{0}" will be updated'.format(name)
ret['changes']['publicurl'] = publicurl
if endpoint.get('adminurl', None) != adminurl:
ret['comment'] = 'Endpoint for service "{0}" will be updated'.format(name)
ret['changes']['adminurl'] = adminurl
if endpoint.get('internalurl', None) != internalurl:
ret['comment'] = 'Endpoint for service "{0}" will be updated'.format(name)
ret['changes']['internalurl'] = internalurl
if ret['comment'].endswith('already exists'):
return ret
else:
__salt__['keystone.endpoint_delete'](name,
profile=profile,
**connection_args)
ret['comment'] = 'Endpoint for service "{0}" has been updated'.format(name)
ret['changes']['Endpoint'] = 'Will be updated'
else:
if __opts__.get('test'):
ret['result'] = None
ret['changes']['Endpoint'] = 'Will be created'
ret['comment'] = 'Endpoint for service "{0}" will be added'.format(name)
return ret
elif _OS_IDENTITY_API_VERSION > 2:
ret['changes'] = __salt__['keystone.endpoint_create'](
name,
region=region,
@ -761,11 +679,94 @@ def endpoint_present(name,
internalurl=internalurl,
profile=profile,
**connection_args)
if endpoint and 'Error' not in endpoint and endpoint.get('region') == region:
if _OS_IDENTITY_API_VERSION > 2:
change_url = False
change_interface = False
if endpoint.get('url', None) != url:
ret['comment'] = _changes('URL changes from "{0}" to "{1}"'.format(endpoint.get('url', None), url))
change_url = True
if endpoint.get('interface', None) != interface:
ret['comment'] = _changes('Interface changes from "{0}" to "{1}"'.format(endpoint.get('interface', None), interface))
change_interface = True
if __opts__.get('test') and (change_url or change_interface):
ret['result'] = None
ret['changes']['Endpoint'] = 'Will be updated'
ret['comment'] += 'Endpoint for service "{0}" will be updated'.format(name)
return ret
if change_url:
ret['changes']['url'] = url
if change_interface:
ret['changes']['interface'] = interface
else:
change_publicurl = False
change_adminurl = False
change_internalurl = False
if endpoint.get('publicurl', None) != publicurl:
change_publicurl = True
ret['comment'] = _changes('Public URL changes from "{0}" to "{1}"'.format(
endpoint.get('publicurl', None), publicurl)
)
if endpoint.get('adminurl', None) != adminurl:
change_adminurl = True
ret['comment'] = _changes('Admin URL changes from "{0}" to "{1}"'.format(
endpoint.get('adminurl', None), adminurl)
)
if endpoint.get('internalurl', None) != internalurl:
change_internalurl = True
ret['comment'] = _changes('Internal URL changes from "{0}" to "{1}"'.format(
endpoint.get('internal', None), internalurl)
)
if __opts__.get('test') and (change_publicurl or change_adminurl or change_internalurl):
ret['result'] = None
ret['comment'] += 'Endpoint for service "{0}" will be updated'.format(name)
ret['changes']['Endpoint'] = 'Will be updated'
return ret
if change_publicurl:
ret['changes']['publicurl'] = publicurl
if change_adminurl:
ret['changes']['adminurl'] = adminurl
if change_internalurl:
ret['changes']['internalurl'] = internalurl
if ret['comment']: # changed
__salt__['keystone.endpoint_delete'](name, region, profile=profile, **connection_args)
_createEndpoint()
ret['comment'] += 'Endpoint for service "{0}" has been updated'.format(name)
else:
# Add new endpoint
if __opts__.get('test'):
ret['result'] = None
ret['changes']['Endpoint'] = 'Will be created'
ret['comment'] = 'Endpoint for service "{0}" will be added'.format(name)
return ret
_createEndpoint()
ret['comment'] = 'Endpoint for service "{0}" has been added'.format(name)
if ret['comment'] == '': # => no changes
ret['result'] = None
ret['comment'] = 'Endpoint for service "{0}" already exists'.format(name)
return ret
def endpoint_absent(name, profile=None, **connection_args):
def endpoint_absent(name, region=None, profile=None, **connection_args):
'''
Ensure that the endpoint for a service doesn't exist in Keystone catalog
@ -778,7 +779,7 @@ def endpoint_absent(name, profile=None, **connection_args):
'comment': 'Endpoint for service "{0}" is already absent'.format(name)}
# Check if service is present
endpoint = __salt__['keystone.endpoint_get'](name,
endpoint = __salt__['keystone.endpoint_get'](name, region,
profile=profile,
**connection_args)
if not endpoint:
@ -789,7 +790,7 @@ def endpoint_absent(name, profile=None, **connection_args):
ret['comment'] = 'Endpoint for service "{0}" will be deleted'.format(name)
return ret
# Delete service
__salt__['keystone.endpoint_delete'](name,
__salt__['keystone.endpoint_delete'](name, region,
profile=profile,
**connection_args)
ret['comment'] = 'Endpoint for service "{0}" has been deleted'.format(name)

View File

@ -119,6 +119,35 @@ class KeystoneStateTest(ModuleCase, SaltReturnAssertsMixin):
profile='adminv2')
self.assertTrue(ret['keystone_|-nova_|-nova_|-endpoint_present']['result'])
# Region Two
ret = self.run_state('keystone.endpoint_present',
name='nova',
description='Nova Service',
publicurl='http://localhost:8774/v2.1/%(tenant_id)s',
internalurl='http://localhost:8774/v2.1/%(tenant_id)s',
adminurl='http://localhost:8774/v2.1/%(tenant_id)s',
region='RegionTwo',
profile='adminv2')
self.assertTrue(ret['keystone_|-nova_|-nova_|-endpoint_present']['result'])
# Region One, change publicurl
ret = self.run_state('keystone.endpoint_present',
name='nova',
description='Nova Service',
publicurl='http://127.0.0.1:8774/v2.1/%(tenant_id)s',
internalurl='http://localhost:8774/v2.1/%(tenant_id)s',
adminurl='http://localhost:8774/v2.1/%(tenant_id)s',
region='RegionOne',
profile='adminv2')
self.assertTrue(ret['keystone_|-nova_|-nova_|-endpoint_present']['result'])
ret = self.run_state('keystone.endpoint_get',
name='nova',
region='RegionOne',
profile='adminv2')
self.assertTrue(ret['keystone_|-testv3_|-testv3_|-endpoint_present']['result'])
self.assertTrue(ret['keystone_|-testv3_|-testv3_|-endpoint_present']['publicurl'].start_with('http://127.0.0.1'))
ret = self.run_state('keystone.tenant_present',
name='test',
description='Test Tenant',
@ -180,6 +209,52 @@ class KeystoneStateTest(ModuleCase, SaltReturnAssertsMixin):
profile='adminv3')
self.assertTrue(ret['keystone_|-testv3_|-testv3_|-endpoint_present']['result'])
# Region Two
ret = self.run_state('keystone.endpoint_present',
name='testv3',
description='Glance Service',
interface='public',
url='http://localhost:9292',
region='RegionTwo',
profile='adminv3')
self.assertTrue(ret['keystone_|-testv3_|-testv3_|-endpoint_present']['result'])
ret = self.run_state('keystone.endpoint_present',
name='testv3',
description='Glance Service',
interface='internal',
url='http://localhost:9292',
region='RegionTwo',
profile='adminv3')
self.assertTrue(ret['keystone_|-testv3_|-testv3_|-endpoint_present']['result'])
ret = self.run_state('keystone.endpoint_present',
name='testv3',
description='Glance Service',
interface='admin',
url='http://localhost:9292',
region='RegionTwo',
profile='adminv3')
self.assertTrue(ret['keystone_|-testv3_|-testv3_|-endpoint_present']['result'])
# Region One, change
ret = self.run_state('keystone.endpoint_present',
name='testv3',
description='Glance Service',
interface='public',
url='http://127.0.0.1:9292',
region='RegionOne',
profile='adminv3')
self.assertTrue(ret['keystone_|-testv3_|-testv3_|-endpoint_present']['result'])
ret = self.run_state('keystone.endpoint_get',
name='testv3',
region='RegionOne',
interface='public',
profile='adminv3')
self.assertTrue(ret['keystone_|-testv3_|-testv3_|-endpoint_present']['result'])
self.assertTrue(ret['keystone_|-testv3_|-testv3_|-endpoint_present']['endpoint']['url'] == 'http://127.0.0.1:9292')
ret = self.run_state('keystone.project_present',
name='testv3',
description='Test v3 Tenant',

View File

@ -78,7 +78,7 @@ class MockEndpoints(object):
"""
def __init__(self):
self.id = '007'
self.region = 'region'
self.region = 'RegionOne'
self.adminurl = 'adminurl'
self.internalurl = 'internalurl'
self.publicurl = 'publicurl'
@ -507,20 +507,26 @@ class KeystoneTestCase(TestCase, LoaderModuleMockMixin):
'''
Test if it return a specific endpoint (keystone endpoint-get)
'''
self.assertDictEqual(keystone.endpoint_get('nova', profile='openstack'),
self.assertDictEqual(keystone.endpoint_get('nova',
'RegionOne',
profile='openstack'),
{'Error': 'Could not find the specified service'})
ret = {'Error': 'Could not find endpoint for the specified service'}
MockServices.flag = 1
self.assertDictEqual(keystone.endpoint_get('iptables',
'RegionOne',
profile='openstack'), ret)
MockServices.flag = 0
self.assertDictEqual(keystone.endpoint_get('iptables',
'RegionOne',
profile='openstack'),
{'adminurl': 'adminurl', 'id': '007',
{'adminurl': 'adminurl',
'id': '007',
'internalurl': 'internalurl',
'publicurl': 'publicurl', 'region': 'region',
'publicurl': 'publicurl',
'region': 'RegionOne',
'service_id': '117'})
# 'endpoint_list' function tests: 1
@ -531,10 +537,12 @@ class KeystoneTestCase(TestCase, LoaderModuleMockMixin):
(keystone endpoints-list)
'''
self.assertDictEqual(keystone.endpoint_list(profile='openstack1'),
{'007': {'adminurl': 'adminurl', 'id': '007',
{'007': {'adminurl': 'adminurl',
'id': '007',
'internalurl': 'internalurl',
'publicurl': 'publicurl',
'region': 'region', 'service_id': '117'}})
'region': 'RegionOne',
'service_id': '117'}})
# 'endpoint_create' function tests: 1
@ -549,10 +557,13 @@ class KeystoneTestCase(TestCase, LoaderModuleMockMixin):
self.assertDictEqual(keystone.endpoint_create('iptables',
'http://public/url',
'http://internal/url',
'http://adminurl/url'),
{'adminurl': 'adminurl', 'id': '007',
'http://adminurl/url',
'RegionOne'),
{'adminurl': 'adminurl',
'id': '007',
'internalurl': 'internalurl',
'publicurl': 'publicurl', 'region': 'region',
'publicurl': 'publicurl',
'region': 'RegionOne',
'service_id': '117'})
# 'endpoint_delete' function tests: 1
@ -562,11 +573,11 @@ class KeystoneTestCase(TestCase, LoaderModuleMockMixin):
Test if it delete an endpoint for an Openstack service
'''
ret = {'Error': 'Could not find any endpoints for the service'}
self.assertDictEqual(keystone.endpoint_delete('nova'), ret)
self.assertDictEqual(keystone.endpoint_delete('nova', 'RegionOne'), ret)
with patch.object(keystone, 'endpoint_get',
MagicMock(side_effect=[{'id': '117'}, None])):
self.assertTrue(keystone.endpoint_delete('iptables'))
self.assertTrue(keystone.endpoint_delete('iptables', 'RegionOne'))
# 'role_create' function tests: 1

View File

@ -294,6 +294,7 @@ class KeystoneTestCase(TestCase, LoaderModuleMockMixin):
Test to ensure the specified endpoints exists for service
'''
name = 'nova'
region = 'RegionOne'
ret = {'name': name,
'changes': {},
@ -301,7 +302,7 @@ class KeystoneTestCase(TestCase, LoaderModuleMockMixin):
'comment': ''}
endpoint = {'adminurl': None,
'region': 'RegionOne',
'region': None,
'internalurl': None,
'publicurl': None,
'id': 1, 'service_id': None}
@ -311,25 +312,22 @@ class KeystoneTestCase(TestCase, LoaderModuleMockMixin):
mock = MagicMock(return_value=True)
with patch.dict(keystone.__salt__, {'keystone.endpoint_get': mock_lst,
'keystone.endpoint_create': mock}):
comt = ('Endpoint for service "{0}" already exists'.format(name))
ret.update({'comment': comt})
ret.update({'comment': comt, 'result': None, 'changes': {}})
self.assertDictEqual(keystone.endpoint_present(name), ret)
with patch.dict(keystone.__opts__, {'test': True}):
comt = ('Endpoint for service "{0}" will be added'.format(name))
ret.update({'comment': comt, 'result': None,
'changes': {'Endpoint': 'Will be created'}})
ret.update({'comment': comt, 'result': None, 'changes': {'Endpoint': 'Will be created'}})
self.assertDictEqual(keystone.endpoint_present(name), ret)
comt = ('Endpoint for service "{0}" will be updated'
.format(name))
ret.update({'comment': comt,
'changes': {'Endpoint': 'Will be updated'}})
comt = ('Endpoint for service "{0}" already exists'.format(name))
ret.update({'comment': comt, 'result': None, 'changes': {}})
self.assertDictEqual(keystone.endpoint_present(name), ret)
with patch.dict(keystone.__opts__, {'test': False}):
comt = ('Endpoint for service "{0}" has been added'
.format(name))
comt = ('Endpoint for service "{0}" has been added'.format(name))
ret.update({'comment': comt, 'result': True, 'changes': True})
self.assertDictEqual(keystone.endpoint_present(name), ret)
@ -341,6 +339,7 @@ class KeystoneTestCase(TestCase, LoaderModuleMockMixin):
exist in Keystone catalog
'''
name = 'nova'
region = 'RegionOne'
comment = ('Endpoint for service "{0}" is already absent'.format(name))
ret = {'name': name,
'changes': {},
@ -349,10 +348,10 @@ class KeystoneTestCase(TestCase, LoaderModuleMockMixin):
mock_lst = MagicMock(side_effect=[[], ['Error']])
with patch.dict(keystone.__salt__, {'keystone.endpoint_get': mock_lst}):
self.assertDictEqual(keystone.endpoint_absent(name), ret)
self.assertDictEqual(keystone.endpoint_absent(name, region), ret)
with patch.dict(keystone.__opts__, {'test': True}):
comt = ('Endpoint for service "{0}" will be deleted'
.format(name))
ret.update({'comment': comt, 'result': None})
self.assertDictEqual(keystone.endpoint_absent(name), ret)
self.assertDictEqual(keystone.endpoint_absent(name, region), ret)