| 1 | package host |
| 2 | |
| 3 | import ( |
| 4 | "context" |
| 5 | "errors" |
| 6 | "os/exec" |
| 7 | "testing" |
| 8 | |
| 9 | "github.com/carlosframework/platform/internal/activator" |
| 10 | "github.com/carlosframework/platform/internal/hostbox" |
| 11 | "github.com/carlosframework/platform/internal/hostclaim" |
| 12 | "github.com/carlosframework/platform/internal/registry" |
| 13 | ) |
| 14 | |
| 15 | // R1 in the wake runtime (with the claimwakeassembly shared edit): the |
| 16 | // relocation target's probe is admitted at probing where op.exec is this |
| 17 | // box, only with region HA's attempts bound through the router. The |
| 18 | // source's ordinary wake in starting or releasing, a target's ordinary |
| 19 | // wake, a probe at any other phase and a probe on another box all keep the |
| 20 | // typed refusal or K6's ErrChanged, before any lease or reservation. |
| 21 | func TestPlan11WakeAdmitsOnlyTheRelocationProbe(t *testing.T) { |
| 22 | ready := func(context.Context, *exec.Cmd, registry.Route, ClaimLaunchInputs, string) error { return nil } |
| 23 | moves := &plan9D2Attempts{} |
| 24 | plan9 := &ClaimWakeAssembly{Operations: moves, ProbeReady: ready} |
| 25 | probe := activator.StartPolicy{Probe: true} |
| 26 | var refusal *ClaimDependencyError |
| 27 | if err := plan9.admitsOperation(plan11Relocating("probing"), probe, "box-2"); !errors.As(err, &refusal) { |
| 28 | t.Fatalf("relocating probe without region HA: %v", err) |
| 29 | } |
| 30 | w := &ClaimWakeAssembly{Operations: claimOperationRouter{hostclaim.KindLanding: {Attempts: moves, ProbeReady: ready}, hostclaim.KindRelocating: {Attempts: &plan9D2Attempts{}, ProbeReady: ready}}, ProbeReady: ready} |
| 31 | if err := w.admitsOperation(plan11Relocating("probing"), probe, "box-2"); err != nil { |
| 32 | t.Fatalf("relocation probe: %v", err) |
| 33 | } |
| 34 | for name, tc := range map[string]struct { |
| 35 | o hostclaim.Observed |
| 36 | p activator.StartPolicy |
| 37 | box string |
| 38 | }{ |
| 39 | "source ordinary in starting": {plan11Relocating("starting"), activator.StartPolicy{}, "box-1"}, |
| 40 | "source ordinary in releasing": {plan11Relocating("releasing"), activator.StartPolicy{}, "box-1"}, |
| 41 | "target ordinary in probing": {plan11Relocating("probing"), activator.StartPolicy{}, "box-2"}, |
| 42 | "target ordinary in serving": {plan11Relocating("serving"), activator.StartPolicy{}, "box-2"}, |
| 43 | "probe in installed": {plan11Relocating("installed"), probe, "box-2"}, |
| 44 | "probe in probe-failed": {plan11Relocating("probe-failed"), probe, "box-2"}, |
| 45 | "probe on another box": {plan11Relocating("probing"), probe, "box-1"}, |
| 46 | } { |
| 47 | if err := w.admitsOperation(tc.o, tc.p, tc.box); !errors.Is(err, hostbox.ErrChanged) && !errors.As(err, &refusal) { |
| 48 | t.Errorf("%s admitted: %v", name, err) |
| 49 | } |
| 50 | } |
| 51 | // Landing is unchanged through the router. |
| 52 | landing := plan9D5Kind(hostclaim.KindLanding) |
| 53 | landing.Claim.Op.Phase, landing.Claim.Op.Exec = "probing", "box-2" |
| 54 | if err := w.admitsOperation(landing, probe, "box-2"); err != nil { |
| 55 | t.Fatalf("landing probe: %v", err) |
| 56 | } |
| 57 | // No probe readiness for the kind refuses its probe. |
| 58 | w.Operations = claimOperationRouter{hostclaim.KindRelocating: {Attempts: &plan9D2Attempts{}}} |
| 59 | if err := w.admitsOperation(plan11Relocating("probing"), probe, "box-2"); !errors.As(err, &refusal) { |
| 60 | t.Fatalf("relocation probe without readiness: %v", err) |
| 61 | } |
| 62 | } |
| 63 | |
| 64 | // bindOperation binds a relocating start to region HA's journal, not moves'. |
| 65 | func TestPlan11WakeBindsTheRelocationJournal(t *testing.T) { |
| 66 | moves, reloc := &plan9D2Attempts{}, &plan9D2Attempts{} |
| 67 | w := &ClaimWakeAssembly{Operations: claimOperationRouter{hostclaim.KindLanding: {Attempts: moves}, hostclaim.KindRelocating: {Attempts: reloc}}} |
| 68 | s := activator.ClaimStart{Ready: func(context.Context, *exec.Cmd) error { return nil }} |
| 69 | if err := w.bindOperation(&s, OperationStart{Admitted: plan11Relocating("probing"), Policy: activator.StartPolicy{Probe: true}}); err != nil { |
| 70 | t.Fatal(err) |
| 71 | } |
| 72 | if err := s.Reserve(context.Background(), 1); err != nil || len(reloc.calls) != 1 || len(moves.calls) != 0 { |
| 73 | t.Fatalf("bound journal: %v %v %v", err, reloc.calls, moves.calls) |
| 74 | } |
| 75 | var refusal *ClaimDependencyError |
| 76 | if err := w.bindOperation(&activator.ClaimStart{Ready: s.Ready}, OperationStart{Admitted: plan9D5Kind(hostclaim.KindRestoring)}); !errors.As(err, &refusal) { |
| 77 | t.Fatalf("unrouted kind bound: %v", err) |
| 78 | } |
| 79 | } |
| 80 | |