Skip to content

Commit

Permalink
Modify settings idempotently
Browse files Browse the repository at this point in the history
  • Loading branch information
spetrosi committed Dec 6, 2023
1 parent 0324568 commit 15d210a
Show file tree
Hide file tree
Showing 3 changed files with 141 additions and 21 deletions.
33 changes: 22 additions & 11 deletions library/bootloader_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
options:
bootloader_settings:
description: List of kernels and their command line parameters that you want to set.
description: List of dict of kernels and their command line parameters that you want to set.
required: true
type: list
elements: dict
Expand Down Expand Up @@ -84,8 +84,15 @@ def get_kernels(bootloader_setting_kernel, kernels_keys):
return kernels


def get_boot_args(kernel_info):
args = re.search(r'args="(.*)"', kernel_info)
if args is None:
return None
return args.group(1)


def get_rm_boot_args_cmd(kernel_info, kernel):
bootloader_args = re.search(r'args="(.*)"', kernel_info).group(1)
bootloader_args = get_boot_args(kernel_info)
return (
"grubby --update-kernel="
+ kernel
Expand All @@ -94,10 +101,11 @@ def get_rm_boot_args_cmd(kernel_info, kernel):
)


def get_mod_boot_args_cmd(bootloader_setting_options, kernel):
def get_mod_boot_args_cmd(bootloader_setting_options, kernel, kernel_info):
boot_absent_args = ""
boot_present_args = ""
boot_mod_args = ""
bootloader_args = get_boot_args(kernel_info)
for kernel_setting in bootloader_setting_options:
if {"previous": "replaced"} == kernel_setting:
continue
Expand All @@ -106,15 +114,21 @@ def get_mod_boot_args_cmd(bootloader_setting_options, kernel):
else:
setting_name = kernel_setting["name"]
if "state" in kernel_setting and kernel_setting["state"] == "absent":
boot_absent_args += setting_name + " "
if bootloader_args and re.search(
r"(^|$| )" + setting_name + r"(^|$| )", bootloader_args
):
boot_absent_args += setting_name + " "
else:
boot_present_args += setting_name + " "
if bootloader_args and (
not re.search(r"(^|$| )" + setting_name + r"(^|$| )", bootloader_args)
):
boot_present_args += setting_name + " "
if 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.strip())
if boot_mod_args:
return "grubby --update-kernel=" + escapeval(kernel) + boot_mod_args
return "grubby --update-kernel=" + kernel + boot_mod_args


def run_module():
Expand All @@ -137,8 +151,6 @@ def run_module():
# args/params passed to the execution, as well as if the module
# supports check mode
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_keys)
Expand All @@ -156,15 +168,14 @@ def run_module():
rm_boot_args_cmd = get_rm_boot_args_cmd(stdout, kernel)
if rm_boot_args_cmd:
rc, stdout, stderr = module.run_command(rm_boot_args_cmd)
result["rm_boot_args_cmd"].append(rm_boot_args_cmd)
result["changed"] = True
rc, stdout, stderr = module.run_command("grubby --info=" + kernel)
# Configure boot settings
mod_boot_args_cmd = get_mod_boot_args_cmd(
bootloader_setting["options"], kernel
bootloader_setting["options"], kernel, stdout
)
if mod_boot_args_cmd:
rc, stdout, stderr = module.run_command(mod_boot_args_cmd)
result["mod_boot_args_cmd"].append(mod_boot_args_cmd)
result["changed"] = True
# if the user is working with this module in only check mode we do not
# want to make any changes to the environment, just return the current
Expand Down
95 changes: 95 additions & 0 deletions tests/unit/test_bootloader_facts.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# -*- coding: utf-8 -*-

# Copyright: (c) 2023, Sergei Petrosian <[email protected]>
# SPDX-License-Identifier: GPL-2.0-or-later
#
""" Unit tests for the bootloader_settings module """

from __future__ import absolute_import, division, print_function

__metaclass__ = type

import unittest

import bootloader_facts

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"
index=1
kernel="/boot/vmlinuz-6.5.10-100.fc37.x86_64"
args="ro rootflags=subvol=root rd.luks.uuid=luks-9da1fdf5-14ac-49fd-a388-8b1ee48f3df1 rhgb quiet $tuned_params"
root="UUID=65c70529-e9ad-4778-9001-18fe8c525285"
initrd="/boot/initramfs-6.5.10-100.fc37.x86_64.img $tuned_initrd"
title="Fedora Linux (6.5.10-100.fc37.x86_64) 37 (Workstation Edition)"
id="c44543d15b2c4e898912c2497f734e67-6.5.10-100.fc37.x86_64"
index=2
kernel="/boot/vmlinuz-6.5.7-100.fc37.x86_64"
args="ro rootflags=subvol=root rd.luks.uuid=luks-9da1fdf5-14ac-49fd-a388-8b1ee48f3df1 rhgb quiet $tuned_params"
root="UUID=65c70529-e9ad-4778-9001-18fe8c525285"
initrd="/boot/initramfs-6.5.7-100.fc37.x86_64.img $tuned_initrd"
title="Fedora Linux (6.5.7-100.fc37.x86_64) 37 (Workstation Edition)"
id="c44543d15b2c4e898912c2497f734e67-6.5.7-100.fc37.x86_64"
index=3
kernel="/boot/vmlinuz-0-rescue-c44543d15b2c4e898912c2497f734e67"
args="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-0-rescue-c44543d15b2c4e898912c2497f734e67.img"
title="Fedora Linux (0-rescue-c44543d15b2c4e898912c2497f734e67) 36 (Workstation Edition)"
id="c44543d15b2c4e898912c2497f734e67-0-rescue"
"""

FACTS = [
{
"args": "$tuned_params ro rootflags=subvol=root rd.luks.uuid=luks-9da1fdf5-14ac-49fd-a388-8b1ee48f3df1 rhgb quiet",
"id": "c44543d15b2c4e898912c2497f734e67-6.5.12-100.fc37.x86_64",
"index": "0",
"initrd": "/boot/initramfs-6.5.12-100.fc37.x86_64.img $tuned_initrd",
"kernel": "/boot/vmlinuz-6.5.12-100.fc37.x86_64",
"root": "UUID=65c70529-e9ad-4778-9001-18fe8c525285",
"title": "Fedora Linux (6.5.12-100.fc37.x86_64) 37 (Workstation Edition)",
},
{
"args": "ro rootflags=subvol=root rd.luks.uuid=luks-9da1fdf5-14ac-49fd-a388-8b1ee48f3df1 rhgb quiet $tuned_params",
"id": "c44543d15b2c4e898912c2497f734e67-6.5.10-100.fc37.x86_64",
"index": "1",
"initrd": "/boot/initramfs-6.5.10-100.fc37.x86_64.img $tuned_initrd",
"kernel": "/boot/vmlinuz-6.5.10-100.fc37.x86_64",
"root": "UUID=65c70529-e9ad-4778-9001-18fe8c525285",
"title": "Fedora Linux (6.5.10-100.fc37.x86_64) 37 (Workstation Edition)",
},
{
"args": "ro rootflags=subvol=root rd.luks.uuid=luks-9da1fdf5-14ac-49fd-a388-8b1ee48f3df1 rhgb quiet $tuned_params",
"id": "c44543d15b2c4e898912c2497f734e67-6.5.7-100.fc37.x86_64",
"index": "2",
"initrd": "/boot/initramfs-6.5.7-100.fc37.x86_64.img $tuned_initrd",
"kernel": "/boot/vmlinuz-6.5.7-100.fc37.x86_64",
"root": "UUID=65c70529-e9ad-4778-9001-18fe8c525285",
"title": "Fedora Linux (6.5.7-100.fc37.x86_64) 37 (Workstation Edition)",
},
{
"args": "ro rootflags=subvol=root rd.luks.uuid=luks-9da1fdf5-14ac-49fd-a388-8b1ee48f3df1 rhgb quiet",
"id": "c44543d15b2c4e898912c2497f734e67-0-rescue",
"index": "3",
"initrd": "/boot/initramfs-0-rescue-c44543d15b2c4e898912c2497f734e67.img",
"kernel": "/boot/vmlinuz-0-rescue-c44543d15b2c4e898912c2497f734e67",
"root": "UUID=65c70529-e9ad-4778-9001-18fe8c525285",
"title": "Fedora Linux (0-rescue-c44543d15b2c4e898912c2497f734e67) 36 (Workstation Edition)",
},
]


class InputValidator(unittest.TestCase):
"""test functions that process bootloader_settings argument"""

def test_get_facts(self):
kernels = bootloader_facts.get_facts(INFO)
self.assertEqual(
FACTS,
kernels,
)
34 changes: 24 additions & 10 deletions tests/unit/test_bootloader_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
{"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"},
{"name": "arg_without_val_absent", "state": "absent"},
{"previous": "replaced"},
]

Expand Down Expand Up @@ -48,7 +48,7 @@
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"
args="arg_with_str_value_absent=test_value arg_with_int_value_absent=1 arg_without_val_absent"
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)"
Expand Down Expand Up @@ -88,49 +88,63 @@ def test_get_kernels(self):
kernels = bootloader_settings.get_kernels(KERNELS[7]["kernel"], kernels_keys)
self.assertEqual(["ALL"], kernels)

def test_get_boot_args(self):
bootloader_args = bootloader_settings.get_boot_args(INFO)
self.assertEqual(
bootloader_args,
"arg_with_str_value_absent=test_value arg_with_int_value_absent=1 arg_without_val_absent",
)
bootloader_args = bootloader_settings.get_boot_args("")
self.assertEqual(bootloader_args, None)

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'",
+ "'arg_with_str_value_absent=test_value arg_with_int_value_absent=1 arg_without_val_absent'",
rm_boot_args_cmd,
)

def test_get_mod_boot_args_cmd(self):
args = (
"--remove-args='arg_with_str_value_absent=test_value arg_with_int_value_absent=1 arg_without_val' "
"--remove-args='arg_with_str_value_absent=test_value arg_with_int_value_absent=1 arg_without_val_absent' "
+ "--args='arg_with_str_value=test_value arg_with_int_value=1 arg_without_val'"
)
mod_boot_args_cmd = bootloader_settings.get_mod_boot_args_cmd(
OPTIONS, str(KERNELS[1]["kernel"]["kernel_index"])
OPTIONS, str(KERNELS[1]["kernel"]["kernel_index"]), INFO
)
self.assertEqual(
"grubby --update-kernel=2 " + args,
mod_boot_args_cmd,
)
mod_boot_args_cmd = bootloader_settings.get_mod_boot_args_cmd(
OPTIONS, KERNELS[3]["kernel"]["kernel_path"]
OPTIONS, KERNELS[3]["kernel"]["kernel_path"], INFO
)
self.assertEqual(
"grubby --update-kernel=/path/3 " + args,
mod_boot_args_cmd,
)
mod_boot_args_cmd = bootloader_settings.get_mod_boot_args_cmd(
OPTIONS, "TITLE=" + KERNELS[5]["kernel"]["kernel_title"]
OPTIONS,
bootloader_settings.escapeval(
"TITLE=" + KERNELS[5]["kernel"]["kernel_title"]
),
INFO,
)
self.assertEqual(
"grubby --update-kernel='TITLE=Fedora Linux (1.1.11-300.fc37.x86_64) 37 (Workstation Edition)' " + args,
"grubby --update-kernel='TITLE=Fedora Linux (1.1.11-300.fc37.x86_64) 37 (Workstation Edition)' "
+ args,
mod_boot_args_cmd,
)
mod_boot_args_cmd = bootloader_settings.get_mod_boot_args_cmd(
OPTIONS, KERNELS[6]["kernel"]
OPTIONS, KERNELS[6]["kernel"], INFO
)
self.assertEqual(
"grubby --update-kernel=DEFAULT " + args,
mod_boot_args_cmd,
)
mod_boot_args_cmd = bootloader_settings.get_mod_boot_args_cmd(
OPTIONS, KERNELS[7]["kernel"]
OPTIONS, KERNELS[7]["kernel"], INFO
)
self.assertEqual(
"grubby --update-kernel=ALL " + args,
Expand Down

0 comments on commit 15d210a

Please sign in to comment.