Allow release selection to work for subordinate charms
The release selection function bases its decision on installed packages and falls back to looking up OpenStack release codename from source configuration option when no packages are installed. Subordinate charms do not have a source configuration option, thus we want to make it possible for a charm author to request the release selection decision be made based on what is currently available in the system APT cache alone. Our principle charm should already have configured the system with the desired UCA pocket enabled. The charm author requests this behaviour by setting the ``source_config_key`` to an empty string. Note that functions for upgrading between releases etc also depend on the charm having a source configuration option but that is OK as the subordinate has no business dealing with that and should defer such operations to its principle charm. Change-Id: Ieae81619e06dc287c2c42ec944425be4de13d0d6 Closes-Bug: #1865510
This commit is contained in:
parent
72cfde8308
commit
d8b376cde2
|
@ -125,6 +125,9 @@ class OpenStackCharm(BaseOpenStackCharm,
|
|||
# Useful for charms managing software from UCA and consuming the
|
||||
# `openstack` layer directly for re-use of common code, but not being a
|
||||
# OpenStack component.
|
||||
#
|
||||
# Subordinate charms should set this to an empty string ('') to activate
|
||||
# special handling of release selection.
|
||||
source_config_key = 'openstack-origin'
|
||||
|
||||
@property
|
||||
|
|
|
@ -472,8 +472,9 @@ class BaseOpenStackCharm(object, metaclass=BaseOpenStackCharmMeta):
|
|||
return version_or_codename
|
||||
|
||||
@staticmethod
|
||||
def get_os_codename_package(package, codenames, fatal=True):
|
||||
"""Derive OpenStack release codename from an installed package.
|
||||
def get_os_codename_package(package, codenames, fatal=True,
|
||||
apt_cache_sufficient=False):
|
||||
"""Derive OpenStack release codename from a package.
|
||||
|
||||
:param package: Package name to lookup (ie. in apt cache)
|
||||
:type package: str
|
||||
|
@ -492,6 +493,13 @@ class BaseOpenStackCharm(object, metaclass=BaseOpenStackCharmMeta):
|
|||
:type codenames: Dict[str,collections.OrderedDict[Tuple(str,str)]]
|
||||
:param fatal: Raise exception if pkg not installed
|
||||
:type fatal: bool
|
||||
:param apt_cache_sufficient: When False (the default) version from an
|
||||
installed package will be used, when True version from the systems
|
||||
APT cache will be used. This is useful for subordinate charms who
|
||||
need working release selection prior to package installation and
|
||||
has no way of using fall back to version of a package the principle
|
||||
charm has installed nor package source configuration option.
|
||||
:type apt_cache_sufficient: bool
|
||||
:returns: OpenStack version name corresponding to package
|
||||
:rtype: Optional[str]
|
||||
:raises: AttributeError, ValueError
|
||||
|
@ -508,11 +516,15 @@ class BaseOpenStackCharm(object, metaclass=BaseOpenStackCharmMeta):
|
|||
'Could not determine version of package with no installation '
|
||||
'candidate: {}'.format(package))
|
||||
raise e
|
||||
if not pkg.current_ver:
|
||||
if not fatal:
|
||||
return None
|
||||
|
||||
vers = fetch.apt_pkg.upstream_version(pkg.current_ver.ver_str)
|
||||
if apt_cache_sufficient:
|
||||
vers = fetch.apt_pkg.upstream_version(pkg.version)
|
||||
else:
|
||||
if not pkg.current_ver:
|
||||
if not fatal:
|
||||
return None
|
||||
vers = fetch.apt_pkg.upstream_version(pkg.current_ver.ver_str)
|
||||
|
||||
# x.y match only for 20XX.X
|
||||
# and ignore patch level for other packages
|
||||
match = re.match('^(\d+)\.(\d+)', vers)
|
||||
|
|
|
@ -103,7 +103,8 @@ def make_default_select_release_handler():
|
|||
# instance defined package codename dictionary.
|
||||
singleton = get_charm_instance()
|
||||
release_version = singleton.get_os_codename_package(
|
||||
singleton.release_pkg, singleton.package_codenames)
|
||||
singleton.release_pkg, singleton.package_codenames,
|
||||
apt_cache_sufficient=(not singleton.source_config_key))
|
||||
if release_version is None:
|
||||
# Surprisingly get_os_codename_package called with
|
||||
# ``Fatal=True`` does not raise an error when the charm
|
||||
|
|
|
@ -787,6 +787,15 @@ class TestMyOpenStackCharm(BaseOpenStackCharmTest):
|
|||
chm_core.BaseOpenStackCharm.get_os_codename_package(
|
||||
'testpkg', codenames),
|
||||
'newton')
|
||||
self.upstream_version.assert_called_once_with(
|
||||
pkg_mock.current_ver.ver_str)
|
||||
self.upstream_version.reset_mock()
|
||||
self.assertEqual(
|
||||
chm_core.BaseOpenStackCharm.get_os_codename_package(
|
||||
'testpkg', codenames, apt_cache_sufficient=True),
|
||||
'newton')
|
||||
self.upstream_version.assert_called_once_with(
|
||||
pkg_mock.version)
|
||||
# Test non-fatal fail
|
||||
self.assertEqual(
|
||||
chm_core.BaseOpenStackCharm.get_os_codename_package(
|
||||
|
|
|
@ -130,11 +130,23 @@ class TestDefaults(BaseOpenStackCharmTest):
|
|||
'cinder-common', source_key='fake-config-key')
|
||||
# No release set, charm class provides package_codenames
|
||||
kv.reset_mock()
|
||||
singleton.get_os_codename_package.reset_mock()
|
||||
singleton.get_os_codename_package.side_effect = None
|
||||
singleton.get_os_codename_package.return_value = 'three'
|
||||
singleton.source_config_key = 'fake-config-key'
|
||||
release = h.map['function']()
|
||||
self.assertEqual(release, 'three')
|
||||
singleton.get_os_codename_package.assert_called_once_with(
|
||||
mock.ANY, mock.ANY, apt_cache_sufficient=False)
|
||||
kv.set.assert_called_once_with(chm.OPENSTACK_RELEASE_KEY, 'three')
|
||||
# No release set, charm class has empty ``source_config_key``
|
||||
singleton.get_os_codename_package.reset_mock()
|
||||
singleton.source_config_key = ''
|
||||
singleton.get_os_codename_package.return_value = 'four'
|
||||
release = h.map['function']()
|
||||
self.assertEqual(release, 'four')
|
||||
singleton.get_os_codename_package.assert_called_once_with(
|
||||
mock.ANY, mock.ANY, apt_cache_sufficient=True)
|
||||
|
||||
def test_default_select_package_type_handler(self):
|
||||
self.assertIn('charm.default-select-package-type',
|
||||
|
|
Loading…
Reference in New Issue