ADR 0593 §7: the composer with its refusals leaves mesh-sdk, so mesh-sdk carries no composition rule. The catalogue functions only the node-engine's composition reaches (Resolve, Resolution's Compose, Declaration, DataItems, LeftOut, Rules and the rest, the settings, placeholder and template refusals, the rendering helpers) are copied with their tests into internal/compose/resolution; a method of a mesh-sdk shape becomes a function taking it first. The composition calls its own copies, and the captured catalogue its tests read lives here now, shared by mesh-compose's tests. Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
66 lines
2.7 KiB
Go
66 lines
2.7 KiB
Go
package resolution
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
mcat "git.novox.be/novox/mesh-sdk/go/catalogue"
|
|
)
|
|
|
|
// artifactsInto composes the artifact store's address into a resource's `image` and `source`.
|
|
//
|
|
// **Composed here, at the last moment before a machine, and stored nowhere.** A kept reference is
|
|
// routed through the store as this network reaches it now. A reference recorded with an address
|
|
// before references were kept without one is re-routed the same way — but only when the mesh
|
|
// built it (`with.Built` names every `<module>/<artifact>` it has), because a module may run an
|
|
// image from a public registry under its own name and that one is exactly where it says.
|
|
//
|
|
// A kept reference with no store to route it through is refused: sent as it is, the runtime would
|
|
// refuse the scheme on the machine, one push away from the reason.
|
|
//
|
|
// **What this does not reach: the images genesis pinned.** The installer builds the control plane
|
|
// and the builder before the mesh exists, pushes them itself and pins their manifests to
|
|
// `<registry>:<port>/mesh-controller@…` and `<registry>:<port>/mesh-builder@…` — single-segment
|
|
// repositories with no build record, so `with.Built` does not name them and they are left as
|
|
// written until each is rebuilt through the mesh, which records it by digest and path. Until then
|
|
// a registry that moves strands exactly those two on a recreate, and the control plane's is the
|
|
// one that cannot be repaired through the mesh. Rebuild both through `build` before moving the
|
|
// store (novox/hq 04-ISSUES/102, finding F4).
|
|
func artifactsInto(resource map[string]any, module string, with mcat.Rendering) error {
|
|
for _, key := range []string{"image", "source"} {
|
|
written, ok := resource[key].(string)
|
|
if !ok {
|
|
continue
|
|
}
|
|
if _, kept := mcat.InArtifactStore(written); kept {
|
|
if with.ArtifactStore == "" {
|
|
return fmt.Errorf(
|
|
"%s's %v names %s, which is in the mesh's artifact store, and this mesh has no "+
|
|
"artifact store on its network to fetch it from — nothing assigned offers "+
|
|
"%s, or the machine offering it is not on the private network",
|
|
module, resource["id"], written, mcat.ArtifactStoreProvision)
|
|
}
|
|
resource[key] = mcat.Routed(written, with.ArtifactStore)
|
|
continue
|
|
}
|
|
if with.ArtifactStore == "" {
|
|
continue
|
|
}
|
|
recorded := mcat.Recorded(written)
|
|
if recorded == written {
|
|
continue
|
|
}
|
|
path, _ := mcat.InArtifactStore(recorded)
|
|
repository := path
|
|
if at := strings.IndexAny(path, "@"); at >= 0 {
|
|
repository = path[:at]
|
|
} else if blobs := strings.Index(path, "/blobs/"); blobs >= 0 {
|
|
repository = path[:blobs]
|
|
}
|
|
if with.Built[repository] {
|
|
resource[key] = mcat.Routed(recorded, with.ArtifactStore)
|
|
}
|
|
}
|
|
return nil
|
|
}
|