diff --git a/.stestr.conf b/.stestr.conf new file mode 100644 index 0000000..5fcccac --- /dev/null +++ b/.stestr.conf @@ -0,0 +1,3 @@ +[DEFAULT] +test_path=./unit_tests +top_dir=./ diff --git a/.testr.conf b/.testr.conf deleted file mode 100644 index 801646b..0000000 --- a/.testr.conf +++ /dev/null @@ -1,8 +0,0 @@ -[DEFAULT] -test_command=OS_STDOUT_CAPTURE=${OS_STDOUT_CAPTURE:-1} \ - OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} \ - OS_TEST_TIMEOUT=${OS_TEST_TIMEOUT:-60} \ - ${PYTHON:-python} -m subunit.run discover -t ./ ./unit_tests $LISTOPT $IDOPTION - -test_id_option=--load-list $IDFILE -test_list_option=--list diff --git a/src/layer.yaml b/src/layer.yaml index bcb29d5..53e94b3 100644 --- a/src/layer.yaml +++ b/src/layer.yaml @@ -4,6 +4,7 @@ includes: - interface:rabbitmq - interface:keystone - interface:barbican-hsm + - interface:barbican-secrets repo: https://github.com/openstack/charm-barbican options: basic: diff --git a/src/lib/charm/openstack/barbican.py b/src/lib/charm/openstack/barbican.py index 8c0ae5d..1e9e2bd 100644 --- a/src/lib/charm/openstack/barbican.py +++ b/src/lib/charm/openstack/barbican.py @@ -78,6 +78,18 @@ def slot_id(hsm): return '' +@charms_openstack.adapters.adapter_property('secrets') +def plugins(secrets): + """Provide a plugins property to the template if it exists""" + return secrets.relation.plugins + + +@charms_openstack.adapters.adapter_property('secrets') +def plugins_string(secrets): + """Provide a plugins_string property to the template if it exists""" + return secrets.relation.plugins_string + + class BarbicanCharm(charms_openstack.charm.HAOpenStackCharm): """BarbicanCharm provides the specialisation of the OpenStackCharm functionality to manage a barbican unit. diff --git a/src/metadata.yaml b/src/metadata.yaml index 60f498e..076e89d 100644 --- a/src/metadata.yaml +++ b/src/metadata.yaml @@ -24,3 +24,6 @@ requires: hsm: interface: barbican-hsm optional: true + secrets: + interface: barbican-secrets + optional: true diff --git a/src/reactive/barbican_handlers.py b/src/reactive/barbican_handlers.py index 81f20f8..571759b 100644 --- a/src/reactive/barbican_handlers.py +++ b/src/reactive/barbican_handlers.py @@ -53,5 +53,16 @@ def render_stuff(*args): hookenv.log("about to call the render_configs with {}".format(args)) with charm.provide_charm_instance() as barbican_charm: barbican_charm.render_with_interfaces( - charm.optional_interfaces(args, 'hsm.available')) + charm.optional_interfaces(args, + 'hsm.available', + 'secrets.available')) barbican_charm.assess_status() + + +@reactive.when('secrets.new-plugin') +def secrets_plugin_configure(): + hookenv.log('Received information about secrets plugin', + level=hookenv.INFO) + reactive.clear_flag('secrets.new-plugin') + reactive.set_flag('secrets.available') + reactive.set_flag('config.changed') diff --git a/src/templates/rocky/barbican.conf b/src/templates/rocky/barbican.conf index 26a9671..d042140 100644 --- a/src/templates/rocky/barbican.conf +++ b/src/templates/rocky/barbican.conf @@ -15,7 +15,20 @@ host_href = {{ options.external_endpoints.barbican_worker.url }} [secretstore] namespace = barbican.secretstore.plugin +{% if secrets and secrets.plugins_string -%} +enabled_secretstore_plugins = {{ secrets.plugins_string }} +{% else %} enabled_secretstore_plugins = store_crypto +{%- endif %} + +{% if secrets -%} +{% for plugin in secrets.plugins -%} +[{{ plugin.name }}_plugin] +{% for key, value in plugin.data.items() -%} +{{ key }} = {{ value }} +{% endfor %} +{% endfor %} +{%- endif %} [crypto] namespace = barbican.crypto.plugin diff --git a/tox.ini b/tox.ini index f2a880e..864fa7c 100644 --- a/tox.ini +++ b/tox.ini @@ -48,7 +48,7 @@ deps = -r{toxinidir}/test-requirements.txt commands = ostestr {posargs} [testenv:pep8] -basepython = python3.5 +basepython = python3 deps = -r{toxinidir}/test-requirements.txt commands = flake8 {posargs} src unit_tests diff --git a/unit_tests/test_barbican_handlers.py b/unit_tests/test_barbican_handlers.py index 332ecca..b263f4d 100644 --- a/unit_tests/test_barbican_handlers.py +++ b/unit_tests/test_barbican_handlers.py @@ -38,6 +38,7 @@ class TestRegisteredHooks(test_utils.TestRegisteredHooks): 'render_stuff': ('shared-db.available', 'identity-service.available', 'amqp.available',), + 'secrets_plugin_configure': ('secrets.new-plugin',), } } # test that the hooks were registered via the @@ -45,7 +46,7 @@ class TestRegisteredHooks(test_utils.TestRegisteredHooks): self.registered_hooks_test_helper(handlers, hook_set, defaults) -class TestRenderStuff(test_utils.PatchHelper): +class TestBarbicanHandlers(test_utils.PatchHelper): def test_render_stuff(self): barbican_charm = mock.MagicMock() @@ -56,7 +57,8 @@ class TestRenderStuff(test_utils.PatchHelper): self.patch_object(handlers.charm, 'optional_interfaces') def _optional_interfaces(args, *interfaces): - self.assertEqual(interfaces, ('hsm.available', )) + self.assertEqual(interfaces, ('hsm.available', + 'secrets.available', )) return args + ('hsm', ) self.optional_interfaces.side_effect = _optional_interfaces @@ -65,3 +67,13 @@ class TestRenderStuff(test_utils.PatchHelper): barbican_charm.render_with_interfaces.assert_called_once_with( ('arg1', 'arg2', 'hsm')) barbican_charm.assess_status.assert_called_once_with() + + def test_secrets_plugin_configure(self): + self.patch_object(handlers.reactive, 'clear_flag') + self.patch_object(handlers.reactive, 'set_flag') + handlers.secrets_plugin_configure() + self.clear_flag.assert_called_once_with('secrets.new-plugin') + self.set_flag.assert_has_calls([ + mock.call('secrets.available'), + mock.call('config.changed'), + ]) diff --git a/unit_tests/test_lib_charm_openstack_barbican.py b/unit_tests/test_lib_charm_openstack_barbican.py index 001dcf4..4ed6401 100644 --- a/unit_tests/test_lib_charm_openstack_barbican.py +++ b/unit_tests/test_lib_charm_openstack_barbican.py @@ -61,6 +61,21 @@ class TestHSMProperties(Helper): self.assertEqual(barbican.slot_id(hsm), 'a-slot_id') +class TestSecretsProperties(Helper): + + def test_plugins(self): + secrets = mock.MagicMock() + plugins = {'name': 'a-name'} + secrets.relation.plugins = plugins + self.assertEqual(barbican.plugins(secrets), plugins) + + def test_plugins_string(self): + secrets = mock.MagicMock() + plugins_string = 'a-name_plugin' + secrets.relation.plugins_string = plugins_string + self.assertEqual(barbican.plugins_string(secrets), plugins_string) + + class TestBarbicanCharm(Helper): def test_action_generate_mkek(self):