package bootstrap import ( "context" "strings" "testing" ) // An installer that carries a builder and was told nothing refuses, and says what is missing. // // **Exercised rather than assumed.** This is the refusal that stands between a person and a // machine left holding a store, a broker and no control plane — the failure the whole preflight // exists to prevent — and a refusal nothing tests is a refusal nobody has read. func TestAnInstallerWithNothingToBuildRefuses(t *testing.T) { err := Source{}.Check() if err == nil { t.Fatal("a source naming no repository was accepted; nothing would have been built") } for _, want := range []string{"--source", "--source-ref"} { if !strings.Contains(err.Error(), want) { t.Errorf("the refusal does not name %s, so it does not say how to fix it: %v", want, err) } } } // A repository without a commit refuses too, because a branch is somebody else's moving target. func TestABranchIsNotACommit(t *testing.T) { err := Source{Repository: "https://example.invalid/mesh-controller.git"}.Check() if err == nil { t.Fatal("a source with no ref was accepted; genesis would have built whatever a branch pointed at") } if !strings.Contains(err.Error(), "--source-ref") { t.Errorf("the refusal does not name the flag that fixes it: %v", err) } } // And a repository with a commit is enough. func TestARepositoryAndACommitIsEnough(t *testing.T) { if err := (Source{Repository: "https://example.invalid/mesh-controller.git", Ref: "a1b2c3d4"}).Check(); err != nil { t.Fatalf("a repository and a commit were refused: %v", err) } } // **The build hands over the manifest, and the installer registers that one.** The control plane // used to have two manifests — one at the root of its repository, which the mesh reads whenever // it rebuilds the control plane from source, and a copy in the catalogue, which genesis read — and // nothing kept them equal (novox/hq 04-ISSUES/072). The builder already reports the manifest it // built, artifact resolved to the image; genesis takes it from there and reads no second copy. func TestTheBuildHandsOverTheManifestTheMeshWillHold(t *testing.T) { manifest := `{"module":"mesh-controller","version":"1","resources":[` + `{"id":"server","type":"container","name":"mesh-controller","image":"` + builtImage + `"}]}` runtime := &asked{answer: func(string, []string) (string, error) { return `{"module":"mesh-controller","commit":"a1b2c3d4","manifest":` + manifest + `,"made":[{"name":"server","kind":"image","reference":"` + builtImage + `"}]}` + "\n", nil }} built, err := BuildControlPlane(context.Background(), runtime.run, "mesh-builder:test", Source{Repository: "https://example.invalid/mesh-controller.git", Ref: "a1b2c3d4"}, false, func(string) {}) if err != nil { t.Fatal(err) } if built.Image != builtImage { t.Errorf("the built image is %q", built.Image) } if string(built.Manifest) != manifest { t.Errorf("the manifest handed over is not the one the builder reported:\n%s", built.Manifest) } } // A result without a manifest is a build the installer cannot finish, and it is refused beside the // builder that said it rather than at step 9 with a message about a missing file. func TestABuildReportingNoManifestIsRefused(t *testing.T) { runtime := &asked{answer: func(string, []string) (string, error) { return `{"module":"mesh-controller","commit":"a1b2c3d4",` + `"made":[{"name":"server","kind":"image","reference":"` + builtImage + `"}]}`, nil }} _, err := BuildControlPlane(context.Background(), runtime.run, "mesh-builder:test", Source{Repository: "https://example.invalid/mesh-controller.git", Ref: "a1b2c3d4"}, false, func(string) {}) if err == nil || !strings.Contains(err.Error(), "no manifest") { t.Fatalf("a build reporting no manifest was accepted, or refused for another reason: %v", err) } } // And a manifest that does not name the image the build produced describes some other build. func TestABuildWhoseManifestNamesAnotherImageIsRefused(t *testing.T) { runtime := &asked{answer: func(string, []string) (string, error) { return `{"module":"mesh-controller","commit":"a1b2c3d4","manifest":{"module":"mesh-controller",` + `"resources":[{"id":"server","type":"container","image":"sha256:` + strings.Repeat("9", 64) + `"}]},` + `"made":[{"name":"server","kind":"image","reference":"` + builtImage + `"}]}`, nil }} _, err := BuildControlPlane(context.Background(), runtime.run, "mesh-builder:test", Source{Repository: "https://example.invalid/mesh-controller.git", Ref: "a1b2c3d4"}, false, func(string) {}) if err == nil || !strings.Contains(err.Error(), "does not name that image") { t.Fatalf("a manifest naming another image was accepted, or refused for another reason: %v", err) } }