From 32e4d822c101793a44f669ab1d12b8cb946e33fa Mon Sep 17 00:00:00 2001 From: Liam Young Date: Mon, 5 Nov 2018 18:36:06 +0000 Subject: [PATCH] Only check for one unit for container scoped rels. When checking goal state, only look for one unit to be available when examining container scoped relations as a principle unit only ever has a relation with a single unit of a given subordinate application. Change-Id: I02f34358060c98c0702d3d7b58d52427c2a0445a Closes-Bug: #1801754 --- hooks/keystone_utils.py | 25 +++++++++++++++++++++++-- unit_tests/test_keystone_utils.py | 24 ++++++++++++++++++++++-- 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/hooks/keystone_utils.py b/hooks/keystone_utils.py index 8e1b516c..5906e453 100644 --- a/hooks/keystone_utils.py +++ b/hooks/keystone_utils.py @@ -76,6 +76,7 @@ from charmhelpers.core.decorators import ( from charmhelpers.core.hookenv import ( atexit, + cached, config, expected_peer_units, expected_related_units, @@ -84,6 +85,7 @@ from charmhelpers.core.hookenv import ( leader_set, log, local_unit, + metadata, relation_get, relation_set, relation_id, @@ -2239,6 +2241,18 @@ def fernet_keys_rotate_and_sync(log_func=log): level=INFO) +@cached +def container_scoped_relations(): + '''Get all the container scoped relations''' + md = metadata() + relations = [] + for relation_type in ('provides', 'requires', 'peers'): + for relation in md.get(relation_type, []): + if md[relation_type][relation].get('scope') == 'container': + relations.append(relation) + return relations + + def is_expected_scale(): """Query juju goal-state to determine whether our peer- and dependency- relations are at the expected scale. @@ -2269,8 +2283,15 @@ def is_expected_scale(): for dep in deps: if not dep[1]: return False - if (len(related_units(relid=dep[1])) < - len(list(expected_related_units(reltype=dep[0])))): + # Goal state returns every unit even for container scoped + # relations but the charm only ever has a relation with + # the local unit. + if dep[0] in container_scoped_relations(): + expected_count = 1 + else: + expected_count = len( + list(expected_related_units(reltype=dep[0]))) + if len(related_units(relid=dep[1])) < expected_count: return False except NotImplementedError: return True diff --git a/unit_tests/test_keystone_utils.py b/unit_tests/test_keystone_utils.py index b95f3bad..51ebc7d7 100644 --- a/unit_tests/test_keystone_utils.py +++ b/unit_tests/test_keystone_utils.py @@ -1310,13 +1310,16 @@ class TestKeystoneUtils(CharmTestCase): mock_fernet_rotate.assert_called_once_with() mock_key_leader_set.assert_called_once_with() + @patch.object(utils, 'container_scoped_relations') @patch.object(utils, 'expected_related_units') @patch.object(utils, 'expected_peer_units') @patch.object(utils, 'related_units') @patch.object(utils, 'expect_ha') @patch.object(utils, 'relation_ids') def test_is_expected_scale(self, relation_ids, expect_ha, related_units, - expected_peer_units, expected_related_units): + expected_peer_units, expected_related_units, + container_scoped_relations): + container_scoped_relations.return_value = ['ha'] relation_ids.return_value = ['FAKE_RID'] expect_ha.return_value = False related_units.return_value = ['unit/0', 'unit/1', 'unit/2'] @@ -1328,13 +1331,16 @@ class TestKeystoneUtils(CharmTestCase): call(reltype='shared-db')]) related_units.assert_called_with(relid='FAKE_RID') + @patch.object(utils, 'container_scoped_relations') @patch.object(utils, 'expected_related_units') @patch.object(utils, 'expected_peer_units') @patch.object(utils, 'related_units') @patch.object(utils, 'expect_ha') @patch.object(utils, 'relation_ids') def test_is_expected_scale_ha(self, relation_ids, expect_ha, related_units, - expected_peer_units, expected_related_units): + expected_peer_units, expected_related_units, + container_scoped_relations): + container_scoped_relations.return_value = ['ha'] relation_ids.return_value = ['FAKE_RID'] expect_ha.return_value = True related_units.return_value = ['unit/0', 'unit/1', 'unit/2'] @@ -1381,3 +1387,17 @@ class TestKeystoneUtils(CharmTestCase): expected_peer_units.side_effect = NotImplementedError self.assertTrue(utils.is_expected_scale()) expected_related_units.assert_not_called() + + @patch.object(utils, 'metadata') + def test_container_scoped_relations(self, metadata): + _metadata = { + 'provides': { + 'amqp': {'interface': 'rabbitmq'}, + 'identity-service': {'interface': 'keystone'}, + 'ha': { + 'interface': 'hacluster', + 'scope': 'container'}}, + 'peers': { + 'cluster': {'interface': 'openstack-ha'}}} + metadata.return_value = _metadata + self.assertEqual(utils.container_scoped_relations(), ['ha'])