Files
felhom-controller/controller/internal/stacks/install_id_test.go
T

72 lines
3.0 KiB
Go

package stacks
import (
"os"
"path/filepath"
"testing"
)
// D47 (operator ruling 2026-10-25; R-1269) — the app's record names the install its data belongs to. Through the
// PRODUCTION writers: the restore write (PersistUnitRedeployConfigGate), a later load-then-save, EnsureInstallID.
// COMPANION RED-PROOF: drop the `case gate.InstallID != ""` branch in PersistUnitRedeployConfigGate →
// TestD47_ARestoreTakesTheUnitsInstall fails (the app keeps the replaced install's id, and its next backup would
// set aside the very unit it was restored from).
// A restore from a unit that records an install: the app now holds that unit's data, so it IS that install.
func TestD47_ARestoreTakesTheUnitsInstall(t *testing.T) {
m := gateManager(t, gatedYml)
writeAppYaml(t, gappDir(m), "deployed: true\ninstall_id: bbbb000000000002\nenv:\n SUBDOMAIN: gapp\n")
must(t, m.PersistUnitRedeployConfigGate("gapp", gateEnv, GateAtBackup{InstallID: "aaaa000000000001"}))
if got := LoadAppConfig(gappDir(m)); got == nil || got.InstallID != "aaaa000000000001" {
t.Fatalf("the restored app must be the unit's install, got %+v", got)
}
}
// A unit that records no install (before D47): the app keeps its own identity — a restore is not a new install.
func TestD47_ARestoreOfAnUnrecordedUnitKeepsTheAppsInstall(t *testing.T) {
m := gateManager(t, gatedYml)
writeAppYaml(t, gappDir(m), "deployed: true\ninstall_id: bbbb000000000002\nenv:\n SUBDOMAIN: gapp\n")
must(t, m.PersistUnitRedeployConfigGate("gapp", gateEnv, GateAtBackup{}))
if got := LoadAppConfig(gappDir(m)); got == nil || got.InstallID != "bbbb000000000002" {
t.Fatalf("an unrecorded unit's restore keeps the app's own install, got %+v", got)
}
}
// A removed app restored from an unrecorded unit gets an identity (never empty after a restore).
func TestD47_ARemovedAppRestoredGetsAnInstall(t *testing.T) {
m := gateManager(t, gatedYml)
must(t, m.PersistUnitRedeployConfigGate("gapp", gateEnv, GateAtBackup{}))
if got := LoadAppConfig(gappDir(m)); got == nil || len(got.InstallID) != 16 {
t.Fatalf("a restored app must have an install id, got %+v", got)
}
}
// An app installed before D47 gets one identity once; a second call returns the same one.
func TestD47_EnsureInstallIDMintsOnce(t *testing.T) {
m := gateManager(t, gatedYml)
writeAppYaml(t, gappDir(m), "deployed: true\nenv:\n SUBDOMAIN: gapp\ndesired_state: running\n")
m.mu.Lock()
m.stacks["gapp"].Deployed = true
m.mu.Unlock()
a, err := m.EnsureInstallID("gapp")
must(t, err)
b, err := m.EnsureInstallID("gapp")
must(t, err)
if len(a) != 16 || a != b {
t.Fatalf("one identity, minted once: %q then %q", a, b)
}
if got := LoadAppConfig(gappDir(m)); got.DesiredState != DesiredStateRunning {
t.Fatalf("minting the identity must change nothing else: %+v", got)
}
}
func writeAppYaml(t *testing.T, dir, body string) {
t.Helper()
if err := os.MkdirAll(dir, 0o755); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(dir, "app.yaml"), []byte(body), 0o600); err != nil {
t.Fatal(err)
}
}