From 0ec8bcfd2f1bd28b703a3e962159e63a8010ec8b Mon Sep 17 00:00:00 2001 From: "Gareth J. Greenaway" Date: Tue, 27 Nov 2018 13:56:13 -0800 Subject: [PATCH] When using the gem installed state, when passing a version that includes greater than or less than symbols, ensure that the installed versions meets that requirement. --- salt/states/gem.py | 30 ++++++++++++++++++++++++++---- tests/unit/states/test_gem.py | 13 +++++++++++++ 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/salt/states/gem.py b/salt/states/gem.py index 63bf359ef6..3134e8534b 100644 --- a/salt/states/gem.py +++ b/salt/states/gem.py @@ -16,6 +16,9 @@ you can specify what ruby version and gemset to target. ''' from __future__ import absolute_import +import salt.utils + +import re import logging log = logging.getLogger(__name__) @@ -84,10 +87,29 @@ def installed(name, # pylint: disable=C0103 'Use of argument ruby found, but neither rvm or rbenv is installed' ) gems = __salt__['gem.list'](name, ruby, gem_bin=gem_bin, runas=user) - if name in gems and version is not None and str(version) in gems[name]: - ret['result'] = True - ret['comment'] = 'Gem is already installed.' - return ret + if name in gems and version is not None: + match = re.match(r'(>=|>|<|<=)', version) + if match: + # Grab the comparison + cmpr = match.group() + + # Clear out 'default:' and any whitespace + installed_version = re.sub('default: ', '', gems[name][0]).strip() + + # Clear out comparison from version and whitespace + desired_version = re.sub(cmpr, '', version).strip() + + if salt.utils.compare_versions(installed_version, + cmpr, + desired_version): + ret['result'] = True + ret['comment'] = 'Installed Gem meets version requirements.' + return ret + else: + if str(version) in gems[name]: + ret['result'] = True + ret['comment'] = 'Gem is already installed.' + return ret elif name in gems and version is None: ret['result'] = True ret['comment'] = 'Gem is already installed.' diff --git a/tests/unit/states/test_gem.py b/tests/unit/states/test_gem.py index 3ffd40bec5..a347e23475 100644 --- a/tests/unit/states/test_gem.py +++ b/tests/unit/states/test_gem.py @@ -47,6 +47,19 @@ class TestGemState(TestCase, LoaderModuleMockMixin): ri=False, gem_bin=None ) + def test_installed_version(self): + gems = {'foo': ['1.0'], 'bar': ['2.0']} + gem_list = MagicMock(return_value=gems) + gem_install_succeeds = MagicMock(return_value=True) + + with patch.dict(gem.__salt__, {'gem.list': gem_list}): + with patch.dict(gem.__salt__, + {'gem.install': gem_install_succeeds}): + ret = gem.installed('foo', version='>= 1.0') + self.assertEqual(True, ret['result']) + self.assertEqual('Installed Gem meets version requirements.', + ret['comment']) + def test_removed(self): gems = ['foo', 'bar'] gem_list = MagicMock(return_value=gems)