Files
computer-playbook/plugins/action/database_query.py
kevinveenbirkenbachandClaude Opus 4.8 5e14c7e2d0 fix(database_query): read query_file on the controller via action plugin
database_query is a module: it opens query_file on the host it runs on. In swarm the task is delegated to the stack host, which has no repo checkout at role_path, so query_file is not found. A new action plugin (same name auto-wraps the module) reads query_file on the controller and passes the SQL as 'query', so every role's query_file: works in both compose and swarm with no call-site changes. Reverts the per-call-site fider workaround in favour of this root fix, which also covers mattermost, odoo, openproject and pixelfed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 01:27:46 +02:00

53 lines
1.7 KiB
Python
Executable File

#!/usr/bin/env python3
"""Action plugin for the ``database_query`` module.
The module opens ``query_file`` on the host it runs on. In swarm,
``database_query`` is delegated to the stack host, which has no repo
checkout at ``role_path``, so a target-side open fails with
``could not read query_file``. Reading the file here on the controller and
handing the SQL to the module as ``query`` keeps every role's
``query_file:`` call working in both compose and swarm, without rewriting
call sites.
"""
from __future__ import annotations
from pathlib import Path
from typing import Any
from ansible.errors import AnsibleActionFail
from ansible.plugins.action import ActionBase
class ActionModule(ActionBase):
def run(
self, tmp: Any = None, task_vars: dict[str, Any] | None = None
) -> dict[str, Any]:
if task_vars is None:
task_vars = {}
result = super().run(tmp, task_vars)
self._templar.available_variables = task_vars
args = dict(self._task.args)
query_file = args.get("query_file")
if query_file and not args.get("query"):
query_file = self._templar.template(query_file)
try:
with Path(query_file).open(encoding="utf-8") as handle:
args["query"] = handle.read()
except OSError as exc:
raise AnsibleActionFail(
f"could not read query_file {query_file!r} on the controller: {exc}"
) from exc
args.pop("query_file", None)
result.update(
self._execute_module(
module_name="database_query",
module_args=args,
task_vars=task_vars,
)
)
return result