Raise a process-form controller at genesis as the container it replaces (hq issue 223)
The controller's manifest now declares a Go bundle the host runs as a process (novox/hq issue 213). Genesis cannot run that: the bundle is fetched from the artifact store and compiled in a toolchain, and the mesh makes both long after the controller. The builder, asked to build the manifest at genesis, refuses for lack of the Go toolchain. So genesis raises the controller as before, as a container, and the first push hands it over to the process through `replaces` (issue 223, option b). - Step 3 clones the controller at the commit with the carried builder's git and reads its manifest. In the image form (an older controller) it builds through the builder as before. In the process form it builds the repository's own Dockerfile and hands step 9 a manifest of its own shape: the process becomes a container with the id the process `replaces`, the image genesis built, host network, and every host path the process's env names mounted at that same path read-only. Secrets belong to the image's user (65534) until the process's account takes them over. `prepares` is dropped: the temporary controller from the same commit already migrated the stores, and a pinned image is nothing the controller can derive a step from. - Steps 4 to 9 are unchanged: they take the manifest as they did. - apply.ForTests lets the bootstrap's test apply a process. The first composed declaration from the process manifest names `mesh-controller.server`, which is what the host recorded for the genesis container, so the first apply hands over and leaves one controller.
This commit is contained in:
@@ -6,6 +6,8 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@@ -112,6 +114,43 @@ func BuildControlPlane(ctx context.Context, run Runner, builderTag string, sourc
|
||||
return Built{}, nil
|
||||
}
|
||||
|
||||
// **Which form the controller is in at that commit** (novox/hq issue 223). An image the module
|
||||
// builds is the form genesis always raised, and the builder builds it as before. A process the
|
||||
// module runs from a Go bundle cannot be built here — its toolchain is one the mesh makes later —
|
||||
// so genesis builds the controller's own Dockerfile and raises it as the container that process
|
||||
// replaces (genesis_form.go).
|
||||
workspace, err := os.MkdirTemp("", "mesh-genesis-*")
|
||||
if err != nil {
|
||||
return Built{}, err
|
||||
}
|
||||
defer os.RemoveAll(workspace)
|
||||
dir, commit, err := cloneAt(ctx, run, builderTag, source, workspace)
|
||||
if err != nil {
|
||||
return Built{}, fmt.Errorf("the control plane could not be fetched from %s at %s: %w",
|
||||
source.Repository, shortRef(source.Ref), err)
|
||||
}
|
||||
raw, err := os.ReadFile(filepath.Join(dir, "module.json"))
|
||||
if err != nil {
|
||||
return Built{}, fmt.Errorf("%s at %s has no module manifest: %w", source.Repository, shortRef(source.Ref), err)
|
||||
}
|
||||
form, err := processFormOf(raw)
|
||||
if err != nil {
|
||||
return Built{}, err
|
||||
}
|
||||
if form.Found {
|
||||
image, err := buildGenesisImage(ctx, run, dir)
|
||||
if err != nil {
|
||||
return Built{}, err
|
||||
}
|
||||
manifest, err := genesisForm(raw, form, image)
|
||||
if err != nil {
|
||||
return Built{}, err
|
||||
}
|
||||
say(fmt.Sprintf(" built %s from %s, as the container its process %s replaces (%s)",
|
||||
ControlPlaneModule, shortRef(commit), form.Process, form.Replaces))
|
||||
return Built{Module: ControlPlaneModule, Commit: commit, Image: image, Manifest: manifest}, nil
|
||||
}
|
||||
|
||||
out, err := run(ctx, "docker", args...)
|
||||
if err != nil {
|
||||
return Built{}, fmt.Errorf("the control plane could not be built from %s at %s: %w",
|
||||
|
||||
Reference in New Issue
Block a user