pyrtan / sourcev0.13.0 · main

pyrtan / examples / disk-space / disk-space.toml

2,148 bytes · last changed 2026-10-26 in The catalog grows up: namespaces, publishing by pull request through the gate, gap reports gossiped back to authors; release 0.8.0

1# How full a filesystem is, by asking df on the box this tree runs on. A
2# shell node runs one program by name, with its arguments as a list: no
3# shell reads the line, so nothing in an argument is ever a command.
4# `commands` is the allow-list, as `hosts` is for HTTP; `df` is all this
5# tree may run. A service started with --egress public refuses shell nodes
6# altogether: a hosted box is not lent out.
7
8name = "disk-space"
9version = 2
10namespace = "pyrtan"
11description = "How full a filesystem is, from df on the box this tree runs on."
12tags = ["ops", "box", "read-only"]
13license = "MIT"
14commands = ["df"]
15start = "df"
16
17[[triggers]]
18pattern = "[how] full is the disk"
19[[triggers]]
20pattern = "disk space"
21[[triggers]]
22pattern = "disk space on {mount:word}"
23
24[inputs.mount]
25type = "str"
26default = "/"
27description = "A mount point, or any path on the filesystem to measure"
28
29[nodes.df]
30kind = "observe"
31shell = { command = "df", args = ["-P", "{{ inputs.mount }}"] }
32into = "df" # state.df = { command, args, status, ok, stdout, stderr, body, json, lines }
33extract = [
34 { into = "percent", regex = "(\\d+)%", group = 1 },
35 { into = "mounted", regex = "%\\s+(\\S+)\\s*$", group = 1 },
36]
37next = "ran"
38
39[nodes.ran]
40kind = "decide"
41on = "df.ok"
42branches = [{ when = { eq = true }, then = "number" }, { else = "failed" }]
43
44[nodes.number]
45kind = "set"
46set = { pct = "{{ state.percent | int }}" }
47next = "level"
48
49[nodes.level]
50kind = "decide"
51on = "pct"
52branches = [
53 { when = { lt = 80 }, then = "fine" },
54 { when = { lt = 95 }, then = "tight" },
55 { else = "full" },
56]
57
58[nodes.fine]
59kind = "done"
60say = "{{ state.mounted }} is {{ state.pct }}% full."
61output = { mounted = "{{ state.mounted }}", percent = "{{ state.pct }}" }
62
63[nodes.tight]
64kind = "done"
65say = "{{ state.mounted }} is {{ state.pct }}% full; make room soon."
66output = { mounted = "{{ state.mounted }}", percent = "{{ state.pct }}" }
67
68[nodes.full]
69kind = "fail"
70reason = "disk-full"
71say = "{{ state.mounted }} is {{ state.pct }}% full."
72
73[nodes.failed]
74kind = "fail"
75reason = "df-failed"
76say = "df could not measure {{ inputs.mount }}: {{ state.df.stderr | strip }}"