Skip to content

Commit

Permalink
Change gppkg version compatibility check to use magic number
Browse files Browse the repository at this point in the history
* We were using string comparison for our version checks and did not account for two digit numbers.
  For example:
  comparing '5.0.10.0' to '5.0.5.0' will return 5.0.5.0 being greater

  Switching to magic number comparison, fixing this issue.

* Add unit test for gppkg
  • Loading branch information
Chibin committed Oct 20, 2016
1 parent 538b930 commit 2c0b82f
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 5 deletions.
26 changes: 22 additions & 4 deletions gpMgmt/bin/gppylib/operations/package.py
Original file line number Diff line number Diff line change
Expand Up @@ -387,9 +387,14 @@ def execute(self):
logger.error('%s requires Greenplum Database version %s' % (gppkg.pkgname, required_gpdb_version))
return False

if not 'orca' in gppkg.version and ".".join(map(str,gpdb_version.version)) >= '4.3.5':
logger.error('Greenplum Database requires orca version of %s' % (gppkg.pkg))
return False
# last bumped version (4.3.5.0)
orca_compatible_minor_version = 40305
gpdb_magic_num = self._convert_to_magic_number_version(gpdb_version)

if 'orca' not in gppkg.version and \
gpdb_magic_num >= orca_compatible_minor_version:
logger.error('Greenplum Database requires orca version of %s' % (gppkg.pkg))
return False

return True

Expand All @@ -399,13 +404,26 @@ def _get_gpdb_version(self):
Returns a string consisting of the major
release version
'''

logger.debug('_get_gpdb_version')
self.gphome = gp.get_gphome()
version = gp.GpVersion.local('local GP software version check', self.gphome)
gpdb_version = GpVersion(version.strip())
return gpdb_version

def _convert_to_magic_number_version(self, gpversion_obj):
'''
Converts GPDB version to the GPDB magic number
Returns an int consisting of the major and minor release version
'''
logger.debug('_convert_to_magic_number_version')

ver_list = gpversion_obj.version

# The generation of the magic version number (GP_VERSION_NUM) is
# retreived from our configure.in file
magic_num = "%d%02d%02d" % (ver_list[0], ver_list[1],
ver_list[2] if len(ver_list) > 2 else 0)
return int(magic_num)


class ValidateInstallPackage(Operation):
Expand Down
5 changes: 4 additions & 1 deletion gpMgmt/bin/gppylib/test/unit/gp_unittest.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,20 @@ class GpTestCase(unittest.TestCase):
def __init__(self, methodName='runTest'):
super(GpTestCase, self).__init__(methodName)
self.patches = []
self.mock_objs = []

def apply_patches(self, patches):
if self.patches:
raise Exception('Test class is already patched!')
self.patches = patches
[p.start() for p in self.patches]
self.mock_objs = [p.start() for p in self.patches]

# if you have a tearDown() in your test class,
# be sure to call this using super.tearDown()
def tearDown(self):
[p.stop() for p in self.patches]
self.mock_objs = []


# hide unittest dependencies here
def run_tests():
Expand Down
91 changes: 91 additions & 0 deletions gpMgmt/bin/gppylib/test/unit/test_unit_package.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
from mock import *
from gp_unittest import *
from gppylib.operations.package import IsVersionCompatible


class IsVersionCompatibleTestCase(GpTestCase):
def setUp(self):
self.gppkg_mock_values = \
{'main_rpm': 'plperl-1.1-2.x86_64.rpm',
'postupdate': [],
'pkgname': 'plperl',
'description': 'some description.',
'postinstall': [{'Master': "some reason to restart database"}],
'postuninstall': [],
'abspath': 'plperl-ossv5.12.4_pv1.3_gpdb4.3-rhel5-x86_64.gppkg',
'preinstall': [],
'version': 'ossv5.12.4_pv1.2_gpdb4.3',
'pkg': 'plperl-ossv5.12.4_pv1.3_gpdb4.3-rhel5-x86_64.gppkg',
'dependencies': [],
'file_list': ['deps',
'gppkg_spec.yml',
'plperl-1.1-2.x86_64.rpm'],
'gpdbversion': Mock(),
'preuninstall': [],
'os': 'rhel5',
'architecture': 'x86_64'}

self.apply_patches([
patch('gppylib.operations.package.logger',
return_value=Mock(spec=['log', 'info', 'debug', 'error'])),
])
self.mock_logger = self.mock_objs[0]

def _is_requires_orca_logged(self, gppkg_name, log_messages):
return ('Greenplum Database requires orca version of '
'%s' % gppkg_name in log_messages)

@patch('gppylib.operations.package.GpVersion',
return_value=Mock(version=[4, 3, 10, 0]))
def test__execute_reports_incompatability(self, mock_gpversion):
logger = self.mock_logger
gppkg_mock_values = self.gppkg_mock_values
gppkg = Mock(**gppkg_mock_values)

subject = IsVersionCompatible(gppkg)
subject.execute()

gppkg_name = 'plperl-ossv5.12.4_pv1.3_gpdb4.3-rhel5-x86_64.gppkg'
# call object is a tuple of method name and arg list tuple
log_messages = [args[1][0] for args in logger.method_calls]
self.assertTrue(self._is_requires_orca_logged(gppkg_name,
log_messages))

@patch('gppylib.operations.package.GpVersion',
return_value=Mock(version=[4, 3, 3, 0]))
def test__execute_reports_compatability_with_older_version(self,
mock_gpversion):
logger = self.mock_logger
gppkg_mock_values = self.gppkg_mock_values
gppkg = Mock(**gppkg_mock_values)

subject = IsVersionCompatible(gppkg)
subject.execute()

gppkg_name = 'plperl-ossv5.12.4_pv1.3_gpdb4.3-rhel5-x86_64.gppkg'
# call object is a tuple of method name and arg list tuple
log_messages = [args[1][0] for args in logger.method_calls]
self.assertFalse(self._is_requires_orca_logged(gppkg_name,
log_messages))

def test__execute_compatible(self):
logger = self.mock_logger
gppkg_name = 'plperl-ossv5.12.4_pv1.3_gpdb4.3orca-rhel5-x86_64.gppkg'
modified_gppkg_mock_values = \
{'abspath': gppkg_name,
'version': 'ossv5.12.4_pv1.2_gpdb4.3orca',
'pkg': gppkg_name}

gppkg_mock_values = self.gppkg_mock_values
gppkg_mock_values.update(**modified_gppkg_mock_values)
gppkg = Mock(**gppkg_mock_values)

subject = IsVersionCompatible(gppkg)
subject.execute()

log_messages = [args[1][0] for args in logger.method_calls]
self.assertFalse(self._is_requires_orca_logged(gppkg_name,
log_messages))

if __name__ == '__main__':
run_tests()

0 comments on commit 2c0b82f

Please sign in to comment.