ENG-10: the composition writes beside each routed image the seat it came through and that seat's holder, no part of a container's spec (design 51, issue 1966; needs mesh-sdk request R1)

Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
This commit is contained in:
2026-11-04 11:46:33 +01:00
parent 60358d01e9
commit 3eef84d979
5 changed files with 74 additions and 0 deletions
+10
View File
@@ -111,6 +111,16 @@ func TestAReplacementImageIsPresentBeforeTheRunningContainerIsRemoved(t *testing
{"id":"store","type":"container","name":"store","image":"`+pinned+`","env":{"PGDATA":"/data"}}
]}`)
want := containerSpec(d.Resources[0].(*declaration.Container), inputs{})
// The seat and holder a routed image names (ENG-10) are no part of what a container is: another holder is the same spec,
// so a declaration composed again for it replaces no container.
for _, holder := range []string{"distribution", "elsewhere"} {
named := parseTrusted(t, `{"declaration":1,"resources":[
{"id":"store","type":"container","name":"store","image":"`+pinned+`","image-seat":"mesh-artifact-store","image-holder":"`+holder+`","env":{"PGDATA":"/data"}}
]}`)
if got := containerSpec(named.Resources[0].(*declaration.Container), inputs{}); got != want {
t.Errorf("a container naming the holder %s has another spec than one naming none", holder)
}
}
var order []string
created := false
run := func(ctx context.Context, name string, args ...string) (string, error) {
+7
View File
@@ -168,6 +168,13 @@ func (c *composer) places(nodeName string, resolved Resolved) (Placed, error) {
// Where this machine reaches each mesh seat's holder, for ${seat:<seat>:reach} (novox/hq ADR 0222).
if store != "" {
r.SeatReach = map[string]string{"mesh-artifact-store": store}
// And its holder, from the holdings on record, written beside each image routed through it (design 51, ENG-10).
for _, h := range c.in.Holdings {
if hs, ok := catalogue.SeatNamed(h.Claim); ok && hs.Name == "mesh-artifact-store" && h.Scope == catalogue.ScopeMesh && h.Module != "" {
r.SeatHolder = map[string]string{"mesh-artifact-store": h.Module}
break
}
}
}
r.Settings = settings
r.Given = given
+16
View File
@@ -272,6 +272,22 @@ func TestTheArtifactStoreIsReachedOverTheNetworkOrOnLoopbackForItsHolder(t *test
if got := placed(t, in, "anchor").Rendering.Built; !got["mesh-sdk"] {
t.Errorf("built is %v", got)
}
// Its holder, from the holdings on record, beside the address (design 51, ENG-10): none on record names none, and a change
// of the holder is the rendering's.
if got := placed(t, in, "anchor").Rendering.SeatHolder; got != nil {
t.Errorf("a store with no holder on record names %v", got)
}
in.Holdings = []catalogue.Held{{Claim: "mesh-artifact-store", Scope: catalogue.ScopeMesh, Node: "anchor", Module: "artifacts"}}
if got := placed(t, in, "laptop").Rendering.SeatHolder["mesh-artifact-store"]; got != "" {
t.Errorf("a machine that reaches no store names its holder %q", got)
}
if got := placed(t, in, "anchor").Rendering.SeatHolder["mesh-artifact-store"]; got != "artifacts" {
t.Errorf("the store's holder is %q", got)
}
in.Holdings[0].Module = "distribution"
if got := placed(t, in, "anchor").Rendering.SeatHolder["mesh-artifact-store"]; got != "distribution" {
t.Errorf("after the holder changed it is %q", got)
}
}
// A zone a module declares is placed where the mesh put it: settled from that node's settings, at the node's private address, on
+18
View File
@@ -41,6 +41,7 @@ func artifactsInto(resource map[string]any, module string, with mcat.Rendering)
module, resource["id"], written, mcat.ArtifactStoreProvision)
}
resource[key] = mcat.Routed(written, with.ArtifactStore)
imageSeatInto(resource, key, with)
continue
}
if with.ArtifactStore == "" {
@@ -59,7 +60,24 @@ func artifactsInto(resource map[string]any, module string, with mcat.Rendering)
}
if with.Built[repository] {
resource[key] = mcat.Routed(recorded, with.ArtifactStore)
imageSeatInto(resource, key, with)
}
}
return nil
}
// artifactSeat is the seat an image is routed through: the artifact store's (the registries' four seats follow as the
// references name them).
const artifactSeat = "mesh-artifact-store"
// imageSeatInto writes beside a container's routed image the seat the reference came through and that seat's holder (design 51
// *distribution's first delivery*, issue 1966 ENG-10), so the node-engine finds by the declaration whom a failed pull waits
// on, never by a module's name. Neither is part of what a container is: a declaration composed again for a new holder
// replaces no container. Nothing is written where the holder is not on record, or for a resource that is no container.
func imageSeatInto(resource map[string]any, key string, with mcat.Rendering) {
if key != "image" || resource["type"] != "container" || with.SeatHolder[artifactSeat] == "" {
return
}
resource["image-seat"] = artifactSeat
resource["image-holder"] = with.SeatHolder[artifactSeat]
}
@@ -46,6 +46,29 @@ func TestAnImageTheMeshBuiltIsRoutedThroughTheStoreWhenDeclared(t *testing.T) {
t.Errorf("composing wrote the address into the catalogue's copy: %v", got)
}
// The seat the image came through and its holder, beside it (ENG-10); a holder not on record writes neither, a public
// image and an archive carry none, and a holder changing changes the declaration but not the container's spec.
if got := fileNamed(out, "gitea.server"); got["image-seat"] != nil || got["image-holder"] != nil {
t.Errorf("a holder not on record was written: %v %v", got["image-seat"], got["image-holder"])
}
held := mcat.Rendering{ArtifactStore: "anchor.internal:5101", SeatHolder: map[string]string{"mesh-artifact-store": "distribution"}}
held1, err := Declaration(r, held)
if err != nil {
t.Fatal(err)
}
if got := fileNamed(held1, "gitea.server"); got["image-seat"] != "mesh-artifact-store" || got["image-holder"] != "distribution" {
t.Errorf("the routed image names its seat and holder as %v %v", got["image-seat"], got["image-holder"])
}
for _, id := range []string{"gitea.config", "gitea.cache"} {
if got := fileNamed(held1, id); got["image-seat"] != nil || got["image-holder"] != nil || got["seat"] != nil {
t.Errorf("%s names a seat: %v", id, got)
}
}
held.SeatHolder = map[string]string{"mesh-artifact-store": "other-holder"}
if held2, err := Declaration(r, held); err != nil || fileNamed(held2, "gitea.server")["image-holder"] != "other-holder" {
t.Errorf("a new holder is not written: %v", err)
}
// And the store moves: the same record, another address, without a rebuild.
out, err = Declaration(r, mcat.Rendering{ArtifactStore: "laptop.internal:5000"})
if err != nil {