Only a thing built and never run is unassignable #25

Merged
jschoubben merged 1 commits from fix/only-a-build-input-is-unassignable into main 2026-09-14 15:33:03 +00:00
2 changed files with 60 additions and 1 deletions
Showing only changes of commit 25d2fe1308 - Show all commits
+44
View File
@@ -0,0 +1,44 @@
package inventory
import (
"testing"
"github.com/novox/mesh-control/internal/catalogue"
)
// The image every module is compiled on top of is built and never run.
func TestAThingBuiltAndNeverRunIsABuildInput(t *testing.T) {
m := catalogue.Manifest{
Module: "mesh-tools",
Build: &catalogue.Build{Artifacts: []catalogue.Artifact{{Name: "runtime", Kind: "image"}}},
}
if !IsBuildInput(m) {
t.Fatal("a module that builds an artifact and places nothing is assignable, so `assign` " +
"succeeds and the machine is sent a declaration containing nothing of it")
}
}
// The private network declares no resources either, and is assigned to every machine that has to
// reach another one.
//
// **This is the one that matters.** Reading "no resources" as "runs nowhere" refused it, and a
// four-machine bed stopped dead at the first assignment — the control plane computes its resources
// when it composes a declaration, so there is nothing in its manifest to see.
func TestTheMeshsOwnNetworkIsNotABuildInput(t *testing.T) {
if IsBuildInput(catalogue.Manifest{Module: "networking"}) {
t.Fatal("the private network was refused as a thing that runs nowhere; nothing could " +
"then reach anything else")
}
}
// And an ordinary module that both builds and runs is assignable, which is most of them.
func TestAModuleThatBuildsAndRunsIsAssignable(t *testing.T) {
m := catalogue.Manifest{
Module: "postgres",
Build: &catalogue.Build{Artifacts: []catalogue.Artifact{{Name: "runtime", Kind: "image"}}},
Resources: []map[string]any{{"id": "server", "type": "container"}},
}
if IsBuildInput(m) {
t.Fatal("a module that builds something and also runs it was refused")
}
}
+16 -1
View File
@@ -906,7 +906,7 @@ func (i *Inventory) runsSomewhere(ctx context.Context, module string) error {
// fault and refusing the assignment here would report it as the wrong one.
return nil
}
if m.Computed != "" || len(m.Resources) > 0 {
if !IsBuildInput(m) {
return nil
}
return fmt.Errorf(
@@ -914,3 +914,18 @@ func (i *Inventory) runsSomewhere(ctx context.Context, module string) error {
"builds and other modules are built on top of, not something a machine runs — "+
"`module list` shows what it produces", module)
}
// IsBuildInput reports whether a module exists to be built and never to be run.
//
// **The signal is that it builds something and places nothing** — not merely that it declares no
// resources. Those are different, and confusing them refused a module the mesh itself ships: the
// private network declares no resources either, because the control plane computes them when it
// composes a machine's declaration, and it is assigned to every machine that has to reach another
// one. Refusing it stopped a four-machine bed dead.
//
// Its own function because it is a judgement rather than a lookup, and a judgement with a wrong
// answer this expensive should be testable without a database.
func IsBuildInput(m catalogue.Manifest) bool {
builds := m.Build != nil && len(m.Build.Artifacts) > 0
return builds && m.Computed == "" && len(m.Resources) == 0
}