The fourth review (hq issue 339): the safe reading of a file that asks for a setting and does not say is that root or a consumer trusts it, so its settings are the terminal's; `"trusted": false` is the opt-out. With that, nothing unsafe is left to refuse: `module check` lists and counts the unmarked files and never refuses them.
73 lines
3.3 KiB
Go
73 lines
3.3 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/novox/mesh-controller/internal/catalogue"
|
|
)
|
|
|
|
// Every catalogue module that runs something long-lived declares how it is ready (novox/hq ADR 0240 rule
|
|
// 8): `module check` warns and counts the undeclared before the date, and refuses them from it.
|
|
func TestModuleCheckCountsTheUndeclaredAndRefusesThemFromTheDate(t *testing.T) {
|
|
dir := t.TempDir()
|
|
digest := "@sha256:" + strings.Repeat("a", 64)
|
|
path := filepath.Join(dir, "module.json")
|
|
os.WriteFile(path, []byte(`{"module":"web","listens":[{"name":"web","port":80,"from":"mesh"}],"resources":[
|
|
{"id":"server","type":"container","name":"web","image":"registry.example/web`+digest+`","ports":["80"],
|
|
"health":{"kind":"http","endpoint":"web"}},
|
|
{"id":"worker","type":"container","name":"web-worker","image":"registry.example/web`+digest+`"},
|
|
{"id":"seed","type":"container","name":"web-seed","image":"registry.example/web`+digest+`","run-once":true}]}`), 0o600)
|
|
defer func() { checkNow = time.Now }()
|
|
|
|
checkNow = func() time.Time { return catalogue.HealthRequiredFrom.Add(-time.Hour) }
|
|
var out bytes.Buffer
|
|
if err := moduleCheck([]string{path}, &out); err != nil {
|
|
t.Fatalf("refused before the date: %v\n%s", err, out.String())
|
|
}
|
|
for _, want := range []string{"ready: server by http / on web every 30s", "WARNING: worker stay(s) up",
|
|
catalogue.HealthRequiredFrom.Format("2006-01-02"), UndeclaredHealthLine + " 1"} {
|
|
if !strings.Contains(out.String(), want) {
|
|
t.Errorf("the check does not say %q:\n%s", want, out.String())
|
|
}
|
|
}
|
|
|
|
checkNow = func() time.Time { return catalogue.HealthRequiredFrom }
|
|
out.Reset()
|
|
if err := moduleCheck([]string{path}, &out); err == nil {
|
|
t.Fatalf("a long-running resource without health passed after the date:\n%s", out.String())
|
|
}
|
|
if !strings.Contains(out.String(), "web: worker stays up and does not say how it is ready") {
|
|
t.Errorf("the refusal does not name the resource:\n%s", out.String())
|
|
}
|
|
}
|
|
|
|
// A file that asks for a setting without saying whether it is trusted counts as trusted (novox/hq issue 339):
|
|
// `module check` lists and counts it, and never refuses it — there is nothing unsafe to refuse.
|
|
func TestModuleCheckListsUnmarkedFilesAndNeverRefusesThem(t *testing.T) {
|
|
dir := t.TempDir()
|
|
path := filepath.Join(dir, "module.json")
|
|
os.WriteFile(path, []byte(`{"module":"power","resources":[
|
|
{"id":"logind","type":"file","path":"/etc/systemd/logind.conf.d/power.conf","mode":"0644","trusted":true,
|
|
"content":"HandleLidSwitch=${setting:lid}\n"},
|
|
{"id":"note","type":"file","path":"/var/lib/power/note","mode":"0644","content":"${setting:greeting}\n"}]}`), 0o600)
|
|
defer func() { checkNow = time.Now }()
|
|
for _, at := range []time.Time{time.Date(2026, 10, 1, 0, 0, 0, 0, time.UTC), time.Date(2036, 1, 1, 0, 0, 0, 0, time.UTC)} {
|
|
checkNow = func() time.Time { return at }
|
|
var out bytes.Buffer
|
|
if err := moduleCheck([]string{path}, &out); err != nil {
|
|
t.Fatalf("refused at %v: %v\n%s", at, err, out.String())
|
|
}
|
|
for _, want := range []string{"note ask(s) for a setting and do(es) not say whether it is trusted, so it counts as trusted",
|
|
UnsaidTrustLine + " 1"} {
|
|
if !strings.Contains(out.String(), want) {
|
|
t.Errorf("the check does not say %q:\n%s", want, out.String())
|
|
}
|
|
}
|
|
}
|
|
}
|