Genesis registers the control plane with the manifest its build produced
The control plane's manifest existed twice: at the root of its repository, read whenever the mesh rebuilds it from source, and as a copy in the catalogue, read by genesis. Nothing kept them equal, and the first rebuild replaced the mesh's record with the repository's shape while every later push was refused (novox/hq 04-ISSUES/072). The builder's one-shot result already carries the manifest it built, artifact resolved to the image; step 3 keeps it and step 9 registers it, re-pinning the built image's bare id to the reference the registry assigned. The catalogue is still read for the registry's and the builder's manifests and for phase two.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package bootstrap
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
@@ -57,13 +58,19 @@ type Built struct {
|
||||
// Image is the artifact, named by the digest of its own configuration — the identity a machine
|
||||
// can use with nothing serving it, and the same one the installer used for a carried image.
|
||||
Image string
|
||||
// Manifest is the module as the mesh should hold it: the manifest at the root of the repository
|
||||
// that was built, its artifact resolved to Image. It is the control plane's ONE manifest
|
||||
// (novox/hq ADR 0069) — the installer used to read a second copy out of the catalogue, and the
|
||||
// two drifted apart the first time somebody edited one (novox/hq 04-ISSUES/072).
|
||||
Manifest []byte
|
||||
}
|
||||
|
||||
// builderOutput is the part of the builder's one-shot result this needs.
|
||||
type builderOutput struct {
|
||||
Module string `json:"module"`
|
||||
Commit string `json:"commit"`
|
||||
Made []struct {
|
||||
Module string `json:"module"`
|
||||
Commit string `json:"commit"`
|
||||
Manifest json.RawMessage `json:"manifest"`
|
||||
Made []struct {
|
||||
Name string `json:"name"`
|
||||
Kind string `json:"kind"`
|
||||
Reference string `json:"reference"`
|
||||
@@ -142,8 +149,25 @@ func BuildControlPlane(ctx context.Context, run Runner, builderTag string, sourc
|
||||
result.Module, len(images))
|
||||
}
|
||||
|
||||
// The manifest is what the mesh will hold the control plane as, so a result without one is
|
||||
// a build the installer cannot finish — refused here, beside the builder that said it, rather
|
||||
// than at step 9 with a message about a missing file.
|
||||
manifest := bytes.TrimSpace(result.Manifest)
|
||||
if len(manifest) == 0 || bytes.Equal(manifest, []byte("null")) {
|
||||
return Built{}, fmt.Errorf(
|
||||
"%s built, and the builder reported no manifest for it. The installer registers the "+
|
||||
"control plane with the manifest the build produced — the one at the root of its "+
|
||||
"repository, its artifact resolved — and has no other copy to use", result.Module)
|
||||
}
|
||||
if !bytes.Contains(manifest, []byte(`"`+images[0]+`"`)) {
|
||||
return Built{}, fmt.Errorf(
|
||||
"%s built %s, and the manifest the builder reported does not name that image, so "+
|
||||
"the installer cannot tell which of its resources runs the control plane",
|
||||
result.Module, images[0])
|
||||
}
|
||||
|
||||
say(fmt.Sprintf(" built %s from %s", result.Module, shortRef(result.Commit)))
|
||||
return Built{Module: result.Module, Commit: result.Commit, Image: images[0]}, nil
|
||||
return Built{Module: result.Module, Commit: result.Commit, Image: images[0], Manifest: manifest}, nil
|
||||
}
|
||||
|
||||
func shortRef(ref string) string {
|
||||
|
||||
Reference in New Issue
Block a user