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. The main change here that allows this
is to support matching major and minor version up to X.Y.Z as
opposed to previously only matching the major version X.

Related-Bug: #1973303

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

View File

@ -1163,6 +1163,33 @@ 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
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 +1247,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,36 @@ 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', '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([