diff --git a/cmd/mesh-controller/build.go b/cmd/mesh-controller/build.go index 310c9d91..97f69f40 100644 --- a/cmd/mesh-controller/build.go +++ b/cmd/mesh-controller/build.go @@ -5,10 +5,11 @@ import ( "errors" "flag" "fmt" - "github.com/novox/mesh-controller/internal/conditions" "io" "os" + "github.com/novox/mesh-controller/internal/conditions" + "git.novox.be/novox/mesh-sdk/go/catalogue" "github.com/novox/mesh-controller/internal/inventory" ) @@ -127,17 +128,13 @@ type takenBuild struct { carried func() error } -// registerJudged judges a recorded build and registers its module, or says why not. +// registerJudged registers its module, or says why not. func registerJudged(ctx context.Context, inv *inventory.Inventory, j takenBuild) (catalogue.Manifest, error) { manifest, kept := j.manifest, j.kept notRegistered := func(err error) (catalogue.Manifest, error) { return manifest, fmt.Errorf("%s built %s (%s), recorded and not registered: %w", j.by, manifest.Module, short(j.commit), err) } - if err := namesNoInstallation(manifest); err != nil { - return manifest, fmt.Errorf("%s built %s (%s), and the mesh does not register it: %w", - j.by, j.what, short(j.commit), err) - } // **Only from the repository the catalogue builds the module from** (novox/hq ADR 0266): else the trunk // below is the trunk of whatever repository was built, which may be one an agent made — and a module named // `sudo` from it would be what the next push sends. Another repository is the operator's, at the terminal. @@ -150,18 +147,12 @@ func registerJudged(ctx context.Context, inv *inventory.Inventory, j takenBuild) return notRegistered(err) } } - // Then the module is judged against the list the mesh publishes, as every manifest read again is: one naming a - // key that list does not hold, or of another type, is refused here and never enters the catalogue. + // The manifest was judged once, by the indexer, and its verdict taken before this (buildOfKey; ADR 0578 §3). if j.carried != nil { if err := j.carried(); err != nil { return manifest, err } } - if manifest.NamesPredefined() { - if _, err := catalogue.ParseManifest(kept.Manifest); err != nil { - return notRegistered(fmt.Errorf("judged against the list of predefined keys the mesh publishes, %w", err)) - } - } // **A build whose source is unchanged is never a move** (novox/hq issue 280): a rebuild made from // what the build the mesh stands on was made from registers that build's artifacts at the new // commit, so no machine is sent a new digest for a source nobody changed — an image is not @@ -172,7 +163,7 @@ func registerJudged(ctx context.Context, inv *inventory.Inventory, j takenBuild) return manifest, err } if stands != "" && stands != kept.ID && len(raw) > 0 { - if was, err := catalogue.ParseManifest(raw); err == nil && was.Module == manifest.Module { + if was, err := catalogue.Decode(raw); err == nil && was.Module == manifest.Module { fmt.Printf("%s at %s was made from the source %s was: registered with its artifacts, no move\n", manifest.Module, short(j.commit), stands) manifest = was diff --git a/cmd/mesh-controller/check_test.go b/cmd/mesh-controller/check_test.go deleted file mode 100644 index eaa088b5..00000000 --- a/cmd/mesh-controller/check_test.go +++ /dev/null @@ -1,32 +0,0 @@ -package main - -import ( - "strings" - - "testing" - - "git.novox.be/novox/mesh-sdk/go/catalogue" -) - -func TestRegistrationRefusesADefinitionNamingAnInstallation(t *testing.T) { - // novox/hq ADR 0155: the check moves to registration once the catalogue passes it. Both - // ways in — `module add` and a build's result — go through this, and a name declared on - // purpose passes with its reason. - named := catalogue.Manifest{Module: "idp", Resources: []map[string]any{ - {"id": "server", "type": "container", "image": "x@sha256:aa", - "env": map[string]any{"KC_HOSTNAME": "https://login.mesh-one.be"}}, - }} - err := namesNoInstallation(named) - if err == nil || !strings.Contains(err.Error(), "login.mesh-one.be") || - !strings.Contains(err.Error(), catalogue.NamesOnPurpose) { - t.Fatalf("a definition naming an installation is refused with the name and the way out; got %v", err) - } - meant := catalogue.Manifest{Module: "site", Resources: []map[string]any{ - {"id": "server", "type": "container", "image": "registry.mesh-one.be/org/site@sha256:cc", - catalogue.NamesOnPurpose: map[string]any{ - "registry.mesh-one.be": "built outside the mesh until its repository is a build source here"}}, - }} - if err := namesNoInstallation(meant); err != nil { - t.Fatalf("a name declared on purpose passes; got %v", err) - } -} diff --git a/cmd/mesh-controller/key_takein_test.go b/cmd/mesh-controller/key_takein_test.go index 6ea232ee..36e31561 100644 --- a/cmd/mesh-controller/key_takein_test.go +++ b/cmd/mesh-controller/key_takein_test.go @@ -171,6 +171,8 @@ func TestAKeyIsTakenInOnTheIndexersVerdictAndNeverJudgedHere(t *testing.T) { holds string }{ {"an unread word", `{"module":"x","version":"1","not-a-word-yet":true,` + tail, false, ""}, + {"a fallback to a predefined key, no list at hand", `{"module":"x","version":"1","config":{"font-size":{"type":"number", + "description":"size","default":10,"predefined":"font-size"}},` + tail, false, ""}, {"no verdict is accepted", `{"module":"x","version":"1",` + tail, false, ""}, {"a refusal is held and named", `{"module":"x","version":"1",` + tail, true, "names a seat nothing declares"}, } { diff --git a/cmd/mesh-controller/modules.go b/cmd/mesh-controller/modules.go index 87eefe0c..8ae34c2e 100644 --- a/cmd/mesh-controller/modules.go +++ b/cmd/mesh-controller/modules.go @@ -8,7 +8,6 @@ import ( "fmt" "net" "os" - "path/filepath" "slices" "sort" "strings" @@ -102,17 +101,15 @@ func moduleCommand(ctx context.Context, args []string) error { if err != nil { return err } - // A manifest handed over by hand takes each template's text from the tree beside it (novox/hq ADR 0349 §2). - if m, err = catalogue.WithTemplatesFrom(m, filepath.Dir(positionals[0])); err != nil { - return err + // A manifest handed over by hand is not judged here (ADR 0578 §3): a templated one has no build to read its + // texts from, so it is refused by name. + if p := catalogue.HeldTemplateProblem(m); p != "" { + return errors.New(p) } from, err := whereItComesFrom(*repo, *ref, *commit, *path, *self) if err != nil { return err } - if err := namesNoInstallation(m); err != nil { - return err - } if err := inv.RegisterModule(ctx, m, from); err != nil { return err } @@ -1388,29 +1385,6 @@ func whereItComesFrom(repository, ref, commit, path string, self bool) (inventor return from, nil } -// namesNoInstallation is the mesh refusing a definition that names an installation, at the moment -// it would enter the catalogue (novox/hq ADR 0112, ADR 0155). `module check` says the same thing -// earlier, where the author is; this is the last moment the mesh can still say no, and a -// definition that got past the check — written elsewhere, or checked by nobody — is refused here -// in the same words. A name meant on purpose is declared with its reason and passes. -func namesNoInstallation(m catalogue.Manifest) error { - if problems := catalogue.TrustProblems(m); len(problems) > 0 { - return fmt.Errorf("%s", strings.Join(problems, "; ")) - } - // And a module that declares a setting names the keys of its mergeable files (novox/hq ADR 0326 - // §3, issue 574): judged where a definition is written, never where a stored build is read again. - if problems := catalogue.WrittenSettingsProblems(m); len(problems) > 0 { - return fmt.Errorf("%s", strings.Join(problems, "; ")) - } - named := catalogue.InstallationProblems(m) - if len(named) == 0 { - return nil - } - return fmt.Errorf("%s names an installation, and a definition names none — declare a name meant "+ - "on purpose under %s with its reason, or take it out:\n - %s", - m.Module, catalogue.NamesOnPurpose, strings.Join(named, "\n - ")) -} - // seatClaimed is one seat a module claims, as its runtime needs it: the name, the scope (a // node-scoped seat's verb carries the machine, design 33 §4) and the verbs the seat promises. type seatClaimed struct { diff --git a/cmd/mesh-controller/written_settings_test.go b/cmd/mesh-controller/written_settings_test.go deleted file mode 100644 index f781cd06..00000000 --- a/cmd/mesh-controller/written_settings_test.go +++ /dev/null @@ -1,32 +0,0 @@ -package main - -import ( - "os" - "path/filepath" - "strings" - "testing" - - "git.novox.be/novox/mesh-sdk/go/catalogue" -) - -// ADR 0326 §3 is judged where a definition is written (novox/hq issue 574): namesNoInstallation, which `module add`, a build taken in and the merge gate's registration run. -func TestWhereADefinitionIsWrittenADeclaringModuleNamesItsFilesKeys(t *testing.T) { - const silent = `{"module":"mail-client","version":"1", - "settings":{"prefs":{"kind":"preference","default":"// none","why":"its own defaults until a machine names one"}}, - "resources":[ - {"id":"user-js","type":"file","path":"/var/lib/mail-client/user.js","mode":"0644","content":"${setting:prefs}\n"}, - {"id":"accounts","type":"file","path":"/var/lib/mail-client/accounts.json","mode":"0600","merge":"json", - "content":"{}\n"%s}]}` - dir := t.TempDir() - bad := filepath.Join(dir, "bad.json") - os.WriteFile(bad, []byte(strings.Replace(silent, "%s", "", 1)), 0o600) - - raw, _ := os.ReadFile(bad) - m, err := catalogue.ParseManifest(raw) - if err != nil { - t.Fatalf("reading it is not where it is judged: %v", err) - } - if err := namesNoInstallation(m); err == nil || !strings.Contains(err.Error(), "names no takes-settings") { - t.Fatalf("registration passed it: %v", err) - } -}