From 9e2d1164f06ed8a16e4bf183b16860477d5fb0e1 Mon Sep 17 00:00:00 2001 From: jochen Date: Thu, 22 Oct 2026 11:07:50 +0200 Subject: [PATCH] Give mesh-build-image the registry's address as the seat's reach, which the provisioner's client fills (issue 1703) --- modules/mesh-build-image/README.md | 2 +- .../cmd/mesh-build-image/compose_test.go | 76 +++++++++++++++++++ .../cmd/mesh-build-image/manifest_test.go | 2 +- modules/mesh-build-image/files/registry | 2 +- 4 files changed, 79 insertions(+), 3 deletions(-) create mode 100644 modules/mesh-build-image/cmd/mesh-build-image/compose_test.go diff --git a/modules/mesh-build-image/README.md b/modules/mesh-build-image/README.md index 2c41ecf1..9ebca6cb 100644 --- a/modules/mesh-build-image/README.md +++ b/modules/mesh-build-image/README.md @@ -35,4 +35,4 @@ The Dockerfile's steps may use the network (ADR 0487 ยง6); nothing a step can re until it is removed at R4g. - `build_image_step`, `build_image_steps`, `build_image_status` and `build_image_health` read. -The registry's address is bound from the `artifact-store` provision into `/registry` (`files/registry`). +The registry's address is placed into `/registry` as `${seat:mesh-artifact-store:reach}` (host:port): the provisioner's client fills a moved module's placement, and the artifact store has not moved, so a `${bound:artifact-store:...}` is refused at composition (issue 1703). diff --git a/modules/mesh-build-image/cmd/mesh-build-image/compose_test.go b/modules/mesh-build-image/cmd/mesh-build-image/compose_test.go new file mode 100644 index 00000000..04f9a2ed --- /dev/null +++ b/modules/mesh-build-image/cmd/mesh-build-image/compose_test.go @@ -0,0 +1,76 @@ +package main + +import ( + "os" + "path/filepath" + "strings" + "testing" + + "git.novox.be/novox/mesh-sdk/go/catalogue" +) + +// Issue 1703 (the live failure of the first assignment): the module is moved, so the provisioner's client on the node +// fills its templates, and it fills only config, secrets, collections, placement and what a moved provider told it. +// The registry's address therefore cannot be a ${bound:artifact-store:...} (the artifact store has not moved): it is the +// placement ${seat:mesh-artifact-store:reach}, the form the container runtime's daemon.json uses. This composes the +// module on a machine with buildah and the artifact store reachable, handing its files to the client as a node does. +func TestTheModuleComposesWhereItsFilesAreHandedToTheProvisionersClient(t *testing.T) { + built := func(m catalogue.Manifest) []catalogue.Built { + texts := map[string]string{} + entries, err := os.ReadDir(filepath.Join(moduleDir, "files")) + if err != nil { + t.Fatal(err) + } + for _, e := range entries { + raw, err := os.ReadFile(filepath.Join(moduleDir, "files", e.Name())) + if err != nil { + t.Fatal(err) + } + texts[e.Name()] = string(raw) + } + return []catalogue.Built{ + {Name: "tools", Kind: "bundle", Reference: catalogue.ArtifactStoreScheme + "mesh-build-image/tools/blobs/sha256:" + strings.Repeat("a", 64), Digest: "sha256:" + strings.Repeat("a", 64)}, + {Name: "files", Kind: "archive", Reference: catalogue.ArtifactStoreScheme + "mesh-build-image/files/blobs/sha256:" + strings.Repeat("b", 64), Digest: "sha256:" + strings.Repeat("b", 64), Texts: texts}, + } + } + read := func(name string) catalogue.Manifest { + m, err := catalogue.ReadTreeManifestWritten(catalogueRoot, filepath.Join(catalogueRoot, "modules", name)) + if err != nil { + t.Fatalf("modules/%s: %v", name, err) + } + return m + } + image := read("mesh-build-image") + resolved, err := image.Resolve(built(image)) + if err != nil { + t.Fatal(err) + } + shelf := map[string]catalogue.Manifest{ + "mesh-build-image": resolved, + "buildah": read("buildah"), + "forge": {Module: "forge", Version: "1", Provides: []catalogue.Offer{{Name: "forge-account"}}}, + "store": {Module: "store", Version: "1", Provides: []catalogue.Offer{{Name: "artifact-store"}}}, + } + node := catalogue.Node{Name: "builder", Site: "house", + Capabilities: map[string]bool{"package-manager": true, "user-namespaces": true}} + r, err := catalogue.Resolve(shelf, []string{"forge", "store", "buildah", "mesh-build-image"}, node, catalogue.World{}) + if err != nil { + t.Fatal(err) + } + r.Account = "op" + // What the resolution states for the node: the forge's provider has moved, the artifact store's has not. + r.Needs = []catalogue.Needed{ + {Name: "forge-account", For: "mesh-build-image", Module: "forge", From: "novox", At: "10.7.0.1", ProviderMoved: true, + Serves: map[string]any{"known_host": "[novox.internal]:222 ssh-ed25519 AAAA", "host_key": "ssh-ed25519 AAAA", "ssh_host": "novox.internal", "ssh_alias": "mesh-forge", "ssh_port": "222", "ssh_base": "ssh://git@novox.internal:222/", "https_base": "https://git.novox.be/"}}, + {Name: "artifact-store", For: "mesh-build-image", Module: "store", From: "novox", At: "10.7.0.1", Serves: map[string]any{"port": "5000"}}, + } + with := catalogue.Rendering{Hands: true, Provisioner: "mesh-provisioner-client", ArtifactStore: "store:5000", + Needed: map[string]map[string]string{"mesh-build-image": {"broker": "sealed-to-the-node"}}} + c, err := r.Compose(with) + if err != nil { + t.Fatalf("the module does not compose on a machine with buildah and the artifact store: %v", err) + } + if _, asked := c.Plans["mesh-build-image"].Placement["seat:mesh-artifact-store:reach"]; !asked { + t.Errorf("the plan's placement %v does not ask where the registry is reached", c.Plans["mesh-build-image"].Placement) + } +} diff --git a/modules/mesh-build-image/cmd/mesh-build-image/manifest_test.go b/modules/mesh-build-image/cmd/mesh-build-image/manifest_test.go index b6f81390..be79ad76 100644 --- a/modules/mesh-build-image/cmd/mesh-build-image/manifest_test.go +++ b/modules/mesh-build-image/cmd/mesh-build-image/manifest_test.go @@ -114,7 +114,7 @@ func TestManifestKeepsItsStatesClaimsNoSeatAndDeclaresItsHealthTool(t *testing.T t.Errorf("registry file = %v, want ${dir:state}/registry (the program reads /registry)", reg) } tpl, _ := os.ReadFile(filepath.Join(moduleDir, "files", "registry")) - if strings.TrimSpace(string(tpl)) != "${bound:artifact-store:at}:${bound:artifact-store:port}" { + if strings.TrimSpace(string(tpl)) != "${seat:mesh-artifact-store:reach}" { t.Errorf("registry template = %q", tpl) } } diff --git a/modules/mesh-build-image/files/registry b/modules/mesh-build-image/files/registry index 044345fd..1bcadab2 100644 --- a/modules/mesh-build-image/files/registry +++ b/modules/mesh-build-image/files/registry @@ -1 +1 @@ -${bound:artifact-store:at}:${bound:artifact-store:port} +${seat:mesh-artifact-store:reach}