Files
mesh-host/internal/apply/runtime_roots_more_test.go
T
jochen ff2553f4db
mesh/merge-gate pass: builds mesh-host → ace, g14, novox, shanks; no bus step; every machine composes with the change as it did without (4 of 4 compose)
mesh/repo-check pass: its merge-check.sh passed
mesh/delivery superseded: a newer head of the same pull request
Ask the running runtimes where they keep their data, and read every form a unit says it in
The third review of #64 (hq issue 339): an ExecStart continued over lines, a
quoted path, a variable from Environment= or EnvironmentFile= across the unit
and its drop-ins, dockerd's --config-file and podman's TOML literal strings
each hid a data root from the guard. The running runtimes are now asked first
(docker info, podman info) on a runner of the guard's own, and the files are
read beside them in all those forms.
2026-10-09 01:22:11 +02:00

63 lines
2.5 KiB
Go

package apply
import (
"context"
"errors"
"os"
"path/filepath"
"strings"
"testing"
)
// The forms a runtime's data root is said in (novox/hq issue 339, the third review): an ExecStart continued over
// lines, single quotes, a variable from Environment= or EnvironmentFile=, dockerd's --config-file, and TOML literal
// strings in podman's storage.conf. And the running runtimes are asked first: they say where they really keep it.
func TestEveryFormOfADataRootIsRead(t *testing.T) {
dir := t.TempDir()
write := func(name, content string) string {
t.Helper()
p := filepath.Join(dir, name)
if err := os.MkdirAll(filepath.Dir(p), 0o755); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(p, []byte(content), 0o644); err != nil {
t.Fatal(err)
}
return p
}
envFile := write("docker.env", "DOCKER_ROOT=/data/from-env-file\n")
other := write("other-daemon.json", `{"data-root": "/data/from-config-file"}`)
unit := write("lib/docker.service", "[Service]\nEnvironment=\"ROOT=/data/from-env\"\nEnvironmentFile=-"+envFile+"\n"+
"ExecStart=/usr/bin/dockerd \\\n -H fd:// \\\n --data-root '/data/continued'\n")
dropIn := write("etc/docker.service.d/root.conf", "[Service]\nExecStart=\nExecStart=/usr/bin/dockerd --data-root=$ROOT "+
"--graph=${DOCKER_ROOT} --config-file "+other+"\n")
storage := write("containers/storage.conf", "[storage]\ngraphroot = '/data/podman-literal'\n")
before := runtimeConfigs
runtimeConfigs = runtimeFiles{daemonJSON: filepath.Join(dir, "none.json"), units: []string{unit},
dropInDirs: []string{filepath.Dir(dropIn)}, storageConf: storage}
t.Cleanup(func() { runtimeConfigs = before })
roots := strings.Join(readRuntimeRoots(context.Background(), nil), " ")
for _, want := range []string{"/data/continued", "/data/from-env", "/data/from-env-file", "/data/from-config-file",
"/data/podman-literal"} {
if !strings.Contains(roots+" ", want+" ") {
t.Errorf("%s was not read: %s", want, roots)
}
}
// Asked of the running runtimes first; what they answer counts beside the files.
asked := func(_ context.Context, name string, args ...string) (string, error) {
switch name {
case "docker":
return "/srv/docker-live\n", nil
case "podman":
return "", errors.New("podman: not installed")
}
return "", errors.New("unexpected")
}
roots = strings.Join(readRuntimeRoots(context.Background(), asked), " ")
if !strings.Contains(roots, "/srv/docker-live") || !strings.Contains(roots, "/data/continued") {
t.Errorf("the running runtime's answer, or the files beside it, are missing: %s", roots)
}
}