Skip to content
This repository has been archived by the owner on Jun 26, 2020. It is now read-only.

Commit

Permalink
Merge "Add versionutils for version compatibility checks"
Browse files Browse the repository at this point in the history
  • Loading branch information
Jenkins authored and openstack-gerrit committed Oct 8, 2013
2 parents 59b473d + d7d74a7 commit aae2b1c
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 19 deletions.
23 changes: 4 additions & 19 deletions openstack/common/rpc/common.py
Expand Up @@ -29,6 +29,7 @@
from openstack.common import jsonutils
from openstack.common import local
from openstack.common import log as logging
from openstack.common import versionutils


CONF = cfg.CONF
Expand Down Expand Up @@ -441,31 +442,15 @@ def inner(*args, **kwargs):
return outer


# TODO(sirp): we should deprecate this in favor of
# using `versionutils.is_compatible` directly
def version_is_compatible(imp_version, version):
"""Determine whether versions are compatible.
:param imp_version: The version implemented
:param version: The version requested by an incoming message.
"""
version_parts = version.split('.')
imp_version_parts = imp_version.split('.')
try:
rev = version_parts[2]
except IndexError:
rev = 0
try:
imp_rev = imp_version_parts[2]
except IndexError:
imp_rev = 0

if int(version_parts[0]) != int(imp_version_parts[0]): # Major
return False
if int(version_parts[1]) > int(imp_version_parts[1]): # Minor
return False
if (int(version_parts[1]) == int(imp_version_parts[1]) and
int(rev) > int(imp_rev)): # Revision
return False
return True
return versionutils.is_compatible(version, imp_version)


def serialize_msg(raw_msg):
Expand Down
45 changes: 45 additions & 0 deletions openstack/common/versionutils.py
@@ -0,0 +1,45 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4

# Copyright (c) 2013 OpenStack Foundation
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

"""
Helpers for comparing version strings.
"""

import pkg_resources


def is_compatible(requested_version, current_version, same_major=True):
"""Determine whether `requested_version` is satisfied by
`current_version`; in other words, `current_version` is >=
`requested_version`.
:param requested_version: version to check for compatibility
:param current_version: version to check against
:param same_major: if True, the major version must be identical between
`requested_version` and `current_version`. This is used when a
major-version difference indicates incompatibility between the two
versions. Since this is the common-case in practice, the default is
True.
:returns: True if compatible, False if not
"""
requested_parts = pkg_resources.parse_version(requested_version)
current_parts = pkg_resources.parse_version(current_version)

if same_major and (requested_parts[0] != current_parts[0]):
return False

return current_parts >= requested_parts
70 changes: 70 additions & 0 deletions tests/unit/test_versionutils.py
@@ -0,0 +1,70 @@
# vim: tabstop=4 shiftwidth=4 softtabstop=4

# Copyright (c) 2013 OpenStack Foundation
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

from openstack.common import test
from openstack.common import versionutils


class IsCompatibleTestCase(test.BaseTestCase):
def test_same_version(self):
self.assertTrue(versionutils.is_compatible('1', '1'))
self.assertTrue(versionutils.is_compatible('1.0', '1.0'))
self.assertTrue(versionutils.is_compatible('1.0.0', '1.0.0'))

def test_requested_minor_greater(self):
self.assertFalse(versionutils.is_compatible('1.1', '1.0'))

def test_requested_minor_less_than(self):
self.assertTrue(versionutils.is_compatible('1.0', '1.1'))

def test_requested_patch_greater(self):
self.assertFalse(versionutils.is_compatible('1.0.1', '1.0.0'))

def test_requested_patch_less_than(self):
self.assertTrue(versionutils.is_compatible('1.0.0', '1.0.1'))

def test_requested_patch_not_present_same(self):
self.assertTrue(versionutils.is_compatible('1.0', '1.0.0'))

def test_requested_patch_not_present_less_than(self):
self.assertTrue(versionutils.is_compatible('1.0', '1.0.1'))

def test_current_patch_not_present_same(self):
self.assertTrue(versionutils.is_compatible('1.0.0', '1.0'))

def test_current_patch_not_present_less_than(self):
self.assertFalse(versionutils.is_compatible('1.0.1', '1.0'))

def test_same_major_true(self):
"""Even though the current version is 2.0, since `same_major` defaults
to `True`, 1.0 is deemed incompatible.
"""
self.assertFalse(versionutils.is_compatible('2.0', '1.0'))
self.assertTrue(versionutils.is_compatible('1.0', '1.0'))
self.assertFalse(versionutils.is_compatible('1.0', '2.0'))

def test_same_major_false(self):
"""With `same_major` set to False, then major version compatibiity
rule is not enforced, so a current version of 2.0 is deemed to satisfy
a requirement of 1.0.
"""
self.assertFalse(versionutils.is_compatible('2.0', '1.0',
same_major=False))
self.assertTrue(versionutils.is_compatible('1.0', '1.0',
same_major=False))
self.assertTrue(versionutils.is_compatible('1.0', '2.0',
same_major=False))

0 comments on commit aae2b1c

Please sign in to comment.