The module that provides artifact-store runs Distribution, the OCI reference implementation. It was called registry, which named neither the software nor the provision. Claude-Session: https://claude.ai/code/session_01D6qtiYU3P9jk3pnAXyAFyx
217 lines
7.7 KiB
Go
217 lines
7.7 KiB
Go
package bootstrap
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net/http"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
// Step 7 installs the one module whose image can never come from the mesh's own registry, because
|
|
// it IS the mesh's own registry (novox/hq 04-ISSUES/029). These tests defend that, and defend the
|
|
// distinction the whole verify layer of this program is built on: a container that is up is not a
|
|
// service that answers.
|
|
|
|
// catalogueWith writes a fake catalogue checkout holding one module's manifest.
|
|
//
|
|
// A fixture here rather than the real catalogue, unlike the substrate example the rewrite tests
|
|
// use: the catalogue is a different repository on a different branch, and a test that read it
|
|
// would pass or fail according to what somebody else had checked out.
|
|
func catalogueWith(t *testing.T, module, manifest string) string {
|
|
t.Helper()
|
|
root := t.TempDir()
|
|
dir := filepath.Join(root, catalogueDir, module)
|
|
if err := os.MkdirAll(dir, 0o755); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := os.WriteFile(filepath.Join(dir, "module.json"), []byte(manifest), 0o644); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
return root
|
|
}
|
|
|
|
const upstreamRegistryManifest = `{
|
|
"module": "distribution",
|
|
"version": "1",
|
|
"provides": [{"name": "artifact-store", "scope": "mesh"}],
|
|
"capabilities": ["container-runtime"],
|
|
"resources": [
|
|
{"id": "state", "type": "directory", "path": "/var/lib/mesh/registry", "mode": "0700"},
|
|
{"id": "store", "type": "container", "name": "mesh-registry",
|
|
"image": "registry@sha256:a3d8aaa63ed8681a604f1dea0aa03f100d5895b6a58ace528858a7b332415373",
|
|
"ports": ["5000:5000"]}
|
|
]
|
|
}`
|
|
|
|
// aMeshThatAgrees answers every command the installer issues at steps 7 and 9 the way a working
|
|
// mesh would, except for whatever a test overrides.
|
|
func aMeshThatAgrees(answers map[string]string) func(string, []string) (string, error) {
|
|
return func(name string, args []string) (string, error) {
|
|
joined := strings.Join(args, " ")
|
|
for fragment, said := range answers {
|
|
if strings.Contains(joined, fragment) {
|
|
return said, nil
|
|
}
|
|
}
|
|
switch {
|
|
case name != "docker":
|
|
return "", fmt.Errorf("unexpected program %q", name)
|
|
case args[0] == "cp":
|
|
return "", nil
|
|
case args[0] == "inspect":
|
|
return "true running\n", nil
|
|
case args[0] == "exec":
|
|
return "", nil
|
|
}
|
|
return "", fmt.Errorf("unexpected: %v", args)
|
|
}
|
|
}
|
|
|
|
func installing(t *testing.T, catalogue string) Options {
|
|
t.Helper()
|
|
return Options{
|
|
Node: "anchor",
|
|
Catalogue: catalogue,
|
|
Registry: "127.0.0.1:5000",
|
|
Timeout: time.Second,
|
|
Wait: 0,
|
|
}
|
|
}
|
|
|
|
// A container that is up is not a registry that serves. `/v2/` is the registry API's own "yes, I
|
|
// am one and I am ready", and the step after this pushes to it — so it is refused here rather than
|
|
// discovered inside a `docker push`.
|
|
func TestARegistryContainerThatIsUpIsNotARegistryThatServes(t *testing.T) {
|
|
previous := answerEvery
|
|
answerEvery = time.Millisecond
|
|
defer func() { answerEvery = previous }()
|
|
|
|
runtime := &asked{answer: aMeshThatAgrees(nil)}
|
|
deps := Deps{
|
|
Run: runtime.run,
|
|
Fetch: func(context.Context, string) (int, string, error) {
|
|
return http.StatusInternalServerError, "", nil
|
|
},
|
|
}
|
|
|
|
_, err := InstallRegistry(context.Background(),
|
|
installing(t, catalogueWith(t, RegistryModule, upstreamRegistryManifest)),
|
|
deps, controlPlane{container: "temp-mesh-control", run: runtime.run, timeout: time.Second},
|
|
func(string) {})
|
|
if err == nil {
|
|
t.Fatal("a registry whose container is up and which answers 500 was accepted")
|
|
}
|
|
for _, wanted := range []string{"/v2/", "Running is not serving"} {
|
|
if !strings.Contains(err.Error(), wanted) {
|
|
t.Errorf("the refusal does not mention %q:\n%v", wanted, err)
|
|
}
|
|
}
|
|
}
|
|
|
|
// The whole of step 7, against a mesh that agrees: registered, assigned, pushed, up, and answering.
|
|
func TestARegistryThatAnswersIsAccepted(t *testing.T) {
|
|
runtime := &asked{answer: aMeshThatAgrees(nil)}
|
|
deps := Deps{
|
|
Run: runtime.run,
|
|
Fetch: func(context.Context, string) (int, string, error) {
|
|
return http.StatusOK, "{}", nil
|
|
},
|
|
}
|
|
|
|
out, err := InstallRegistry(context.Background(),
|
|
installing(t, catalogueWith(t, RegistryModule, upstreamRegistryManifest)),
|
|
deps, controlPlane{container: "temp-mesh-control", run: runtime.run, timeout: time.Second},
|
|
func(string) {})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if out.Container != "mesh-registry" {
|
|
t.Errorf("the registry's container is %q", out.Container)
|
|
}
|
|
if out.Answered != http.StatusOK {
|
|
t.Errorf("the registry answered %d", out.Answered)
|
|
}
|
|
// Registered, assigned and pushed, through the same three commands a person types.
|
|
for _, wanted := range []string{
|
|
"module add /distribution-module.json",
|
|
"assign anchor distribution",
|
|
"push anchor",
|
|
} {
|
|
if !runtime.ran(wanted) {
|
|
t.Errorf("the installer never ran %q: %v", wanted, runtime.commands)
|
|
}
|
|
}
|
|
}
|
|
|
|
// **The registry's image is upstream and it is never built.** A manifest carrying the catalogue's
|
|
// placeholder digest would mean somebody had made this module buildable — which is the cycle
|
|
// novox/hq 04-ISSUES/029 settled: a module that provides the artifact store cannot be delivered
|
|
// through the artifact store.
|
|
func TestARegistryManifestThatWantsBuildingIsRefused(t *testing.T) {
|
|
wants := strings.Replace(upstreamRegistryManifest,
|
|
"registry@sha256:a3d8aaa63ed8681a604f1dea0aa03f100d5895b6a58ace528858a7b332415373",
|
|
"mesh-runtime-registry@"+placeholderDigest, 1)
|
|
|
|
runtime := &asked{answer: aMeshThatAgrees(nil)}
|
|
_, err := InstallRegistry(context.Background(),
|
|
installing(t, catalogueWith(t, RegistryModule, wants)),
|
|
Deps{Run: runtime.run}, controlPlane{container: "temp-mesh-control", run: runtime.run},
|
|
func(string) {})
|
|
if err == nil {
|
|
t.Fatal("a registry manifest naming an image the mesh would have to build was accepted")
|
|
}
|
|
if !strings.Contains(err.Error(), "04-ISSUES/029") {
|
|
t.Errorf("the refusal does not name the decision it rests on: %v", err)
|
|
}
|
|
if runtime.ran("module add") {
|
|
t.Error("it was registered anyway")
|
|
}
|
|
}
|
|
|
|
// A catalogue that is not there is said plainly, with what --catalog is. This is the most likely
|
|
// mistake anybody makes at this step and the least interesting to debug.
|
|
func TestACatalogueThatIsNotThereIsSaidPlainly(t *testing.T) {
|
|
runtime := &asked{answer: aMeshThatAgrees(nil)}
|
|
_, err := InstallRegistry(context.Background(),
|
|
installing(t, filepath.Join(t.TempDir(), "nowhere")),
|
|
Deps{Run: runtime.run}, controlPlane{container: "temp-mesh-control", run: runtime.run},
|
|
func(string) {})
|
|
if err == nil {
|
|
t.Fatal("a catalogue that does not exist was accepted")
|
|
}
|
|
if !strings.Contains(err.Error(), "--catalog") {
|
|
t.Errorf("the refusal does not say what to fix: %v", err)
|
|
}
|
|
}
|
|
|
|
// A refusal from the control plane is repeated verbatim. mesh-control refuses in paragraphs —
|
|
// "nothing provides route, wanted by registry" — and an installer that reported "exit status 1"
|
|
// would throw away the only thing a person can act on.
|
|
func TestWhatTheMeshRefusedIsRepeated(t *testing.T) {
|
|
refusal := "nothing provides \"route\", wanted by registry"
|
|
runtime := &asked{answer: func(name string, args []string) (string, error) {
|
|
if strings.Contains(strings.Join(args, " "), "push") {
|
|
return refusal, fmt.Errorf("exit status 1")
|
|
}
|
|
return aMeshThatAgrees(nil)(name, args)
|
|
}}
|
|
|
|
_, err := InstallRegistry(context.Background(),
|
|
installing(t, catalogueWith(t, RegistryModule, upstreamRegistryManifest)),
|
|
Deps{Run: runtime.run}, controlPlane{container: "temp-mesh-control", run: runtime.run,
|
|
timeout: time.Second}, func(string) {})
|
|
if err == nil {
|
|
t.Fatal("a push the mesh refused was reported as successful")
|
|
}
|
|
if !strings.Contains(err.Error(), refusal) {
|
|
t.Errorf("what the mesh said is not in the failure:\n%v", err)
|
|
}
|
|
if !strings.Contains(err.Error(), "run this installer again") {
|
|
t.Errorf("the failure does not say a re-run continues from here:\n%v", err)
|
|
}
|
|
}
|