Merge pull request 'systemd owns its package; systemd-networkd configures networkd and claims none' (#261) from fix/systemd-owns-its-package into main

This commit was merged in pull request #261.
This commit is contained in:
2026-10-04 10:17:23 +00:00
3 changed files with 17 additions and 12 deletions
+1 -7
View File
@@ -2,7 +2,6 @@
"module": "systemd-networkd", "module": "systemd-networkd",
"version": "1", "version": "1",
"capabilities": [ "capabilities": [
"package-manager",
"service-manager", "service-manager",
"uplink-systemd-networkd" "uplink-systemd-networkd"
], ],
@@ -13,17 +12,12 @@
} }
], ],
"resources": [ "resources": [
{
"id": "package",
"type": "package",
"package": "systemd"
},
{ {
"id": "config", "id": "config",
"type": "file", "type": "file",
"path": "/etc/systemd/network/00-mesh0.network", "path": "/etc/systemd/network/00-mesh0.network",
"mode": "0644", "mode": "0644",
"content": "# Managed by the mesh (module systemd-networkd). Replaced on every push; edit\n# the catalogue instead.\n#\n# This machine's uplink is systemd-networkd's, and the mesh asks one thing of it\n# here (novox/hq ADR 0117): leave the private network's interface alone. mesh0\n# is the mesh's; the mesh brings it up and configures it itself. The mesh never\n# declares a link, an address, a route, a wireless network or its credentials,\n# nor a network file for any of this machine's own interfaces \u2014 those are\n# the operator's, and the link they make is the only channel the mesh reaches\n# this machine over.\n#\n# 00-: networkd applies the first .network file, in alphanumeric order across\n# every directory, that matches an interface, and ignores every later one even\n# if it matches too (systemd.network(5), [Match]). A catch-all of the operator's\n# \u2014 Name=*, Type=ether, a file with no [Match] at all \u2014 sorted before\n# this one would claim mesh0 first. 00 sorts before every numbered prefix the\n# man page recommends.\n#\n# Unmanaged=yes: \"no attempts are made to bring up or configure matching links,\n# equivalent to when there are no matching network files\" (systemd.network(5),\n# [Link], since 233). A match that ends the search, and does nothing else.\n#\n# No DNS setting, because none is needed: networkd never writes\n# /etc/resolv.conf. What it learns from a lease it hands only to\n# systemd-resolved, and the resolver file stays whatever resolv-conf wrote.\n# Whether resolved runs, and what it does with that, is the resolver\n# configuration's question, not the uplink's.\n#\n# The service is reloaded when this file changes, never restarted: a restart\n# drops the links networkd holds, this machine's channel to the mesh among them.\n[Match]\nName=mesh0\n\n[Link]\nUnmanaged=yes\n" "content": "# Managed by the mesh (module systemd-networkd). Replaced on every push; edit\n# the catalogue instead.\n#\n# This machine's uplink is systemd-networkd's, and the mesh asks one thing of it\n# here (novox/hq ADR 0117): leave the private network's interface alone. mesh0\n# is the mesh's; the mesh brings it up and configures it itself. The mesh never\n# declares a link, an address, a route, a wireless network or its credentials,\n# nor a network file for any of this machine's own interfaces — those are\n# the operator's, and the link they make is the only channel the mesh reaches\n# this machine over.\n#\n# 00-: networkd applies the first .network file, in alphanumeric order across\n# every directory, that matches an interface, and ignores every later one even\n# if it matches too (systemd.network(5), [Match]). A catch-all of the operator's\n# — Name=*, Type=ether, a file with no [Match] at all — sorted before\n# this one would claim mesh0 first. 00 sorts before every numbered prefix the\n# man page recommends.\n#\n# Unmanaged=yes: \"no attempts are made to bring up or configure matching links,\n# equivalent to when there are no matching network files\" (systemd.network(5),\n# [Link], since 233). A match that ends the search, and does nothing else.\n#\n# No DNS setting, because none is needed: networkd never writes\n# /etc/resolv.conf. What it learns from a lease it hands only to\n# systemd-resolved, and the resolver file stays whatever resolv-conf wrote.\n# Whether resolved runs, and what it does with that, is the resolver\n# configuration's question, not the uplink's.\n#\n# The service is reloaded when this file changes, never restarted: a restart\n# drops the links networkd holds, this machine's channel to the mesh among them.\n[Match]\nName=mesh0\n\n[Link]\nUnmanaged=yes\n"
}, },
{ {
"id": "service", "id": "service",
+10 -2
View File
@@ -2,7 +2,8 @@
"module": "systemd", "module": "systemd",
"version": "1", "version": "1",
"capabilities": [ "capabilities": [
"service-manager" "service-manager",
"package-manager"
], ],
"claims": [ "claims": [
{ {
@@ -34,5 +35,12 @@
] ]
} }
] ]
} },
"resources": [
{
"id": "package",
"type": "package",
"package": "systemd"
}
]
} }
+6 -3
View File
@@ -156,9 +156,12 @@ test("a unit's name is never an option", async () => {
assert.deepEqual(calls[0].args.slice(-2), ["--", "-x*"]); assert.deepEqual(calls[0].args.slice(-2), ["--", "-x*"]);
}); });
test("the manifest declares no package — the service manager is always there, and networkd declares it too", () => { test("the manifest owns the systemd package — the service manager's own, never a component module's", () => {
const m = JSON.parse(readFileSync(new URL("../module.json", import.meta.url), "utf8")); const m = JSON.parse(readFileSync(new URL("../module.json", import.meta.url), "utf8"));
assert.ok(!(m.resources ?? []).some((r: { type: string }) => r.type === "package")); assert.ok((m.resources ?? []).some((r: { type: string; package?: string }) => r.type === "package" && r.package === "systemd"));
assert.ok(!m.capabilities.includes("package-manager")); assert.ok(m.capabilities.includes("package-manager"));
// networkd is a component of systemd and configures it; it never claims the package.
const networkd = JSON.parse(readFileSync(new URL("../../systemd-networkd/module.json", import.meta.url), "utf8"));
assert.ok(!(networkd.resources ?? []).some((r: { type: string; package?: string }) => r.type === "package" && r.package === "systemd"));
assert.deepEqual(m.claims[0].serves, ["units", "status", "start", "stop", "restart", "enable", "disable", "journal"]); assert.deepEqual(m.claims[0].serves, ["units", "status", "start", "stop", "restart", "enable", "disable", "journal"]);
}); });