Hint placeholders#
A hint is an offer an installed app makes on another page of the web UI: "AdGuard Home is running at 10.99.0.10 — point the router's resolver at it", together with the exact operations that would do it. The operator still stages and commits them. Nothing is applied by a hint.
The operations in a hint are templates, because the catalogue ships to every router and cannot know any one router's addresses. A path element may carry a placeholder, which is resolved from the router the hint is offered on, never from the catalogue.
curl -sk "$R/api/apps/hints/dns" -H "Authorization: Bearer $T"[
{
"app_id": "adguard",
"app_name": "AdGuard Home",
"address": "10.99.0.10",
"title": "Point the resolver at AdGuard Home",
"body": "…",
"ops": [
{"op": "set", "path": ["service","dns","forwarding","name-server","10.99.0.10"]}
]
}
]The four placeholders#
| Placeholder | Resolved from |
|---|---|
{{address}} | The app's own container address, as the router's configuration holds it. Per app, added to the variable set for that app's hints only. |
{{dhcp.network}} | The first shared-network name under service dhcp-server that has at least one subnet, taking names in sorted order. |
{{dhcp.subnet}} | That scope's first subnet, again in sorted order. |
{{dns.domain}} | system domain-name. If that is unset, the first authoritative zone under service dns forwarding. |
The pattern is {{[a-z.]+}} and it is matched inside a path element, so a template
may embed one in a larger string. Every occurrence of the same placeholder in one hint
resolves to the same value.
When a placeholder cannot be filled#
A hint whose router cannot fill a placeholder keeps its advice and loses its operations. The body gains a sentence naming what was missing:
(No commands offered: the router has no DHCP scope yet.)| Missing | The sentence |
|---|---|
address | the container has no address yet |
dhcp.network | the router has no DHCP scope yet |
dhcp.subnet | the router has no DHCP subnet yet |
dns.domain | the router has no domain (set system domain-name, or an authoritative zone) |
| anything else | <name> is unknown |
That behaviour is not politeness. Staging a command with an empty path element fails at
commit with an error the operator did not cause, and an operation that named one
laboratory's LAN 10.0.0.0/16 was once staged, verbatim, on every router the catalogue
shipped to. Nothing site-specific may be written into the catalogue itself.
An app running on the host network has no container address, so its {{address}} hints
become advice.
Which apps offer hints#
An app contributes hints only when all of these hold:
- it matched a catalogue entry by image;
- it is not disabled in the configuration (
container name <n> disable); - the hint's
pageequals the page being asked about.
The pages hints target#
GET /api/apps/hints/{page} takes the page name. The catalogue currently places 20
hints on twelve pages:
| Page | Hints |
|---|---|
dns | 5 |
firewall | 3 |
nat | 2 |
dhcp | 2 |
apps, certificates, daemons, qos, routes, sessions, system, wireguard | 1 each |
Re-derive that for the version you are running:
python3 -c '
import json, collections
c = json.load(open("agent/catalog.json"))
n = collections.Counter(h["page"]
for a in c["apps"]
for h in a.get("integration", {}).get("hints", []))
print(dict(n))
'Anatomy of a hint#
| Field | Meaning |
|---|---|
page | The UI page it appears on. |
title | One line, shown as the offer. |
body | The explanation. A missing placeholder appends its note here. |
ops | Zero or more {op, path} templates. op is set or delete. |
A hint with no ops at all is pure advice, which is legitimate — some of them exist to
tell you a thing is possible, not to write it for you.
Cost#
Resolving the variables reads three configuration subtrees — service dhcp-server,
system and service dns — from the agent's read cache, and listing installed apps reads
the container configuration. Every one of those is a cached read; the endpoint does not
health-probe, so asking for hints does not cost a probe round trip per app.
See also#
- Catalogue schema — the
integration.hintsfield. - The catalogue — which entries offer hints, in the Integration column.
- Endpoint index —
GET /api/apps/hints/{page}. - The commands Wheelhouse runs — the subtrees read here.
- Apps are configuration
Checked against#
agent/catalog.go (Hint, HintOp, expandOps,
placeholder),
agent/apps.go (hintsForPage, missingHintNote,
resolveHintVars, handleAppHints, collectInstalled),
agent/catalog.json,
agent/catalog_test.go,
docs/apps.md "Integration".