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)