Normalize PBS alert threshold defaults on config update

Back-port v5 fix 117ec901d to v6, adapted to v6's config subpackage.
Adds NormalizePBSDefaults (called from UpdateConfig alongside the other
Normalize*Defaults) and pbs.cpu/pbs.memory to ValidateHysteresisThresholds.
PBS was the only monitored resource type whose thresholds were not
normalized on UpdateConfig, so user-supplied configs with nil/negative
PBS thresholds were never defaulted and a Trigger=0 'disable' sentinel
did not clear the Clear value. Adds regression test.
This commit is contained in:
rcourtman 2026-06-04 09:37:28 +01:00
parent ae8c2558cc
commit 0fcad7c67a
3 changed files with 88 additions and 0 deletions

View file

@ -3029,6 +3029,65 @@ func TestNormalizeStorageDefaultsPreservesZeroTrigger(t *testing.T) {
// TestNormalizeNodeDefaultsTemperaturePreservesZeroTrigger verifies that setting
// NodeDefaults.Temperature threshold to 0 is preserved to disable temperature alerting.
func TestNormalizePBSDefaultsPreservesZeroTrigger(t *testing.T) {
t.Run("nil PBSDefaults get factory defaults", func(t *testing.T) {
m := newTestManager(t)
cfg := AlertConfig{
Enabled: true,
PBSDefaults: ThresholdConfig{},
}
m.UpdateConfig(cfg)
m.mu.RLock()
defer m.mu.RUnlock()
if m.config.PBSDefaults.CPU == nil {
t.Fatal("CPU defaults should be set")
}
if m.config.PBSDefaults.CPU.Trigger != 80 {
t.Errorf("CPU trigger = %v, want 80", m.config.PBSDefaults.CPU.Trigger)
}
if m.config.PBSDefaults.Memory == nil {
t.Fatal("Memory defaults should be set")
}
if m.config.PBSDefaults.Memory.Trigger != 85 {
t.Errorf("Memory trigger = %v, want 85", m.config.PBSDefaults.Memory.Trigger)
}
})
t.Run("Trigger=0 preserved to disable alerting", func(t *testing.T) {
m := newTestManager(t)
cfg := AlertConfig{
Enabled: true,
PBSDefaults: ThresholdConfig{
CPU: &HysteresisThreshold{Trigger: 99, Clear: 94},
Memory: &HysteresisThreshold{Trigger: 0, Clear: 50},
},
}
m.UpdateConfig(cfg)
m.mu.RLock()
defer m.mu.RUnlock()
if m.config.PBSDefaults.CPU.Trigger != 99 {
t.Errorf("CPU trigger = %v, want 99", m.config.PBSDefaults.CPU.Trigger)
}
if m.config.PBSDefaults.Memory == nil {
t.Fatal("Memory threshold should be preserved")
}
if m.config.PBSDefaults.Memory.Trigger != 0 {
t.Errorf("Memory trigger = %v, want 0", m.config.PBSDefaults.Memory.Trigger)
}
if m.config.PBSDefaults.Memory.Clear != 0 {
t.Errorf("Memory clear = %v, want 0", m.config.PBSDefaults.Memory.Clear)
}
})
}
func TestNormalizeNodeDefaultsTemperaturePreservesZeroTrigger(t *testing.T) {
// t.Parallel()

View file

@ -158,6 +158,32 @@ func NormalizePMGDefaults(config *AlertConfig) {
}
}
// NormalizePBSDefaults ensures PBS server threshold defaults exist.
// Trigger=0 is allowed and means "disable alerting for this metric".
func NormalizePBSDefaults(config *AlertConfig) {
if config.PBSDefaults.CPU == nil || config.PBSDefaults.CPU.Trigger < 0 {
config.PBSDefaults.CPU = &HysteresisThreshold{Trigger: 80, Clear: 75}
} else if config.PBSDefaults.CPU.Trigger == 0 {
config.PBSDefaults.CPU.Clear = 0
} else if config.PBSDefaults.CPU.Clear <= 0 {
config.PBSDefaults.CPU.Clear = config.PBSDefaults.CPU.Trigger - 5
if config.PBSDefaults.CPU.Clear <= 0 {
config.PBSDefaults.CPU.Clear = 75
}
}
if config.PBSDefaults.Memory == nil || config.PBSDefaults.Memory.Trigger < 0 {
config.PBSDefaults.Memory = &HysteresisThreshold{Trigger: 85, Clear: 80}
} else if config.PBSDefaults.Memory.Trigger == 0 {
config.PBSDefaults.Memory.Clear = 0
} else if config.PBSDefaults.Memory.Clear <= 0 {
config.PBSDefaults.Memory.Clear = config.PBSDefaults.Memory.Trigger - 5
if config.PBSDefaults.Memory.Clear <= 0 {
config.PBSDefaults.Memory.Clear = 80
}
}
}
func NormalizeSnapshotDefaults(config *AlertConfig) {
if config.SnapshotDefaults.WarningDays < 0 {
config.SnapshotDefaults.WarningDays = 0
@ -519,6 +545,8 @@ func ValidateHysteresisThresholds(config *AlertConfig) {
EnsureValidHysteresis(config.NodeDefaults.CPU, "node.cpu")
EnsureValidHysteresis(config.NodeDefaults.Memory, "node.memory")
EnsureValidHysteresis(config.NodeDefaults.Temperature, "node.temperature")
EnsureValidHysteresis(config.PBSDefaults.CPU, "pbs.cpu")
EnsureValidHysteresis(config.PBSDefaults.Memory, "pbs.memory")
EnsureValidHysteresis(&config.StorageDefault, "storage")
EnsureValidHysteresis(config.KubernetesDefaults.CPU, "kubernetes.cpu")
EnsureValidHysteresis(config.KubernetesDefaults.Memory, "kubernetes.memory")

View file

@ -28,6 +28,7 @@ func (m *Manager) UpdateConfig(config AlertConfig) {
alertconfig.NormalizeStorageDefaults(&config)
alertconfig.NormalizeDockerDefaults(&config)
alertconfig.NormalizePMGDefaults(&config)
alertconfig.NormalizePBSDefaults(&config)
alertconfig.NormalizeSnapshotDefaults(&config)
alertconfig.NormalizeBackupDefaults(&config)
alertconfig.NormalizeNodeDefaults(&config)