Allow bespoke get_charm_instance method to be used
Allow a charm to use the new register_get_charm_instance decorator to register the method to be used when getting a charm instance. Currently get_charm_instance expects standard OpenStack versioning, this change allows are a charm to register an alternative get_charm_instance method that can handle an alternative versioning system. Perhaps controversially the default method is not defined in charms_openstack.charm.defaults. I have kept it in core because it felt a more natural fit there given it relies on core._releases but I am open to moving it if that is preferable. Change-Id: I42574654bc1f314b49049e80861d4039f8484dff
This commit is contained in:
parent
4907569ebc
commit
38de241ce6
|
@ -45,6 +45,10 @@ _singleton = None
|
|||
# This is to enable the defining code to define which release is used.
|
||||
_release_selector_function = None
|
||||
|
||||
# `_get_charm_instance_function` holds a function that takes optionally takes a
|
||||
# release and returns the corresponding charm class.
|
||||
_get_charm_instance_function = None
|
||||
|
||||
# `_package_type_selector_function` holds a function that optionally takes a
|
||||
# package type and commutes it to another package type or just returns a
|
||||
# package type. This is to enable the defining code to define which
|
||||
|
@ -100,7 +104,8 @@ class provide_charm_instance(object):
|
|||
return False
|
||||
|
||||
|
||||
def get_charm_instance(release=None, package_type='deb', *args, **kwargs):
|
||||
def default_get_charm_instance(release=None, package_type='deb', *args,
|
||||
**kwargs):
|
||||
"""Get an instance of the charm based on the release (or use the
|
||||
default if release is None).
|
||||
|
||||
|
@ -147,6 +152,24 @@ def get_charm_instance(release=None, package_type='deb', *args, **kwargs):
|
|||
return cls(release=release, *args, **kwargs)
|
||||
|
||||
|
||||
def get_charm_instance(release=None, package_type='deb', *args, **kwargs):
|
||||
"""Get an instance of the charm based on the release (or use the
|
||||
default if release is None).
|
||||
|
||||
Use a bespoke method if one is registered otherwise uses the default
|
||||
default_get_charm_instance.
|
||||
|
||||
:param release: lc string representing release wanted.
|
||||
:param package_type: string representing the package type required
|
||||
:returns: BaseOpenStackCharm() derived class according to cls.releases
|
||||
"""
|
||||
return (_get_charm_instance_function or default_get_charm_instance)(
|
||||
release=release,
|
||||
package_type=package_type,
|
||||
*args,
|
||||
**kwargs)
|
||||
|
||||
|
||||
def register_os_release_selector(f):
|
||||
"""Register a function that determines what the release is for the
|
||||
invocation run. This allows the charm to define HOW the release is
|
||||
|
@ -171,6 +194,31 @@ def register_os_release_selector(f):
|
|||
return f
|
||||
|
||||
|
||||
def register_get_charm_instance(f):
|
||||
"""Register a function that supplies a charm class for a given
|
||||
release.
|
||||
|
||||
Usage:
|
||||
|
||||
@register_get_charm_instance
|
||||
def my_get_charm_instance(release=None, *args, **kwargs):
|
||||
if release == X:
|
||||
cls = CharmClassX
|
||||
return cls(release=release, *args, **kwargs)
|
||||
|
||||
The function should return a string which is an OS release.
|
||||
"""
|
||||
global _get_charm_instance_function
|
||||
if _get_charm_instance_function is None:
|
||||
# we can only do this once in a system invocation.
|
||||
_get_charm_instance_function = f
|
||||
else:
|
||||
raise RuntimeError(
|
||||
"Only a single get_charm_instance is supported."
|
||||
" Called with {}".format(f.__name__))
|
||||
return f
|
||||
|
||||
|
||||
def register_package_type_selector(f):
|
||||
"""Register a function that determines what the package type is for the
|
||||
invocation run. This allows the charm to define HOW the package type is
|
||||
|
|
|
@ -57,6 +57,36 @@ class TestRegisterOSReleaseSelector(unittest.TestCase):
|
|||
chm_core._release_selector_function = save_rsf
|
||||
|
||||
|
||||
class TestRegisterGetCharmInstance(unittest.TestCase):
|
||||
|
||||
def test_register(self):
|
||||
save_rsf = chm_core._get_charm_instance_function
|
||||
chm_core._get_charm_instance_function = None
|
||||
|
||||
@chm_core.register_get_charm_instance
|
||||
def test_func():
|
||||
pass
|
||||
|
||||
self.assertEqual(chm_core._get_charm_instance_function, test_func)
|
||||
chm_core._get_charm_instance_function = save_rsf
|
||||
|
||||
def test_cant_register_more_than_once(self):
|
||||
save_rsf = chm_core._get_charm_instance_function
|
||||
chm_core._get_charm_instance_function = None
|
||||
|
||||
@chm_core.register_get_charm_instance
|
||||
def test_func1():
|
||||
pass
|
||||
|
||||
with self.assertRaises(RuntimeError):
|
||||
@chm_core.register_get_charm_instance
|
||||
def test_func2():
|
||||
pass
|
||||
|
||||
self.assertEqual(chm_core._get_charm_instance_function, test_func1)
|
||||
chm_core._get_charm_instance_function = save_rsf
|
||||
|
||||
|
||||
class TestBaseOpenStackCharmMeta(BaseOpenStackCharmTest):
|
||||
|
||||
def setUp(self):
|
||||
|
@ -103,6 +133,7 @@ class TestFunctions(BaseOpenStackCharmTest):
|
|||
def setUp(self):
|
||||
super().setUp(chm_core.BaseOpenStackCharm, TEST_CONFIG)
|
||||
self.patch_object(chm_core, '_releases', new={})
|
||||
chm_core._get_charm_instance_function = None
|
||||
|
||||
class TestC1(chm_core.BaseOpenStackCharm):
|
||||
release = 'icehouse'
|
||||
|
|
Loading…
Reference in New Issue