From 123b8447ed40a9c5339bd181ce707d726d09a565 Mon Sep 17 00:00:00 2001 From: Liam Young Date: Mon, 15 Aug 2022 14:08:01 +0000 Subject: [PATCH] Handle JSON data from dashboard plugins The dashboard-plugin interface sends relation data json encoded but the charm does not decode the local-settings key. This change decodes the data. I have not been able to find any classic plugins that rely on sending raw data but to maintain backwards compatability just incase the charm will fallback to the old behaviour if the relation data is not json encoded. Change-Id: I3f956ae811cb6c46b5e2ab31f1353678a35e623a Closes-Bug: #1986538 --- hooks/horizon_contexts.py | 22 +++++++++++++++++++++- unit_tests/test_horizon_contexts.py | 16 ++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/hooks/horizon_contexts.py b/hooks/horizon_contexts.py index 76766503..f100fb8e 100644 --- a/hooks/horizon_contexts.py +++ b/hooks/horizon_contexts.py @@ -341,6 +341,13 @@ class LocalSettingsContext(OSContextGenerator): relations = [] + # Juju 'internal' data like egress-address is not json encoded. So only + # try and decode the keys we know to expect. + json_keys = [ + 'local-settings', + 'priority', + 'conflicting-packages', + 'install-packages'] for rid in relation_ids("dashboard-plugin"): try: unit = related_units(rid)[0] @@ -349,7 +356,20 @@ class LocalSettingsContext(OSContextGenerator): else: rdata = relation_get(unit=unit, rid=rid) if set(('local-settings', 'priority')) <= set(rdata.keys()): - relations.append((unit, rdata)) + # Classic dashboard plugins may send non-json data but + # reactive charms send json. Attempt to json decode the + # data but fallback if that fails. + decoded_data = {} + try: + for key in rdata.keys(): + if key in json_keys: + decoded_data[key] = json.loads(rdata[key]) + else: + decoded_data[key] = rdata[key] + except (json.decoder.JSONDecodeError, TypeError): + relations.append((unit, rdata)) + else: + relations.append((unit, decoded_data)) ctxt = { 'settings': [ diff --git a/unit_tests/test_horizon_contexts.py b/unit_tests/test_horizon_contexts.py index 13594c6c..a5acf285 100644 --- a/unit_tests/test_horizon_contexts.py +++ b/unit_tests/test_horizon_contexts.py @@ -1324,6 +1324,22 @@ class TestHorizonContexts(CharmTestCase): '# horizon-plugin/0\n' 'FOO = True']}) + def test_LocalSettingsContextJSON(self): + self.relation_ids.return_value = ['plugin:0', 'plugin-too:0'] + self.related_units.side_effect = [['horizon-plugin/0'], + ['horizon-plugin-too/0']] + # One JSON and one raw relation + self.relation_get.side_effect = [{'priority': "99", + 'local-settings': '"FOO = True"'}, + {'priority': 60, + 'local-settings': 'BAR = False'}] + + self.assertEqual(horizon_contexts.LocalSettingsContext()(), + {'settings': ['# horizon-plugin-too/0\n' + 'BAR = False', + '# horizon-plugin/0\n' + 'FOO = True']}) + def test_WebSSOFIDServiceProviderContext(self): def relation_ids_side_effect(rname): return {