Support same pkg version for multiple releases

It is possible for the version of a package to remain the same
across multiple releases of openstack so this adds support to
get_os_codename_package() to allow this. If releases A, B and C
have version N and we are on release B this will return release
C so that it does not look like there is an upgrade necessary.

Change-Id: I138f61312efb728544276483b1a459b9eeecafdb
This commit is contained in:
Edward Hope-Morley 2024-04-23 14:47:08 +01:00
parent 018b72d734
commit eeac9befb2
2 changed files with 70 additions and 7 deletions

View File

@ -1163,6 +1163,36 @@ class BaseOpenStackCharmActions(object):
return vers
def get_closest_release_match(self, package_version, codenames):
# Multiple releases can share the same version of the package so this
# collects contiguous versions, maintaining order then picks the most
# recent version that is less than or equal to what is installed.
reversed_codenames = collections.OrderedDict(
reversed(codenames.items()))
vr_match = None
splitver = package_version.split('.')
for dotpos in reversed(range(3)):
if dotpos >= len(splitver):
continue
ver_pfix = '.'.join(splitver[0:dotpos + 1])
for ver, rname in reversed_codenames.items():
if not ver.startswith(ver_pfix):
continue
if ((vr_match is None or ver > vr_match[0]) and
ver <= package_version):
vr_match = (ver, rname)
break
if vr_match:
break
if vr_match and isinstance(vr_match[1], list):
vr_match = vr_match[0], vr_match[1][-1]
return vr_match
def get_os_codename_package(self, package, codenames, fatal=True,
apt_cache_sufficient=False):
"""Derive OpenStack release codename from a package.
@ -1220,20 +1250,22 @@ class BaseOpenStackCharmActions(object):
if codename:
return codename
vers = self.get_package_version(
package_version = self.get_package_version(
package,
apt_cache_sufficient=apt_cache_sufficient)
# Generate a major version number for newer semantic
# versions of openstack projects
major_vers = vers.split('.')[0]
except Exception:
if fatal:
raise
else:
return None
if (package in codenames and
major_vers in codenames[package]):
return codenames[package][major_vers]
if package not in codenames:
return
vr_match = self.get_closest_release_match(package_version,
codenames[package])
if vr_match:
return vr_match[1]
def get_os_version_snap(self, snap, fatal=True):
"""Derive OpenStack version number from an installed snap.

View File

@ -885,6 +885,37 @@ class TestMyOpenStackCharm(BaseOpenStackCharmTest):
for call in self.render.call_args_list:
self.assertTrue(call[1]['context'])
def test_get_closest_release_match(self):
codenames = collections.OrderedDict([('3.9', 'ussuri'),
('4.0', 'victoria'),
('4.0.1',
['wallaby', 'xena', 'yoga'])])
self.assertEqual(self.target.get_closest_release_match('4',
codenames),
None)
self.assertEqual(self.target.get_closest_release_match('4.0',
codenames),
('4.0', 'victoria'))
self.assertEqual(self.target.get_closest_release_match('4.0.1',
codenames),
('4.0.1', 'yoga'))
self.assertEqual(self.target.get_closest_release_match('4.0.2',
codenames),
('4.0.1', 'yoga'))
codenames['4.0.3'] = 'yoga'
self.assertEqual(self.target.get_closest_release_match('4.0.2',
codenames),
('4.0.1', 'yoga'))
self.assertEqual(self.target.get_closest_release_match('4.0.1.1',
codenames),
('4.0.1', 'yoga'))
def test_get_os_codename_package(self):
codenames = {
'testpkg': collections.OrderedDict([