From 5770428e916ab62c6814e6dff3f1136a6f7689f2 Mon Sep 17 00:00:00 2001 From: Matt Martz Date: Wed, 19 Mar 2014 11:27:40 -0500 Subject: [PATCH] Add version_compare filter --- docsite/rst/playbooks_variables.rst | 26 ++++++++++++++++++ lib/ansible/runner/filter_plugins/core.py | 32 +++++++++++++++++++++++ test/units/TestFilters.py | 23 ++++++++++++++++ 3 files changed, 81 insertions(+) diff --git a/docsite/rst/playbooks_variables.rst b/docsite/rst/playbooks_variables.rst index 908eaa2fcc..18aa31dcf3 100644 --- a/docsite/rst/playbooks_variables.rst +++ b/docsite/rst/playbooks_variables.rst @@ -208,6 +208,32 @@ To get the symmetric difference of 2 lists (items exclusive to each list):: {{ list1 | symmetric_difference(list2) }} +.. _version_comparison_filters: + +Version Comparison Filters +-------------------------- + +.. versionadded:: 1.6 + +To compare a version number, such as checking if the ``ansible_distribution_version`` +version is greater than or equal to '12.04', you can use the ``version_compare`` filter:: + +The ``version_compare`` filter can also be used to evaluate the ``ansible_distribution_version``:: + + {{ ansible_distribution_version | version_compare('12.04', '>=') }} + +If ``ansible_distribution_version`` is greater than or equal to 12, this filter will return True, otherwise +it will return False. + +The ``version_compare`` filter accepts the following operators:: + + <, lt, <=, le, >, gt, >=, ge, ==, =, eq, !=, <>, ne + +This filter also accepts a 3rd parameter, ``strict`` which defines if strict version parsing should +be used. The default is ``False``, and if set as ``True`` will use more strict version parsing:: + + {{ sample_version_var | version_compare('1.0', operator='lt', strict=True) }} + .. _other_useful_filters: Other Useful Filters diff --git a/lib/ansible/runner/filter_plugins/core.py b/lib/ansible/runner/filter_plugins/core.py index a511b18bcb..8bad776cbe 100644 --- a/lib/ansible/runner/filter_plugins/core.py +++ b/lib/ansible/runner/filter_plugins/core.py @@ -23,8 +23,10 @@ import types import pipes import glob import re +import operator as py_operator from ansible import errors from ansible.utils import md5s +from distutils.version import LooseVersion, StrictVersion def to_nice_yaml(*a, **kw): '''Make verbose, human readable yaml''' @@ -151,6 +153,33 @@ def symmetric_difference(a, b): def union(a, b): return set(a).union(b) +def version_compare(value, version, operator='eq', strict=False): + ''' Perform a version comparison on a value ''' + op_map = { + '==': 'eq', '=': 'eq', 'eq': 'eq', + '<': 'lt', 'lt': 'lt', + '<=': 'le', 'le': 'le', + '>': 'gt', 'gt': 'gt', + '>=': 'ge', 'ge': 'ge', + '!=': 'ne', '<>': 'ne', 'ne': 'ne' + } + + if strict: + Version = StrictVersion + else: + Version = LooseVersion + + if operator in op_map: + operator = op_map[operator] + else: + raise errors.AnsibleFilterError('Invalid operator type') + + try: + method = getattr(py_operator, operator) + return method(Version(str(value)), Version(str(version))) + except Exception, e: + raise errors.AnsibleFilterError('Version comparison: %s' % e) + class FilterModule(object): ''' Ansible core jinja2 filters ''' @@ -213,5 +242,8 @@ class FilterModule(object): 'difference': difference, 'symmetric_difference': symmetric_difference, 'union': union, + + # version comparison + 'version_compare': version_compare, } diff --git a/test/units/TestFilters.py b/test/units/TestFilters.py index e79d4c8970..9389147516 100644 --- a/test/units/TestFilters.py +++ b/test/units/TestFilters.py @@ -152,3 +152,26 @@ class TestFilters(unittest.TestCase): #out = open(dest).read() #self.assertEqual(DEST, out) + def test_version_compare(self): + self.assertTrue(ansible.runner.filter_plugins.core.version_compare(0, 1.1, 'lt', False)) + self.assertTrue(ansible.runner.filter_plugins.core.version_compare(1.1, 1.2, '<')) + + self.assertTrue(ansible.runner.filter_plugins.core.version_compare(1.2, 1.2, '==')) + self.assertTrue(ansible.runner.filter_plugins.core.version_compare(1.2, 1.2, '=')) + self.assertTrue(ansible.runner.filter_plugins.core.version_compare(1.2, 1.2, 'eq')) + + + self.assertTrue(ansible.runner.filter_plugins.core.version_compare(1.3, 1.2, 'gt')) + self.assertTrue(ansible.runner.filter_plugins.core.version_compare(1.3, 1.2, '>')) + + self.assertTrue(ansible.runner.filter_plugins.core.version_compare(1.3, 1.2, 'ne')) + self.assertTrue(ansible.runner.filter_plugins.core.version_compare(1.3, 1.2, '!=')) + self.assertTrue(ansible.runner.filter_plugins.core.version_compare(1.3, 1.2, '<>')) + + self.assertTrue(ansible.runner.filter_plugins.core.version_compare(1.1, 1.1, 'ge')) + self.assertTrue(ansible.runner.filter_plugins.core.version_compare(1.2, 1.1, '>=')) + + self.assertTrue(ansible.runner.filter_plugins.core.version_compare(1.1, 1.1, 'le')) + self.assertTrue(ansible.runner.filter_plugins.core.version_compare(1.0, 1.1, '<=')) + + self.assertTrue(ansible.runner.filter_plugins.core.version_compare('12.04', 12, 'ge'))