From a6dd7ce58c31dc84d932b0c946b4099f383c3542 Mon Sep 17 00:00:00 2001 From: Alexei Znamensky <103110+russoz@users.noreply.github.com> Date: Sat, 2 May 2026 10:35:57 +1200 Subject: [PATCH] supervisorctl: use parallel bulk commands when `name=all` (#11953) * feat(supervisorctl): use parallel bulk commands for name=all When name=all, dispatch a single `supervisorctl start/stop/restart all` instead of iterating per process, matching the CLI's parallel behaviour. Also extract inline status-filter lambdas into named module-level functions. Fixes #8159 * feat(changelog): add fragment for PR 11953 --- .../11953-supervisorctl-parallel-all.yml | 4 ++ plugins/modules/supervisorctl.py | 46 ++++++++++++++++--- 2 files changed, 43 insertions(+), 7 deletions(-) create mode 100644 changelogs/fragments/11953-supervisorctl-parallel-all.yml diff --git a/changelogs/fragments/11953-supervisorctl-parallel-all.yml b/changelogs/fragments/11953-supervisorctl-parallel-all.yml new file mode 100644 index 0000000000..83703adf4d --- /dev/null +++ b/changelogs/fragments/11953-supervisorctl-parallel-all.yml @@ -0,0 +1,4 @@ +minor_changes: + - supervisorctl - when ``name=all``, dispatch a single ``supervisorctl start/stop/restart all`` + command (https://github.com/ansible-collections/community.general/issues/8159, + https://github.com/ansible-collections/community.general/pull/11953). diff --git a/plugins/modules/supervisorctl.py b/plugins/modules/supervisorctl.py index bf7b6b5825..374d2d0bb5 100644 --- a/plugins/modules/supervisorctl.py +++ b/plugins/modules/supervisorctl.py @@ -117,6 +117,22 @@ import os from ansible.module_utils.basic import AnsibleModule, is_executable +def _is_active(status): + return status in ("RUNNING", "STARTING") + + +def _is_not_active(status): + return not _is_active(status) + + +def _is_strictly_running(status): + return status in ("RUNNING",) + + +def _always(_status): + return True + + def main(): arg_spec = dict( name=dict(type="str", required=True), @@ -231,13 +247,31 @@ def main(): if exit_module: module.exit_json(changed=True, name=name, state=state, affected=to_take_action_on) + if name == "all" and state in ("started", "stopped", "restarted"): + if state == "restarted": + run_supervisorctl("update", check_rc=True) + processes = get_matched_processes() + status_filters = { + "started": _is_not_active, + "stopped": _is_active, + "restarted": _always, + } + to_act_on = [p for p, s in processes if status_filters[state](s)] + if not to_act_on: + module.exit_json(changed=False, name=name, state=state) + if module.check_mode: + module.exit_json(changed=True) + actions = {"started": "start", "stopped": "stop", "restarted": "restart"} + run_supervisorctl(actions[state], "all", check_rc=True) + module.exit_json(changed=True, name=name, state=state, affected=to_act_on) + if state == "restarted": rc, out, err = run_supervisorctl("update", check_rc=True) processes = get_matched_processes() if len(processes) == 0: module.fail_json(name=name, msg="ERROR (no such process)") - take_action_on_processes(processes, lambda s: True, "restart", "started") + take_action_on_processes(processes, _always, "restart", "started") processes = get_matched_processes() @@ -246,9 +280,7 @@ def main(): module.exit_json(changed=False, name=name, state=state) if stop_before_removing: - take_action_on_processes( - processes, lambda s: s in ("RUNNING", "STARTING"), "stop", "stopped", exit_module=False - ) + take_action_on_processes(processes, _is_active, "stop", "stopped", exit_module=False) if module.check_mode: module.exit_json(changed=True) @@ -277,13 +309,13 @@ def main(): module.fail_json(name=name, msg="ERROR (no such process)") if state == "started": - take_action_on_processes(processes, lambda s: s not in ("RUNNING", "STARTING"), "start", "started") + take_action_on_processes(processes, _is_not_active, "start", "started") if state == "stopped": - take_action_on_processes(processes, lambda s: s in ("RUNNING", "STARTING"), "stop", "stopped") + take_action_on_processes(processes, _is_active, "stop", "stopped") if state == "signalled": - take_action_on_processes(processes, lambda s: s in ("RUNNING",), f"signal {signal}", "signalled") + take_action_on_processes(processes, _is_strictly_running, f"signal {signal}", "signalled") if __name__ == "__main__":