Providers read the seat's plans and retire only on the operator's yes, removing the credential
ADR 0570 clauses 2 and 5: gitea, keycloak, postgres and route-adapter read mesh-provisioner.plans and .provisions instead of the controller's assignments. postgres hands the database to a keeper and drops the login; keycloak replaces the client's secret and keeps the client, so the data stays (issue 1954, V4).
This commit is contained in:
@@ -10,31 +10,74 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestRetiringLocksMarksAndDropsNothing(t *testing.T) {
|
||||
// ADR 0570 clause 5, on the operator's yes: the login's database and objects go to its keeper, marked; its sessions
|
||||
// end; the login is dropped; the database is not.
|
||||
func TestRetiringHandsTheDatabaseToAKeeperAndRemovesTheLogin(t *testing.T) {
|
||||
f, c := newFake(admin)
|
||||
f.answer(`shobj_description\(oid`, []string{"c"}, []string{`{"mesh":"consumer","node":"ace"}`})
|
||||
f.answer(`SELECT 1 FROM pg_roles`, []string{"?column?"}, []string{"1"})
|
||||
f.answer(`pg_roles WHERE rolname = 'mesh_ace_letta'$`, []string{"?column?"}, []string{"1"})
|
||||
f.answer(`pg_database WHERE datname = 'mesh_ace_letta'$`, []string{"?column?"}, []string{"1"})
|
||||
at := time.Date(2026, 10, 6, 12, 0, 0, 0, time.UTC)
|
||||
if err := c.RetireRole(ctx, "mesh_ace_letta", "the mesh stopped asking for it", at); err != nil {
|
||||
if err := c.RetireRole(ctx, "mesh_ace_letta", "the operator approved its retirement", at); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
sql := f.statements()
|
||||
if !has(sql, `ALTER ROLE "mesh_ace_letta" NOLOGIN`) || !has(sql, `pg_terminate_backend.*usename = 'mesh_ace_letta'`) ||
|
||||
!has(sql, `COMMENT ON ROLE "mesh_ace_letta" IS '\{"mesh":"consumer","node":"ace","retired":"2026-10-06T12:00:00Z","why":"the mesh stopped asking for it"\}'`) {
|
||||
t.Fatal(strings.Join(sql, "\n"))
|
||||
var order []string
|
||||
for _, call := range f.calls {
|
||||
switch {
|
||||
case strings.HasPrefix(call.SQL, "SELECT"):
|
||||
case strings.HasPrefix(call.SQL, "REASSIGN"), strings.HasPrefix(call.SQL, "DROP OWNED"):
|
||||
order = append(order, call.Database+": "+call.SQL)
|
||||
default:
|
||||
order = append(order, call.SQL)
|
||||
}
|
||||
}
|
||||
noDrop(t, sql)
|
||||
if has(sql, `REVOKE|ALLOW_CONNECTIONS|RENAME`) {
|
||||
t.Fatal("retiring touched the database:", strings.Join(sql, "\n"))
|
||||
if !has(f.statements(), `pg_terminate_backend.*usename = 'mesh_ace_letta'`) {
|
||||
t.Fatal(strings.Join(f.statements(), "\n"))
|
||||
}
|
||||
want := []string{
|
||||
`CREATE ROLE "mesh_ace_letta~retired" NOLOGIN`,
|
||||
`COMMENT ON ROLE "mesh_ace_letta~retired" IS '{"mesh":"consumer","node":"ace","retired":"2026-10-06T12:00:00Z","why":"the operator approved its retirement","login":"mesh_ace_letta"}'`,
|
||||
`ALTER ROLE "mesh_ace_letta" NOLOGIN`,
|
||||
`mesh_ace_letta: REASSIGN OWNED BY "mesh_ace_letta" TO "mesh_ace_letta~retired"`,
|
||||
`mesh_ace_letta: DROP OWNED BY "mesh_ace_letta"`,
|
||||
`DROP ROLE "mesh_ace_letta"`,
|
||||
}
|
||||
if strings.Join(order, "\n") != strings.Join(want, "\n") {
|
||||
t.Fatalf("sent:\n%s\nwant:\n%s", strings.Join(order, "\n"), strings.Join(want, "\n"))
|
||||
}
|
||||
if has(f.statements(), `DROP DATABASE|REVOKE|ALLOW_CONNECTIONS|RENAME`) {
|
||||
t.Fatal("retiring touched the database:", strings.Join(f.statements(), "\n"))
|
||||
}
|
||||
|
||||
// No such role: nothing to retire, nothing done.
|
||||
f, c = newFake(admin)
|
||||
if err := c.RetireRole(ctx, "gone", "x", at); err != nil || has(f.statements(), `ALTER|COMMENT`) {
|
||||
if err := c.RetireRole(ctx, "gone", "x", at); err != nil || has(f.statements(), `ALTER|COMMENT|CREATE|DROP`) {
|
||||
t.Fatal(f.statements(), err)
|
||||
}
|
||||
}
|
||||
|
||||
// A login made again takes back what its keeper kept, and the keeper goes; with no keeper, nothing is sent.
|
||||
func TestALoginMadeAgainReclaimsWhatItsKeeperKept(t *testing.T) {
|
||||
f, c := newFake(admin)
|
||||
if err := c.Reclaim(ctx, "mesh_ace_letta", "mesh_ace_letta"); err != nil || has(f.statements(), `REASSIGN|DROP`) {
|
||||
t.Fatal(f.statements(), err)
|
||||
}
|
||||
f, c = newFake(admin)
|
||||
f.answer(`pg_roles WHERE rolname = 'mesh_ace_letta~retired'$`, []string{"?column?"}, []string{"1"})
|
||||
if err := c.Reclaim(ctx, "mesh_ace_letta", "mesh_ace_letta"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var got []string
|
||||
for _, call := range f.calls[1:] {
|
||||
got = append(got, call.Database+": "+call.SQL)
|
||||
}
|
||||
want := `mesh_ace_letta: REASSIGN OWNED BY "mesh_ace_letta~retired" TO "mesh_ace_letta"` + "\n" +
|
||||
`mesh_ace_letta: DROP OWNED BY "mesh_ace_letta~retired"` + "\n" + `postgres: DROP ROLE "mesh_ace_letta~retired"`
|
||||
if strings.Join(got, "\n") != want {
|
||||
t.Fatal(strings.Join(got, "\n"))
|
||||
}
|
||||
}
|
||||
|
||||
func TestTheInventoryIsWhatTheMeshMadeByMarkOrShape(t *testing.T) {
|
||||
f, c := newFake(admin)
|
||||
f.answer(`FROM pg_roles r`, []string{"rolname", "rolcanlogin", "mark", "mesh_shaped", "size"},
|
||||
@@ -44,6 +87,7 @@ func TestTheInventoryIsWhatTheMeshMadeByMarkOrShape(t *testing.T) {
|
||||
[]string{"locked_before", "f", "", "t", "400"},
|
||||
[]string{"hal_registry", "t", "", "f", "500"},
|
||||
[]string{"jochens", "t", "", "t", ""},
|
||||
[]string{"mesh_ace_umami~retired", "f", `{"mesh":"consumer","node":"ace","retired":"2026-10-29T12:00:00Z","why":"approved","login":"mesh_ace_umami"}`, "f", "600"},
|
||||
)
|
||||
f.answer(`_deleted_`, []string{"datname", "size"}, []string{"mesh_novox_gitea_deleted_20261005", "7771827"})
|
||||
inv, err := c.Inventory(ctx)
|
||||
@@ -53,7 +97,7 @@ func TestTheInventoryIsWhatTheMeshMadeByMarkOrShape(t *testing.T) {
|
||||
if strings.Join(inv.Active, ",") != "active_marked,active_shaped" {
|
||||
t.Fatalf("active: %v", inv.Active)
|
||||
}
|
||||
if len(inv.Retired) != 3 {
|
||||
if len(inv.Retired) != 4 {
|
||||
t.Fatalf("%+v", inv.Retired)
|
||||
}
|
||||
r := inv.Retired[0]
|
||||
@@ -64,7 +108,10 @@ func TestTheInventoryIsWhatTheMeshMadeByMarkOrShape(t *testing.T) {
|
||||
if r := inv.Retired[1]; r.Consumer != "locked_before" || !r.RetiredAt.IsZero() || r.Kind != harness.KindConsumer {
|
||||
t.Fatalf("found locked without a mark: %+v", r)
|
||||
}
|
||||
if r := inv.Retired[2]; r.Kind != KindSetAside || r.RetiredAt.Format("20060102") != "20261005" || r.SizeBytes != 7771827 {
|
||||
if r := inv.Retired[2]; r.Consumer != "mesh_ace_umami" || r.SizeBytes != 600 || r.Why != "approved" {
|
||||
t.Fatalf("a keeper is listed under the login it keeps for: %+v", r)
|
||||
}
|
||||
if r := inv.Retired[3]; r.Kind != KindSetAside || r.RetiredAt.Format("20060102") != "20261005" || r.SizeBytes != 7771827 {
|
||||
t.Fatalf("set aside: %+v", r)
|
||||
}
|
||||
}
|
||||
@@ -97,6 +144,18 @@ func TestDeletingDropsTheDatabaseThenTheRole(t *testing.T) {
|
||||
if db < 0 || role < db {
|
||||
t.Fatal(sql)
|
||||
}
|
||||
// A login removed on retiring: the database, then its keeper.
|
||||
f, c = newFake(admin)
|
||||
f.answer(`SELECT pg_database_size`, []string{"size"}, []string{"9000"})
|
||||
f.answer(`pg_roles WHERE rolname = 'mesh_ace_umami~retired'$`, []string{"?column?"}, []string{"1"})
|
||||
if _, err := c.DeleteRetired(ctx, harness.Retired{Consumer: "mesh_ace_umami", Kind: harness.KindConsumer}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
sql = strings.Join(f.statements(), "\n")
|
||||
db, keeper := strings.Index(sql, `DROP DATABASE "mesh_ace_umami"`), strings.Index(sql, `DROP ROLE "mesh_ace_umami~retired"`)
|
||||
if db < 0 || keeper < db {
|
||||
t.Fatal(sql)
|
||||
}
|
||||
// A role still owning a set-aside database is kept, and said.
|
||||
f, c = newFake(admin)
|
||||
f.answer(`SELECT rolcanlogin`, []string{"rolcanlogin"}, []string{"f"})
|
||||
|
||||
Reference in New Issue
Block a user