From 6332175493a861d5e4540725e28fe80fb5d8d85a Mon Sep 17 00:00:00 2001 From: Dexter <45038532+munchtoast@users.noreply.github.com> Date: Wed, 27 Aug 2025 16:01:47 -0400 Subject: [PATCH] pacemaker: Add regex checking for maintenance-mode (#10707) * Add regex checking for maintenance-mode * Add changelog fragment * Apply suggestions from code review Co-authored-by: Felix Fontein Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> --------- Co-authored-by: Felix Fontein Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> --- ...10707-pacemaker-maintenance-mode-regex.yml | 2 + plugins/module_utils/pacemaker.py | 6 ++- .../modules/test_pacemaker_cluster.yaml | 24 +++++++++++ .../modules/test_pacemaker_resource.yaml | 40 +++++++++++++++++++ 4 files changed, 70 insertions(+), 2 deletions(-) create mode 100644 changelogs/fragments/10707-pacemaker-maintenance-mode-regex.yml diff --git a/changelogs/fragments/10707-pacemaker-maintenance-mode-regex.yml b/changelogs/fragments/10707-pacemaker-maintenance-mode-regex.yml new file mode 100644 index 0000000000..ba5e08edd3 --- /dev/null +++ b/changelogs/fragments/10707-pacemaker-maintenance-mode-regex.yml @@ -0,0 +1,2 @@ +bugfixes: + - "pacemaker - use regex for matching ``maintenance-mode`` output to determine cluster maintenance status (https://github.com/ansible-collections/community.general/issues/10426, https://github.com/ansible-collections/community.general/pull/10707)." diff --git a/plugins/module_utils/pacemaker.py b/plugins/module_utils/pacemaker.py index 740ac38bfe..03a5432148 100644 --- a/plugins/module_utils/pacemaker.py +++ b/plugins/module_utils/pacemaker.py @@ -6,8 +6,9 @@ from __future__ import absolute_import, division, print_function __metaclass__ = type -from ansible_collections.community.general.plugins.module_utils.cmd_runner import CmdRunner, cmd_runner_fmt +import re +from ansible_collections.community.general.plugins.module_utils.cmd_runner import CmdRunner, cmd_runner_fmt _state_map = { "present": "create", @@ -45,7 +46,8 @@ def fmt_resource_argument(value): def get_pacemaker_maintenance_mode(runner): with runner("cli_action config") as ctx: rc, out, err = ctx.run(cli_action="property") - maintenance_mode_output = list(filter(lambda string: "maintenance-mode=true" in string.lower(), out.splitlines())) + maint_mode_re = re.compile(r"maintenance-mode.*true", re.IGNORECASE) + maintenance_mode_output = [line for line in out.splitlines() if maint_mode_re.search(line)] return bool(maintenance_mode_output) diff --git a/tests/unit/plugins/modules/test_pacemaker_cluster.yaml b/tests/unit/plugins/modules/test_pacemaker_cluster.yaml index 785a7cb4f6..5408b04a42 100644 --- a/tests/unit/plugins/modules/test_pacemaker_cluster.yaml +++ b/tests/unit/plugins/modules/test_pacemaker_cluster.yaml @@ -371,6 +371,30 @@ test_cases: rc: 0 out: 'maintenance-mode=true' err: "" + - id: test_maintenance_minimal_input_initial_online_version_change + input: + state: maintenance + output: + changed: true + previous_value: 'maintenance-mode: false' + value: 'maintenance-mode: true' + mocks: + run_command: + - command: [/testbin/pcs, property, config, maintenance-mode] + environ: *env-def + rc: 0 + out: 'maintenance-mode: false' + err: "" + - command: [/testbin/pcs, property, set, maintenance-mode=true] + environ: *env-def + rc: 0 + out: "" + err: "" + - command: [/testbin/pcs, property, config, maintenance-mode] + environ: *env-def + rc: 0 + out: 'maintenance-mode: true' + err: "" - id: test_maintenance_minimal_input_initial_offline input: state: maintenance diff --git a/tests/unit/plugins/modules/test_pacemaker_resource.yaml b/tests/unit/plugins/modules/test_pacemaker_resource.yaml index 5ecd1797e5..bb56ec1bbe 100644 --- a/tests/unit/plugins/modules/test_pacemaker_resource.yaml +++ b/tests/unit/plugins/modules/test_pacemaker_resource.yaml @@ -189,6 +189,46 @@ test_cases: rc: 0 out: " * virtual-ip\t(ocf:heartbeat:IPAddr2):\t Stopped" err: "" + - id: test_present_minimal_input_resource_maintenance_mode_version_change + input: + state: present + name: virtual-ip + resource_type: + resource_name: IPaddr2 + resource_option: + - "ip=[192.168.2.1]" + output: + changed: true + previous_value: null + value: " * virtual-ip\t(ocf:heartbeat:IPAddr2):\t Stopped" + mocks: + run_command: + - command: [/testbin/pcs, resource, status, virtual-ip] + environ: *env-def + rc: 1 + out: "" + err: "" + - command: [/testbin/pcs, property, config] + environ: *env-def + rc: 0 + out: | + Cluster Properties: cib-bootstrap-options + cluster-infrastructure: corosync + cluster-name: hacluster + dc-version: 2.1.9-1.fc41-7188dbf + have-watchdog: false + maintenance-mode: true + err: "" + - command: [/testbin/pcs, resource, create, virtual-ip, IPaddr2, "ip=[192.168.2.1]", --wait=300] + environ: *env-def + rc: 1 + out: "" + err: "Error: resource 'virtual-ip' is not running on any node" + - command: [/testbin/pcs, resource, status, virtual-ip] + environ: *env-def + rc: 0 + out: " * virtual-ip\t(ocf:heartbeat:IPAddr2):\t Stopped" + err: "" - id: test_absent_minimal_input_resource_not_exist input: state: absent