Fix func27-smoke which fails
This was a combination of the smoke test being incorrectly specified and there being no assess_status() at the end of the hsm_connected() function. Also the assess_status() was removed from the layer-openstack which meant that the status wasn't updating. The change adds in an assess_status() call, but also reworks the tests so that they use the new features in charms.openstack, and also uses defaults for config-changed and assess-status hooks/events. The gate that tox.ini is the keystone-v2 version of the tests. Change-Id: Ib8082a083b05eba872d8a2e5fe477352df25ccbb Closes-Bug: #1629624
This commit is contained in:
parent
ff0224dbac
commit
b00cb733a8
|
@ -42,9 +42,19 @@ def install():
|
|||
|
||||
|
||||
def on_hsm_connected(hsm):
|
||||
"""When SoftHSM connects to Barbican, configure Barbican with the
|
||||
information necessary to configure the plugin.
|
||||
|
||||
:param hsm: the hsm relation object
|
||||
"""
|
||||
BarbicanSoftHSMCharm.singleton.on_hsm_connected(hsm)
|
||||
|
||||
|
||||
def assess_status():
|
||||
"""Call the charm assess_status function"""
|
||||
BarbicanSoftHSMCharm.singleton.assess_status()
|
||||
|
||||
|
||||
class BarbicanSoftHSMCharm(charms_openstack.charm.OpenStackCharm):
|
||||
|
||||
service_name = 'barbican-softhsm'
|
||||
|
|
|
@ -14,8 +14,15 @@
|
|||
|
||||
import charms.reactive as reactive
|
||||
|
||||
import charms_openstack.charm
|
||||
|
||||
import charm.openstack.softhsm as softhsm
|
||||
|
||||
# Use the charms.openstack defaults for common states and hooks
|
||||
charms_openstack.charm.use_defaults(
|
||||
'config.changed',
|
||||
'update-status')
|
||||
|
||||
|
||||
# use a synthetic state to ensure that it get it to be installed independent of
|
||||
# the install hook.
|
||||
|
@ -29,3 +36,4 @@ def install_packages():
|
|||
def hsm_connected(hsm):
|
||||
softhsm.on_hsm_connected(hsm)
|
||||
reactive.set_state('hsm.available')
|
||||
softhsm.assess_status()
|
||||
|
|
|
@ -1 +1,3 @@
|
|||
TODO: write Amulet tests.
|
||||
|
||||
Note that gate-basic-xenial-mitaka is the keystone V2 version of the tests.
|
||||
|
|
|
@ -15,118 +15,44 @@
|
|||
from __future__ import absolute_import
|
||||
from __future__ import print_function
|
||||
|
||||
import unittest
|
||||
|
||||
import mock
|
||||
|
||||
import reactive.handlers as handlers
|
||||
|
||||
|
||||
_when_args = {}
|
||||
_when_not_args = {}
|
||||
import charms_openstack.test_utils as test_utils
|
||||
|
||||
|
||||
def mock_hook_factory(d):
|
||||
class TestRegisteredHooks(test_utils.TestRegisteredHooks):
|
||||
|
||||
def mock_hook(*args, **kwargs):
|
||||
|
||||
def inner(f):
|
||||
# remember what we were passed. Note that we can't actually
|
||||
# determine the class we're attached to, as the decorator only gets
|
||||
# the function.
|
||||
try:
|
||||
d[f.__name__].append(dict(args=args, kwargs=kwargs))
|
||||
except KeyError:
|
||||
d[f.__name__] = [dict(args=args, kwargs=kwargs)]
|
||||
return f
|
||||
return inner
|
||||
return mock_hook
|
||||
|
||||
|
||||
class TestBarbicanHandlers(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls._patched_when = mock.patch('charms.reactive.when',
|
||||
mock_hook_factory(_when_args))
|
||||
cls._patched_when_started = cls._patched_when.start()
|
||||
cls._patched_when_not = mock.patch('charms.reactive.when_not',
|
||||
mock_hook_factory(_when_not_args))
|
||||
cls._patched_when_not_started = cls._patched_when_not.start()
|
||||
# force requires to rerun the mock_hook decorator:
|
||||
# try except is Python2/Python3 compatibility as Python3 has moved
|
||||
# reload to importlib.
|
||||
try:
|
||||
reload(handlers)
|
||||
except NameError:
|
||||
import importlib
|
||||
importlib.reload(handlers)
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
cls._patched_when.stop()
|
||||
cls._patched_when_started = None
|
||||
cls._patched_when = None
|
||||
cls._patched_when_not.stop()
|
||||
cls._patched_when_not_started = None
|
||||
cls._patched_when_not = None
|
||||
# and fix any breakage we did to the module
|
||||
try:
|
||||
reload(handlers)
|
||||
except NameError:
|
||||
import importlib
|
||||
importlib.reload(handlers)
|
||||
|
||||
def setUp(self):
|
||||
self._patches = {}
|
||||
self._patches_start = {}
|
||||
|
||||
def tearDown(self):
|
||||
for k, v in self._patches.items():
|
||||
v.stop()
|
||||
setattr(self, k, None)
|
||||
self._patches = None
|
||||
self._patches_start = None
|
||||
|
||||
def patch(self, obj, attr, return_value=None):
|
||||
mocked = mock.patch.object(obj, attr)
|
||||
self._patches[attr] = mocked
|
||||
started = mocked.start()
|
||||
started.return_value = return_value
|
||||
self._patches_start[attr] = started
|
||||
setattr(self, attr, started)
|
||||
|
||||
def test_registered_hooks(self):
|
||||
# test that the hooks actually registered the relation expressions that
|
||||
# are meaningful for this interface: this is to handle regressions.
|
||||
# The keys are the function names that the hook attaches to.
|
||||
when_patterns = {
|
||||
'hsm_connected': ('hsm.connected', ),
|
||||
def test_hooks(self):
|
||||
defaults = [
|
||||
'config.changed',
|
||||
'update-status']
|
||||
hook_set = {
|
||||
'when': {
|
||||
'hsm_connected': ('hsm.connected', ),
|
||||
},
|
||||
'when_not': {
|
||||
'install_packages': ('charm.installed', ),
|
||||
}
|
||||
}
|
||||
when_not_patterns = {
|
||||
'install_packages': ('charm.installed', ),
|
||||
}
|
||||
# check the when hooks are attached to the expected functions
|
||||
for t, p in [(_when_args, when_patterns),
|
||||
(_when_not_args, when_not_patterns)]:
|
||||
for f, args in t.items():
|
||||
# check that function is in patterns
|
||||
# print("f: {}, args: {}".format(f, args))
|
||||
self.assertTrue(f in p.keys())
|
||||
# check that the lists are equal
|
||||
l = [a['args'][0] for a in args]
|
||||
self.assertEqual(l, sorted(p[f]))
|
||||
# test that the hooks were registered via the
|
||||
# reactive.barbican_handlers
|
||||
self.registered_hooks_test_helper(handlers, hook_set, defaults)
|
||||
|
||||
|
||||
class TestBarbicanHandlers(test_utils.PatchHelper):
|
||||
|
||||
def test_install_packages(self):
|
||||
self.patch(handlers.softhsm, 'install')
|
||||
self.patch(handlers.reactive, 'set_state')
|
||||
self.patch_object(handlers.softhsm, 'install')
|
||||
self.patch_object(handlers.reactive, 'set_state')
|
||||
handlers.install_packages()
|
||||
self.install.assert_called_once_with()
|
||||
self.set_state.assert_called_once_with('charm.installed')
|
||||
|
||||
def test_hsm_connected(self):
|
||||
self.patch(handlers.softhsm, 'on_hsm_connected')
|
||||
self.patch(handlers.reactive, 'set_state')
|
||||
self.patch_object(handlers.softhsm, 'on_hsm_connected')
|
||||
self.patch_object(handlers.reactive, 'set_state')
|
||||
self.patch_object(handlers.softhsm, 'assess_status')
|
||||
handlers.hsm_connected('hsm-thing')
|
||||
self.on_hsm_connected.assert_called_once_with('hsm-thing')
|
||||
self.set_state.assert_called_once_with('hsm.available')
|
||||
self.assess_status.assert_called_once_with()
|
||||
|
|
|
@ -16,53 +16,33 @@ from __future__ import absolute_import
|
|||
from __future__ import print_function
|
||||
|
||||
import textwrap
|
||||
import unittest
|
||||
|
||||
import mock
|
||||
|
||||
import charm.openstack.softhsm as softhsm
|
||||
|
||||
|
||||
class Helper(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self._patches = {}
|
||||
self._patches_start = {}
|
||||
# patch out the select_release to always return 'mitaka'
|
||||
# self.patch(softhsm.unitdata, 'kv')
|
||||
# _getter = mock.MagicMock()
|
||||
# _getter.get.return_value = softhsm.BarbicanSoftHSMCharm.release
|
||||
# self.kv.return_value = _getter
|
||||
|
||||
def tearDown(self):
|
||||
for k, v in self._patches.items():
|
||||
v.stop()
|
||||
setattr(self, k, None)
|
||||
self._patches = None
|
||||
self._patches_start = None
|
||||
|
||||
def patch(self, obj, attr, return_value=None, **kwargs):
|
||||
mocked = mock.patch.object(obj, attr, **kwargs)
|
||||
self._patches[attr] = mocked
|
||||
started = mocked.start()
|
||||
started.return_value = return_value
|
||||
self._patches_start[attr] = started
|
||||
setattr(self, attr, started)
|
||||
import charms_openstack.test_utils as test_utils
|
||||
|
||||
|
||||
class TestSoftHSM(Helper):
|
||||
class TestSoftHSM(test_utils.PatchHelper):
|
||||
|
||||
def test_install(self):
|
||||
self.patch(softhsm.BarbicanSoftHSMCharm.singleton, 'install')
|
||||
self.patch_object(softhsm.BarbicanSoftHSMCharm.singleton, 'install')
|
||||
softhsm.install()
|
||||
self.install.assert_called_once_with()
|
||||
|
||||
def test_on_hsm_connected(self):
|
||||
self.patch(softhsm.BarbicanSoftHSMCharm.singleton,
|
||||
'on_hsm_connected')
|
||||
self.patch_object(softhsm.BarbicanSoftHSMCharm.singleton,
|
||||
'on_hsm_connected')
|
||||
softhsm.on_hsm_connected('hsm-thing')
|
||||
self.on_hsm_connected.assert_called_once_with('hsm-thing')
|
||||
|
||||
def test_assess_status(self):
|
||||
self.patch_object(softhsm.BarbicanSoftHSMCharm.singleton,
|
||||
'assess_status')
|
||||
softhsm.assess_status()
|
||||
self.assess_status.assert_called_once_with()
|
||||
|
||||
def test_read_pins_from_store(self):
|
||||
# test with no file (patch open so that it raises an error)
|
||||
mock_open = mock.MagicMock(return_value=mock.sentinel.file_handle)
|
||||
|
@ -84,9 +64,9 @@ class TestSoftHSM(Helper):
|
|||
|
||||
def test_write_pins_to_store(self):
|
||||
f = mock.MagicMock()
|
||||
self.patch(softhsm.os, 'fdopen', return_value=f)
|
||||
self.patch(softhsm.os, 'open', return_value='opener')
|
||||
self.patch(softhsm.json, 'dump')
|
||||
self.patch_object(softhsm.os, 'fdopen', return_value=f)
|
||||
self.patch_object(softhsm.os, 'open', return_value='opener')
|
||||
self.patch_object(softhsm.json, 'dump')
|
||||
softhsm.write_pins_to_store('1234', '5678')
|
||||
self.open.assert_called_once_with(
|
||||
softhsm.STORED_PINS_FILE,
|
||||
|
@ -115,23 +95,23 @@ class TestSoftHSM(Helper):
|
|||
User PIN init.: yes
|
||||
Label: barbican_token
|
||||
""")
|
||||
self.patch(softhsm.subprocess, 'check_output',
|
||||
return_value=result.encode())
|
||||
self.patch_object(softhsm.subprocess, 'check_output',
|
||||
return_value=result.encode())
|
||||
self.assertEqual(softhsm.read_slot_id('barbican_token'), '5')
|
||||
self.check_output.assert_called_once_with(
|
||||
[softhsm.SOFTHSM2_UTIL_CMD, '--show-slots'])
|
||||
self.assertEqual(softhsm.read_slot_id('not_found'), None)
|
||||
|
||||
|
||||
class TestBarbicanSoftHSMCharm(Helper):
|
||||
class TestBarbicanSoftHSMCharm(test_utils.PatchHelper):
|
||||
|
||||
def test_install(self):
|
||||
self.patch(softhsm.charms_openstack.charm.OpenStackCharm,
|
||||
'install')
|
||||
self.patch(softhsm.ch_core_host, 'add_user_to_group')
|
||||
self.patch_object(softhsm.charms_openstack.charm.OpenStackCharm,
|
||||
'install')
|
||||
self.patch_object(softhsm.ch_core_host, 'add_user_to_group')
|
||||
c = softhsm.BarbicanSoftHSMCharm()
|
||||
self.patch(c, 'setup_token_store')
|
||||
self.patch(softhsm.hookenv, 'status_set')
|
||||
self.patch_object(c, 'setup_token_store')
|
||||
self.patch_object(softhsm.hookenv, 'status_set')
|
||||
c.install()
|
||||
self.install.assert_called_once_with()
|
||||
self.add_user_to_group.assert_called_once_with('barbican', 'softhsm')
|
||||
|
@ -140,17 +120,17 @@ class TestBarbicanSoftHSMCharm(Helper):
|
|||
'waiting', 'Charm installed and token store configured')
|
||||
|
||||
def test_setup_token_store(self):
|
||||
self.patch(softhsm, 'read_pins_from_store')
|
||||
self.patch(softhsm.os.path, 'exists')
|
||||
self.patch(softhsm.os.path, 'isdir')
|
||||
self.patch(softhsm.shutil, 'rmtree')
|
||||
self.patch(softhsm.os, 'remove')
|
||||
self.patch(softhsm.os, 'makedirs')
|
||||
self.patch(softhsm.os, 'chmod')
|
||||
self.patch(softhsm.ch_core_host, 'pwgen')
|
||||
self.patch(softhsm, 'write_pins_to_store')
|
||||
self.patch(softhsm.subprocess, 'check_call')
|
||||
self.patch(softhsm.hookenv, 'log')
|
||||
self.patch_object(softhsm, 'read_pins_from_store')
|
||||
self.patch_object(softhsm.os.path, 'exists')
|
||||
self.patch_object(softhsm.os.path, 'isdir')
|
||||
self.patch_object(softhsm.shutil, 'rmtree')
|
||||
self.patch_object(softhsm.os, 'remove')
|
||||
self.patch_object(softhsm.os, 'makedirs')
|
||||
self.patch_object(softhsm.os, 'chmod')
|
||||
self.patch_object(softhsm.ch_core_host, 'pwgen')
|
||||
self.patch_object(softhsm, 'write_pins_to_store')
|
||||
self.patch_object(softhsm.subprocess, 'check_call')
|
||||
self.patch_object(softhsm.hookenv, 'log')
|
||||
# first, pretend that the token store is already setup.
|
||||
self.read_pins_from_store.return_value = ('1234', '5678', )
|
||||
c = softhsm.BarbicanSoftHSMCharm()
|
||||
|
@ -183,12 +163,12 @@ class TestBarbicanSoftHSMCharm(Helper):
|
|||
|
||||
def test_on_hsm_connected(self):
|
||||
hsm = mock.MagicMock()
|
||||
self.patch(softhsm, 'read_pins_from_store')
|
||||
self.patch(softhsm, 'read_slot_id')
|
||||
self.patch(softhsm.hookenv, 'status_set')
|
||||
self.patch(softhsm.hookenv, 'log')
|
||||
self.patch_object(softhsm, 'read_pins_from_store')
|
||||
self.patch_object(softhsm, 'read_slot_id')
|
||||
self.patch_object(softhsm.hookenv, 'status_set')
|
||||
self.patch_object(softhsm.hookenv, 'log')
|
||||
c = softhsm.BarbicanSoftHSMCharm()
|
||||
self.patch(c, 'setup_token_store')
|
||||
self.patch_object(c, 'setup_token_store')
|
||||
# simulate not being able to set up the token store
|
||||
self.read_pins_from_store.return_value = None, None
|
||||
with self.assertRaises(RuntimeError):
|
||||
|
|
Loading…
Reference in New Issue