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 = [{