Registering a module is an overwrite. Recording the forge's port ran `module add` every time, so a genesis re-run pointed at an older catalogue would replace the manifest of a forge that is built and assigned — with a push a few lines later. Registering is only here so a settings row has a module row to hang on, and that row is already there on a mesh that knows the forge. So: ask first, and skip. Two comments narrowed to what is true. What follows the node's setting is what the mesh derives from a module's ports — its container mapping, its filter rule, its opening and what it serves. The forge's own address in its runtime's environment (hq 088) and its route contribution's port do not, and are already wrong for any port the mesh assigned. And a settings layer is the module's, not one resource's: a second mergeable file on the builder would be given `serves` too. novox/hq 04-ISSUES/085
170 lines
6.8 KiB
Go
170 lines
6.8 KiB
Go
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", "at", "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])
|
|
}
|
|
}
|
|
|
|
// knowingControl is a control plane that already has the forge in its catalogue, as a mesh that
|
|
// has been running has.
|
|
type knowingControl struct{ controlRecorder }
|
|
|
|
func (k *knowingControl) run(ctx context.Context, name string, args ...string) (string, error) {
|
|
out, err := k.controlRecorder.run(ctx, name, args...)
|
|
if name == "docker" && args[0] == "exec" && len(args) > 4 &&
|
|
args[3] == "module" && args[4] == "list" {
|
|
return ForgeModule + " 1 assigned to anchor\n", nil
|
|
}
|
|
return out, err
|
|
}
|
|
|
|
func TestARerunDoesNotReplaceAForgeTheMeshAlreadyHas(t *testing.T) {
|
|
t.Setenv("TMPDIR", t.TempDir())
|
|
k := &knowingControl{controlRecorder{settings: map[string]string{}}}
|
|
control := controlPlane{container: "mesh-controller", run: k.run, timeout: time.Second}
|
|
// An older checkout than the mesh is running, which is what makes an overwrite here damage.
|
|
o := Options{Node: "anchor", Catalogue: aCatalogueWith(t, ForgeModule, `{"module": "gitea"}`),
|
|
Ports: FoundationPorts{Packages: 3100}, Wait: time.Second}
|
|
if err := recordTheForgesPort(context.Background(), o, control, quietly); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
// Registering is an overwrite, and the manifest of a forge that is built and assigned is not
|
|
// this installer's to replace with whatever checkout it was pointed at.
|
|
if k.index("module add") >= 0 {
|
|
t.Errorf("a re-run replaced the registered forge's manifest: %v", k.told)
|
|
}
|
|
// The port is still recorded: a settings row needs the module row, and it is already there.
|
|
if got := k.settings["gitea-settings.json"]; got != `{"ports":{"3000":3100}}` {
|
|
t.Errorf("the forge's port was not recorded on a mesh that knows it: %q", got)
|
|
}
|
|
}
|
|
|
|
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)
|
|
}
|
|
}
|