From 6eb3b45e4c5b16eec6054844f6e6b80bb57ab69a Mon Sep 17 00:00:00 2001 From: Sergei Petrosian Date: Wed, 6 Dec 2023 10:58:02 +0100 Subject: [PATCH] Add unit tests for bootloader_settings and bootloader_facts --- library/bootloader_facts.py | 31 ++- library/bootloader_settings.py | 16 +- pytest_extra_requirements.txt | 4 +- tests/unit/test_bootloader_settings.py | 347 +++++++------------------ 4 files changed, 129 insertions(+), 269 deletions(-) diff --git a/library/bootloader_facts.py b/library/bootloader_facts.py index c4d6eae..f917b79 100644 --- a/library/bootloader_facts.py +++ b/library/bootloader_facts.py @@ -31,6 +31,21 @@ from ansible.module_utils.basic import AnsibleModule +def get_facts(stdout): + stdout_lines = stdout.strip().split("\n") + kernels = [] + index_count = 0 + for line in stdout_lines: + if re.search(r"index=\d+", line): + index_count += 1 + kernels.append({}) + search = re.search(r"(.*?)=(.*)", line) + key = search.group(1).strip('"') + value = search.group(2).strip('"') + kernels[index_count - 1].update({key: value}) + return kernels + + def run_module(): # define available arguments/parameters a user can pass to the module module_args = dict() @@ -51,18 +66,10 @@ def run_module(): rc, stdout, stderr = module.run_command("grubby --info=ALL") if "Permission denied" in stderr: module.fail_json(msg="You must run this as sudo", **result) - stdout_lines = stdout.strip().split("\n") - kernels = [] - index_count = 0 - for line in stdout_lines: - if re.search(r"index=\d+", line): - index_count += 1 - kernels.append({}) - search = re.search(r"(.*?)=(.*)", line) - key = search.group(1).strip('"') - value = search.group(2).strip('"') - kernels[index_count - 1].update({key: value}) - result["ansible_facts"]["bootloader_facts"] = kernels + # result.append(["stdout"]) + # result["ansible_facts"].append(["stdout"]) + result["ansible_facts"]["stdout"] = get_facts(stdout) + result["ansible_facts"]["bootloader_facts"] = get_facts(stdout) # in the event of a successful module execution, you will want to # simple AnsibleModule.exit_json(), passing the key/value results diff --git a/library/bootloader_settings.py b/library/bootloader_settings.py index 12baa3c..503dae8 100644 --- a/library/bootloader_settings.py +++ b/library/bootloader_settings.py @@ -61,8 +61,7 @@ def escapeval(val): return ansible_six_moves.shlex_quote(str(val)) -def get_kernels(bootloader_setting_kernel): - kernels_keys = ["kernel_index", "kernel_path", "kernel_title", "DEFAULT", "ALL"] +def get_kernels(bootloader_setting_kernel, kernels_keys): kernels = [] for kernel_key in kernels_keys: if kernel_key in bootloader_setting_kernel and kernel_key != bootloader_setting_kernel: @@ -70,7 +69,7 @@ def get_kernels(bootloader_setting_kernel): if kernel_key == "kernel_title": kernel_key_prefix = "TITLE=" if not isinstance(bootloader_setting_kernel[kernel_key], list): - kernels.append(kernel_key_prefix + bootloader_setting_kernel[kernel_key]) + kernels.append(kernel_key_prefix + str(bootloader_setting_kernel[kernel_key])) else: for kernel_entry in bootloader_setting_kernel[kernel_key]: kernels.append(kernel_key_prefix + str(kernel_entry)) @@ -105,11 +104,11 @@ def get_mod_boot_args_cmd(bootloader_setting_options, kernel): else: boot_present_args += setting_name + " " if boot_absent_args: - boot_mod_args = " --remove-args=" + escapeval(boot_absent_args) + boot_mod_args = " --remove-args=" + escapeval(boot_absent_args.strip()) if len(boot_present_args) > 0: - boot_mod_args += " --args=" + escapeval(boot_present_args) + boot_mod_args += " --args=" + escapeval(boot_present_args.strip()) if boot_mod_args: - return "grubby --update-kernel=" + kernel + boot_mod_args + return "grubby --update-kernel=" + escapeval(kernel) + boot_mod_args def run_module(): @@ -132,11 +131,12 @@ def run_module(): module = AnsibleModule(argument_spec=module_args, supports_check_mode=True) result['rm_boot_args_cmd'] = [] result['mod_boot_args_cmd'] = [] + kernels_keys = ["kernel_index", "kernel_path", "kernel_title", "DEFAULT", "ALL"] for bootloader_setting in module.params["bootloader_settings"]: - kernels = get_kernels(bootloader_setting["kernel"]) + kernels = get_kernels(bootloader_setting["kernel"], kernels_keys) if not kernels: module.fail_json( - msg = 'bootloader_settings.kernel must contain one of %s' % ', '.join(kernels_keys), + msg='bootloader_settings.kernel must contain one of %s' % ', '.join(kernels_keys), **result ) for kernel in kernels: diff --git a/pytest_extra_requirements.txt b/pytest_extra_requirements.txt index d1e7463..8e11eaa 100644 --- a/pytest_extra_requirements.txt +++ b/pytest_extra_requirements.txt @@ -2,6 +2,6 @@ # Write extra requirements for running pytest here: # If you need ansible then uncomment the following line: -#-ransible_pytest_extra_requirements.txt +-ransible_pytest_extra_requirements.txt # If you need mock then uncomment the following line: -#mock ; python_version < "3.0" +mock ; python_version < "3.0" diff --git a/tests/unit/test_bootloader_settings.py b/tests/unit/test_bootloader_settings.py index f45b8bf..e4c8af4 100644 --- a/tests/unit/test_bootloader_settings.py +++ b/tests/unit/test_bootloader_settings.py @@ -10,271 +10,124 @@ __metaclass__ = type import unittest -# import pytest import bootloader_settings -# import os -# import tempfile -# import shutil -# import unittest -# import re -# import copy -# from configobj import ConfigObj - -# try: -# from unittest.mock import Mock -# except ImportError: -# from mock import Mock - -# import kernel_settings -# import tuned +OPTIONS = [ + {"name": "arg_with_str_value", "value": "test_value"}, + {"name": "arg_with_int_value", "value": 1, "state": "present"}, + {"name": "arg_without_val", "state": "present"}, + {"name": "arg_with_str_value_absent", "value": "test_value", "state": "absent"}, + {"name": "arg_with_int_value_absent", "value": 1, "state": "absent"}, + {"name": "arg_without_val", "state": "absent"}, + {"previous": "replaced"}, +] -bootloader_settings: [ - { - "kernel": { - "kernel_index": [ - 0, - 1 - ] - }, - "options": [ - { - "name": "arg_with_str_value", - "value": "test_value" - }, - { - "name": "arg_with_int_value", - "value": 1 - }, - { - "name": "arg_with_state_present", - "state": "present" - }, - { - "name": "arg_without_state_present" - }, - { - "name": "arg_without_state_absent", - "state": "absent" - }, - { - "previous": "replaced" - } - ] - }, - { - "kernel": { - "kernel_index": 2 - }, - "options": [ - { - "name": "arg_with_str_value", - "value": "test_value" - }, - { - "name": "arg_with_int_value", - "value": 1 - }, - { - "name": "arg_with_state_present", - "state": "present" - }, - { - "name": "arg_without_state_present" - }, - { - "name": "arg_without_state_absent", - "state": "absent" - }, - { - "previous": "replaced" - } - ] - }, - { - "kernel": { - "kernel_path": [ - "/path/1", - "/path/2" - ] - }, - "options": [ - { - "name": "arg_with_str_value", - "value": "test_value" - }, - { - "name": "arg_with_int_value", - "value": 1 - }, - { - "name": "arg_with_state_present", - "state": "present" - }, - { - "name": "arg_without_state_present" - }, - { - "name": "arg_without_state_absent", - "state": "absent" - }, - { - "previous": "replaced" - } - ] - }, - { - "kernel": { - "kernel_path": "/path/3" - }, - "options": [ - { - "name": "arg_with_str_value", - "value": "test_value" - }, - { - "name": "arg_with_int_value", - "value": 1 - }, - { - "name": "arg_with_state_present", - "state": "present" - }, - { - "name": "arg_without_state_present" - }, - { - "name": "arg_without_state_absent", - "state": "absent" - }, - { - "previous": "replaced" - } - ] - }, +KERNELS = [ + {"kernel": {"kernel_index": [0, 1]}}, + {"kernel": {"kernel_index": 2}}, + {"kernel": {"kernel_path": ["/path/1", "/path/2"]}}, + {"kernel": {"kernel_path": "/path/3"}}, { "kernel": { "kernel_title": [ "Fedora Linux (1.1.11-100.fc37.x86_64) 37 (Workstation Edition)", - "Fedora Linux (2.2.22-200.fc37.x86_64) 37 (Workstation Edition)" + "Fedora Linux (1.1.11-200.fc37.x86_64) 37 (Workstation Edition)", ] }, - "options": [ - { - "name": "arg_with_str_value", - "value": "test_value" - }, - { - "name": "arg_with_int_value", - "value": 1 - }, - { - "name": "arg_with_state_present", - "state": "present" - }, - { - "name": "arg_without_state_present" - }, - { - "name": "arg_without_state_absent", - "state": "absent" - }, - { - "previous": "replaced" - } - ] }, { "kernel": { - "kernel_title": "Fedora Linux (3.3.33-300.fc37.x86_64) 37 (Workstation Edition)" + "kernel_title": "Fedora Linux (1.1.11-300.fc37.x86_64) 37 (Workstation Edition)" }, - "options": [ - { - "name": "arg_with_str_value", - "value": "test_value" - }, - { - "name": "arg_with_int_value", - "value": 1 - }, - { - "name": "arg_with_state_present", - "state": "present" - }, - { - "name": "arg_without_state_present" - }, - { - "name": "arg_without_state_absent", - "state": "absent" - }, - { - "previous": "replaced" - } - ] }, - { - "kernel": "DEFAULT", - "options": [ - { - "name": "arg_with_str_value", - "value": "test_value" - }, - { - "name": "arg_with_int_value", - "value": 1 - }, - { - "name": "arg_with_state_present", - "state": "present" - }, - { - "name": "arg_without_state_present" - }, - { - "name": "arg_without_state_absent", - "state": "absent" - }, - { - "previous": "replaced" - } - ] - }, - { - "kernel": "ALL", - "options": [ - { - "name": "arg_with_str_value", - "value": "test_value" - }, - { - "name": "arg_with_int_value", - "value": 1 - }, - { - "name": "arg_with_state_present", - "state": "present" - }, - { - "name": "arg_without_state_present" - }, - { - "name": "arg_without_state_absent", - "state": "absent" - }, - { - "previous": "replaced" - } - ] - } + {"kernel": "DEFAULT"}, + {"kernel": "ALL"}, ] +INFO = """ +index=0 +kernel="/boot/vmlinuz-6.5.12-100.fc37.x86_64" +args="$tuned_params ro rootflags=subvol=root rd.luks.uuid=luks-9da1fdf5-14ac-49fd-a388-8b1ee48f3df1 rhgb quiet" +root="UUID=65c70529-e9ad-4778-9001-18fe8c525285" +initrd="/boot/initramfs-6.5.12-100.fc37.x86_64.img $tuned_initrd" +title="Fedora Linux (6.5.12-100.fc37.x86_64) 37 (Workstation Edition)" +id="c44543d15b2c4e898912c2497f734e67-6.5.12-100.fc37.x86_64" +""" + +kernels_keys = ["kernel_index", "kernel_path", "kernel_title", "DEFAULT", "ALL"] -class InputValidator(TestCase): + +class InputValidator(unittest.TestCase): """test functions that process bootloader_settings argument""" def test_get_kernels(self): - """test get_kernels function against sample input""" - kernels = get_kernels(bootloader_settings[0]["kernel"]) - self.assertEqual([0, 1], kernels) + kernels = bootloader_settings.get_kernels(KERNELS[0]["kernel"], kernels_keys) + self.assertEqual(["0", "1"], kernels) + kernels = bootloader_settings.get_kernels(KERNELS[1]["kernel"], kernels_keys) + self.assertEqual(["2"], kernels) + kernels = bootloader_settings.get_kernels(KERNELS[2]["kernel"], kernels_keys) + self.assertEqual(["/path/1", "/path/2"], kernels) + kernels = bootloader_settings.get_kernels(KERNELS[3]["kernel"], kernels_keys) + self.assertEqual(["/path/3"], kernels) + kernels = bootloader_settings.get_kernels(KERNELS[4]["kernel"], kernels_keys) + self.assertEqual( + [ + "TITLE=Fedora Linux (1.1.11-100.fc37.x86_64) 37 (Workstation Edition)", + "TITLE=Fedora Linux (1.1.11-200.fc37.x86_64) 37 (Workstation Edition)", + ], + kernels, + ) + kernels = bootloader_settings.get_kernels(KERNELS[5]["kernel"], kernels_keys) + self.assertEqual( + ["TITLE=Fedora Linux (1.1.11-300.fc37.x86_64) 37 (Workstation Edition)"], + kernels, + ) + kernels = bootloader_settings.get_kernels(KERNELS[6]["kernel"], kernels_keys) + self.assertEqual(["DEFAULT"], kernels) + kernels = bootloader_settings.get_kernels(KERNELS[7]["kernel"], kernels_keys) + self.assertEqual(["ALL"], kernels) + + def test_get_rm_boot_args_cmd(self): + rm_boot_args_cmd = bootloader_settings.get_rm_boot_args_cmd(INFO, "0") + self.assertEqual( + "grubby --update-kernel=0 --remove-args='$tuned_params ro rootflags=subvol=root rd.luks.uuid=luks-9da1fdf5-14ac-49fd-a388-8b1ee48f3df1 rhgb quiet'", + rm_boot_args_cmd, + ) + + def test_get_mod_boot_args_cmd(self): + mod_boot_args_cmd = bootloader_settings.get_mod_boot_args_cmd( + OPTIONS, str(KERNELS[1]["kernel"]["kernel_index"]) + ) + self.assertEqual( + "grubby --update-kernel=2 --remove-args='arg_with_str_value_absent=test_value arg_with_int_value_absent=1 arg_without_val' --args='arg_with_str_value=test_value arg_with_int_value=1 arg_without_val'", + mod_boot_args_cmd, + ) + mod_boot_args_cmd = bootloader_settings.get_mod_boot_args_cmd( + OPTIONS, KERNELS[3]["kernel"]["kernel_path"] + ) + self.assertEqual( + "grubby --update-kernel=/path/3 --remove-args='arg_with_str_value_absent=test_value arg_with_int_value_absent=1 arg_without_val' --args='arg_with_str_value=test_value arg_with_int_value=1 arg_without_val'", + mod_boot_args_cmd, + ) + mod_boot_args_cmd = bootloader_settings.get_mod_boot_args_cmd( + OPTIONS, KERNELS[5]["kernel"]["kernel_title"] + ) + self.assertEqual( + "grubby --update-kernel='Fedora Linux (1.1.11-300.fc37.x86_64) 37 (Workstation Edition)' --remove-args='arg_with_str_value_absent=test_value arg_with_int_value_absent=1 arg_without_val' --args='arg_with_str_value=test_value arg_with_int_value=1 arg_without_val'", + mod_boot_args_cmd, + ) + mod_boot_args_cmd = bootloader_settings.get_mod_boot_args_cmd( + OPTIONS, KERNELS[6]["kernel"] + ) + self.assertEqual( + "grubby --update-kernel=DEFAULT --remove-args='arg_with_str_value_absent=test_value arg_with_int_value_absent=1 arg_without_val' --args='arg_with_str_value=test_value arg_with_int_value=1 arg_without_val'", + mod_boot_args_cmd, + ) + mod_boot_args_cmd = bootloader_settings.get_mod_boot_args_cmd( + OPTIONS, KERNELS[7]["kernel"] + ) + self.assertEqual( + "grubby --update-kernel=ALL --remove-args='arg_with_str_value_absent=test_value arg_with_int_value_absent=1 arg_without_val' --args='arg_with_str_value=test_value arg_with_int_value=1 arg_without_val'", + mod_boot_args_cmd, + )