package hostops import ( "encoding/json" "github.com/carlosframework/platform/internal/hostclaim" "github.com/carlosframework/platform/internal/park" "github.com/carlosframework/platform/internal/provision" "testing" ) func TestPlan13LossSourceRegionIsEngineName(t *testing.T) { for _, tc := range []struct{ from, to, want string }{ {"", "uk", park.HomeRegion}, {"ie", "uk", "ie"}, {"uk", "", "uk"}, } { t.Run(tc.from+"-"+tc.to, func(t *testing.T) { in := moveLossIntent{Move: lossOp, Incarnation: "inc", Target: "target", TargetRegion: park.PlacementRegion(tc.to)} rec := provision.Record{Region: tc.to, Move: &provision.MoveState{ID: lossOp, Incarnation: "inc", From: tc.from, To: tc.to, State: provision.MoveLanding}} op := hostclaim.Op{ID: lossOp, Kind: hostclaim.KindLanding} if err := recordLossIntent(&in, rec, "etag", 1, op, "claim-etag", nil); err != nil { t.Fatal(err) } if in.SourceRegion != tc.want || rec.Move.From != tc.from || rec.Region != tc.to { t.Fatalf("%+v %+v", in, rec) } raw, err := json.Marshal(in) if err != nil { t.Fatal(err) } var persisted map[string]any if err = json.Unmarshal(raw, &persisted); err != nil { t.Fatal(err) } if persisted["source_region"] != tc.want { t.Fatal(persisted) } }) } } func TestPlan13HomeLossDeclarationKeepsPlacement(t *testing.T) { w := newLossWorld(t, "landing", func(c *hostclaim.Claim, r *provision.Record, _ *AppAdmission) { r.Move.From = "" c.Op.Intent["home_region"] = "ie" }) w.control.homeRegion = "ie" inspect := w.inspect(t, "uk-label") after, err := w.declare(w.submission(inspect)) if err != nil { t.Fatal(err) } rec, _ := w.record(t) if rec.Region != "" || rec.Move.From != "" { t.Fatalf("record leaked engine token: %+v", rec) } loss, err := hostclaim.ReadLossRecord(t.Context(), w.raw, w.pub, inspect.Details.ID) if err != nil { t.Fatal(err) } in, _, err := lossIntentOf(loss.Record) if err != nil { t.Fatal(err) } if in.SourceRegion != park.HomeRegion || after.Claim.Op.Kind != hostclaim.KindRestoring { t.Fatalf("%+v", in) } } func TestPlan13LossRecoveryNamedHomeAdmission(t *testing.T) { for _, home := range []string{"ie", "", "uk"} { in := moveLossIntent{Kind: moveLossIntentKind, Move: "move", Incarnation: "inc", Rollback: "rb_abcdefghijklmnopqrstuvwxyz", Target: "target", Source: "source", TargetRegion: "uk", SourceRegion: park.HomeRegion, RecordKey: "record", RecordETag: "etag", RecordState: moveLossRecordLanding} raw, _ := in.encode() loss := hostclaim.LossRecord{ID: "loss_1", OpID: "move", Box: "target", HolderIncarnation: "inc", ConfirmedConsequences: hostclaim.LossConsequences{RecoveryIntent: raw}} c := hostclaim.Claim{Holder: &hostclaim.Holder{Incarnation: "inc", Key: "record", Stamp: 7}, Op: hostclaim.Op{Kind: hostclaim.KindRestoring, ID: "move", Phase: hostclaim.PhaseProbing, Exec: "source", Intent: map[string]string{"source": "source", "target": "target", "to": "uk", "rollback": in.Rollback, "home_region": home}, Journal: map[string]string{hostclaim.JournalSourceStamp: "7", "lost_target_released": "loss_1"}}} err := MoveLossRecoveryOwner().ValidateLossRecovery(c, loss, hostclaim.Admission{Box: "source", Region: "ie", Mode: "cold"}) if (err == nil) != (home == "ie") { t.Fatal(home, err) } } }