From 0b13c1eb45819c5f0f22d11a65b52a29f5760e9e Mon Sep 17 00:00:00 2001 From: "patchback[bot]" <45432694+patchback[bot]@users.noreply.github.com> Date: Fri, 5 Feb 2021 07:46:15 +0100 Subject: [PATCH] parted: fix regex for version match and partition size output (#1695) (#1731) * Fix 2 regex in parted related to parted version string and to parsing partition size output. * Added changelog fragment. * Updated changelog as per recommendation. * Fix the regex matching the parted version. The space character at the end of the string may or may not be always present * provided sample version output and corrected regex to match * add/correct changelog fragment * split parted_version function to allow creating a test unit * test unit for parted version info * ansible-test sanity fixes * review fix * Update changelogs/fragments/1695-parted-updatedregex.yaml Co-authored-by: Felix Fontein * comment fixes * better function name * Update plugins/modules/system/parted.py Co-authored-by: Felix Fontein * comment fixes Co-authored-by: Claude Robitaille Co-authored-by: Felix Fontein (cherry picked from commit 43da5b88db3299bcf19c3f5b36d387cd7a3f8fb3) Co-authored-by: Anatoly Pugachev --- .../fragments/1695-parted-updatedregex.yaml | 4 ++ plugins/modules/system/parted.py | 44 +++++++++++++------ .../plugins/modules/system/test_parted.py | 32 ++++++++++++++ 3 files changed, 66 insertions(+), 14 deletions(-) create mode 100644 changelogs/fragments/1695-parted-updatedregex.yaml diff --git a/changelogs/fragments/1695-parted-updatedregex.yaml b/changelogs/fragments/1695-parted-updatedregex.yaml new file mode 100644 index 0000000000..fb3a5a5eaa --- /dev/null +++ b/changelogs/fragments/1695-parted-updatedregex.yaml @@ -0,0 +1,4 @@ +bugfixes: + - parted - change the regex that decodes the partition size to better support different formats that parted uses. + Change the regex that validates parted's version string + (https://github.com/ansible-collections/community.general/pull/1695). diff --git a/plugins/modules/system/parted.py b/plugins/modules/system/parted.py index 12c4e67d5c..daf68c298a 100644 --- a/plugins/modules/system/parted.py +++ b/plugins/modules/system/parted.py @@ -241,7 +241,7 @@ def parse_unit(size_str, unit=''): """ Parses a string containing a size or boundary information """ - matches = re.search(r'^(-?[\d.]+)([\w%]+)?$', size_str) + matches = re.search(r'^(-?[\d.]+) *([\w%]+)?$', size_str) if matches is None: # ",," format matches = re.search(r'^(\d+),(\d+),(\d+)$', size_str) @@ -500,6 +500,33 @@ def check_parted_label(device): return False +def parse_parted_version(out): + """ + Returns version tuple from the output of "parted --version" command + """ + lines = [x for x in out.split('\n') if x.strip() != ''] + if len(lines) == 0: + return None, None, None + + # Sample parted versions (see as well test unit): + # parted (GNU parted) 3.3 + # parted (GNU parted) 3.4.5 + # parted (GNU parted) 3.3.14-dfc61 + matches = re.search(r'^parted.+\s(\d+)\.(\d+)(?:\.(\d+))?', lines[0].strip()) + + if matches is None: + return None, None, None + + # Convert version to numbers + major = int(matches.group(1)) + minor = int(matches.group(2)) + rev = 0 + if matches.group(3) is not None: + rev = int(matches.group(3)) + + return major, minor, rev + + def parted_version(): """ Returns the major and minor version of parted installed on the system. @@ -512,21 +539,10 @@ def parted_version(): msg="Failed to get parted version.", rc=rc, out=out, err=err ) - lines = [x for x in out.split('\n') if x.strip() != ''] - if len(lines) == 0: + (major, minor, rev) = parse_parted_version(out) + if major is None: module.fail_json(msg="Failed to get parted version.", rc=0, out=out) - matches = re.search(r'^parted.+(\d+)\.(\d+)(?:\.(\d+))?$', lines[0]) - if matches is None: - module.fail_json(msg="Failed to get parted version.", rc=0, out=out) - - # Convert version to numbers - major = int(matches.group(1)) - minor = int(matches.group(2)) - rev = 0 - if matches.group(3) is not None: - rev = int(matches.group(3)) - return major, minor, rev diff --git a/tests/unit/plugins/modules/system/test_parted.py b/tests/unit/plugins/modules/system/test_parted.py index 5ed7514646..18faf6a6ab 100644 --- a/tests/unit/plugins/modules/system/test_parted.py +++ b/tests/unit/plugins/modules/system/test_parted.py @@ -6,6 +6,7 @@ __metaclass__ = type from ansible_collections.community.general.tests.unit.compat.mock import patch, call from ansible_collections.community.general.plugins.modules.system import parted as parted_module +from ansible_collections.community.general.plugins.modules.system.parted import parse_parted_version from ansible_collections.community.general.plugins.modules.system.parted import parse_partition_info from ansible_collections.community.general.tests.unit.plugins.modules.utils import AnsibleExitJson, AnsibleFailJson, ModuleTestCase, set_module_args @@ -17,6 +18,32 @@ BYT; 2:106MB:368MB:262MB:ext2::; 3:368MB:256061MB:255692MB:::;""" +parted_version_info = {""" + parted (GNU parted) 3.3 + Copyright (C) 2019 Free Software Foundation, Inc. + License GPLv3+: GNU GPL version 3 or later . + This is free software: you are free to change and redistribute it. + There is NO WARRANTY, to the extent permitted by law. + + Written by . + """: (3, 3, 0), """ + parted (GNU parted) 3.4.5 + Copyright (C) 2019 Free Software Foundation, Inc. + License GPLv3+: GNU GPL version 3 or later . + This is free software: you are free to change and redistribute it. + There is NO WARRANTY, to the extent permitted by law. + + Written by . + """: (3, 4, 5), """ + parted (GNU parted) 3.3.14-dfc61 + Copyright (C) 2019 Free Software Foundation, Inc. + License GPLv3+: GNU GPL version 3 or later . + This is free software: you are free to change and redistribute it. + There is NO WARRANTY, to the extent permitted by law. + + Written by . + """: (3, 3, 14)} + # corresponding dictionary after parsing by parse_partition_info parted_dict1 = { "generic": { @@ -311,3 +338,8 @@ class TestParted(ModuleTestCase): }) with patch('ansible_collections.community.general.plugins.modules.system.parted.get_device_info', return_value=parted_dict3): self.execute_module(changed=True) + + def test_version_info(self): + """Test that the parse_parted_version returns the expected tuple""" + for key, value in parted_version_info.items(): + self.assertEqual(parse_parted_version(key), value)