endpoint notification: provide full endpoint
When a remote service requests notification about changes to endpoints, provide the full detail on each endpoint rather than just a checksum of the internal/admin/public URL's. This allows consuming services which require explicit configuration of service endpoint URL's to configure everything via their relation to keystone rather than directly relating to all required services. Change-Id: I39b6e3df17e44c801f5f6bb122407623cbf1c937
This commit is contained in:
parent
6ca8e9b508
commit
f984c4ec9b
|
@ -14,3 +14,4 @@ func-results.json
|
|||
__pycache__
|
||||
.stestr
|
||||
.idea
|
||||
.pydevproject
|
||||
|
|
|
@ -1,14 +1,10 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<?eclipse-pydev version="1.0"?><pydev_project>
|
||||
|
||||
<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.7</pydev_property>
|
||||
|
||||
<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
|
||||
|
||||
<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">python3</pydev_property>
|
||||
<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
|
||||
<path>/keystone/hooks</path>
|
||||
<path>/keystone/unit_tests</path>
|
||||
<path>/${PROJECT_DIR_NAME}</path>
|
||||
</pydev_pathproperty>
|
||||
|
||||
</pydev_project>
|
||||
|
|
|
@ -128,6 +128,7 @@ from keystone_utils import (
|
|||
remove_old_packages,
|
||||
stop_manager_instance,
|
||||
assemble_endpoints,
|
||||
endpoints_dict,
|
||||
endpoints_checksum,
|
||||
)
|
||||
|
||||
|
@ -426,7 +427,8 @@ def db_departed_or_broken():
|
|||
@hooks.hook('identity-service-relation-changed')
|
||||
@restart_on_change(restart_map(), restart_functions=restart_function_map())
|
||||
def identity_changed(relation_id=None, remote_unit=None):
|
||||
notifications = {}
|
||||
notifications_checksums = {}
|
||||
notifications_endpoints = {}
|
||||
if is_elected_leader(CLUSTER_RES):
|
||||
if not is_db_ready():
|
||||
log("identity-service-relation-changed hook fired before db "
|
||||
|
@ -454,7 +456,8 @@ def identity_changed(relation_id=None, remote_unit=None):
|
|||
service = settings.get('service')
|
||||
if service:
|
||||
key = '%s-endpoint-changed' % service
|
||||
notifications[key] = endpoints_checksum(settings)
|
||||
notifications_endpoints[key] = endpoints_dict(settings)
|
||||
notifications_checksums[key] = endpoints_checksum(settings)
|
||||
else:
|
||||
# Some services don't set their name in the 'service' key in the
|
||||
# relation, for those their name is calculated from the prefix of
|
||||
|
@ -466,7 +469,12 @@ def identity_changed(relation_id=None, remote_unit=None):
|
|||
if single.issubset(endpoints[ep]):
|
||||
key = '%s-endpoint-changed' % ep
|
||||
log('endpoint: %s' % ep)
|
||||
notifications[key] = endpoints_checksum(endpoints[ep])
|
||||
notifications_endpoints[key] = (
|
||||
endpoints_dict(endpoints[ep])
|
||||
)
|
||||
notifications_checksums[key] = (
|
||||
endpoints_checksum(endpoints[ep])
|
||||
)
|
||||
else:
|
||||
# Each unit needs to set the db information otherwise if the unit
|
||||
# with the info dies the settings die with it Bug# 1355848
|
||||
|
@ -479,8 +487,9 @@ def identity_changed(relation_id=None, remote_unit=None):
|
|||
|
||||
log('Deferring identity_changed() to service leader.')
|
||||
|
||||
if notifications:
|
||||
send_notifications(notifications)
|
||||
if notifications_endpoints or notifications_checksums:
|
||||
send_notifications(notifications_checksums,
|
||||
notifications_endpoints)
|
||||
|
||||
|
||||
@hooks.hook('identity-credentials-relation-joined',
|
||||
|
|
|
@ -2003,7 +2003,13 @@ def send_id_service_notifications(data):
|
|||
"""
|
||||
id_svc_rel_ids = relation_ids('identity-service')
|
||||
for rid in id_svc_rel_ids:
|
||||
changed = {}
|
||||
changed = relation_get(unit=local_unit(),
|
||||
rid=rid,
|
||||
attribute='ep_changed')
|
||||
if changed:
|
||||
changed = json.loads(changed)
|
||||
else:
|
||||
changed = {}
|
||||
for unit in related_units(rid):
|
||||
rs = relation_get(
|
||||
unit=unit,
|
||||
|
@ -2021,9 +2027,9 @@ def send_id_service_notifications(data):
|
|||
'ep_changed': json.dumps(changed, sort_keys=True)})
|
||||
|
||||
|
||||
def send_notifications(data, force=False):
|
||||
send_id_notifications(data, force=force)
|
||||
send_id_service_notifications(data)
|
||||
def send_notifications(checksum_data, endpoint_data, force=False):
|
||||
send_id_notifications(checksum_data, force=force)
|
||||
send_id_service_notifications(endpoint_data)
|
||||
|
||||
|
||||
def send_id_notifications(data, force=False):
|
||||
|
@ -2565,3 +2571,18 @@ def endpoints_checksum(settings):
|
|||
csum.update(settings.get('admin_url', None).encode('utf-8'))
|
||||
csum.update(settings.get('internal_url', None).encode('utf-8'))
|
||||
return csum.hexdigest()
|
||||
|
||||
|
||||
def endpoints_dict(settings):
|
||||
"""
|
||||
Build a dictionary of endpoint types using settings
|
||||
|
||||
:param settings: dict with urls registered in keystone.
|
||||
:returns: dict of endpoints from settings
|
||||
"""
|
||||
endpoints = {
|
||||
'public': settings.get('public_url', None),
|
||||
'admin': settings.get('admin_url', None),
|
||||
'internal': settings.get('internal_url', None),
|
||||
}
|
||||
return endpoints
|
||||
|
|
|
@ -818,29 +818,28 @@ class TestKeystoneUtils(CharmTestCase):
|
|||
def test_send_id_notifications(self, mock_is_elected_leader,
|
||||
mock_relation_ids, mock_relation_get,
|
||||
mock_relation_set, mock_uuid):
|
||||
checksums = {'foo-endpoint-changed': 1}
|
||||
relation_id = 'testrel:0'
|
||||
mock_uuid.uuid4.return_value = '1234'
|
||||
mock_relation_ids.return_value = [relation_id]
|
||||
mock_is_elected_leader.return_value = False
|
||||
utils.send_notifications({'foo-endpoint-changed': 1})
|
||||
utils.send_id_notifications(checksums)
|
||||
self.assertFalse(mock_relation_set.called)
|
||||
|
||||
mock_is_elected_leader.return_value = True
|
||||
utils.send_notifications({})
|
||||
utils.send_id_notifications({})
|
||||
self.assertFalse(mock_relation_set.called)
|
||||
|
||||
settings = {'foo-endpoint-changed': 1}
|
||||
utils.send_notifications(settings)
|
||||
utils.send_id_notifications(checksums)
|
||||
self.assertTrue(mock_relation_set.called)
|
||||
mock_relation_set.assert_called_once_with(relation_id=relation_id,
|
||||
relation_settings=settings)
|
||||
relation_settings=checksums)
|
||||
mock_relation_set.reset_mock()
|
||||
settings = {'foo-endpoint-changed': 1}
|
||||
utils.send_notifications(settings, force=True)
|
||||
utils.send_id_notifications(checksums, force=True)
|
||||
self.assertTrue(mock_relation_set.called)
|
||||
settings['trigger'] = '1234'
|
||||
checksums['trigger'] = '1234'
|
||||
mock_relation_set.assert_called_once_with(relation_id=relation_id,
|
||||
relation_settings=settings)
|
||||
relation_settings=checksums)
|
||||
|
||||
@patch.object(utils, 'relation_ids')
|
||||
@patch.object(utils, 'related_units')
|
||||
|
@ -873,7 +872,9 @@ class TestKeystoneUtils(CharmTestCase):
|
|||
'glance/0': {
|
||||
'admin_url': 'http://172.20.0.32:9292'},
|
||||
'glance/1': {},
|
||||
'glance/2': {}}
|
||||
'glance/2': {},
|
||||
'keystone/0': {}
|
||||
}
|
||||
|
||||
def _relation_get(unit, rid, attribute):
|
||||
return id_svc_rel_data[unit].get(attribute)
|
||||
|
@ -881,29 +882,40 @@ class TestKeystoneUtils(CharmTestCase):
|
|||
mock_relation_ids.return_value = id_svc_rel_units.keys()
|
||||
mock_related_units.side_effect = _related_units
|
||||
mock_relation_get.side_effect = _relation_get
|
||||
self.local_unit.return_value = 'keystone/0'
|
||||
|
||||
# Check all services subscribed to placement changes are notified.
|
||||
mock_relation_set.reset_mock()
|
||||
utils.send_id_service_notifications(
|
||||
{'placement-endpoint-changed': '4d0633ee'})
|
||||
{'placement-endpoint-changed': {"internal": "http://demo.com"}})
|
||||
mock_relation_set.assert_called_once_with(
|
||||
relation_id='identity-service:2',
|
||||
relation_settings={
|
||||
'ep_changed': '{"placement": "4d0633ee"}'})
|
||||
'ep_changed':
|
||||
'{"placement": {"internal": "http://demo.com"}}'
|
||||
}
|
||||
)
|
||||
|
||||
# Check all services subscribed to neutron changes are notified.
|
||||
mock_relation_set.reset_mock()
|
||||
utils.send_id_service_notifications(
|
||||
{'neutron-endpoint-changed': '1c261658'})
|
||||
{'neutron-endpoint-changed': {"internal": "http://demo.com"}})
|
||||
expected_rel_set_calls = [
|
||||
call(
|
||||
relation_id='identity-service:1',
|
||||
relation_settings={
|
||||
'ep_changed': '{"neutron": "1c261658"}'}),
|
||||
'ep_changed':
|
||||
'{"neutron": {"internal": "http://demo.com"}}'
|
||||
}
|
||||
),
|
||||
call(
|
||||
relation_id='identity-service:2',
|
||||
relation_settings={
|
||||
'ep_changed': '{"neutron": "1c261658"}'})]
|
||||
'ep_changed':
|
||||
'{"neutron": {"internal": "http://demo.com"}}'
|
||||
}
|
||||
)
|
||||
]
|
||||
mock_relation_set.assert_has_calls(
|
||||
expected_rel_set_calls,
|
||||
any_order=True)
|
||||
|
@ -911,19 +923,26 @@ class TestKeystoneUtils(CharmTestCase):
|
|||
# Check multiple ep changes with app subscribing to multiple eps
|
||||
mock_relation_set.reset_mock()
|
||||
utils.send_id_service_notifications(
|
||||
{'neutron-endpoint-changed': '1c261658',
|
||||
'placement-endpoint-changed': '4d0633ee'})
|
||||
{'neutron-endpoint-changed': {"internal": "http://demo.com"},
|
||||
'placement-endpoint-changed': {"internal": "http://demo.com"}})
|
||||
expected_rel_set_calls = [
|
||||
call(
|
||||
relation_id='identity-service:1',
|
||||
relation_settings={
|
||||
'ep_changed': '{"neutron": "1c261658"}'}),
|
||||
'ep_changed':
|
||||
'{"neutron": {"internal": "http://demo.com"}}'
|
||||
}
|
||||
),
|
||||
call(
|
||||
relation_id='identity-service:2',
|
||||
relation_settings={
|
||||
'ep_changed': (
|
||||
'{"neutron": "1c261658", '
|
||||
'"placement": "4d0633ee"}')})]
|
||||
'{"neutron": {"internal": "http://demo.com"}, '
|
||||
'"placement": {"internal": "http://demo.com"}}'
|
||||
)
|
||||
}
|
||||
)
|
||||
]
|
||||
mock_relation_set.assert_has_calls(
|
||||
expected_rel_set_calls,
|
||||
any_order=True)
|
||||
|
|
Loading…
Reference in New Issue