The gate refuses the old tool-container pattern spreading, not a rebuild of what already stands (hq to-be 38 WP2.4, amended by WP3)
Once the runtime module is registered, a module serving tools from a container built on the runtime's image is refused at registration — as written, including every rebuild of the thirty-odd modules already in that shape, from the day the runtime arrives until WP4 onward moves each one. That would stop the catalogue's whole pipeline to make a point the record already makes. Now a module already registered in that shape — judged from the manifest the catalogue holds and what its newest build stood on, the same two things a new registration is judged by — is rebuilt as before; a module new to the catalogue in that shape, or one that had moved to a bundle and comes back, is refused naming the record.
This commit is contained in:
@@ -66,11 +66,15 @@ func (s Source) Current() bool {
|
||||
// gains a requirement, a claim, a resource. What matters is that the change is visible the next
|
||||
// time a node is resolved, which it is.
|
||||
func (i *Inventory) RegisterModule(ctx context.Context, m catalogue.Manifest, from Source) error {
|
||||
// **Once the node's tool runtime is in the catalogue, the pattern it retires is refused**
|
||||
// **Once the node's tool runtime is in the catalogue, the pattern it retires may not spread**
|
||||
// (novox/hq ADR 0175, to-be 38 WP2.4): a module serving its tools from a container built on the
|
||||
// runtime's image. Refused at registration, by name, because this is the mechanism that keeps
|
||||
// the old pattern from returning by habit — a rebuild of an unmoved module stops here with the
|
||||
// record that says why. Before the runtime exists the pattern is accepted as it always was.
|
||||
// runtime's image. Refused at registration, by name, for a module that is new to the catalogue
|
||||
// or that was registered in another shape — the mechanism that keeps the old pattern from
|
||||
// returning by habit. **Not refused for a module already registered in that shape**: the
|
||||
// catalogue holds some thirty of them the day the runtime arrives, each moves to a bundle in
|
||||
// its own change (to-be 38 WP4 onward), and a gate that refused every rebuild of every unmoved
|
||||
// module in the meantime would stop the whole pipeline to make a point the record already makes.
|
||||
// Before the runtime exists the pattern is accepted as it always was.
|
||||
if m.Module != catalogue.RuntimeModule {
|
||||
if why := catalogue.ToolContainerOnTheRuntime(m, from.Against); why != "" {
|
||||
runtime, err := i.hasModule(ctx, catalogue.RuntimeModule)
|
||||
@@ -78,7 +82,13 @@ func (i *Inventory) RegisterModule(ctx context.Context, m catalogue.Manifest, fr
|
||||
return err
|
||||
}
|
||||
if runtime {
|
||||
return fmt.Errorf("%s is not registered: %s", m.Module, why)
|
||||
already, err := i.registeredInThatShape(ctx, m.Module)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !already {
|
||||
return fmt.Errorf("%s is not registered: %s", m.Module, why)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -110,6 +120,26 @@ func (i *Inventory) RegisterModule(ctx context.Context, m catalogue.Manifest, fr
|
||||
return err
|
||||
}
|
||||
|
||||
// registeredInThatShape is whether the catalogue already holds this module as a tools container on
|
||||
// the runtime's image — judged from the manifest it holds and what that module's newest build stood
|
||||
// on, the same two things the gate judges a new registration by. False for a module the catalogue
|
||||
// does not hold.
|
||||
func (i *Inventory) registeredInThatShape(ctx context.Context, name string) (bool, error) {
|
||||
held, err := i.Catalogue(ctx)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
stored, has := held[name]
|
||||
if !has {
|
||||
return false, nil
|
||||
}
|
||||
against, err := i.BuiltAgainst(ctx)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return catalogue.ToolContainerOnTheRuntime(stored, against[name]) != "", nil
|
||||
}
|
||||
|
||||
// hasModule is whether the catalogue holds a module of that name.
|
||||
func (i *Inventory) hasModule(ctx context.Context, name string) (bool, error) {
|
||||
var one int
|
||||
|
||||
@@ -688,29 +688,58 @@ func TestRegisteringWithoutProvenanceKeepsTheSeat(t *testing.T) {
|
||||
|
||||
// Once the node's tool runtime is in the catalogue, a module serving its tools from a container
|
||||
// built on the runtime's image is refused at registration, naming the record (novox/hq ADR 0175,
|
||||
// to-be 38 WP2.4). Before, it is accepted as it always was — so a mesh converts in the order the
|
||||
// design says and nothing is refused before there is anything to move to.
|
||||
// to-be 38 WP2.4) — for a module new to the catalogue or one that had moved away from it; a module
|
||||
// already standing in that shape is rebuilt as before, so the catalogue's pipeline keeps running
|
||||
// while each moves (WP3's amendment). Before the runtime, it is accepted as it always was — so a
|
||||
// mesh converts in the order the design says and nothing is refused before there is anything to
|
||||
// move to.
|
||||
func TestAToolContainerIsRefusedOnceTheRuntimeIsRegistered(t *testing.T) {
|
||||
inv := fresh(t)
|
||||
ctx := t.Context()
|
||||
filter := catalogue.Manifest{Module: "nftables", Version: "1", Tools: []string{"firewall_rules"},
|
||||
Resources: []map[string]any{{"id": "runtime", "type": "container", "name": "mesh-nftables"}}}
|
||||
stoodOn := []string{catalogue.ArtifactStoreScheme + "mesh-tools/runtime@sha256:" + strings.Repeat("d", 64)}
|
||||
|
||||
if err := inv.RegisterModule(t.Context(), filter, Source{Repository: "/r", Against: stoodOn}); err != nil {
|
||||
// Before the runtime exists the old pattern is accepted as it always was — and built, which is
|
||||
// how the catalogue comes to know what the module stood on.
|
||||
if err := inv.RegisterModule(ctx, filter, Source{Repository: "/r", Against: stoodOn}); err != nil {
|
||||
t.Fatalf("before the runtime exists the old pattern is accepted: %v", err)
|
||||
}
|
||||
runtime := catalogue.Manifest{Module: catalogue.RuntimeModule, Version: "1"}
|
||||
if err := inv.RegisterModule(t.Context(), runtime, Source{Repository: "/r"}); err != nil {
|
||||
built := aBuild("nf1", "nftables", "")
|
||||
built.Against = stoodOn
|
||||
if err := inv.RecordBuild(ctx, built); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err := inv.RegisterModule(t.Context(), filter, Source{Repository: "/r", Against: stoodOn})
|
||||
if err == nil || !strings.Contains(err.Error(), "ADR 0175") {
|
||||
t.Fatalf("the old pattern was registered beside the runtime: %v", err)
|
||||
runtime := catalogue.Manifest{Module: catalogue.RuntimeModule, Version: "1"}
|
||||
if err := inv.RegisterModule(ctx, runtime, Source{Repository: "/r"}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// A module that moved its tools to a bundle registers.
|
||||
|
||||
// **A module already registered in that shape is rebuilt without complaint** (to-be 38 WP2.4 as
|
||||
// amended by WP3): some thirty of them stand the day the runtime arrives, and each moves in its
|
||||
// own change. The gate is against the pattern spreading, not against the pipeline running.
|
||||
if err := inv.RegisterModule(ctx, filter, Source{Repository: "/r", Against: stoodOn}); err != nil {
|
||||
t.Fatalf("a rebuild of a module that already had the pattern was refused: %v", err)
|
||||
}
|
||||
// A module new to the catalogue in that shape is refused, naming the record.
|
||||
newcomer := filter
|
||||
newcomer.Module = "lamp"
|
||||
err := inv.RegisterModule(ctx, newcomer, Source{Repository: "/r", Against: stoodOn})
|
||||
if err == nil || !strings.Contains(err.Error(), "ADR 0175") {
|
||||
t.Fatalf("a new module in the old pattern was registered beside the runtime: %v", err)
|
||||
}
|
||||
// And a module that had moved its tools to a bundle may not come back to a container.
|
||||
moved := filter
|
||||
moved.Resources = nil
|
||||
if err := inv.RegisterModule(t.Context(), moved, Source{Repository: "/r", Against: stoodOn}); err != nil {
|
||||
if err := inv.RegisterModule(ctx, moved, Source{Repository: "/r", Against: stoodOn}); err != nil {
|
||||
t.Fatalf("a module whose tools are a bundle was refused: %v", err)
|
||||
}
|
||||
unbuilt := aBuild("nf2", "nftables", "")
|
||||
if err := inv.RecordBuild(ctx, unbuilt); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = inv.RegisterModule(ctx, filter, Source{Repository: "/r", Against: stoodOn})
|
||||
if err == nil || !strings.Contains(err.Error(), "ADR 0175") {
|
||||
t.Fatalf("a module that had moved returned to the old pattern unrefused: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user