From f13e52d79219665650a4ec8973972bad0ad737ce Mon Sep 17 00:00:00 2001 From: Alex Kavanagh <567675+ajkavanagh@users.noreply.github.com> Date: Fri, 28 Jul 2023 10:56:04 +0100 Subject: [PATCH] [stable/antelope] Ensure get_requests_for_local_unit doesn't fail on incomplete relation (#824) If the certificates relation has been set from a consuming charm for certificates, but the provider hasn't supplied a certificate, and the request is in the 'legacy' form, then the get_request_for_local_unit() function in cert_utils fails on accessing the (non-existant) 'ca' parameter in the databag. This patch ensures that if the 'ca' key is missing that the processing moves on to the next relation. (cherry-picked from: c8f47207c1f1652ab2cbecaaad8a83b66f004e5e) Closes LP#2028683 --- charmhelpers/contrib/openstack/cert_utils.py | 33 +++++++++++++------- tests/contrib/openstack/test_cert_utils.py | 24 ++++++++++++++ 2 files changed, 45 insertions(+), 12 deletions(-) diff --git a/charmhelpers/contrib/openstack/cert_utils.py b/charmhelpers/contrib/openstack/cert_utils.py index a25ca995e..6620f59f5 100644 --- a/charmhelpers/contrib/openstack/cert_utils.py +++ b/charmhelpers/contrib/openstack/cert_utils.py @@ -414,18 +414,27 @@ def get_requests_for_local_unit(relation_name=None): is_legacy_request = set(sent).intersection(legacy_keys) for unit in related_units(rid): data = relation_get(rid=rid, unit=unit) - if data.get(raw_certs_key): - bundles.append({ - 'ca': data['ca'], - 'chain': data.get('chain'), - 'certs': json.loads(data[raw_certs_key])}) - elif is_legacy_request: - bundles.append({ - 'ca': data['ca'], - 'chain': data.get('chain'), - 'certs': {sent['common_name']: - {'cert': data.get(local_name + '.server.cert'), - 'key': data.get(local_name + '.server.key')}}}) + # Note: Bug#2028683 - data may not be available if the certificates + # relation hasn't been populated by the providing charm. If no 'ca' + # in the data then don't attempt the bundle at all. + if data.get('ca'): + if data.get(raw_certs_key): + bundles.append({ + 'ca': data['ca'], + 'chain': data.get('chain'), + 'certs': json.loads(data[raw_certs_key]) + }) + elif is_legacy_request: + bundles.append({ + 'ca': data['ca'], + 'chain': data.get('chain'), + 'certs': { + sent['common_name']: { + 'cert': data.get(local_name + '.server.cert'), + 'key': data.get(local_name + '.server.key') + } + } + }) return bundles diff --git a/tests/contrib/openstack/test_cert_utils.py b/tests/contrib/openstack/test_cert_utils.py index 98ad55c92..875e51ff0 100644 --- a/tests/contrib/openstack/test_cert_utils.py +++ b/tests/contrib/openstack/test_cert_utils.py @@ -617,6 +617,30 @@ def fake_relation_get(rid, unit): 'chain': 'MYCHAIN'}] ) + @mock.patch.object(cert_utils, 'local_unit') + @mock.patch.object(cert_utils, 'related_units') + @mock.patch.object(cert_utils, 'relation_ids') + @mock.patch.object(cert_utils, 'relation_get') + def test_get_requests_for_local_unit_half_done( + self, relation_get, relation_ids, related_units, local_unit): + local_unit.return_value = 'rabbitmq-server/2' + + def fake_relation_get(rid, unit): + if unit == 'rabbitmq-server/2': + # i.e. legacy request + return {'certificate_name': + 'eb32103b-27c8-4feb-8771-c7097c7314e8', + 'common_name': 'juju-cd4bb3-5.lxd', + 'sans': '["10.5.100.11", "10.5.0.32"]'} + else: + return {} + + relation_ids.return_value = ['certificates:12'] + related_units.return_value = ['vault/0'] + relation_get.side_effect = fake_relation_get + self.assertEqual( + cert_utils.get_requests_for_local_unit(), []) + @mock.patch.object(cert_utils, 'get_requests_for_local_unit') def test_get_bundle_for_cn(self, get_requests_for_local_unit): get_requests_for_local_unit.return_value = [{