Pandora Plugin Executor

Ejecutor genérico de plugins para Pandora FMS.

Introducción

pandora-plugin_exec es un único binario en Go que sustituye a los plugins por tecnología. Una plantilla YAML describe el trabajo a realizar:

  1. Tareas a ejecutar — peticiones HTTP o ejecuciones de comandos locales.
  2. Filtros (jq o regexp) que extraen valores de la salida de una tarea hacia variables.
  3. Agentes y módulos construidos a partir de esas variables (incluyendo expresiones aritméticas).
  4. Un método de transferencia que entrega los datos resultantes a Pandora FMS.

El ejecutor ejecuta la plantilla una vez y termina (one-shot). Añadir soporte para una nueva tecnología significa escribir una nueva plantilla YAML — no un plugin nuevo, ni un lenguaje nuevo, ni un pipeline de empaquetado nuevo. Está pensado para usarse junto con el agente de Pandora FMS.

template.yml ─▶ ejecutar tareas ─▶ filtrar salidas en variables ─▶ renderizar módulos ─▶ entregar

Audiencia: personas que escriben plantillas y agentes de IA que las generan. Todo lo necesario para escribir una plantilla válida está en este archivo.

De serie, el plugin incluye plantillas ya construidas bajo templates/: ejemplos de aprendizaje y sustitutos directos de plugins de agente que antes venían con el agente. Consulta Plantillas incluidas.

Matriz de compatibilidad

Por ahora solo se ha probado Linux. Windows está planificado, pero todavía no se ha probado.

Plataforma / runtime Estado
Linux amd64 Probado
Linux arm64 No establecido
Windows amd64 No establecido
macOS No establecido

El binario entregado es estático, por lo que no tiene dependencias de runtime en el host.

Prerrequisitos

Para ejecutar el binario:

Por modo de transferencia:

Modo Requisito
agent_plugin Un agente de software de Pandora FMS que pueda invocar el binario mediante module_plugin
tentacle El binario tentacle_client (en $PATH, o su ruta configurada mediante transfer.tentacle.binary) y acceso de red al servidor de Pandora FMS (puerto por defecto 41121)
local Permiso de escritura sobre el directorio de destino (transfer.local.directory)

Parámetros

El ejecutor tiene tres superficies de configuración:

  1. Flags de CLI (esta sección).
  2. Parámetros en tiempo de ejecuciónargs posicionales y params con nombre, pasados después de los flags (esta sección).
  3. La plantilla YAML — tareas, agentes/módulos y transferencia. Referencia completa en Referencia de plantillas.

Flags de CLI

pandora-plugin_exec -t <plantilla.yml> [flags] [args...] [clave=valor...]
Flag Efecto
-t, --template <ruta> Plantilla a ejecutar (obligatorio)
--dry-run Imprime el XML generado por stdout, no transfiere
--strict Aborta en el primer fallo de tarea en lugar de omitir
-v, --verbose Registro de depuración en stderr (resultados de tareas, omisiones, avisos)
--version Imprime la versión y sale
Código de salida Significado
0 Éxito
1 Error de parseo/validación de la plantilla
2 Fallo de tarea bajo --strict
3 Error de transferencia

Los flags van antes de los argumentos: el parseo de flags se detiene en el primer token que no es flag, así que los flags deben preceder a los argumentos (pandora-plugin_exec -t tpl.yml --dry-run sda1, no ... sda1 --dry-run). Un argumento que empieza por guion se rechaza con un error claro en lugar de tratarse silenciosamente como posicional.

Parámetros en tiempo de ejecución

Los tokens que quedan después de los flags alimentan dos variables reservadas, sembradas en el almacén antes de que se ejecute ninguna tarea:

Reglas de parseo:

  1. Cada token se divide por el primer = sin escapar. Un = inmediatamente precedido por \ es un literal escapado y no divide.
  2. El token tiene nombre solo si la clave candidata (tras desescapar \==) coincide con [A-Za-z_][A-Za-z0-9_]*. En caso contrario, todo el token es posicional.

Todo token se clasifica — no hay casos de error. Claves con nombre duplicadas: gana la última. Los valores con aspecto numérico se convierten en números, así que la aritmética funciona con ellos. Las variables de tarea no pueden llamarse args ni params (reservadas); for_each: args sí es válido.

Trampa del escapado en shell: bash consume \= antes de que el ejecutor lo vea. Protege la barra invertida con comillas simples ('query\=a=b') o duplícala (query\\=a=b).

Token Se convierte en
sda1 args[0] = "sda1"
90 args[0] = 90 (número)
host=db01 params.host = "db01"
threshold=90 params.threshold = 90 (número)
conn=user=a;pw=b params.conn = "user=a;pw=b" (solo el primer = divide)
'query\=a=b' posicional "query=a=b" (la clave contendría = — no es un identificador)
=foo posicional "=foo" (clave vacía)
k=1 k=2 params.k = 2 (gana la última)

Parámetros opcionales

Los parámetros en tiempo de ejecución fallan de forma explícita, no silenciosa: referenciar una variable no definida no renderiza una cadena vacía — el módulo se omite con un aviso, para proteger contra erratas. Por tanto, un {{ params.x }} a secas omite el módulo cuando x no se pasó. Para hacer opcional un parámetro, elige un patrón explícito:

Patrón Efecto
{{ params.missing ?? "default" }} Renderiza un valor por defecto cuando falta la clave
when: "'k' in params" Incluye el módulo solo cuando se pasó la clave
{{ len(args) > 1 ? args[1] : "all" }} Protege un acceso posicional según el tamaño

Parámetros aceptados por las plantillas incluidas

Plantilla Parámetro Por defecto Efecto
templates/df_used.yml include Fuerza monitorizar un montaje cuyo fstype está fuera de la lista por defecto (coincidencias exactas de montaje separadas por comas)
templates/df_used.yml exclude Nunca monitoriza un montaje — exclude siempre gana sobre include
templates/pandora_netusage.yml include Monitoriza solo estas interfaces (nombres exactos separados por comas)
templates/pandora_netusage.yml exclude Nunca monitoriza una interfaz — exclude siempre gana sobre include
templates/pandora_mem_used.yml mem_critical 95 Umbral crítico para el porcentaje de Memory_Used
templates/pandora_mem_used.yml swap_critical 95 Umbral crítico para el porcentaje de Swap_Used

Ejecución manual

Formato de ejecución

pandora-plugin_exec -t <plantilla.yml> [flags] [args...] [clave=valor...]

Ejemplos

Ejecuta una plantilla incluida sin enviar nada (el binario pandora-plugin_exec se entrega ya compilado):

pandora-plugin_exec -t templates/df_used.yml --dry-run

Deberías ver bloques XML <module> en stdout, un par por sistema de archivos montado.

Ejecuciones reales con parámetros en tiempo de ejecución:

pandora-plugin_exec -t templates/df_used.yml                        # lista de fstype por defecto
pandora-plugin_exec -t templates/df_used.yml exclude=/DB,/snap      # descarta dos montajes
pandora-plugin_exec -t templates/df_used.yml include=/mnt/zfs       # monitoriza también un montaje zfs

pandora-plugin_exec -t templates/pandora_netusage.yml                          # todas las interfaces
pandora-plugin_exec -t templates/pandora_netusage.yml exclude=lo,docker0       # descarta loopback y docker0
pandora-plugin_exec -t templates/pandora_netusage.yml include=eth0,ens33       # solo eth0 + ens33
pandora-plugin_exec -t templates/pandora_netusage.yml include=lo exclude=lo    # exclude gana → 0 bytes

pandora-plugin_exec -t templates/pandora_mem_used.yml                          # valores por defecto
pandora-plugin_exec -t templates/pandora_mem_used.yml mem_critical=90 swap_critical=85

Modo verbose

-v / --verbose escribe el registro de depuración en stderr, dejando stdout limpio para el XML generado. Informa de los resultados por tarea (variables almacenadas), módulos omitidos y avisos:

pandora-plugin_exec -t templates/df_used.yml --dry-run -v

No hay archivo de log ni nivel de log; la salida verbose es un único flujo de stderr.

Configuración en Pandora FMS

El ejecutor es one-shot: ejecuta la plantilla una vez y termina. La planificación es externa.

Escenario Cómo
Como plugin de agente La plantilla usa transfer.mode: agent_plugin; configuración del agente: module_plugin /usr/bin/pandora-plugin_exec -t /etc/pandora/templates/df_used.yml
Desde cron / lado servidor La plantilla usa el modo tentacle o local; crontab: */5 * * * * pandora-plugin_exec -t /etc/pandora/templates/myapp.yml
Ejecutándose en el propio servidor de Pandora FMS Modo local apuntando al directorio de datos entrantes (/var/spool/pandora/data_in)
Depurando una plantilla pandora-plugin_exec -t plantilla.yml --dry-run -v

No hay asistente ni paquete .disco para este plugin: la instalación consiste en colocar el binario (y las plantillas) donde el agente/cron pueda alcanzarlos, y luego conectar la línea module_plugin o la entrada de crontab mostradas arriba.

Agentes y módulos generados por el plugin

Agentes. Cada bloque agents: se convierte en un documento XML <agent_data> (en los modos tentacle / local). La identidad del agente sale directamente de la plantilla: name, alias, parent_agent_name, description, version, os_name, os_version, timestamp, address, group, interval, agent_mode. En modo agent_plugin no se emite cabecera de agente — solo fragmentos <module> — y con varios bloques agents: cada nombre de módulo se prefija con <nombre_agente> - <nombre_módulo> (separador configurable mediante transfer.module_prefix_separator) para que los módulos no colisionen bajo el único agente real.

Módulos. Un módulo por bloque de módulo resuelto (un bloque for_each se resuelve en un módulo por elemento). El tipo de módulo es el que declare la plantilla (generic_data, generic_data_inc, generic_data_string, async_data, ...) — el ejecutor reenvía los campos del módulo al servidor de datos sin modificarlos. La lista completa de campos de módulo admitidos está en Referencia de plantillas.

Una tarea fallida (error de ejecución, estado HTTP fuera de 2xx, filtro con 0 coincidencias) deja su variable sin definir y registra un aviso; un módulo que referencia una variable sin definir se omite con un aviso y los módulos restantes se entregan igualmente. --strict convierte cualquiera de lo anterior en un aborto (código de salida 2).


Plantillas incluidas

El plugin incluye plantillas ya construidas bajo templates/, divididas en dos grupos.

Ejemplos

Plantilla Propósito
templates/http_api_example.yml Encadenamiento de API HTTP con autenticación por token (login → token → petición autenticada)
templates/local_commands_example.yml Comandos locales como plugin de agente, mostrando todas las formas de resultado de regexp

Sustitutos de plugins de agente heredados

Plantilla Sustituye a
templates/df_used.yml pandora_df_used_go — espacio usado del sistema de archivos
templates/pandora_mem_used.yml pandora_mem_used — memoria y swap
templates/pandora_netusage.yml pandora_netusage — uso de red

Referencia de plantillas

Una plantilla es un archivo YAML con tres secciones: tasks, agents (o modules de nivel superior) y transfer. El parseo es estricto: un nombre de campo desconocido es un error, así que las erratas fallan rápido.

Ejemplo mínimo completo

tasks:
  - name: disk
    type: local
    local: { command: "df --output=pcent / | tail -1 | tr -d ' %'" }
    variable: disk_pct

agents:
  - name: "myhost"
    group: "Servers"
    interval: 300
    modules:
      - name: "Disk used"
        type: generic_data
        data: "{{ disk_pct }}"
        unit: "%"

transfer:
  mode: tentacle
  tentacle: { address: "pandora.example.com" }

tasks: — lista ordenada de ejecuciones

Las tareas se ejecutan secuencialmente, en el orden declarado. Una tarea puede usar variables producidas por tareas anteriores en cualquiera de sus campos de cadena (encadenamiento: login → token → petición autenticada).

Campo Obligatorio Descripción
name Identificador único de tarea (usado en los logs)
type request o local
request si type=request Especificación de petición HTTP (abajo)
local si type=local Especificación de comando (abajo)
filter no Filtro de extracción (abajo). Sin él, se almacena la salida bruta recortada
variable no Nombre bajo el que almacenar el resultado. Debe coincidir con [A-Za-z_][A-Za-z0-9_]*

request: (HTTP)

Campo Obligatorio Por defecto Descripción
url URL de destino. Admite {{ }}
method no GET GET, POST, PUT, DELETE, PATCH, HEAD
headers no Mapa de cabecera → valor. Los valores admiten {{ }}
body no Cuerpo de la petición. Admite {{ }}
timeout no 30 Segundos
skip_tls_verify no false Acepta certificados TLS inválidos

Una respuesta con estado fuera de 2xx es un fallo de tarea. Los cuerpos de respuesta están limitados a 10 MiB.

local: (comando)

Campo Obligatorio Por defecto Descripción
command Se ejecuta con /bin/sh -c. Admite {{ }}. El $ de shell no se toca (awk '{print $5}' funciona tal cual)
timeout no 30 Segundos; el proceso se mata al expirar

Un código de salida distinto de cero es un fallo de tarea (stderr se incluye en el log).

filter: — extracción de valores

Campo Obligatorio Descripción
type jq o regexp
expression La expresión del filtro

Cardinalidad del resultado (ambos tipos de filtro): 0 coincidencias → variable sin definir (semántica de fallo de tarea) · 1 coincidencia → escalar · N coincidencias → array.

jq — la salida de la tarea debe ser JSON válido. La expresión se ejecuta con un motor jq incorporado (no se necesita el binario jq). Cada valor que emite la expresión es un elemento: .token → escalar, .items[].name → array, .items[] → array de objetos.

regexp — sintaxis RE2 de Go (sin backtracking, sin lookahead) aplicada a la salida bruta. Por coincidencia:

Forma del patrón Cada coincidencia se convierte en
Sin grupo de captura (cpu\d) La coincidencia completa (cadena)
Un grupo sin nombre ((\d+)%) El grupo de captura 1 (cadena)
2+ grupos sin nombre ((a)(b)(c)) Array posicional: [[a, b, c], ...]
Grupos con nombre ((?P<mount>...)) Un objeto: nombre del grupo → texto capturado

Usa (?m) para patrones multilínea anclados por línea y (?i) para coincidencia sin distinción de mayúsculas. No mezcles grupos con nombre y sin nombre en la misma regexp si quieres un acceso predecible; la forma con nombre solo expone los campos con nombre.

Coerción de tipos: las cadenas extraídas con aspecto numérico se convierten en números (recursivamente, incluyendo campos de objetos), así que la aritmética funciona con ellas.

Variables y expresiones {{ }}

Cualquier campo de cadena de tareas (después de la tarea que la produce), agentes y módulos puede incluir {{ expresión }}. Las expresiones se evalúan con expr-lang contra el almacén de variables.

Expresión Resultado
{{ token }} Valor de la variable
{{ 100 - disk_pct }} Aritmética
{{ names[0] }} Indexado de array
{{ value.mount }} Campo de objeto (dentro de for_each)
{{ names[index] }} Array paralelo sincronizado (dentro de for_each)

Referenciar una variable no definida es un error → el módulo afectado se omite (o la ejecución aborta bajo --strict).

agents: — un bloque por agente

Obligatorio a menos que uses modules: de nivel superior (ver el modo agent_plugin). Cada agente se convierte en un documento XML <agent_data>.

Campo Obligatorio Descripción
name Nombre del agente
modules Lista de bloques de módulo (al menos uno)
alias no Alias del agente
parent_agent_name no Agente padre
description no Descripción
version no Cadena de versión del agente
os_name, os_version no Identificación del SO
timestamp no Sobrescribe la marca de tiempo de los datos
address no IP/nombre de host
group no Grupo de destino
interval no Segundos (entero)
agent_mode no Modo del agente

Todos los campos de cadena admiten {{ }}.

modules: — bloques de módulo

Los bloques de módulo viven dentro de un agente, o a nivel superior (solo con transfer.mode: agent_plugin).

Campos de control (semántica del ejecutor, no se envían a Pandora):

Campo Descripción
for_each Nombre de variable array. El bloque se expande a un módulo por elemento; {{ value }} e {{ index }} quedan disponibles. Una variable escalar itera como array de 1 elemento. Para grupos de captura sin nombre con 2+ grupos, cada value es un array, así que puedes usar {{ value[0] }}. ¿Varios módulos por elemento? Escribe varios bloques con el mismo for_each
when Expresión booleana expr-lang en bruto (sin {{ }}). Falso → módulo (o elemento) omitido. Dentro de for_each se evalúa por elemento y ve value/index. Ejemplo: when: 'not (value.mount matches "^/DB")'

Campos de datos — los dos obligatorios más el conjunto completo aceptado por el servidor de datos. Los valores pueden ser números o cadenas en YAML; todos admiten {{ }}:

Campo Obligatorio Descripción
name Nombre del módulo
type Tipo de módulo (generic_data, generic_proc, generic_data_string, async_data, ...)
data no Valor del módulo
description no Descripción
unit no Etiqueta de unidad
interval no Intervalo del módulo
tags no Etiquetas
module_group no Grupo de módulo
module_parent, module_parent_unlink no Relación de módulo padre
min_warning, max_warning, min_critical, max_critical no Umbrales numéricos
min_warning_forced, max_warning_forced, min_critical_forced, max_critical_forced no Variantes de umbral forzado
str_warning, str_critical no Umbrales por coincidencia de cadena
str_warning_forced, str_critical_forced no Umbrales de cadena forzados
warning_inverse, critical_inverse no Invertir la lógica del umbral
min, max no Rango de datos válido
post_process no Multiplicador aplicado por el servidor
disabled no Crear deshabilitado
status no Forzar estado
timestamp no Sobrescribe la marca de tiempo de los datos
custom_id no Identificador personalizado
critical_instructions, warning_instructions, unknown_instructions no Instrucciones del operador
quiet no Modo silencioso
min_ff_event, min_ff_event_normal, min_ff_event_warning, min_ff_event_critical no Umbrales FlipFlop
module_ff_interval, ff_type, ff_timeout, each_ff no Comportamiento FlipFlop
crontab no Planificación de módulo estilo cron
extra_data no Carga extra
alert_templates no Lista de nombres de plantillas de alerta a vincular

transfer: — entrega

Campo Obligatorio Descripción
mode tentacle, local o agent_plugin
tentacle.address para tentacle Dirección del servidor Pandora
tentacle.port no (por defecto 41121) Puerto tentacle
tentacle.binary no Ruta a tentacle_client si no está en $PATH
tentacle.extra_args no Argumentos extra del cliente tentacle (lista)
local.directory para local Directorio donde se escribe el archivo XML .data
module_prefix_separator no (por defecto " - ") Separador para el prefijado multi-agente en modo agent_plugin
Modo Salida Caso de uso
tentacle XML <agent_data> completo enviado vía cliente tentacle Ejecución remota (cron, Discovery)
local XML <agent_data> completo escrito en un directorio Ejecutarse en el propio servidor Pandora (apuntando al directorio de entrada), o depuración
agent_plugin Solo fragmentos <module> impresos en stdout — el agente real añade la cabecera Ejecutarse como module_plugin de un agente de software

Particularidades de agent_plugin:


Crear tus propias plantillas

Una plantilla es solo YAML. Constrúyela de arriba a abajo: decide qué medir (tareas), cómo extraer los números (filtros), qué módulos exponer (agentes/módulos) y cómo entregar (transferencia).

Paso 1 — Parte de un ejemplo incluido

templates/local_commands_example.yml es la plantilla completa más corta y demuestra las tres formas de resultado de regexp. Cópiala y sustituye las tareas:

cp templates/local_commands_example.yml templates/my_template.yml

Paso 2 — Escribe las tareas

Cada tarea ejecuta un comando o una petición HTTP y almacena su salida (opcionalmente filtrada) en una variable.

tasks:
  # Un escalar: un valor, sin filtro (se almacena la salida bruta recortada).
  - name: uptime_seconds
    type: local
    local: { command: "awk '{print int($1)}' /proc/uptime" }
    variable: uptime

  # Un escalar mediante una regexp con una sola captura.
  - name: load_avg
    type: local
    local: { command: "cat /proc/loadavg" }
    filter:
      type: regexp
      expression: '^(\d+\.\d+)'
    variable: load1

  # Un array de objetos mediante grupos de captura con nombre.
  - name: df
    type: local
    local: { command: "df -kTP" }
    filter:
      type: regexp
      expression: '(?m)^(?P<fs>\S+)\s+(?P<fstype>\S+)\s+(?P<total>\d+)\s+(?P<used>\d+)\s+\d+\s+(?P<pct>\d+)%\s+(?P<mount>.+)$'
    variable: filesystems

Paso 3 — Convierte variables en módulos

Una variable escalar alimenta directamente un módulo; un array alimenta bloques for_each (un módulo por elemento).

modules:
  - name: "Uptime seconds"
    type: generic_data
    data: "{{ uptime }}"

  - name: "Load average 1m"
    type: generic_data
    data: "{{ load1 }}"

  # Un módulo por sistema de archivos; value.* lee los grupos de captura con nombre.
  - for_each: filesystems
    when: 'value.fstype != "tmpfs"'
    name: "DiskUsed_{{ value.mount }}"
    type: generic_data
    data: "{{ value.pct }}"
    unit: "%"

Dentro de un bloque for_each:

Paso 4 — Elige el modo de transferencia

transfer:
  mode: agent_plugin            # salida solo de módulos; ejecutar como plugin de agente de software
transfer:
  mode: tentacle                # XML de agente completo a un servidor Pandora
  tentacle: { address: "pandora.example.com" }
transfer:
  mode: local                   # XML de agente completo escrito en un directorio
  local: { directory: "/var/spool/pandora/data_in" }

Paso 5 — Valida antes de entregar

pandora-plugin_exec -t templates/my_template.yml --dry-run -v

--dry-run imprime el XML generado sin transferir; -v muestra qué variables se almacenaron y qué módulos se omitieron. El parser es estricto, así que cualquier errata en un nombre de campo falla inmediatamente.

Errores comunes


Referencia rápida del lenguaje de expresiones

Los placeholders {{ }} y las condiciones when: son expresiones expr-lang. Funciones útiles para autores de plantillas:

Categoría Funciones / operadores
Cadenas split(s, sep) · join(list, sep) · upper(s) · lower(s) · trim(s) · replace(s, old, new) · contains(s, sub) · startsWith(s, pre) · endsWith(s, suf) · s matches "patrón-re2"
Colecciones x in list · len(list) · list[i] · first(list) · last(list) · filter(list, pred) · map(list, expr) · all/any/none(list, pred) · sort(list) · uniq(list) · concat(a, b)
Lógica y nil a ?? "default" (coalescencia de nil) · obj?.field (encadenamiento opcional) · cond ? a : b (ternario) · 'clave' in map (presencia de clave)
Números + - * / % · abs(x) · min/max(a, b) · sum(list) · avg(list) · int(x) · float(x) · string(x)
JSON toJSON(x) · fromJSON(s)

En los predicados de filter/map/all/any/none el elemento actual es # (p. ej. filter(filesystems, #.pct > 90)).

No confundas lenguajes: el filter.expression de la tarea no es expr — es jq (vía gojq) o una regexp RE2, según filter.type. expr solo se usa dentro de {{ }} y en when:.


Ejemplo práctico: sustituir un plugin real

templates/df_used.yml sustituye al plugin de agente pandora_df_used_go. El patrón a aprender: una ejecución → array de objetos → N módulos.

tasks:
  - name: df
    type: local
    local: { command: "df -kTP" }
    filter:
      type: regexp
      # Grupos con nombre: cada fila de df se convierte en {fs, fstype, total, used, pct, mount}
      expression: '(?m)^(?P<fs>\S+)\s+(?P<fstype>\S+)\s+(?P<total>\d+)\s+(?P<used>\d+)\s+\d+\s+(?P<pct>\d+)%\s+(?P<mount>.+)$'
    variable: filesystems

modules:
  - for_each: filesystems
    when: >
      (value.fstype matches "^(?i:adfs|affs|autofs|btrfs|cifs|coda|coherent|efs|ext\\d?|hfs|hfsplus|hpfs|jfs|minix|msdos|ncpfs|nfs4?|ntfs|proc|qnx4|reiserfs|smbfs|sysv|ubifs|udf|ufs|umsdos|usbfs|vfat|xenix|xfs|xiafs)$"
      || value.mount in split(params.include ?? "", ","))
      && not (value.mount in split(params.exclude ?? "", ","))
    name: "DiskUsed_{{ value.mount }}"
    type: generic_data
    data: "{{ value.pct }}"
    unit: "%"

  - for_each: filesystems
    when: >
      (value.fstype matches "^(?i:adfs|affs|autofs|btrfs|cifs|coda|coherent|efs|ext\\d?|hfs|hfsplus|hpfs|jfs|minix|msdos|ncpfs|nfs4?|ntfs|proc|qnx4|reiserfs|smbfs|sysv|ubifs|udf|ufs|umsdos|usbfs|vfat|xenix|xfs|xiafs)$"
      || value.mount in split(params.include ?? "", ","))
      && not (value.mount in split(params.exclude ?? "", ","))
    name: "DiskUsed_{{ value.mount }} bytes"
    type: generic_data
    data: "{{ value.used }}"
    unit: "bytes"

transfer:
  mode: agent_plugin

La regexp captura todas las filas de df; la lista permitida de fstype por defecto vive en when: para que los parámetros en tiempo de ejecución puedan sobrescribirla. Observa el escalar plegado (when: >) y la barra invertida duplicada (\\d): los literales de cadena de expr procesan escapes, así que \\d entrega un \d literal al motor de regexp.

Ejemplo de capturas posicionales

Úsalo cuando quieras el orden de captura en lugar de nombres de campo:

tasks:
  - name: fs
    type: local
    local:
      command: |
        printf '/dev/sda1 ext4 40 81 /\n/dev/sdb1 xfs 90 12 /data\n'
    filter:
      type: regexp
      expression: '(?m)^(\S+)\s+(\S+)\s+(\d+)\s+(\d+)\s+(.+)$'
    variable: filesystems

modules:
  - for_each: filesystems
    name: "FS {{ value[0] }}"
    type: generic_data
    data: "{{ value[3] }}"
    unit: "%"

transfer:
  mode: agent_plugin

Ejemplo de API HTTP

templates/http_api_example.yml demuestra el encadenamiento con autenticación por token: una petición login almacena el token de sesión, y las peticiones posteriores lo incorporan mediante Authorization: "Bearer {{ token }}".


Lista de verificación de plantillas (para humanos y generadores de IA)