Files
mesh-controller/internal/catalogue/files_test.go
T

91 lines
3.7 KiB
Go

package catalogue
import (
"encoding/json"
"strings"
"testing"
)
// issue 900, novox/hq ADR 0394 §1: node-files is a node seat whose verbs say the commands they replace.
func TestNodeFilesIsANodeSeatWithEveryVerbOfADR0394(t *testing.T) {
s, ok := SeatNamed(FilesSeat)
if !ok {
t.Fatalf("the mesh defines no seat %s", FilesSeat)
}
if s.Scope != ScopeNode || s.Delivers != "" || !strings.Contains(s.Decision, "ADR 0394") {
t.Errorf("%s: scope %q, delivers %q, decision %q", FilesSeat, s.Scope, s.Delivers, s.Decision)
}
have := map[string]bool{}
replaced := map[string]string{}
for _, v := range s.Serves {
have[v.Name] = true
if v.Optional {
t.Errorf("%s.%s is optional", FilesSeat, v.Name)
}
if len(v.Replaces) == 0 {
t.Errorf("%s.%s says nothing it replaces", FilesSeat, v.Name)
}
for _, c := range v.Replaces {
replaced[c] = v.Name
}
}
for _, name := range []string{"stat", "readlink", "list", "read", "search", "account", "write", "copy", "move",
"delete", "mkdir", "chmod", "chown", "trash", "restore"} {
if !have[name] {
t.Errorf("%s serves no verb %s", FilesSeat, name)
}
}
for command, verb := range map[string]string{"cat": "read", "tee": "write", "cp": "copy", "mv": "move",
"rm": "delete", "mkdir -p": "mkdir", "chmod": "chmod", "chgrp": "chown"} {
if replaced[command] != verb {
t.Errorf("%q is replaced by %q, want %s.%s", command, replaced[command], FilesSeat, verb)
}
}
}
// issue 900, ADR 0394 §2: a holder of node-files runs as the tool runner's account, so it declares no runs-as.
func TestAHolderOfNodeFilesDeclaringRunsAsIsRefused(t *testing.T) {
p := FilesHolderProblems(Manifest{Module: "files", RunsAs: "mesh-files", Claims: []Claim{{Name: FilesSeat}}})
if len(p) != 1 || !strings.Contains(p[0], "0394") || !strings.Contains(p[0], "runs-as") {
t.Errorf("a holder declaring runs-as was not refused: %v", p)
}
if p := FilesHolderProblems(Manifest{Module: "files", Claims: []Claim{{Name: FilesSeat}}}); len(p) != 0 {
t.Errorf("a holder declaring none was refused: %v", p)
}
if p := FilesHolderProblems(Manifest{Module: "other", RunsAs: "x"}); len(p) != 0 {
t.Errorf("a non-holder was judged: %v", p)
}
}
// issue 900, ADR 0394 §4: the holder is told the secret places and the paths modules own on its node.
func TestTheHolderOfNodeFilesIsToldSecretPlacesAndOwnedPaths(t *testing.T) {
files := Manifest{Module: "files", Version: "1", Claims: []Claim{{Name: FilesSeat}},
OwnSecrets: OwnSecrets{"broker": {Path: "/var/lib/files/broker"}}}
host := Manifest{Module: "hostnames", Version: "1", Claims: []Claim{{Name: "node-hostname"}},
Resources: []map[string]any{{"id": "hosts", "type": "file", "path": "/etc/hosts"}}}
app := Manifest{Module: "app", Version: "1",
Resources: []map[string]any{{"id": "conf", "type": "file", "path": "/etc/app/app.conf"}}}
r := Resolution{Node: "anchor", Modules: []Manifest{files, host, app}}
words, err := r.filesWords(files, nil, Rendering{})
if err != nil {
t.Fatal(err)
}
var places []string
if err := json.Unmarshal([]byte(words[ReadsSecretPlaces]), &places); err != nil || len(places) == 0 {
t.Errorf("no secret places: %v %v", err, words)
}
var owned map[string]string
if err := json.Unmarshal([]byte(words[FilesOwnedPaths]), &owned); err != nil {
t.Fatalf("no owned paths: %v (%v)", err, words)
}
if !strings.HasPrefix(owned["/etc/hosts"], "hostnames") {
t.Errorf("/etc/hosts is owned by %q, want hostnames", owned["/etc/hosts"])
}
if !strings.HasPrefix(owned["/etc/app/app.conf"], "app") {
t.Errorf("a placed file is owned by %q, want app", owned["/etc/app/app.conf"])
}
if w, _ := r.filesWords(app, nil, Rendering{}); w[FilesOwnedPaths] != "" {
t.Error("a module not holding node-files is told the owned paths")
}
}