Worked example: replacing a real plugin
templates/df_used.yml replaces the pandora_df_used_go agent plugin. The pattern to learn: one execution → array of objects → N modules.
tasks:
- name: df
type: local
local: { command: "df -kTP" }
filter:
type: regexp
# Named groups: each df row becomes {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
The regexp captures all df rows; the default fstype allow-list lives in when: so runtime params can override it. Note the folded scalar (when: >) and the doubled backslash (\\d): expr string literals process escapes, so \\d delivers a verbatim \d to the regexp engine.
Positional captures example
Use this when you want capture order instead of field names:
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
HTTP API example
templates/http_api_example.yml demonstrates token-auth chaining: a login request stores the session token, and later requests embed it via Authorization: "Bearer {{ token }}".