package bootstrap import ( "context" "os" "path/filepath" "strings" "testing" "time" ) // Defends novox/hq 04-ISSUES/085: the port given for the package registry at genesis is a setting // of a module and not text in a manifest, so registering that manifest again does not put the // catalogue's number back. // theBuildersBinding is the resource the builder carries in place of a binding nothing can resolve // yet, exactly as the catalogue's manifest has it — settable, with the port as its only default. const theBuildersBinding = `{ "module": "builder", "resources": [ { "id": "package-binding", "type": "file", "path": "/var/lib/mesh/builder/package-registry.json", "mode": "0600", "merge": "json", "protected": ["provision", "from", "as"], "content": "{\"provision\": \"package-registry\", \"from\": \"gitea\", \"at\": \"127.0.0.1\", \"as\": \"mesh-builder\", \"serves\": {\"scheme\": \"http\", \"port\": 3000, \"npm-path\": \"/api/packages/novox/npm/\"}}\n" } ] }` func recording(t *testing.T) (*controlRecorder, controlPlane) { t.Helper() t.Setenv("TMPDIR", t.TempDir()) c := &controlRecorder{settings: map[string]string{}} return c, controlPlane{container: "temp-mesh-controller", run: c.run, timeout: time.Second} } func TestTheBuildersPackageRegistryPortIsASettingAndNotTheManifest(t *testing.T) { c, control := recording(t) o := Options{Node: "anchor", Ports: FoundationPorts{Packages: 3100}, Wait: time.Second} if _, err := installModule(context.Background(), o, control, BuilderModule, []byte(theBuildersBinding), quietly); err != nil { t.Fatal(err) } if got := c.settings["builder-settings.json"]; got != `{"serves":{"port":3100}}` { t.Errorf("the builder was told %q about the package registry's port", got) } // The manifest reaches the mesh as the catalogue wrote it. A port rewritten into it here is a // port the next registration from the catalogue silently takes back. if got := c.settings["builder-module.json"]; got != theBuildersBinding { t.Errorf("the installer changed the builder's manifest:\n%s", got) } set, push := c.index("settings set builder"), c.index("push anchor") if set < 0 || push < 0 || set > push { t.Fatalf("the port was not set before the push that raises the builder: %v", c.told) } } func TestTheBuilderOnTheDefaultPackagesPortIsToldNothing(t *testing.T) { c, control := recording(t) o := Options{Node: "anchor", Wait: time.Second} if _, err := installModule(context.Background(), o, control, BuilderModule, []byte(theBuildersBinding), quietly); err != nil { t.Fatal(err) } if c.index("settings") >= 0 { t.Errorf("a genesis on the catalogue's packages port set a setting: %v", c.told) } } // aCatalogueWith writes a checkout holding one module's manifest, which is all the installer reads // a catalogue for. func aCatalogueWith(t *testing.T, module, manifest string) string { t.Helper() dir := t.TempDir() at := filepath.Join(dir, catalogueDir, module) if err := os.MkdirAll(at, 0o700); err != nil { t.Fatal(err) } if err := os.WriteFile(filepath.Join(at, "module.json"), []byte(manifest), 0o600); err != nil { t.Fatal(err) } return dir } const theForgesManifest = `{"module": "gitea", "version": "1"}` func TestThePackagesPortIsTheForgeModulesSettingOnThisNode(t *testing.T) { c, control := recording(t) o := Options{Node: "anchor", Catalogue: aCatalogueWith(t, ForgeModule, theForgesManifest), Ports: FoundationPorts{Packages: 3100}, Wait: time.Second} if err := recordTheForgesPort(context.Background(), o, control, quietly); err != nil { t.Fatal(err) } if got := c.settings["gitea-settings.json"]; got != `{"ports":{"3000":3100}}` { t.Errorf("the forge module was told %q about its port", got) } // Registered so there is something to hold the setting against, and never assigned: the forge // module cannot run until the base it stands on has been built. add, set := c.index("module add"), c.index("settings set gitea") if add < 0 || set < 0 || add > set { t.Fatalf("the forge's setting was recorded against a module the mesh does not know: %v", c.told) } if c.index("assign") >= 0 { t.Errorf("genesis assigned the forge module: %v", c.told) } if !strings.Contains(c.told[set], "--node anchor") { t.Errorf("the forge's port was set for the whole mesh, not this machine: %s", c.told[set]) } } func TestAGenesisOnTheCataloguesPackagesPortRegistersNoForge(t *testing.T) { c, control := recording(t) o := Options{Node: "anchor", Catalogue: aCatalogueWith(t, ForgeModule, theForgesManifest), Wait: time.Second} if err := recordTheForgesPort(context.Background(), o, control, quietly); err != nil { t.Fatal(err) } if len(c.told) != 0 { t.Errorf("a genesis on the defaults told the mesh something new: %v", c.told) } } func TestAForgeManifestTheCatalogueDoesNotHaveIsNamed(t *testing.T) { _, control := recording(t) o := Options{Node: "anchor", Catalogue: t.TempDir(), Ports: FoundationPorts{Packages: 3100}, Wait: time.Second} err := recordTheForgesPort(context.Background(), o, control, quietly) if err == nil || !strings.Contains(err.Error(), ForgeModule) || !strings.Contains(err.Error(), "package registry") { t.Errorf("a missing forge manifest was not explained: %v", err) } }