refactor: dedupe status-severity ranking and small webui helpers

statusSeverity was byte-for-byte duplicated in collector/contract.go and
app/sat_overlay.go (same switch, same comment). Export it as
collector.StatusSeverity and drop the app-package copy.

page_topo.go inlined the same GPU/NIC/RAID class switch as its own
pcieDeviceKind function in one spot — call the function instead.

page_validate.go had its own copy of pages.go's firstNonEmpty (all call
sites already pre-trim their inputs via validateTrimPtr, so the extra
TrimSpace was redundant) — drop the duplicate.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Mikhail Chusavitin
2026-08-18 14:44:52 +03:00
co-authored by Claude Sonnet 5
parent e3697c0a11
commit 134bed3eae
4 changed files with 14 additions and 46 deletions
+4 -19
View File
@@ -237,7 +237,7 @@ func parseStorageSATStatus(summary satSummary) map[string]satStatusResult {
} }
} }
current := result[devName] current := result[devName]
if !current.ok || statusSeverity(stepStatus) > statusSeverity(current.status) { if !current.ok || collector.StatusSeverity(stepStatus) > collector.StatusSeverity(current.status) {
result[devName] = satStatusResult{status: stepStatus, description: desc, ok: true} result[devName] = satStatusResult{status: stepStatus, description: desc, ok: true}
} }
} }
@@ -279,7 +279,7 @@ func mergeComponentStatus(component *schema.HardwareComponentStatus, changedAt,
return return
} }
current := strings.TrimSpace(ptrString(component.Status)) current := strings.TrimSpace(ptrString(component.Status))
if current == "" || current == "Unknown" || statusSeverity(satStatus) > statusSeverity(current) { if current == "" || current == "Unknown" || collector.StatusSeverity(satStatus) > collector.StatusSeverity(current) {
component.Status = appStringPtr(satStatus) component.Status = appStringPtr(satStatus)
if strings.TrimSpace(description) != "" { if strings.TrimSpace(description) != "" {
component.ErrorDescription = appStringPtr(description) component.ErrorDescription = appStringPtr(description)
@@ -300,8 +300,8 @@ func mergeComponentStatusPreferDetail(component *schema.HardwareComponentStatus,
return return
} }
current := strings.TrimSpace(ptrString(component.Status)) current := strings.TrimSpace(ptrString(component.Status))
newSeverity := statusSeverity(satStatus) newSeverity := collector.StatusSeverity(satStatus)
currentSeverity := statusSeverity(current) currentSeverity := collector.StatusSeverity(current)
if current == "" || current == "Unknown" || newSeverity > currentSeverity { if current == "" || current == "Unknown" || newSeverity > currentSeverity {
mergeComponentStatus(component, changedAt, satStatus, description) mergeComponentStatus(component, changedAt, satStatus, description)
return return
@@ -320,21 +320,6 @@ func mergeComponentStatusPreferDetail(component *schema.HardwareComponentStatus,
} }
} }
func statusSeverity(status string) int {
switch strings.TrimSpace(status) {
case "Critical":
return 3
case "Warning":
return 2
case "OK":
return 1
case "Unknown":
return 1 // same as OK — does not override OK from another source
default:
return 0
}
}
func matchesGPUVendor(dev schema.HardwarePCIeDevice, vendor string) bool { func matchesGPUVendor(dev schema.HardwarePCIeDevice, vendor string) bool {
if dev.DeviceClass == nil { if dev.DeviceClass == nil {
return false return false
+3 -3
View File
@@ -70,10 +70,10 @@ func isRAIDClass(class string) bool {
} }
} }
// statusSeverity ranks component statuses so merges can only escalate, never // StatusSeverity ranks component statuses so merges can only escalate, never
// downgrade. Unknown ranks with OK: it means "couldn't tell", not "healthy", // downgrade. Unknown ranks with OK: it means "couldn't tell", not "healthy",
// so it must not silently clear a Warning/Critical raised by an earlier stage. // so it must not silently clear a Warning/Critical raised by an earlier stage.
func statusSeverity(status string) int { func StatusSeverity(status string) int {
switch strings.TrimSpace(status) { switch strings.TrimSpace(status) {
case statusCritical: case statusCritical:
return 3 return 3
@@ -101,7 +101,7 @@ func mergeDeviceStatus(dev *schema.HardwarePCIeDevice, status, description strin
if dev.Status != nil { if dev.Status != nil {
current = strings.TrimSpace(*dev.Status) current = strings.TrimSpace(*dev.Status)
} }
if current != "" && current != statusUnknown && statusSeverity(status) <= statusSeverity(current) { if current != "" && current != statusUnknown && StatusSeverity(status) <= StatusSeverity(current) {
return return
} }
dev.Status = &status dev.Status = &status
+2 -9
View File
@@ -614,15 +614,8 @@ func renderTopoMainDiagram(hw schema.HardwareSnapshot, exportDir string) string
} }
var placed []placedDevice var placed []placedDevice
for _, dev := range hw.PCIeDevices { for _, dev := range hw.PCIeDevices {
var kind string kind := pcieDeviceKind(dev)
switch { if kind == "" {
case dev.DeviceClass != nil && isGPUDeviceClass(*dev.DeviceClass):
kind = "gpu"
case isNICDeviceClassDev(dev):
kind = "nic"
case dev.DeviceClass != nil && isRAIDControllerClass(*dev.DeviceClass):
kind = "raid"
default:
continue continue
} }
col := unknownCol col := unknownCol
+5 -15
View File
@@ -517,7 +517,7 @@ func loadValidateInventory(opts HandlerOptions) validateInventory {
continue continue
} }
cpuTotal++ cpuTotal++
addValidateModel(cpuCounts, validateFirstNonEmpty(validateTrimPtr(cpu.Model), validateTrimPtr(cpu.Manufacturer), "unknown")) addValidateModel(cpuCounts, firstNonEmpty(validateTrimPtr(cpu.Model), validateTrimPtr(cpu.Manufacturer), "unknown"))
} }
memCounts := map[string]int{} memCounts := map[string]int{}
@@ -527,7 +527,7 @@ func loadValidateInventory(opts HandlerOptions) validateInventory {
continue continue
} }
memTotal++ memTotal++
addValidateModel(memCounts, validateFirstNonEmpty(validateTrimPtr(dimm.PartNumber), validateTrimPtr(dimm.Type), validateTrimPtr(dimm.Manufacturer), "unknown")) addValidateModel(memCounts, firstNonEmpty(validateTrimPtr(dimm.PartNumber), validateTrimPtr(dimm.Type), validateTrimPtr(dimm.Manufacturer), "unknown"))
} }
storageCounts := map[string]int{} storageCounts := map[string]int{}
@@ -537,7 +537,7 @@ func loadValidateInventory(opts HandlerOptions) validateInventory {
continue continue
} }
storageTotal++ storageTotal++
addValidateModel(storageCounts, validateFirstNonEmpty(validateTrimPtr(dev.Model), validateTrimPtr(dev.Manufacturer), "unknown")) addValidateModel(storageCounts, firstNonEmpty(validateTrimPtr(dev.Model), validateTrimPtr(dev.Manufacturer), "unknown"))
} }
nvidiaCounts := map[string]int{} nvidiaCounts := map[string]int{}
@@ -550,11 +550,11 @@ func loadValidateInventory(opts HandlerOptions) validateInventory {
} }
if validateIsVendorGPU(dev, "nvidia") { if validateIsVendorGPU(dev, "nvidia") {
nvidiaTotal++ nvidiaTotal++
addValidateModel(nvidiaCounts, validateFirstNonEmpty(validateTrimPtr(dev.Model), validateTrimPtr(dev.Manufacturer), "unknown")) addValidateModel(nvidiaCounts, firstNonEmpty(validateTrimPtr(dev.Model), validateTrimPtr(dev.Manufacturer), "unknown"))
} }
if validateIsVendorGPU(dev, "amd") { if validateIsVendorGPU(dev, "amd") {
amdTotal++ amdTotal++
addValidateModel(amdCounts, validateFirstNonEmpty(validateTrimPtr(dev.Model), validateTrimPtr(dev.Manufacturer), "unknown")) addValidateModel(amdCounts, firstNonEmpty(validateTrimPtr(dev.Model), validateTrimPtr(dev.Manufacturer), "unknown"))
} }
} }
@@ -613,16 +613,6 @@ func validateTrimPtr(value *string) string {
return strings.TrimSpace(*value) return strings.TrimSpace(*value)
} }
func validateFirstNonEmpty(values ...string) string {
for _, value := range values {
value = strings.TrimSpace(value)
if value != "" {
return value
}
}
return ""
}
func validateIsVendorGPU(dev schema.HardwarePCIeDevice, vendor string) bool { func validateIsVendorGPU(dev schema.HardwarePCIeDevice, vendor string) bool {
if dev.VendorID != nil && *dev.VendorID == pciVendorAspeed { if dev.VendorID != nil && *dev.VendorID == pciVendorAspeed {
return false return false