package hostbox import ( "context" "encoding/json" "github.com/carlosframework/platform/internal/hostguard" "github.com/carlosframework/platform/internal/registry" "os" "path/filepath" "testing" ) type noFiles struct{} func (noFiles) Park(context.Context, string, Artifact) error { return ErrTypedInventory } func TestRegistryRowsArchivesInRetirementJournal(t *testing.T) { reg, err := registry.Open(filepath.Join(t.TempDir(), "registry.db")) if err != nil { t.Fatal(err) } defer reg.Close() owner := registry.ClaimOwnership{ClaimIncarnation: "inc", ClaimStamp: 7, ClaimOwner: "owner", ClaimRowID: "route"} route := registry.Route{Host: "shop.example", ClaimOwnership: owner, App: "app"} if err = reg.Upsert(route); err != nil { t.Fatal(err) } in := RetirementInventory{Host: route.Host, Captured: hostguard.Captured{Incarnation: "inc", Stamp: 7}, Ownership: "owner", Artifacts: []Artifact{{Kind: ArtifactRoute, Root: "registry", Name: route.Host, Owner: "owner", RowID: "route"}}} intent, err := NewRetirementJournal("retire", in) if err != nil { t.Fatal(err) } target := hostguard.FenceTarget{Host: route.Host, Incarnation: "inc", Stamp: 7} // Created by the retirement itself, 0700 whatever the test umask. dir := filepath.Join(t.TempDir(), "journal") acks := 0 r := TypedRetirement{JournalDir: dir, Authority: &cleanupAuthority{}, Filesystem: noFiles{}, Rows: RegistryRows{Registry: reg, Inventory: in}, Ack: func(context.Context, RetirementJournal) error { acks++; return nil }} if err = r.Run(context.Background(), target, intent); err != nil { t.Fatal(err) } body, err := os.ReadFile(filepath.Join(dir, "retire.json")) if err != nil { t.Fatal(err) } var j RetirementJournal if err = json.Unmarshal(body, &j); err != nil { t.Fatal(err) } var archive []registry.ClaimRowArchive if err = json.Unmarshal(j.Archives, &archive); err != nil { t.Fatal(err) } if !j.Complete || len(archive) != 1 || archive[0].Row.Ownership != owner { t.Fatalf("incomplete journal: %+v", j) } route.ClaimStamp++ route.ClaimRowID = "successor" route.ClaimOwner = "new-owner" if err = reg.Upsert(route); err != nil { t.Fatal(err) } if err = r.Run(context.Background(), target, intent); err != nil { t.Fatal(err) } got, err := reg.Get(route.Host) if err != nil || got == nil || got.ClaimRowID != "successor" || acks != 2 { t.Fatalf("replay touched successor: %v", err) } }