Adoption mode: a node in use is adopted before it is converged (hq ADR 0100–0103) #20

Merged
jschoubben merged 52 commits from feat/adoption-mode into main 2026-09-22 19:01:47 +00:00
2 changed files with 38 additions and 1 deletions
Showing only changes of commit bd3fd17ad8 - Show all commits
+21 -1
View File
@@ -109,7 +109,7 @@ func lookBefore(ctx context.Context, sys system.System, d *declaration.Declarati
switch {
case src == "":
case strings.HasPrefix(src, "/"):
if present(src) && !recordedPath(known, src) {
if !systemPath(src) && present(src) && !recordedPath(known, src) {
seen["path:"+src] = true
}
default:
@@ -146,6 +146,26 @@ func recordedPath(known store.State, path string) bool {
return false
}
// systemPath is whether a bind-mount source is the machine's own plumbing — the runtime's socket,
// the kernel's filesystems, the devices, the clock — which every machine has and no predecessor's
// data lives in. Mounting it shares nothing that was found.
func systemPath(src string) bool {
clean := filepath.Clean(src)
for _, exact := range []string{"/etc/localtime", "/etc/timezone", "/etc/hosts", "/etc/resolv.conf",
"/etc/machine-id", "/etc/passwd", "/etc/group"} {
if clean == exact {
return true
}
}
for _, under := range []string{"/run", "/var/run", "/sys", "/proc", "/dev", "/usr/share/zoneinfo",
"/etc/ssl", "/etc/ca-certificates", "/etc/pki", "/lib/modules", "/usr/lib/modules"} {
if clean == under || strings.HasPrefix(clean, under+"/") {
return true
}
}
return false
}
// mountSource is what a volume mapping mounts: a path on the machine, or a named volume. Empty for
// an anonymous volume, which mounts nothing that could already be there.
func mountSource(mapping string) string {
+17
View File
@@ -754,3 +754,20 @@ func TestAUserFoundOnTheMachineKeepsItsShellAndGroups(t *testing.T) {
}
}
}
func TestMountingTheMachinesOwnPlumbingIsNotFoundData(t *testing.T) {
// The runtime's socket, the kernel's filesystems and the clock are on every machine; a
// container mounting them shares nothing a predecessor kept (novox/hq ADR 0103).
dir := t.TempDir()
m := &machine{containers: map[string]*fakeContainer{}}
report, state := applyAdopted(t, adopted(t, untaken("hello-web.server"),
`{"id":"hello-web.server","type":"container","name":"hello-web","image":"`+pinned+`",
"volumes":["/var/run/docker.sock:/var/run/docker.sock","/etc/localtime:/etc/localtime:ro",
"/proc/cpuinfo:/host/cpuinfo:ro","/dev/null:/data/null"]}`), store.State{}, m, dir)
if o := outcomeOf(report, "hello-web.server"); o.Action != "created" {
t.Errorf("a container mounting only system paths was not created: %+v", o)
}
if len(state.Held) != 0 {
t.Errorf("held: %+v", state.Held)
}
}