Merge "Rework the default handlers into layer-openstack-*"

This commit is contained in:
Jenkins
2017-08-01 11:40:23 +00:00
committed by Gerrit Code Review
2 changed files with 79 additions and 186 deletions

View File

@@ -1,5 +1,4 @@
import charmhelpers.contrib.openstack.utils as os_utils import charmhelpers.contrib.openstack.utils as os_utils
import charmhelpers.core.hookenv as hookenv
import charmhelpers.core.unitdata as unitdata import charmhelpers.core.unitdata as unitdata
import charms.reactive as reactive import charms.reactive as reactive
@@ -69,20 +68,12 @@ def _map_default_handler(state):
@_map_default_handler('charm.installed') @_map_default_handler('charm.installed')
def make_default_install_handler(): def make_default_install_handler():
"""Set the default charm.installed state so that the default handler in
@reactive.when_not('charm.installed') layer-openstack can run.
def default_install(): Convoluted, because charms.reactive will only run handlers in the reactive
"""Provide a default install handler or hooks directory.
"""
The instance automagically becomes the derived OpenStackCharm instance. reactive.set_state('charms.openstack.do-default-charm.installed')
The kv() key charmers.openstack-release-version' is used to cache the
release being used for this charm. It is determined by the
default_select_release() function below, unless this is overriden by
the charm author
"""
unitdata.kv().unset(OPENSTACK_RELEASE_KEY)
OpenStackCharm.singleton.install()
reactive.set_state('charm.installed')
@_map_default_handler('charm.default-select-release') @_map_default_handler('charm.default-select-release')
@@ -109,94 +100,64 @@ def make_default_select_release_handler():
@_map_default_handler('amqp.connected') @_map_default_handler('amqp.connected')
def make_default_amqp_connection_handler(): def make_default_amqp_connection_handler():
"""Set the default amqp.connected state so that the default handler in
@reactive.when('amqp.connected') layer-openstack can run.
def default_amqp_connection(amqp): Convoluted, because charms.reactive will only run handlers in the reactive
"""Handle the default amqp connection. or hooks directory.
"""
This requires that the charm implements get_amqp_credentials() to reactive.set_state('charms.openstack.do-default-amqp.connected')
provide a tuple of the (user, vhost) for the amqp server
"""
instance = OpenStackCharm.singleton
user, vhost = instance.get_amqp_credentials()
amqp.request_access(username=user, vhost=vhost)
instance.assess_status()
@_map_default_handler('shared-db.connected') @_map_default_handler('shared-db.connected')
def make_default_setup_database_handler(): def make_default_setup_database_handler():
"""Set the default shared-db.connected state so that the default handler in
@reactive.when('shared-db.connected') layer-openstack can run.
def default_setup_database(database): Convoluted, because charms.reactive will only run handlers in the reactive
"""Handle the default database connection setup or hooks directory.
"""
This requires that the charm implements get_database_setup() to provide reactive.set_state('charms.openstack.do-default-shared-db.connected')
a list of dictionaries;
[{'database': ..., 'username': ..., 'hostname': ..., 'prefix': ...}]
The prefix can be missing: it defaults to None.
"""
instance = OpenStackCharm.singleton
for db in instance.get_database_setup():
database.configure(**db)
instance.assess_status()
@_map_default_handler('identity-service.connected') @_map_default_handler('identity-service.connected')
def make_default_setup_endpoint_connection(): def make_default_setup_endpoint_connection():
"""Set the default identity-service.connected state so that the default
@reactive.when('identity-service.connected') handler in layer-openstack can run.
def default_setup_endpoint_connection(keystone): Convoluted, because charms.reactive will only run handlers in the reactive
"""When the keystone interface connects, register this unit into the or hooks directory.
catalog. This is the default handler, and calls on the charm class to """
provide the endpoint information. If multiple endpoints are needed, reactive.set_state(
then a custom endpoint handler will be needed. 'charms.openstack.do-default-identity-service.connected')
"""
instance = OpenStackCharm.singleton
keystone.register_endpoints(instance.service_type,
instance.region,
instance.public_url,
instance.internal_url,
instance.admin_url)
instance.assess_status()
@_map_default_handler('identity-service.available') @_map_default_handler('identity-service.available')
def make_setup_endpoint_available_handler(): def make_setup_endpoint_available_handler():
"""Set the default identity-service.available state so that the default
@reactive.when('identity-service.available') handler in layer-openstack can run.
def default_setup_endpoint_available(keystone): Convoluted, because charms.reactive will only run handlers in the reactive
"""When the identity-service interface is available, this default or hooks directory.
handler switches on the SSL support. """
""" reactive.set_state(
instance = OpenStackCharm.singleton 'charms.openstack.do-default-identity-service.available')
instance.configure_ssl(keystone)
instance.assess_status()
@_map_default_handler('config.changed') @_map_default_handler('config.changed')
def make_default_config_changed_handler(): def make_default_config_changed_handler():
"""Set the default config.changed state so that the default handler in
@reactive.when('config.changed') layer-openstack can run.
def default_config_changed(): Convoluted, because charms.reactive will only run handlers in the reactive
"""Default handler for config.changed state from reactive. Just see if or hooks directory.
our status has changed. This is just to clear any errors that may have """
got stuck due to missing async handlers, etc. reactive.set_state('charms.openstack.do-default-config.changed')
"""
instance = OpenStackCharm.singleton
instance.config_changed()
instance.assess_status()
@_map_default_handler('upgrade-charm') @_map_default_handler('upgrade-charm')
def make_default_upgrade_charm_handler(): def make_default_upgrade_charm_handler():
"""Set the default upgrade-charm state so that the default handler in
@reactive.hook('upgrade-charm') layer-openstack can run.
def default_upgrade_charm(): Convoluted, because charms.reactive will only run handlers in the reactive
"""Default handler for the 'upgrade-charm' hook. or hooks directory.
This calls the charm.singleton.upgrade_charm() function as a default. """
""" reactive.set_state('charms.openstack.do-default-upgrade-charm')
OpenStackCharm.singleton.upgrade_charm()
def default_render_configs(*interfaces): def default_render_configs(*interfaces):
@@ -214,12 +175,9 @@ def default_render_configs(*interfaces):
@_map_default_handler('update-status') @_map_default_handler('update-status')
def make_default_update_status_handler(): def make_default_update_status_handler():
"""Set the default upgrade-status state so that the default handler in
@reactive.hook('update-status') layer-openstack can run.
def default_update_status(): Convoluted, because charms.reactive will only run handlers in the reactive
"""Default handler for update-status state. or hooks directory.
Just call update status. """
""" reactive.set_state('charms.openstack.do-default-update-status')
instance = OpenStackCharm.singleton
hookenv.application_version_set(instance.application_version)
instance.assess_status()

View File

@@ -86,22 +86,11 @@ class TestDefaults(BaseOpenStackCharmTest):
def test_default_install_handler(self): def test_default_install_handler(self):
self.assertIn('charm.installed', chm._default_handler_map) self.assertIn('charm.installed', chm._default_handler_map)
self.patch_object(chm.reactive, 'when_not') self.patch_object(chm.reactive, 'set_state')
h = self.mock_decorator_gen()
self.when_not.side_effect = h.decorator
# call the default handler installer function, and check its map.
f = chm._default_handler_map['charm.installed'] f = chm._default_handler_map['charm.installed']
f() f()
self.assertIn('charm.installed', h.map) self.set_state.assert_called_once_with(
# verify that the installed function calls the charm installer 'charms.openstack.do-default-charm.installed')
self.patch_object(chm, 'OpenStackCharm', name='charm')
kv = mock.MagicMock()
self.patch_object(chm.unitdata, 'kv', new=lambda: kv)
self.patch_object(chm.reactive, 'set_state')
h.map['charm.installed']()
kv.unset.assert_called_once_with(chm.OPENSTACK_RELEASE_KEY)
self.charm.singleton.install.assert_called_once_with()
self.set_state.assert_called_once_with('charm.installed')
def test_default_select_release_handler(self): def test_default_select_release_handler(self):
self.assertIn('charm.default-select-release', chm._default_handler_map) self.assertIn('charm.default-select-release', chm._default_handler_map)
@@ -133,116 +122,62 @@ class TestDefaults(BaseOpenStackCharmTest):
def test_default_amqp_connection_handler(self): def test_default_amqp_connection_handler(self):
self.assertIn('amqp.connected', chm._default_handler_map) self.assertIn('amqp.connected', chm._default_handler_map)
self.patch_object(chm.reactive, 'when') self.patch_object(chm.reactive, 'set_state')
h = self.mock_decorator_gen()
self.when.side_effect = h.decorator
# call the default handler installer function, and check its map. # call the default handler installer function, and check its map.
f = chm._default_handler_map['amqp.connected'] f = chm._default_handler_map['amqp.connected']
f() f()
self.assertIn('amqp.connected', h.map) self.set_state.assert_called_once_with(
# verify that the installed function works 'charms.openstack.do-default-amqp.connected')
self.patch_object(chm, 'OpenStackCharm', name='charm')
self.charm.singleton.get_amqp_credentials.return_value = \
('user', 'vhost')
amqp = mock.MagicMock()
h.map['amqp.connected'](amqp)
self.charm.singleton.get_amqp_credentials.assert_called_once_with()
amqp.request_access.assert_called_once_with(username='user',
vhost='vhost')
self.charm.singleton.assess_status.assert_called_once_with()
def test_default_setup_datatbase_handler(self): def test_default_setup_datatbase_handler(self):
self.assertIn('shared-db.connected', chm._default_handler_map) self.assertIn('shared-db.connected', chm._default_handler_map)
self.patch_object(chm.reactive, 'when') self.patch_object(chm.reactive, 'set_state')
h = self.mock_decorator_gen()
self.when.side_effect = h.decorator
# call the default handler installer function, and check its map. # call the default handler installer function, and check its map.
f = chm._default_handler_map['shared-db.connected'] f = chm._default_handler_map['shared-db.connected']
f() f()
self.assertIn('shared-db.connected', h.map) self.set_state.assert_called_once_with(
# verify that the installed function works 'charms.openstack.do-default-shared-db.connected')
self.patch_object(chm, 'OpenStackCharm', name='charm')
self.charm.singleton.get_database_setup.return_value = [
{'database': 'configuration'}]
database = mock.MagicMock()
h.map['shared-db.connected'](database)
self.charm.singleton.get_database_setup.assert_called_once_with()
database.configure.assert_called_once_with(database='configuration')
self.charm.singleton.assess_status.assert_called_once_with()
def test_default_setup_endpoint_handler(self): def test_default_setup_endpoint_handler(self):
self.assertIn('identity-service.connected', chm._default_handler_map) self.assertIn('identity-service.connected', chm._default_handler_map)
self.patch_object(chm.reactive, 'when') self.patch_object(chm.reactive, 'set_state')
h = self.mock_decorator_gen()
self.when.side_effect = h.decorator
# call the default handler installer function, and check its map.
f = chm._default_handler_map['identity-service.connected'] f = chm._default_handler_map['identity-service.connected']
f() f()
self.assertIn('identity-service.connected', h.map) self.set_state.assert_called_once_with(
# verify that the installed function works 'charms.openstack.do-default-identity-service.connected')
OpenStackCharm = mock.MagicMock()
class Instance(object):
service_type = 'type1'
region = 'region1'
public_url = 'public_url'
internal_url = 'internal_url'
admin_url = 'admin_url'
assess_status = mock.MagicMock()
OpenStackCharm.singleton = Instance
with mock.patch.object(chm, 'OpenStackCharm', new=OpenStackCharm):
keystone = mock.MagicMock()
h.map['identity-service.connected'](keystone)
keystone.register_endpoints.assert_called_once_with(
'type1', 'region1', 'public_url', 'internal_url', 'admin_url')
Instance.assess_status.assert_called_once_with()
def test_default_setup_endpoint_available_handler(self): def test_default_setup_endpoint_available_handler(self):
self.assertIn('identity-service.available', chm._default_handler_map) self.assertIn('identity-service.available', chm._default_handler_map)
self.patch_object(chm.reactive, 'when') self.patch_object(chm.reactive, 'set_state')
h = self.mock_decorator_gen()
self.when.side_effect = h.decorator
# call the default handler installer function, and check its map. # call the default handler installer function, and check its map.
f = chm._default_handler_map['identity-service.available'] f = chm._default_handler_map['identity-service.available']
f() f()
self.assertIn('identity-service.available', h.map) self.set_state.assert_called_once_with(
# verify that the installed function works 'charms.openstack.do-default-identity-service.available')
self.patch_object(chm, 'OpenStackCharm', name='charm')
h.map['identity-service.available']('keystone')
self.charm.singleton.configure_ssl.assert_called_once_with('keystone')
self.charm.singleton.assess_status.assert_called_once_with()
def test_default_config_changed_handler(self): def test_default_config_changed_handler(self):
self.assertIn('config.changed', chm._default_handler_map) self.assertIn('config.changed', chm._default_handler_map)
self.patch_object(chm.reactive, 'when') self.patch_object(chm.reactive, 'set_state')
h = self.mock_decorator_gen()
self.when.side_effect = h.decorator
# call the default handler installer function, and check its map.
f = chm._default_handler_map['config.changed'] f = chm._default_handler_map['config.changed']
f() f()
self.assertIn('config.changed', h.map) self.set_state.assert_called_once_with(
# verify that the installed function works 'charms.openstack.do-default-config.changed')
self.patch_object(chm, 'OpenStackCharm', name='charm')
h.map['config.changed']()
self.charm.singleton.assess_status.assert_called_once_with()
def test_default_update_status_handler(self): def test_default_update_status_handler(self):
self.assertIn('update-status', chm._default_handler_map) self.assertIn('update-status', chm._default_handler_map)
self.patch_object(chm.reactive, 'hook') self.patch_object(chm.reactive, 'set_state')
h = self.mock_decorator_gen()
self.hook.side_effect = h.decorator
# call the default handler installer function, and check its map.
f = chm._default_handler_map['update-status'] f = chm._default_handler_map['update-status']
f() f()
self.assertIn('update-status', h.map) self.set_state.assert_called_once_with(
# verify that the installed function works 'charms.openstack.do-default-update-status')
self.patch_object(chm, 'OpenStackCharm', name='charm')
self.patch_object(chm.hookenv, 'application_version_set') def test_default_upgrade_charm_handler(self):
h.map['update-status']() self.assertIn('upgrade-charm', chm._default_handler_map)
self.charm.singleton.assess_status.assert_called_once_with() self.patch_object(chm.reactive, 'set_state')
self.application_version_set.assert_called_once_with(mock.ANY) f = chm._default_handler_map['upgrade-charm']
f()
self.set_state.assert_called_once_with(
'charms.openstack.do-default-upgrade-charm')
def test_default_render_configs(self): def test_default_render_configs(self):
self.patch_object(chm, 'OpenStackCharm', name='charm') self.patch_object(chm, 'OpenStackCharm', name='charm')