With `-tA` psql drops headers and the row-count footer but still prints
the command tag of every write statement. A guarded
`UPDATE … RETURNING` that matched nothing therefore came back as
`rows: [['UPDATE 0']]`, and web-app-peertube's oidc/enable.yml, which
judges its change by the row count, reported `changed` and restarted
PeerTube on every deploy after the first.
The PostgreSQL rows flags are now `-qtA`. Probed against a running
postgres container:
-tA -> CREATE TABLE / INSERT 0 1 / UPDATE 0 / 3 / UPDATE 1
-qtA -> 3
SELECT output and the MariaDB path (`--batch --skip-column-names`, no
status line) are unchanged.
Fixes#1164
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
3529 invalid comments in 528 files, grandfathered in while the linter
only saw the working-tree diff. Removal ran through the linter's own
collectors, so detection and deletion cannot drift: a comment whose
opener line is blank before it and whose closer line is blank after it
loses all its lines, anything else loses only the comment region, and a
line left holding a bare delimiter goes with it.
Five files keep their comments behind a nocheck marker instead. Four are
upstream configs whose inline docs are upstream's own (mautrix, systemd
journald, nextcloud-oidc-login, MediaWiki). In littlejs the
commented-out entries ARE the deactivation mechanism for an example
tile, so deleting them would delete configuration.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
These commits were made with --no-verify, which skipped make test, leaving three latent lint failures. utils/paths.py: use the cached utils.cache.files.read_text (verified no import cycle) instead of a plain read. .ansible-lint-ignore: add the pixelfed resolve_host_cid load-failure entry (templated playbook_dir include, false positive). library/database_query.py: ruff line-wrap. make test is now fully green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The module execs 'container exec <container>' as an argv list (no shell), using config["container"] = the literal "postgres" in shared mode, which is not a swarm container name -> 'No such container: postgres' for peertube and ~12 other callers. The database lookup already provides a swarm-aware config["address"] = "$(resolve-container-id <stack> <key>)"; expand it here (shlex-split, run the resolver as argv) to a concrete id when present. Compose (address == container) is byte-identical.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Modern MariaDB images (>=11) dropped the `mysql` symlink, so the
hardcoded `mysql` binary in the mariadb engine spec started failing
with rc=127 ("executable file not found") — visible e.g. in the
Pixelfed users-table check looping through its `until` retries.
Switch `_ENGINES["mariadb"]` to an ordered `binaries=("mariadb",
"mysql")`, try them in sequence, and only fall back when the OCI
runtime reports the exact binary we tried missing — engine-side
rc=127s (SQL errors etc.) are not masked.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- `library/database_query.py`: drop `no_log: True` from `config` /
`named_args` argument_spec; add `mask_values` bool param (default
True). When True, the module copies their string values into
`module.no_log_values` at runtime — same effective redaction as
before, but now toggleable per task.
- Roll out `mask_values: "{{ MASK_CREDENTIALS_IN_LOGS | bool }}"` to
every `database_query` call (38 sites across web-app-{odoo,
openproject, peertube}) so the playbook constant in
group_vars/all/00_general.yml drives the redaction end-to-end. Set
it to false on demand for debugging unredacted rc/stderr.
Bundled: roles/web-app-openproject/tasks/02_ldap.yml also drops the
`async:`/`poll:` lines from Update/Create LDAP auth source. The
combination of `async` + `database_query` local-action + `no_log`
masked the async wrapper's result fetch with "Action failed: Unknown
error" while the SQL had actually succeeded (verified: 1 row in
`ldap_auth_sources` after the failing run). Sync execution matches the
pattern used by every other `database_query` caller in the repo.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The first reuse-kept deploy after introducing `database_query` failed
with `couldn't resolve module/action 'database_query'`: ansible only
searches for custom modules along the `library` config path, and the
module had landed under `plugins/modules/` (collection-style layout)
without that path being registered in ansible.cfg.
Realign with the repo's existing convention — `library/cert_check_exists.py`
and `library/docker_bridge_gateway.py` are already there — by relocating
the module to `library/database_query.py`. Make the search path explicit
in ansible.cfg (`library = ./library`) instead of relying on ansible's
implicit playbook-adjacent discovery, so the resolver stays predictable
across CLI / playbook / role-include entry points.
Move the unit suite into `tests/unit/library/` alongside the moved
module, fix the doc-string reference in the lint guard that points
callers at the canonical module location, and drop the now-empty
`tests/unit/plugins/modules/` package.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>