Refactor custom status checks
Refactor custom status checks to allow the charm specific class and the inherited general charm type classes to specify status checks. Change-Id: Ib40fa3b46cc629d5b3e5b199a70cff22451661ee
This commit is contained in:
parent
288e712c0a
commit
ffbfa581c6
|
@ -51,6 +51,7 @@ class OSBaseCharm(CharmBase):
|
|||
|
||||
def __init__(self, framework):
|
||||
super().__init__(framework)
|
||||
self.custom_status_checks = []
|
||||
self._stored.set_default(is_started=False)
|
||||
self._stored.set_default(is_paused=False)
|
||||
self._stored.set_default(series_upgrade=False)
|
||||
|
@ -79,15 +80,47 @@ class OSBaseCharm(CharmBase):
|
|||
def custom_status_check(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def register_status_check(self, custom_check):
|
||||
self.custom_status_checks.append(custom_check)
|
||||
|
||||
def update_status(self):
|
||||
"""Update the charms status
|
||||
|
||||
A charm, or plugin, can register checks to be run when calculating the
|
||||
charms status. Each status method should have a unique name. The custom
|
||||
check should return a StatusBase object. If the check returns an
|
||||
ActiveStatus object then subsequent checks are run, if it returns
|
||||
anything else then the charms status is set to the object the check
|
||||
returned and no subsequent checks are run. If the check returns an
|
||||
ActiveStatus with a specific message then this message will be
|
||||
concatenated with the other active status messages.
|
||||
|
||||
Example::
|
||||
|
||||
class MyCharm(OSBaseCharm):
|
||||
|
||||
def __init__(self, framework):
|
||||
super().__init__(framework)
|
||||
super().register_status_check(self.mycharm_check)
|
||||
|
||||
def mycharm_check(self):
|
||||
if self.model.config['plugin-check-fail'] == 'True':
|
||||
return BlockedStatus(
|
||||
'Plugin Custom check failed')
|
||||
else:
|
||||
return ActiveStatus()
|
||||
|
||||
"""
|
||||
logging.info("Updating status")
|
||||
try:
|
||||
# Custom checks return True if the checked passed else False.
|
||||
# If the check failed the custom check will have set the status.
|
||||
if not self.custom_status_check():
|
||||
active_messages = ['Unit is ready']
|
||||
for check in self.custom_status_checks:
|
||||
_result = check()
|
||||
if isinstance(_result, ActiveStatus):
|
||||
if _result.message:
|
||||
active_messages.append(_result.message)
|
||||
else:
|
||||
self.unit.status = _result
|
||||
return
|
||||
except NotImplementedError:
|
||||
pass
|
||||
if self._stored.series_upgrade:
|
||||
self.unit.status = BlockedStatus(
|
||||
'Ready for do-release-upgrade and reboot. '
|
||||
|
@ -106,7 +139,16 @@ class OSBaseCharm(CharmBase):
|
|||
'Missing relations: {}'.format(', '.join(missing_relations)))
|
||||
return
|
||||
if self._stored.is_started:
|
||||
self.unit.status = ActiveStatus('Unit is ready')
|
||||
_unique = []
|
||||
# Reverse sort the list so that a shorter message that has the same
|
||||
# start as a longer message comes first and can then be omitted.
|
||||
# eg 'Unit is ready' comes after 'Unit is ready and clustered'
|
||||
# and 'Unit is ready' is dropped.
|
||||
for msg in sorted(list(set(active_messages)), reverse=True):
|
||||
dupes = [m for m in _unique if m.startswith(msg)]
|
||||
if not dupes:
|
||||
_unique.append(msg)
|
||||
self.unit.status = ActiveStatus(', '.join(_unique))
|
||||
else:
|
||||
self.unit.status = WaitingStatus('Charm configuration in progress')
|
||||
logging.info("Status updated")
|
||||
|
|
|
@ -29,7 +29,36 @@ from ops.model import (
|
|||
import ops_openstack.core
|
||||
|
||||
|
||||
class OpenStackTestAPICharm(ops_openstack.core.OSBaseCharm):
|
||||
class OpenStackTestPlugin1(ops_openstack.core.OSBaseCharm):
|
||||
|
||||
def __init__(self, framework):
|
||||
super().__init__(framework)
|
||||
super().register_status_check(self.plugin1_status_check)
|
||||
|
||||
def plugin1_status_check(self):
|
||||
if self.model.config.get('plugin1-check-fail', 'False') == 'True':
|
||||
return BlockedStatus(
|
||||
'Plugin1 Custom check failed')
|
||||
else:
|
||||
return ActiveStatus('Unit is ready and awesome')
|
||||
|
||||
|
||||
class OpenStackTestPlugin2(ops_openstack.core.OSBaseCharm):
|
||||
|
||||
def __init__(self, framework):
|
||||
super().__init__(framework)
|
||||
super().register_status_check(self.plugin2_status_check)
|
||||
|
||||
def plugin2_status_check(self):
|
||||
if self.model.config.get('plugin2-check-fail', 'False') == 'True':
|
||||
return BlockedStatus(
|
||||
'Plugin2 Custom check failed')
|
||||
else:
|
||||
return ActiveStatus('Unit is ready and super')
|
||||
|
||||
|
||||
class OpenStackTestAPICharm(OpenStackTestPlugin1,
|
||||
OpenStackTestPlugin2):
|
||||
|
||||
PACKAGES = ['keystone-common']
|
||||
REQUIRED_RELATIONS = ['shared-db']
|
||||
|
@ -38,13 +67,15 @@ class OpenStackTestAPICharm(ops_openstack.core.OSBaseCharm):
|
|||
'/etc/f2.conf': ['apache2', 'ks-api'],
|
||||
'/etc/f3.conf': []}
|
||||
|
||||
def __init__(self, framework):
|
||||
super().__init__(framework)
|
||||
super().register_status_check(self.custom_status_check)
|
||||
|
||||
def custom_status_check(self):
|
||||
if self.model.config.get('custom-check-fail', 'False') == 'True':
|
||||
self.unit.status = MaintenanceStatus(
|
||||
'Custom check failed')
|
||||
return False
|
||||
return MaintenanceStatus('Custom check failed')
|
||||
else:
|
||||
return True
|
||||
return ActiveStatus()
|
||||
|
||||
|
||||
class CharmTestCase(unittest.TestCase):
|
||||
|
@ -131,7 +162,7 @@ class TestOSBaseCharm(CharmTestCase):
|
|||
self.harness.charm.on.update_status.emit()
|
||||
self.assertEqual(
|
||||
self.harness.charm.unit.status.message,
|
||||
'Unit is ready')
|
||||
'Unit is ready and super, Unit is ready and awesome')
|
||||
self.assertIsInstance(
|
||||
self.harness.charm.unit.status,
|
||||
ActiveStatus)
|
||||
|
@ -195,6 +226,33 @@ class TestOSBaseCharm(CharmTestCase):
|
|||
self.harness.charm.unit.status,
|
||||
BlockedStatus)
|
||||
|
||||
def test_update_status_plugin_check_fail(self):
|
||||
self.harness.update_config(
|
||||
key_values={
|
||||
'plugin1-check-fail': 'True',
|
||||
'plugin2-check-fail': 'False'})
|
||||
self.harness.add_relation('shared-db', 'mysql')
|
||||
self.harness.begin()
|
||||
self.harness.charm._stored.is_started = True
|
||||
self.harness.charm.on.update_status.emit()
|
||||
self.assertEqual(
|
||||
self.harness.charm.unit.status.message,
|
||||
'Plugin1 Custom check failed')
|
||||
self.assertIsInstance(
|
||||
self.harness.charm.unit.status,
|
||||
BlockedStatus)
|
||||
self.harness.update_config(
|
||||
key_values={
|
||||
'plugin1-check-fail': 'False',
|
||||
'plugin2-check-fail': 'True'})
|
||||
self.harness.charm.on.update_status.emit()
|
||||
self.assertEqual(
|
||||
self.harness.charm.unit.status.message,
|
||||
'Plugin2 Custom check failed')
|
||||
self.assertIsInstance(
|
||||
self.harness.charm.unit.status,
|
||||
BlockedStatus)
|
||||
|
||||
def test_services(self):
|
||||
self.harness.begin()
|
||||
self.assertEqual(
|
||||
|
|
Loading…
Reference in New Issue