agent v0.86.0: DR-tier-by-default — capability inactive state (GatedBy/GateActive, pbsdr gate via DRConfigured) + F-3 root-run provision parent ownership
Claude-Session: https://claude.ai/code/session_01NptTCFtu7dz2Ru89qHRagN
This commit is contained in:
@@ -125,6 +125,22 @@ func (m *Manager) Status() *hub.PBSDRStatus {
|
||||
return m.status
|
||||
}
|
||||
|
||||
// DRConfigured reports whether the DR tier is configured ON for this box — the capability
|
||||
// prober's GatePBSDR answer (v0.86.0). True when the last-seen descriptor was enabled (any live
|
||||
// status except "disabled"), or, before the first desired-state fetch of this process, when a
|
||||
// previously-converged marker exists (so an applied box never flaps to inactive across an agent
|
||||
// restart). False = no descriptor ever / descriptor disabled → healthy pbsdr capabilities report
|
||||
// "inactive (disabled by configuration)" instead of ok.
|
||||
func (m *Manager) DRConfigured() bool {
|
||||
m.mu.Lock()
|
||||
st := m.status
|
||||
m.mu.Unlock()
|
||||
if st != nil {
|
||||
return st.State != "disabled"
|
||||
}
|
||||
return m.loadMarker() != nil
|
||||
}
|
||||
|
||||
// descriptorHash is the idempotency key: sha256 of the canonical (struct-ordered) JSON.
|
||||
func descriptorHash(b *hub.WirePBSDR) string {
|
||||
j, _ := json.Marshal(b)
|
||||
|
||||
@@ -362,6 +362,46 @@ func TestOldHubAndDisabledCompat(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// DRConfigured (v0.86.0) — the capability prober's GatePBSDR answer. Walks the full lifecycle:
|
||||
// unconfigured → enabled(applied) → restart(marker only) → disabled. Red-proof partner: make
|
||||
// DRConfigured return status!=nil (ignore the "disabled" state) → the disabled case fails.
|
||||
func TestDRConfigured_Lifecycle(t *testing.T) {
|
||||
r := &fakeRunner{}
|
||||
st := &fakeStorage{found: false, active: []bool{true}}
|
||||
c := &fakeConsumer{secret: "S"}
|
||||
m, _ := newTestManager(t, r, st, c)
|
||||
|
||||
// Fresh box, nothing fetched: not configured.
|
||||
if m.DRConfigured() {
|
||||
t.Fatal("fresh manager reports DR configured")
|
||||
}
|
||||
// Old hub / no descriptor: still not configured.
|
||||
m.Apply(context.Background(), true, nil)
|
||||
if m.DRConfigured() {
|
||||
t.Fatal("nil-block reports DR configured")
|
||||
}
|
||||
// Enabled descriptor applied: configured.
|
||||
m.Apply(context.Background(), true, testBlock())
|
||||
if s := m.Status(); s == nil || s.State != "applied" {
|
||||
t.Fatalf("precondition: status = %+v, want applied", s)
|
||||
}
|
||||
if !m.DRConfigured() {
|
||||
t.Fatal("applied box reports DR NOT configured")
|
||||
}
|
||||
// Agent restart (fresh manager over the same state dir): the persisted marker must answer
|
||||
// BEFORE the first desired-state fetch — an applied box never flaps to inactive at boot.
|
||||
m2 := NewManager(r, st, c, filepath.Dir(m.stateDir), "/etc/pve/priv/storage", "",
|
||||
slog.New(slog.NewTextHandler(io.Discard, nil)))
|
||||
if !m2.DRConfigured() {
|
||||
t.Fatal("restarted manager (marker on disk) reports DR NOT configured")
|
||||
}
|
||||
// Operator turns the tier OFF: descriptor disabled wins over the stale marker.
|
||||
m2.Apply(context.Background(), true, &hub.WirePBSDR{Enabled: false, StorageID: "felhom-pbs"})
|
||||
if m2.DRConfigured() {
|
||||
t.Fatal("disabled descriptor still reports DR configured")
|
||||
}
|
||||
}
|
||||
|
||||
// TestWireFieldNames pins the cross-repo descriptor contract (hub/internal/web/pbsdr.go
|
||||
// pbsDRDescriptor): the exact JSON the hub writes must land in WirePBSDR field-for-field.
|
||||
func TestWireFieldNames(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user