logs.tree-tail-export: the bundle's extension listing

The bundle carries system/extensions.json now. The case reads it out of
the tar, holds it to being the status document, and holds every listed
package to naming its id, version, tier, whether it is enabled, and what
the operator granted it - which is what a report from a machine running
extensions has to be read against. covers gains forgectrl's src/extpkg.*,
where the document is built.
This commit is contained in:
ScottW514
2026-09-22 10:12:25 -04:00
parent 5915408147
commit a552541acd
+24 -2
View File
@@ -25,7 +25,7 @@ def _read(path, default=None):
_LOG_COVERS = [("forgectrl", "src/logs.*"), ("forgectrl", "src/fflog.*"), ("forgectrl", "src/sanitize.*"), _LOG_COVERS = [("forgectrl", "src/logs.*"), ("forgectrl", "src/fflog.*"), ("forgectrl", "src/sanitize.*"),
("forgectrl", "src/main.c")] ("forgectrl", "src/extpkg.*"), ("forgectrl", "src/main.c")]
LOGS_ROOT = "/data/log/forgefirm" LOGS_ROOT = "/data/log/forgefirm"
# What the export test plants in the installer's directory: a line to find # What the export test plants in the installer's directory: a line to find
@@ -44,7 +44,10 @@ _PROBE_IP = "192.0.2.77"
"also carries the installer's directory of the tree (logs/install/), which no " "also carries the installer's directory of the tree (logs/install/), which no "
"logger feeds: a probe file planted there for the export comes back in the " "logger feeds: a probe file planted there for the export comes back in the "
"bundle with its addresses redacted, and an install log that the installer " "bundle with its addresses redacted, and an install log that the installer "
"left is in the bundle too.") "left is in the bundle too. system/extensions.json is in it as well: what is "
"installed that is not the firmware, with each package's tier, whether it is "
"enabled, and what the operator granted it, which is what a report about a "
"machine running extensions has to be read against.")
def tree_tail_export(ctx): def tree_tail_export(ctx):
install_dir = os.path.join(LOGS_ROOT, "install") install_dir = os.path.join(LOGS_ROOT, "install")
probe = os.path.join(install_dir, "forgetest-probe.txt") probe = os.path.join(install_dir, "forgetest-probe.txt")
@@ -134,6 +137,25 @@ def _tree_tail_export(ctx, probe):
ctx.check(any(name.endswith("logs/install/install.log") for name in by_name), ctx.check(any(name.endswith("logs/install/install.log") for name in by_name),
"the machine has an install log and the bundle does not") "the machine has an install log and the bundle does not")
# What is installed that is not the firmware. A report that starts "it
# stopped working" reads differently with packages on the machine, and
# the bundle is where that is read.
import json
ext = [name for name in by_name if name.endswith("system/extensions.json")]
ctx.check(ext, "the bundle carries no system/extensions.json")
if ext:
doc = json.loads(by_name[ext[0]].decode("utf-8", "replace"))
ev["extensions"] = {"enabled": doc.get("enabled"), "safe_mode": doc.get("safe_mode"),
"packages": [{k: p.get(k) for k in ("id", "version", "tier", "enabled", "grants")}
for p in doc.get("packages", [])]}
ctx.log("the bundle's extension listing: %s", ev["extensions"])
ctx.check(set(doc) >= {"enabled", "safe_mode", "host", "packages"},
"the listing is not the status document: %s", sorted(doc))
for p in doc.get("packages", []):
ctx.check(set(p) >= {"id", "version", "tier", "enabled", "grants"},
"a listed package does not say what it is: %s", sorted(p))
# The routing test proves the whole path every logger takes: emitter (or # The routing test proves the whole path every logger takes: emitter (or
# relay) -> /dev/log -> rsyslog rules rendered from the settings -> the # relay) -> /dev/log -> rsyslog rules rendered from the settings -> the