Merge remote-tracking branch 'origin/main' into fix/1830-onlyoffice-link
mesh/merge-gate head 47df3a4d607a merged into trunk 529c156f6407 — pass: builds nextcloud, only-office → novox; no bus step; every machine composes with th…
mesh/repo-check head 47df3a4d607a merged into trunk 529c156f6407 — pass: its merge-check.sh passed, each part in its toolchain: merge-check.sh (go), merge-…
mesh/check failed: unit: modules/gitea.test: [gitea] where the poll of merges last looked from could not be read, so none is kept — no runtime | 47df3…
mesh/delivery delivered

This commit is contained in:
jochen
2026-10-22 11:30:58 +02:00
4 changed files with 79 additions and 3 deletions
+1 -1
View File
@@ -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 `<home>/registry` (`files/registry`).
The registry's address is placed into `<home>/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).
@@ -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)
}
}
@@ -114,7 +114,7 @@ func TestManifestKeepsItsStatesClaimsNoSeatAndDeclaresItsHealthTool(t *testing.T
t.Errorf("registry file = %v, want ${dir:state}/registry (the program reads <home>/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)
}
}
+1 -1
View File
@@ -1 +1 @@
${bound:artifact-store:at}:${bound:artifact-store:port}
${seat:mesh-artifact-store:reach}