package host import ( "context" "fmt" "testing" "github.com/carlosframework/platform/internal/hostbox" "github.com/carlosframework/platform/internal/hostclaim" execlease "github.com/carlosframework/platform/internal/hostexec" "github.com/carlosframework/platform/internal/hostguard" "github.com/carlosframework/platform/internal/provision" "github.com/carlosframework/platform/internal/registry" ) func TestPlan14ExecutionPreinstallationAuthority(t *testing.T) { t.Parallel() for _, kind := range []string{hostclaim.KindRelocating, hostclaim.KindLanding, hostclaim.KindMoving} { for _, attack := range []string{"none", "wrong phase", "wrong box", "foreign census", "stale session", "record", "enrollment", "stamp", "incarnation"} { t.Run(kind+"/"+attack, func(t *testing.T) { phase := hostclaim.PhaseInstalling if kind == hostclaim.KindLanding { phase = provision.LandChecking } f, root, iq := plan14InstallRegistration(t, kind, phase) actor, _ := root.InventoryActor(t.Context()) if _, err := hostclaim.Update(t.Context(), f.claims, f.read(), func(c *hostclaim.Claim) error { c.Op.Intent["target_enrollment"] = "en" if kind == hostclaim.KindMoving { c.Op.Exec = "box-0" c.Op.Phase = hostclaim.PhaseMoving } if kind == hostclaim.KindRelocating { c.Op.Exec = "box-0" c.Op.Phase = hostclaim.PhaseStarting } return nil }); err != nil { t.Fatal(err) } q := execlease.ExecutionRequest{Schema: 1, ID: "begin-1", Operation: "executionBegin", Host: iq.Target.Host, Incarnation: iq.Target.Incarnation, Stamp: iq.Target.Stamp, Session: iq.Target.Session, Op: iq.Target.Op} switch attack { case "wrong phase": _, err := hostclaim.Update(t.Context(), f.claims, f.read(), func(c *hostclaim.Claim) error { c.Op.Phase = "probing"; c.Op.Exec = "box-1"; return nil }) if err != nil { t.Fatal(err) } case "wrong box": actor.Box = "unnamed" case "foreign census": if err := root.Reconcile.Registry.Upsert(registry.Route{Host: q.Host, Account: "foreign", App: "foreign"}); err != nil { t.Fatal(err) } case "stale session": q.Session++ case "stamp": q.Stamp++ case "incarnation": q.Incarnation = "other" case "enrollment": actor.Enrollment = "other" case "record": raw, etag, err := f.claims.Get(t.Context(), iq.RecordKey) if err != nil { t.Fatal(err) } _ = raw if _, err = f.claims.Put(t.Context(), iq.RecordKey, []byte(`{"schema":1,"host":"other.example.com","account":"bab","app":"jam"}`), etag); err != nil { t.Fatal(err) } } root.InventoryActor = func(context.Context) (hostbox.Actor, error) { return actor, nil } a, err := root.executionAuthority(t.Context(), q, execlease.ControllerProcess{}) if attack != "none" { if err == nil { t.Fatalf("admitted %s: %+v", attack, a) } return } if err != nil { t.Fatal(err) } if !a.ParticipationOnly || a.Installation != "" { t.Fatalf("preinstallation gained effects: %+v", a) } if _, err := root.Stop.Coordinator.Guard.Capture(q.Host); err == nil { t.Fatal("participation registered installation") } }) } } } func TestPlan14ExecutionPendingRegistration(t *testing.T) { t.Parallel() for _, kind := range []string{hostclaim.KindServing, hostclaim.KindRelocating, hostclaim.KindLanding} { t.Run(kind, func(t *testing.T) { phase := hostclaim.PhaseInstalling if kind == hostclaim.KindLanding { phase = provision.LandChecking } _, root, iq := plan14InstallRegistration(t, kind, phase) store := &plan14RegistrationCrash{rollbackDisk: &rollbackDisk{dir: t.TempDir()}} root.Stop.Coordinator.Guard.Root = hostguard.NewRootAuthority(store) if _, err := root.commitRootInventory(t.Context(), iq); err == nil { t.Fatal("missed registration interruption") } q := execlease.ExecutionRequest{Schema: 1, ID: "pending-registration", Operation: "executionBegin", Host: iq.Target.Host, Incarnation: iq.Target.Incarnation, Stamp: iq.Target.Stamp, Session: iq.Target.Session, Op: iq.Target.Op} a, err := root.executionAuthority(t.Context(), q, execlease.ControllerProcess{}) if err != nil || !a.ParticipationOnly || a.Installation == "" { t.Fatalf("pending registration participation: %+v %v", a, err) } if _, err := root.Stop.Coordinator.Guard.Root.View(t.Context(), q.Host, hostguard.Captured{Incarnation: q.Incarnation, Stamp: q.Stamp}); err == nil { t.Fatal("participation admitted installation effects") } q.Session++ if _, err := root.executionAuthority(t.Context(), q, execlease.ControllerProcess{}); err == nil { t.Fatal("stale pending registration session admitted") } }) } } func TestPlan14ExecutionServingNamesLocalWriter(t *testing.T) { t.Parallel() for _, foreign := range []bool{false, true} { t.Run(fmt.Sprint(foreign), func(t *testing.T) { f, root, iq := plan14InstallRegistration(t, hostclaim.KindServing, "") if _, err := root.commitRootInventory(t.Context(), iq); err != nil { t.Fatal(err) } if foreign { if _, err := hostclaim.Update(t.Context(), f.claims, f.read(), func(c *hostclaim.Claim) error { c.Op.Exec, c.Holder.WriterBox = "box-0", "box-0" return nil }); err != nil { t.Fatal(err) } } q := execlease.ExecutionRequest{Schema: 1, ID: "serving", Operation: "executionView", Host: iq.Target.Host, Incarnation: iq.Target.Incarnation, Stamp: iq.Target.Stamp, Session: iq.Target.Session, Op: iq.Target.Op} _, err := root.executionAuthority(t.Context(), q, execlease.ControllerProcess{}) if foreign && err == nil { t.Fatal("retained local installation granted another box's serving session") } if !foreign && err != nil { t.Fatal(err) } }) } }