PlansHeld holds a module whose build cannot be taken in or whose plan refuses, by composeEach's rule, and composes every other module's plan; sealedFor gives a file the stand-in its own secret's file has (baserow on ace); shipsABundle reads a built manifest's Bundles (nats on novox).
77 lines
3.3 KiB
Go
77 lines
3.3 KiB
Go
package frombustest
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
"testing"
|
|
|
|
"git.novox.be/novox/mesh-sdk/go/compose/frombus"
|
|
"git.novox.be/novox/mesh-sdk/go/delivery"
|
|
)
|
|
|
|
// ADR 0570 clause 2 (issue 1954; a3's H5): the in-memory mesh composes a plan from the bus that hands restic to the
|
|
// provisioner and names its postgres-database, provided by postgres on n1. And one bad module must not drop its node
|
|
// (issue 774): with a module placed beside it whose built manifest cannot be used, or whose plan refuses, PlansHeld
|
|
// still hands restic's plan and names the bad one with why, where Plans refuses the whole node.
|
|
func TestTheProvisionedMeshHandsAPlanWithItsProvision(t *testing.T) {
|
|
fp := "src2:" + strings.Repeat("9", 64)
|
|
for _, row := range []struct {
|
|
name string
|
|
bad string // the indexer's manifest of a module "backup" placed on n1; empty places none
|
|
// built is the manifest backup's done build names; empty gives it no build
|
|
built string
|
|
why string // words backup's hold says
|
|
}{
|
|
{name: "every module composes"},
|
|
{name: "a built manifest that cannot be used",
|
|
bad: `{"module":"backup","version":"1","build":{"artifacts":[{"name":"files","kind":"archive","from":"files"}]}}`,
|
|
built: `{"module":"backup","version":"1","requires":["amqp"]}`, why: "backup"},
|
|
{name: "a plan that refuses",
|
|
bad: `{"module":"backup","version":"1","resources":[{"id":"conf","type":"file","path":"/etc/backup.conf",` +
|
|
`"mode":"0600","content":"key=${secret:nope}"}]}`, why: "${secret:nope}"},
|
|
} {
|
|
b, err := Provisioned()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if row.bad != "" {
|
|
p := b.Placement[Node]
|
|
p.Modules = append(p.Modules, delivery.PlacedModule{Module: "backup"})
|
|
b.Placement[Node] = p
|
|
digest := delivery.ManifestDigest([]byte(row.bad))
|
|
b.Manifests[digest] = []byte(row.bad)
|
|
b.Module["backup"] = delivery.Module{FP2: fp, Manifest: digest}
|
|
if row.built != "" {
|
|
builtDigest := delivery.ManifestDigest([]byte(row.built))
|
|
b.Manifests[builtDigest] = []byte(row.built)
|
|
b.Builds["backup "+fp] = &delivery.BuilderBuild{State: delivery.BuildDone, Manifest: builtDigest,
|
|
Artifacts: []delivery.BuiltArtifact{{Name: "files", Kind: "archive", Reference: "artifact-store://backup/files/blobs/x", Digest: "sha256:x"}}}
|
|
}
|
|
if _, err := frombus.Plans(context.Background(), b, frombus.Mesh{}, frombus.Scope{Node: Node}); err == nil {
|
|
t.Errorf("%s: Plans composed the node; the row does not refuse it", row.name)
|
|
}
|
|
}
|
|
plans, held, err := frombus.PlansHeld(context.Background(), b, frombus.Mesh{}, frombus.Scope{Node: Node})
|
|
if err != nil {
|
|
t.Fatalf("%s: %v", row.name, err)
|
|
}
|
|
restic, handed := plans["restic"]
|
|
if !handed || len(restic.Provisions) != 1 || restic.Provisions[0].Provision != "postgres-database" ||
|
|
restic.Provisions[0].Provider != Node || restic.Provisions[0].ProviderModule != "postgres" {
|
|
t.Fatalf("%s: the plans are %+v (held %v)", row.name, plans, held)
|
|
}
|
|
if row.bad == "" {
|
|
if len(held) > 0 {
|
|
t.Errorf("%s: held %v", row.name, held)
|
|
}
|
|
continue
|
|
}
|
|
if why, ok := held["backup"]; !ok || !strings.Contains(why, row.why) || len(held) != 1 {
|
|
t.Errorf("%s: held %v, want backup alone, saying %q", row.name, held, row.why)
|
|
}
|
|
if _, planned := plans["backup"]; planned {
|
|
t.Errorf("%s: the held module has a plan", row.name)
|
|
}
|
|
}
|
|
}
|