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 covered: a later merge that contains it was delivered: novox/mesh-host@7c046a8a1d84 (merged as d28ca959 into main, walk plan-17915049347305…
The review of #64 asked for containerd's tree, dockerd's --data-root from its unit and drop-ins, and podman's graphroot to be refused like docker's own (hq issue 339); and the controller now tells a directory a send found from one found before it, which needs the time it was first found kept across applies instead of the time of the last apply. A hand-over now names the resource it was for, so it lapses if another declaration points at the path.
139 lines
5.5 KiB
Go
139 lines
5.5 KiB
Go
package apply
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/novox/mesh-host/internal/store"
|
|
)
|
|
|
|
// A directory used as found is never quiet, and a person at the machine can hand it over (novox/hq issue 339).
|
|
func TestAFoundDirectoryIsSaidAndCanBeHandedOver(t *testing.T) {
|
|
dir := t.TempDir()
|
|
found := filepath.Join(dir, "found")
|
|
if err := os.Mkdir(found, 0o700); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
decl := `{"id":"notes.data","type":"directory","path":"` + found + `","mode":"0755"}`
|
|
var said []string
|
|
log := func(line string) { said = append(said, line) }
|
|
_, state, err := Apply(context.Background(), archHost(t), declare(t, decl), store.State{}, store.OriginDeclared,
|
|
noServices, log, nil)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !strings.Contains(strings.Join(said, "\n"), "WARNING notes.data") {
|
|
t.Fatalf("the apply did not warn of a directory used as found: %q", said)
|
|
}
|
|
if a, _ := state.Find("notes.data"); !a.AsFound || !strings.Contains(a.Declared, "755") {
|
|
t.Fatalf("the record does not say what was declared: %+v", a)
|
|
}
|
|
// Said again at the next apply: a warning once is a warning missed.
|
|
said = nil
|
|
if _, state, err = Apply(context.Background(), archHost(t), declare(t, decl), state, store.OriginDeclared,
|
|
noServices, log, nil); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !strings.Contains(strings.Join(said, "\n"), "WARNING notes.data") {
|
|
t.Fatalf("the next apply did not warn again: %q", said)
|
|
}
|
|
|
|
// Handed over: the next apply gives it the declared mode and it is the mesh's.
|
|
before := HandedOver
|
|
HandedOver = func() map[string]bool { return map[string]bool{handOverKey("notes.data", found): true} }
|
|
t.Cleanup(func() { HandedOver = before })
|
|
if _, state, err = Apply(context.Background(), archHost(t), declare(t, decl), state, store.OriginDeclared,
|
|
noServices, nil, nil); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if info, _ := os.Stat(found); info.Mode().Perm() != 0o755 {
|
|
t.Fatalf("a directory handed over was not given its declared mode: %o", info.Mode().Perm())
|
|
}
|
|
if a, _ := state.Find("notes.data"); a.AsFound {
|
|
t.Fatal("a directory handed over is still recorded as found")
|
|
}
|
|
}
|
|
|
|
// The review's additions to the guard: the spool, /opt, the container runtimes' data wherever the runtime keeps
|
|
// it, and an account's .ssh as an access or a mount, or as a directory anywhere but its own home.
|
|
func TestTheRuntimesDataAndAnySSHAreRefused(t *testing.T) {
|
|
cfg := filepath.Join(t.TempDir(), "daemon.json")
|
|
if err := os.WriteFile(cfg, []byte(`{"data-root":"/storage/docker"}`), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
before := runtimeConfigs
|
|
runtimeConfigs = runtimeFiles{daemonJSON: cfg}
|
|
t.Cleanup(func() { runtimeConfigs = before })
|
|
for _, kind := range []placing{placingDirectory, placingAccess, placingMount} {
|
|
for _, path := range []string{"/var/spool/cron", "/opt/app", "/var/lib/docker/volumes/x",
|
|
"/var/lib/containers/storage", "/storage/docker", "/storage/docker/overlay2"} {
|
|
if err := refusePath(path, kind, "notes", ""); err == nil {
|
|
t.Errorf("%v at %s was taken", kind, path)
|
|
}
|
|
}
|
|
}
|
|
for _, path := range []string{"/srv/backup/.ssh", "/srv/backup/.ssh/keys"} {
|
|
for _, kind := range []placing{placingDirectory, placingAccess, placingMount} {
|
|
if err := refusePath(path, kind, "notes", ""); err == nil {
|
|
t.Errorf("%v at %s was taken", kind, path)
|
|
}
|
|
}
|
|
}
|
|
if err := refusePath("/storage/dockerish", placingAccess, "notes", ""); err != nil {
|
|
t.Errorf("a path beside the data root: %v", err)
|
|
}
|
|
}
|
|
|
|
// When a directory was found is kept from the first apply that found it (novox/hq issue 339): the controller
|
|
// tells a directory a send found from one found before it by that time, so it must not move with every apply.
|
|
func TestWhenADirectoryWasFoundIsKept(t *testing.T) {
|
|
dir := t.TempDir()
|
|
found := filepath.Join(dir, "found")
|
|
if err := os.Mkdir(found, 0o700); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
decl := `{"id":"notes.data","type":"directory","path":"` + found + `","mode":"0755"}`
|
|
_, state, err := Apply(context.Background(), archHost(t), declare(t, decl), store.State{}, store.OriginDeclared,
|
|
noServices, nil, nil)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
first, _ := state.Find("notes.data")
|
|
if first.FoundAt.IsZero() {
|
|
t.Fatal("no time the directory was found")
|
|
}
|
|
time.Sleep(10 * time.Millisecond)
|
|
_, state, err = Apply(context.Background(), archHost(t), declare(t, decl), state, store.OriginDeclared, noServices, nil, nil)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if again, _ := state.Find("notes.data"); !again.FoundAt.Equal(first.FoundAt) {
|
|
t.Fatalf("found at %v, then %v: the time moved with the apply", first.FoundAt, again.FoundAt)
|
|
}
|
|
}
|
|
|
|
// A hand-over is for the resource that was used as found there: another declaration that later points another
|
|
// resource at the same path is not handed anything (novox/hq issue 339).
|
|
func TestAHandOverIsForTheResourceThatAskedForIt(t *testing.T) {
|
|
dir := t.TempDir()
|
|
found := filepath.Join(dir, "found")
|
|
if err := os.Mkdir(found, 0o700); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
before := HandedOver
|
|
HandedOver = func() map[string]bool { return map[string]bool{handOverKey("notes.data", found): true} }
|
|
t.Cleanup(func() { HandedOver = before })
|
|
other := `{"id":"other.data","type":"directory","path":"` + found + `","mode":"0755"}`
|
|
if _, _, err := Apply(context.Background(), archHost(t), declare(t, other), store.State{}, store.OriginDeclared,
|
|
noServices, nil, nil); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if info, _ := os.Stat(found); info.Mode().Perm() != 0o700 {
|
|
t.Fatalf("a hand-over for notes.data gave other.data the directory: mode %o", info.Mode().Perm())
|
|
}
|
|
}
|