The controller is a Go program and was the one piece of the mesh's own Go code still shipped and run as an image (novox/hq issue 213; ADR 0188 §1: a module's own code is bundles; §3: a service bundle is a process). The manifest now builds one Go bundle, `controller`, and runs it as the process `mesh-controller` (`./mesh-controller serve`) under an account the module declares. What the container gave it, replaced: - host network: a process is on the host's network; nothing it reads names a container network - user 65534: the account `mesh-controller`, which owns its secrets and its state directory - the eight mounts: the env names the host paths the mesh already places (the store, broker and bus files under the state directory, the broker's certificate under /var/lib/mesh-broker-tls); the `broker` mount was read by nothing and is gone with the others - `container-runtime` is no longer required on its machine Its preparation is the same binary with `prepare`, as a run-once process, and the process `replaces` the container `server`: the host keeps the container answering until the process is running (mesh-host). Needs the previous commit live in the running controller, and the host's `replaces` on the controller's machine, before it is registered. No image is built by the mesh any more. The Dockerfile stays for genesis and the lab (`make image`, its Go base now pinned in the Makefile).
53 lines
1.7 KiB
Go
53 lines
1.7 KiB
Go
package store
|
|
|
|
import (
|
|
"encoding/json"
|
|
"os"
|
|
"testing"
|
|
)
|
|
|
|
// **The manifest's placeholder, unfilled, reaches a store reader and changes nothing.**
|
|
//
|
|
// The control plane composes its own declaration, so the manifest naming `${seat:…}` can be
|
|
// composed by a control plane one build older than it — one that passes the literal through as
|
|
// the value. That is the state of the live control-node between this manifest landing and its
|
|
// next build being pushed, and a reader that refused the literal would leave it headless
|
|
// (novox/hq 04-ISSUES/102, finding F1). So the reader is held to ignoring exactly what
|
|
// module.json says, not a placeholder shaped like it.
|
|
func TestTheManifestsOwnPlaceholderUnfilledLeavesTheStoreWhereTheFileSays(t *testing.T) {
|
|
raw, err := os.ReadFile("../../module.json")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var m struct {
|
|
Resources []struct {
|
|
Type string `json:"type"`
|
|
Env map[string]string `json:"env"`
|
|
} `json:"resources"`
|
|
}
|
|
if err := json.Unmarshal(raw, &m); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var written string
|
|
for _, r := range m.Resources {
|
|
if r.Type == "process" {
|
|
written = r.Env["MESH_STORE_INVENTORY_PORT"]
|
|
}
|
|
}
|
|
if written == "" {
|
|
t.Fatal("module.json no longer names MESH_STORE_INVENTORY_PORT")
|
|
}
|
|
|
|
alone(t)
|
|
t.Setenv(Variable(example), dsn)
|
|
t.Setenv(PortVariable(example), written)
|
|
opened, err := Open(t.Context(), example)
|
|
if err != nil {
|
|
t.Fatalf("the unfilled placeholder was refused, which is a headless control plane: %v", err)
|
|
}
|
|
defer opened.Close()
|
|
if got := opened.Pool().Config().ConnConfig.Port; got != 5432 {
|
|
t.Fatalf("the store is on %d; with the placeholder unfilled, the file's port stands", got)
|
|
}
|
|
}
|