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) } }