The merge brought in main's new roles and carried this branch's cross-cutting renames and lints past them, so files that never conflicted were left inconsistent. make quality-high is green again: 4 test targets, 15 lint targets.a05071fe78renamed get_entity_name to entity_name. Three files main added still used the old name and merged cleanly because this branch never touched them: plugins/lookup/email.py raised ImportError on import, which also took down sys-ctl-hlth-msmtp's mail_recipient lookup; web-app-stalwart/tasks/00_core.yml applied `| get_entity_name`, a filter that does not exist (the registration in plugins/filter/get/entity_name.py is `entity_name`), so a compose deploy of stalwart would have failed while rendering sys-stk-front-proxy's vars; and test_database.py patched a name the module no longer binds. web-app-stalwart and web-app-mailu spell DEPLOYMENT_MODE out in 15 places. The named booleans in group_vars/all/18_swarm.yml are the SPOT and the bare form is the idiom: 177 existing uses, and web-app-listmonk/tasks/utils/mcp.yml:42,49 drives both as mutually exclusive `when:` conditions, which a truthy string would break. svc-net-tor-smtp pinned aiosmtpd and PySocks inside its Dockerfile, where Dependabot cannot see them. The pins move to files/requirements.txt; since sys-svc-compose stages only the Dockerfile, 00_core.yml now stages the requirements file into the build context too. stalwart's webui_version had no upstream declared. Its three inline `environment:` blocks stay, with a nocheck each: the role sets no docker_compose_env, so one templates/env.j2 would also be the env_file of the sibling containers, and clamav would receive the recovery admin credential and the OIDC client secret. The 13 bindings in stalwart's playwright env.js defaulted to "" and were consumed unconditionally. Every key is emitted unconditionally by playwright.env.j2 from a lookup that fails rather than yields empty, and OIDC_ISSUER_URL always concatenates the realm path, so requireDotenvValue is the correct binding. gitlab's adminUsername gets the toBeTruthy guard its two siblings already had. web-svc-api and svc-cache-package collided with stalwart on local.http 8094 and 8095 and move to 8098 and 8099, which exhausts the 8001-8099 band. svc-ai-agent-broker collided with stalwart on 192.168.223.0/24 and moves to 192.168.81.0/24; the suggester only subdivides blocks already in use at the requested prefix, so the move was validated with --block. web-app-weblate calls lookup('email') without emitting lookup('container_extra_hosts'), so on an onion deploy its SMTP client drops every message without an error. test_main.py read the primary domain from a literal while main moved INFINITO_DOMAIN to main.infinito.test. It now takes the value from default_domain_primary(), in the shapee2beab9f1cuses on feature/web-app-wazuh/add-role, so that branch merges here without a conflict. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Ansible Plugins (plugins/) 🧩
This document is the central reference for plugin types and plugin placement in Infinito.Nexus.
Not to be confused with application addons. This
plugins/directory holds Ansible plugins (action / filter / lookup) that extend the automation engine itself. Some applications also call their own extensions "plugins" (e.g. Nextcloud, WordPress). Those application-level extensions, whatever the app calls them natively, are declared through the unifiedmeta/addons/contract, documented in Unified Addons. An app "plugin" is an addon; an Ansible plugin lives here.
Current Project Layout 🗂️
plugins/
├── action/ # custom action plugins
├── filter/ # custom Jinja2 filters
└── lookup/ # custom lookup plugins
Configured plugin paths in this repository are defined in ansible.cfg:
action_plugins = ./plugins/actionfilter_plugins = ./plugins/filterlookup_plugins = ./plugins/lookup
All Common Ansible Plugin Types 📚
The table below summarizes common Ansible plugin types and their conventional directory names.
| Emoji | Plugin Type | Conventional Directory | Purpose |
|---|---|---|---|
| ⚙️ | action |
action_plugins/ or plugins/action/ |
Wrap/extend module execution behavior at task runtime. |
| 🔐 | become |
become_plugins/ |
Implement privilege escalation methods. |
| 💾 | cache |
cache_plugins/ |
Persist gathered facts and cached data between runs. |
| 📣 | callback |
callback_plugins/ |
React to play/task events (logging, reporting, notifications). |
| 🖧 | cliconf |
cliconf_plugins/ |
Define CLI command transport behavior (mainly network platforms). |
| 🔌 | connection |
connection_plugins/ |
Control how Ansible connects to targets (ssh, local, etc.). |
| 🔍 | filter |
filter_plugins/ or plugins/filter/ |
Add Jinja2 filters for data transformation. |
| 🌐 | httpapi |
httpapi_plugins/ |
API transport layer over HTTP(S), mainly for network devices. |
| 🧭 | inventory |
inventory_plugins/ |
Build dynamic inventories from APIs, services, or files. |
| 👉 | lookup |
lookup_plugins/ or plugins/lookup/ |
Resolve dynamic values during playbook processing. |
| 🛰️ | netconf |
netconf_plugins/ |
NETCONF transport integration for network automation. |
| 🐚 | shell |
shell_plugins/ |
Adjust shell command wrapping/execution behavior. |
| 🧠 | strategy |
strategy_plugins/ |
Customize task scheduling/execution strategy. |
| ✅ | test |
test_plugins/ |
Add Jinja2 tests used in conditions and templates. |
| 📦 | vars |
vars_plugins/ |
Load variables from custom sources. |
Which Plugin Type to Use 🧭
action ⚙️
Use when task execution behavior itself must be changed or wrapped.
Examples:
- centralized retry logic (
uri_retry.py), - argument normalization before module dispatch,
- pre/post task orchestration.
filter 🔍
Use for pure data transformation in Jinja2 expressions.
Examples:
- mapping/normalizing dictionaries,
- deriving computed fields for templates,
- deterministic formatting helpers.
lookup 👉
Use when a value must be dynamically resolved at runtime.
Examples:
- computing IDs from role metadata,
- resolving paths/version data,
- reading structured project data for templates/tasks.
callback 📣
Use to hook into execution events and shape output/reporting.
inventory 🧭
Use when host/group data should come from a dynamic source.
strategy 🧠
Use to alter how tasks are scheduled/executed across hosts.
vars 📦
Use to load variables from custom backends.
connection, become, shell 🔌🔐🐚
Use to customize low-level execution and privilege mechanics.
cache 💾
Use to persist facts/results across runs for performance and consistency.
cliconf, httpapi, netconf 🖧🌐🛰️
Use in network automation contexts requiring protocol-specific transport behavior.
test ✅
Use to add custom Jinja2 test operators for conditional logic.
Best Practices 🧪
- Keep plugin interfaces explicit and stable.
- Keep plugin logic focused; move shared logic to
utils/. - Add unit tests for plugin behavior and integration tests for end-to-end flows.
- Prefer deterministic outputs and avoid hidden global state.
- Document any plugin-specific task arguments in the plugin docstring and README.
References 🔗
- Ansible plugin development: docs.ansible.com
- Ansible plugin index (all types): docs.ansible.com
- Ansible
ansible-docplugin types:ansible-doc -t ...