package hostactors import ( "context" "encoding/json" "github.com/carlosframework/platform/internal/hostfloor" "github.com/carlosframework/platform/internal/release" "strings" "testing" "time" ) type reportsFixture struct { d Directory box, console Report wire []byte } func (e reportsFixture) BoxReport(context.Context, string, Box) (Report, error) { return e.box, nil } func (e reportsFixture) ConsoleReport(context.Context, string, Console) (Report, error) { return e.console, nil } func (e reportsFixture) LocalConsole(context.Context) (Report, error) { return e.console, nil } func (e reportsFixture) Identity(context.Context, string) ([]byte, error) { return e.wire, nil } func (e reportsFixture) Fence(ctx context.Context, o Observed, ref string, now time.Time) (bool, error) { return e.d.TerminationFence(ctx, o, ref, now) } func censusFixture(t *testing.T) (Directory, Observed, reportsFixture, hostfloor.Verified, Scope, time.Time) { t.Helper() ctx := context.Background() d, sg, o := fixture(t) now := time.Now().UTC() tag := "v1.2.3" hash := strings.Repeat("a", 64) rel := release.SystemRelease{ConsoleArtifacts: map[string]release.SystemArtifact{"linux-amd64": {Key: "bootstrap/console/build123/carlos-linux-amd64", SHA256: hash}}, Version: "build123", ReleaseTag: tag, MovesProtocol: 1, Artifacts: map[string]release.SystemArtifact{"linux-amd64": {Key: release.SystemArtifactKey("build123", "linux-amd64"), SHA256: hash}}} if _, err := release.PromoteSystem(ctx, d.Store, sg, "router", "stable", rel, release.SystemPromoteOptions{}); err != nil { t.Fatal(err) } wire, _, err := d.Store.Get(ctx, release.SystemPointerKey("router", "stable")) if err != nil { t.Fatal(err) } key, err := release.IdentityKey(tag) if err != nil { t.Fatal(err) } if err := release.CreateExact(ctx, d.Store, key, wire); err != nil { t.Fatal(err) } floor := hostfloor.Floor{Min: 1, MinRelease: tag} raw, _ := json.Marshal(floor) f := hostfloor.Verified{Floor: floor, Digest: hostfloor.Digest(raw)} o.Roster.Regions = map[string]Region{"ie": {Account: "123", AWSRegion: "eu-west-1", Namespaces: []string{"platform"}, Pools: []string{"default"}}} o.Roster.Publication = "published" o.Roster.FloorSHA256 = f.Digest c := Console{Enrollment: strings.Repeat("c", 32), InstanceID: "console-1", Namespaces: []string{"platform"}, DeploymentBucket: d.Bucket} o.Roster.Consoles["console-1"] = c box := Report{Component: "router", GeneratedAt: now, Actor: "box", Enrollment: o.Roster.Boxes["box"].Enrollment, InstanceID: "i-box", Release: "build123", ReleaseTag: tag, Platform: "linux-amd64", BinarySHA256: hash, MovesProtocol: 1, BootID: "boot", FloorSHA256: f.Digest, FloorGuardReady: true, HostClaimEnabled: true} console := box console.Component = "console" console.Actor = "console-1" console.Enrollment = c.Enrollment console.InstanceID = "console-1" console.ProcessID = "process-1" return d, o, reportsFixture{d: d, box: box, console: console, wire: wire}, f, Scope{Namespace: "platform", Regions: []string{"ie"}, Pools: []string{"default"}, ConsoleID: "console-1"}, now } func TestCensusRejectsMissingStaleAndWrongImages(t *testing.T) { for _, field := range []string{"good", "old-box", "old-console", "future", "image", "floor", "flag", "enrollment", "scope", "unknown-participant", "unknown-region", "unknown-pool", "unknown-namespace"} { t.Run(field, func(t *testing.T) { d, o, e, f, scope, now := censusFixture(t) switch field { case "old-box": e.box.GeneratedAt = now.Add(-16 * time.Minute) case "old-console": e.console.GeneratedAt = now.Add(-16 * time.Minute) case "future": e.box.GeneratedAt = now.Add(6 * time.Second) case "image": e.box.BinarySHA256 = strings.Repeat("b", 64) case "floor": e.console.FloorSHA256 = "" case "flag": e.box.HostClaimEnabled = false case "enrollment": e.box.Enrollment = "another" case "scope": scope.Regions = nil case "unknown-region": scope.Regions = []string{"nowhere"} case "unknown-pool": scope.Pools = []string{"nowhere"} case "unknown-namespace": scope.Namespace = "unknown" case "unknown-participant": scope.Participants = []string{"unknown"} } _, err := Census(context.Background(), o, e, d.PublicKey, f, scope, now) if (err == nil) != (field == "good") { t.Fatal(field, err) } }) } }