ADR 0328 supersedes ADR 0325: shared data is a library with one home, kept usable by its group rather than by ACL entries. The engine now makes each library's group and each module's user in its libraries' groups; keeps a library's root and requested sub-paths in its group with group write and setgid on its home, making missing sub-paths as the root is; waits for the operator's word before touching a root that holds data, and on the take act walks it by descriptor (no link, same filesystem, bounded and resumed, files with other names left); holds the containers of a library whose disk or mount is not there; and puts the tool runner's account in the group. The ACL keeping, mask repair and watch are gone; an access is again as before ADR 0325.
57 lines
2.2 KiB
Go
57 lines
2.2 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/novox/mesh-host/internal/apply"
|
|
"github.com/novox/mesh-host/internal/declaration"
|
|
"github.com/novox/mesh-host/internal/link"
|
|
)
|
|
|
|
// A library whose root holds data never taken is said waiting with one access wait: the access `library:<name>`, the
|
|
// part its name, words with no path, the filesystem's name, and reason keep (novox/hq ADR 0328 §8); one whose root
|
|
// is absent waits with reason disk (§9). Neither carries a module.
|
|
func TestALibrarySaysItsWaitWithoutWordsToParse(t *testing.T) {
|
|
was := apply.Libraries
|
|
apply.Libraries = apply.NewLibraryMemory()
|
|
defer func() { apply.Libraries = was }()
|
|
dir := t.TempDir()
|
|
root := filepath.Join(dir, "media")
|
|
if err := os.MkdirAll(filepath.Join(root, "a film"), 0o755); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
d, err := declaration.Parse([]byte(`{"declaration":1,"groups":[{"name":"mesh-media","gid":62000},` +
|
|
`{"name":"mesh-books","gid":62001}],"libraries":[` +
|
|
`{"library":"media","root":"` + root + `","group":"mesh-media","gid":62000,"home":true},` +
|
|
`{"library":"books","root":"` + filepath.Join(dir, "books") + `","group":"mesh-books","gid":62001,"home":true}],` +
|
|
`"owns_nothing":true,"resources":[]}`))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
j := newLibraryJudge()
|
|
j.set(d, nil)
|
|
vs, _ := j.look(time.Now())
|
|
if len(vs) != 2 {
|
|
t.Fatalf("the libraries are not said: %+v", vs)
|
|
}
|
|
books, media := vs[0], vs[1]
|
|
if media.Kind != link.KindLibrary || media.Resource != "library:media" || media.Module != "" ||
|
|
media.State != link.StateWaiting || len(media.AccessWaits) != 1 {
|
|
t.Fatalf("a library holding data is not said waiting: %+v", media)
|
|
}
|
|
raw, _ := json.Marshal(media.AccessWaits[0])
|
|
want := `{"kind":"access","access":"library:media","part":"media","what":"let the mesh keep the library media",` +
|
|
`"placed":"` + media.AccessWaits[0].Placed + `","reason":"keep"}`
|
|
if string(raw) != want || !strings.HasPrefix(media.AccessWaits[0].Placed, "fs-") {
|
|
t.Fatalf("the wait reads %s", raw)
|
|
}
|
|
if strings.Contains(media.Reason, dir) || len(books.AccessWaits) != 1 || books.AccessWaits[0].Reason != link.WaitDisk {
|
|
t.Fatalf("a missing root does not wait for its disk, or a reason names a path: %+v %+v", books, media)
|
|
}
|
|
}
|