From c4f153e5820f4103f0e7e1a16b2b959477f0ed3a Mon Sep 17 00:00:00 2001 From: Corey Bryant Date: Fri, 15 Sep 2023 15:55:10 -0400 Subject: [PATCH] Ensure get_requests_for_local_unit doesn't fail on incomplete relation This is a rebuild/make sync for charms to pickup the fix in charmhelpers to fix any inadvertant accesses of ['ca'] in the relation data before it is available from vault in the certificates relation. Fix in charmhelpers is in [1]. [1] https://github.com/juju/charm-helpers/pull/824 Closes-Bug: #2028683 Change-Id: I3393fc63fa066b15f3e67c526ab3f2abe0ead028 --- charmhelpers/contrib/openstack/cert_utils.py | 33 ++++++++++------ charmhelpers/contrib/openstack/context.py | 8 ++-- .../templates/wsgi-openstack-api.conf | 2 +- .../templates/wsgi-openstack-metadata.conf | 2 +- charmhelpers/contrib/storage/linux/ceph.py | 8 +++- charmhelpers/core/unitdata.py | 39 ++++++++++++++++++- charmhelpers/fetch/snap.py | 2 +- 7 files changed, 72 insertions(+), 22 deletions(-) diff --git a/charmhelpers/contrib/openstack/cert_utils.py b/charmhelpers/contrib/openstack/cert_utils.py index a25ca99..6620f59 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/charmhelpers/contrib/openstack/context.py b/charmhelpers/contrib/openstack/context.py index 24a13d0..42f1503 100644 --- a/charmhelpers/contrib/openstack/context.py +++ b/charmhelpers/contrib/openstack/context.py @@ -1748,9 +1748,9 @@ def __init__(self, name=None, script=None, admin_script=None, def __call__(self): total_processes = _calculate_workers() - enable_wsgi_rotation = config('wsgi-rotation') - if enable_wsgi_rotation is None: - enable_wsgi_rotation = True + enable_wsgi_socket_rotation = config('wsgi-socket-rotation') + if enable_wsgi_socket_rotation is None: + enable_wsgi_socket_rotation = True ctxt = { "service_name": self.service_name, "user": self.user, @@ -1764,7 +1764,7 @@ def __call__(self): "public_processes": int(math.ceil(self.public_process_weight * total_processes)), "threads": 1, - "wsgi_rotation": enable_wsgi_rotation, + "wsgi_socket_rotation": enable_wsgi_socket_rotation, } return ctxt diff --git a/charmhelpers/contrib/openstack/templates/wsgi-openstack-api.conf b/charmhelpers/contrib/openstack/templates/wsgi-openstack-api.conf index 2cb735e..de5f603 100644 --- a/charmhelpers/contrib/openstack/templates/wsgi-openstack-api.conf +++ b/charmhelpers/contrib/openstack/templates/wsgi-openstack-api.conf @@ -12,7 +12,7 @@ Listen {{ admin_port }} Listen {{ public_port }} {% endif -%} -{% if wsgi_rotation -%} +{% if wsgi_socket_rotation -%} WSGISocketRotation On {% else -%} WSGISocketRotation Off diff --git a/charmhelpers/contrib/openstack/templates/wsgi-openstack-metadata.conf b/charmhelpers/contrib/openstack/templates/wsgi-openstack-metadata.conf index 2cb735e..de5f603 100644 --- a/charmhelpers/contrib/openstack/templates/wsgi-openstack-metadata.conf +++ b/charmhelpers/contrib/openstack/templates/wsgi-openstack-metadata.conf @@ -12,7 +12,7 @@ Listen {{ admin_port }} Listen {{ public_port }} {% endif -%} -{% if wsgi_rotation -%} +{% if wsgi_socket_rotation -%} WSGISocketRotation On {% else -%} WSGISocketRotation Off diff --git a/charmhelpers/contrib/storage/linux/ceph.py b/charmhelpers/contrib/storage/linux/ceph.py index 2e1fc1b..6ec67cb 100644 --- a/charmhelpers/contrib/storage/linux/ceph.py +++ b/charmhelpers/contrib/storage/linux/ceph.py @@ -158,15 +158,19 @@ def get_osd_settings(relation_name): return _order_dict_by_key(osd_settings) -def send_application_name(relid=None): +def send_application_name(relid=None, app_name=None): """Send the application name down the relation. :param relid: Relation id to set application name in. :type relid: str + :param app_name: Application name to send in the relation. + :type app_name: str """ + if app_name is None: + app_name = application_name() relation_set( relation_id=relid, - relation_settings={'application-name': application_name()}) + relation_settings={'application-name': app_name}) def send_osd_settings(): diff --git a/charmhelpers/core/unitdata.py b/charmhelpers/core/unitdata.py index 8f4bbc6..65153f1 100644 --- a/charmhelpers/core/unitdata.py +++ b/charmhelpers/core/unitdata.py @@ -151,6 +151,7 @@ def config_changed(): import datetime import itertools import json +import logging import os import pprint import sqlite3 @@ -521,6 +522,42 @@ class DeltaSet(Record): def kv(): global _KV + + # If we are running unit tests, it is useful to go into memory-backed KV store to + # avoid concurrency issues when running multiple tests. This is not a + # problem when juju is running normally. + + env_var = os.environ.get("CHARM_HELPERS_TESTMODE", "auto").lower() + if env_var not in ["auto", "no", "yes"]: + logging.warning("Unknown value for CHARM_HELPERS_TESTMODE '%s'" + ", assuming 'no'", env_var) + env_var = "no" + + if env_var == "no": + in_memory_db = False + elif env_var == "yes": + in_memory_db = True + elif env_var == "auto": + # If UNIT_STATE_DB is set, respect this request + if "UNIT_STATE_DB" in os.environ: + in_memory_db = False + # Autodetect normal juju execution by looking for juju variables + elif "JUJU_CHARM_DIR" in os.environ or "JUJU_UNIT_NAME" in os.environ: + in_memory_db = False + else: + # We are probably running in unit test mode + logging.warning("Auto-detected unit test environment for KV store.") + in_memory_db = True + else: + # Help the linter realise that in_memory_db is always set + raise Exception("Cannot reach this line") + if _KV is None: - _KV = Storage() + if in_memory_db: + _KV = Storage(":memory:") + else: + _KV = Storage() + else: + if in_memory_db and _KV.db_path != ":memory:": + logging.warning("Running with in_memory_db and KV is not set to :memory:") return _KV diff --git a/charmhelpers/fetch/snap.py b/charmhelpers/fetch/snap.py index 36d6bce..7ab7ce3 100644 --- a/charmhelpers/fetch/snap.py +++ b/charmhelpers/fetch/snap.py @@ -52,7 +52,7 @@ def _snap_exec(commands): :param commands: List commands :return: Integer exit code """ - assert type(commands) == list + assert isinstance(commands, list) retry_count = 0 return_code = None