Files
computer-playbook/plugins
kevinveenbirkenbachandClaude Opus 5.5 96ebefb9db perf(spot): re-render only the users SPOT after a token store write
A token store write re-rendered the whole applications SPOT: merged_applications_cache_key carried the token store digest, so the applications_carrier park in sys-token-store/tasks/write_many.yml missed its key and rendered all 269 applications again (stalwart compose roundtrip 18.3 s and 10.2 s per pass, swarm pass 1 12.2 s and 12.6 s).

Rendered from the real roles tree under an empty, a realistic and an exhaustive token store (298 users x 269 applications), the applications tree differs only under <app>.users.<key>.tokens (28783 leaves in 46 applications, 0 elsewhere); the 69 password leaves that also differ change between two renders of the same store. No code reads a token through the applications tree: every reader goes through lookup('users'), lookup('config', <app>, 'users.<key>...') (served from get_merged_users), lookup('email') or the sys_token_store_users fact, and the users carrier keys on the store.

The token digest therefore moves from merged_applications_cache_key into merged_users_cache_key, whose value stays the same. A store write keeps the applications carrier and the write_many park re-renders the users alone; the task is renamed to match. applications.md now says that user records inside the payload can predate every store write and that application config must not derive a value from a token.

Real ansible-playbook harness on 2.20.6 with the real roles, group_vars and write_many.yml: the re-park after a first mint and after a rotation drops from 4.0 s to 0.55 s on one host (applications renders 1 -> 0), and every token probe (users, config users path, email password, stalwart_users) equals the old code in compose and swarm mode. Dropping the digest from the users key as well leaves those probes stale, which the harness and two unit tests catch.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-29 15:56:08 +01:00
..
…

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 unified meta/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/action
  • filter_plugins = ./plugins/filter
  • lookup_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 🔗