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.
63 lines
2.5 KiB
Go
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)
|
|
}
|
|
}
|