package host import ( "context" "errors" "os/exec" "testing" "github.com/carlosframework/platform/internal/activator" "github.com/carlosframework/platform/internal/hostbox" "github.com/carlosframework/platform/internal/hostclaim" "github.com/carlosframework/platform/internal/registry" ) // R1 in the wake runtime (with the claimwakeassembly shared edit): the // relocation target's probe is admitted at probing where op.exec is this // box, only with region HA's attempts bound through the router. The // source's ordinary wake in starting or releasing, a target's ordinary // wake, a probe at any other phase and a probe on another box all keep the // typed refusal or K6's ErrChanged, before any lease or reservation. func TestPlan11WakeAdmitsOnlyTheRelocationProbe(t *testing.T) { ready := func(context.Context, *exec.Cmd, registry.Route, ClaimLaunchInputs, string) error { return nil } moves := &plan9D2Attempts{} plan9 := &ClaimWakeAssembly{Operations: moves, ProbeReady: ready} probe := activator.StartPolicy{Probe: true} var refusal *ClaimDependencyError if err := plan9.admitsOperation(plan11Relocating("probing"), probe, "box-2"); !errors.As(err, &refusal) { t.Fatalf("relocating probe without region HA: %v", err) } w := &ClaimWakeAssembly{Operations: claimOperationRouter{hostclaim.KindLanding: {Attempts: moves, ProbeReady: ready}, hostclaim.KindRelocating: {Attempts: &plan9D2Attempts{}, ProbeReady: ready}}, ProbeReady: ready} if err := w.admitsOperation(plan11Relocating("probing"), probe, "box-2"); err != nil { t.Fatalf("relocation probe: %v", err) } for name, tc := range map[string]struct { o hostclaim.Observed p activator.StartPolicy box string }{ "source ordinary in starting": {plan11Relocating("starting"), activator.StartPolicy{}, "box-1"}, "source ordinary in releasing": {plan11Relocating("releasing"), activator.StartPolicy{}, "box-1"}, "target ordinary in probing": {plan11Relocating("probing"), activator.StartPolicy{}, "box-2"}, "target ordinary in serving": {plan11Relocating("serving"), activator.StartPolicy{}, "box-2"}, "probe in installed": {plan11Relocating("installed"), probe, "box-2"}, "probe in probe-failed": {plan11Relocating("probe-failed"), probe, "box-2"}, "probe on another box": {plan11Relocating("probing"), probe, "box-1"}, } { if err := w.admitsOperation(tc.o, tc.p, tc.box); !errors.Is(err, hostbox.ErrChanged) && !errors.As(err, &refusal) { t.Errorf("%s admitted: %v", name, err) } } // Landing is unchanged through the router. landing := plan9D5Kind(hostclaim.KindLanding) landing.Claim.Op.Phase, landing.Claim.Op.Exec = "probing", "box-2" if err := w.admitsOperation(landing, probe, "box-2"); err != nil { t.Fatalf("landing probe: %v", err) } // No probe readiness for the kind refuses its probe. w.Operations = claimOperationRouter{hostclaim.KindRelocating: {Attempts: &plan9D2Attempts{}}} if err := w.admitsOperation(plan11Relocating("probing"), probe, "box-2"); !errors.As(err, &refusal) { t.Fatalf("relocation probe without readiness: %v", err) } } // bindOperation binds a relocating start to region HA's journal, not moves'. func TestPlan11WakeBindsTheRelocationJournal(t *testing.T) { moves, reloc := &plan9D2Attempts{}, &plan9D2Attempts{} w := &ClaimWakeAssembly{Operations: claimOperationRouter{hostclaim.KindLanding: {Attempts: moves}, hostclaim.KindRelocating: {Attempts: reloc}}} s := activator.ClaimStart{Ready: func(context.Context, *exec.Cmd) error { return nil }} if err := w.bindOperation(&s, OperationStart{Admitted: plan11Relocating("probing"), Policy: activator.StartPolicy{Probe: true}}); err != nil { t.Fatal(err) } if err := s.Reserve(context.Background(), 1); err != nil || len(reloc.calls) != 1 || len(moves.calls) != 0 { t.Fatalf("bound journal: %v %v %v", err, reloc.calls, moves.calls) } var refusal *ClaimDependencyError if err := w.bindOperation(&activator.ClaimStart{Ready: s.Ready}, OperationStart{Admitted: plan9D5Kind(hostclaim.KindRestoring)}); !errors.As(err, &refusal) { t.Fatalf("unrouted kind bound: %v", err) } }