package store // v0.51.0 dr_tier one-time legacy backfill — "initialize from reality": on the migration that // ADDS the column, a customer whose host already carries an ENABLED pbs_dr descriptor flips ON; // everyone else stays OFF (never auto-cascade a legacy box). Simulated against a genuine // pre-v0.51.0 database file (tables without dr_tier), then opened through store.New so the REAL // migrate() path runs. Red-proof partner: make the backfill ignore `"enabled":false` vs true // (set every pbs_dr customer ON) → the disabled-descriptor case fails. import ( "database/sql" "io" "log" "path/filepath" "testing" _ "modernc.org/sqlite" ) func TestDRTierBackfill_InitializesFromReality(t *testing.T) { dbPath := filepath.Join(t.TempDir(), "legacy.db") // 1. Build a PRE-v0.51.0 database: customer_configs + hosts WITHOUT dr_tier. raw, err := sql.Open("sqlite", dbPath) if err != nil { t.Fatal(err) } mustExec := func(q string, args ...any) { t.Helper() if _, err := raw.Exec(q, args...); err != nil { t.Fatalf("legacy seed: %v (%s)", err, q) } } mustExec(`CREATE TABLE customer_configs ( customer_id TEXT PRIMARY KEY, customer_name TEXT NOT NULL DEFAULT '', domain TEXT NOT NULL DEFAULT '', email TEXT NOT NULL DEFAULT '', retrieval_password TEXT NOT NULL, api_key TEXT NOT NULL, config_json TEXT NOT NULL DEFAULT '{}', created_at DATETIME NOT NULL DEFAULT (datetime('now')), updated_at DATETIME NOT NULL DEFAULT (datetime('now')) )`) mustExec(`CREATE TABLE hosts ( host_id TEXT PRIMARY KEY, customer_id TEXT NOT NULL, api_key TEXT NOT NULL, agent_version TEXT NOT NULL DEFAULT '', last_report_at DATETIME, desired_json TEXT NOT NULL DEFAULT '{}', desired_generation INTEGER NOT NULL DEFAULT 0, dr_record_json TEXT NOT NULL DEFAULT '{}', created_at DATETIME NOT NULL DEFAULT (datetime('now')), updated_at DATETIME NOT NULL DEFAULT (datetime('now')) )`) seedCustomer := func(id string) { mustExec(`INSERT INTO customer_configs (customer_id, retrieval_password, api_key) VALUES (?, ?, ?)`, id, "pw", "key-"+id) } seedCustomer("applied") // host carries an ENABLED descriptor → must flip ON seedCustomer("disabled") // descriptor present but enabled:false → must stay OFF seedCustomer("plain") // no descriptor at all → must stay OFF seedCustomer("hostless") // no host row → must stay OFF mustExec(`INSERT INTO hosts (host_id, customer_id, api_key, desired_json) VALUES (?, ?, ?, ?)`, "applied-01", "applied", "h1", `{"pbs_dr":{"enabled":true,"storage_id":"felhom-pbs","namespace":"applied"}}`) mustExec(`INSERT INTO hosts (host_id, customer_id, api_key, desired_json) VALUES (?, ?, ?, ?)`, "disabled-01", "disabled", "h2", `{"pbs_dr":{"enabled":false,"storage_id":"felhom-pbs","namespace":"disabled"}}`) mustExec(`INSERT INTO hosts (host_id, customer_id, api_key, desired_json) VALUES (?, ?, ?, ?)`, "plain-01", "plain", "h3", `{}`) if err := raw.Close(); err != nil { t.Fatal(err) } // 2. Open through the real store — migrate() adds dr_tier and runs the one-time backfill. st, err := New(dbPath, log.New(io.Discard, "", 0)) if err != nil { t.Fatalf("store.New over the legacy db: %v", err) } defer st.Close() want := map[string]bool{"applied": true, "disabled": false, "plain": false, "hostless": false} for id, wantOn := range want { cfg, err := st.GetCustomerConfig(id) if err != nil || cfg == nil { t.Fatalf("read %s: %v", id, err) } if cfg.DRTier != wantOn { t.Errorf("customer %s: dr_tier=%v, want %v (initialize from reality)", id, cfg.DRTier, wantOn) } } // 3. The backfill is ONE-TIME: a later flag change must survive a re-open (the ALTER now // fails → no re-backfill stomping operator decisions). cfg, _ := st.GetCustomerConfig("applied") cfg.DRTier = false // operator opts the customer out if err := st.SaveCustomerConfig(cfg); err != nil { t.Fatal(err) } st.Close() st2, err := New(dbPath, log.New(io.Discard, "", 0)) if err != nil { t.Fatal(err) } defer st2.Close() cfg2, _ := st2.GetCustomerConfig("applied") if cfg2.DRTier { t.Fatal("re-open re-ran the backfill and stomped the operator's opt-out") } }