A container may name networks it also joins once created, for the per-machine setting that keeps a found network while a neighbour still resolves it there: joined after the run, part of the spec, refused when it cannot be joined. A declaration may say which modules the mesh left out because a stored setting cannot compose with its definition. Absence used to read as removal; a left-out module's records are kept and said, and its holds are not released. Genesis raises the bootstrap forge under the gitea module's container name, with its image digest and its data directory mounted at /data, so the module holds it by the found rule instead of raising a second forge beside it (issue 090). The network is the one difference left for a take to say. Before this the forge had no volume: its repositories were the container's, lost with it.
80 lines
2.6 KiB
Go
80 lines
2.6 KiB
Go
package bootstrap
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
// What genesis raises, it raises as the module that succeeds it declares — name, data directory
|
|
// and image — so the module adopts it by the found rule that already exists (novox/hq ADR 0163,
|
|
// rule 7; issue 090). The network is the one difference left: the bootstrap forge runs on the
|
|
// machine's network to reach the store on its loopback, and a take says so.
|
|
func TestGenesisRaisesTheForgeAsTheModuleDeclaresIt(t *testing.T) {
|
|
var ran [][]string
|
|
run := func(_ context.Context, name string, args ...string) (string, error) {
|
|
if name == "docker" && args[0] == "container" {
|
|
return "", nil // not raised yet
|
|
}
|
|
ran = append(ran, append([]string{name}, args...))
|
|
return "", nil
|
|
}
|
|
if err := raiseGiteaServer(context.Background(), run, time.Second, "pw", DefaultPorts(), quietly); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var raised []string
|
|
for _, r := range ran {
|
|
if r[0] == "docker" && r[1] == "run" {
|
|
raised = r
|
|
}
|
|
}
|
|
line := strings.Join(raised, " ")
|
|
for _, want := range []string{"--name gitea ", "--volume " + giteaDataDir + ":/data", " " + giteaImage} {
|
|
if !strings.Contains(line+" ", want) {
|
|
t.Errorf("the forge is not raised with %q: %s", want, line)
|
|
}
|
|
}
|
|
if giteaBootstrap != ForgeModule {
|
|
t.Errorf("the bootstrap forge is %q and the module names its container %q", giteaBootstrap, ForgeModule)
|
|
}
|
|
|
|
// Against the module's own manifest, where the catalogue is checked out beside this repository.
|
|
var manifest []byte
|
|
for _, candidate := range []string{"../../../mesh-catalog/modules/gitea/module.json", "../../../../../mesh-catalog/modules/gitea/module.json"} {
|
|
if raw, err := os.ReadFile(filepath.Clean(candidate)); err == nil {
|
|
manifest = raw
|
|
break
|
|
}
|
|
}
|
|
if manifest == nil {
|
|
t.Skip("the catalogue is not beside this checkout; the module's pin is not compared")
|
|
}
|
|
var m struct {
|
|
Resources []struct {
|
|
ID, Type, Name, Image string
|
|
Volumes []string
|
|
} `json:"resources"`
|
|
}
|
|
if err := json.Unmarshal(manifest, &m); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for _, r := range m.Resources {
|
|
if r.Type != "container" || r.ID != "server" {
|
|
continue
|
|
}
|
|
if r.Name != giteaBootstrap {
|
|
t.Errorf("the module names its container %q; genesis raises %q", r.Name, giteaBootstrap)
|
|
}
|
|
if r.Image != giteaImage {
|
|
t.Errorf("the module pins %s; genesis raises %s — the two must move together", r.Image, giteaImage)
|
|
}
|
|
if len(r.Volumes) != 1 || !strings.HasSuffix(r.Volumes[0], ":/data") {
|
|
t.Errorf("the module mounts %v; genesis mounts %s:/data", r.Volumes, giteaDataDir)
|
|
}
|
|
}
|
|
}
|