metis/pkg/facts/aggregate.go

64 lines
1.8 KiB
Go

package facts
import (
"metis/pkg/inventory"
)
// ClassSummary captures aggregated sentinel facts per class.
type ClassSummary struct {
Class string `json:"class"`
Nodes []string `json:"nodes"`
Kernels map[string]int `json:"kernels,omitempty"`
OSImages map[string]int `json:"os_images,omitempty"`
Containerd map[string]int `json:"containerd,omitempty"`
K3sVersions map[string]int `json:"k3s_versions,omitempty"`
PackageStats map[string]map[string]int `json:"package_stats,omitempty"` // pkg -> version -> count
}
// Aggregate groups snapshots by inventory class and tallies version drift.
func Aggregate(inv *inventory.Inventory, snaps []Snapshot) map[string]*ClassSummary {
result := map[string]*ClassSummary{}
for _, s := range snaps {
class := "unknown"
if inv != nil {
if node, cls, err := inv.FindNode(s.Hostname); err == nil && cls != nil && node != nil {
class = cls.Name
}
}
sum, ok := result[class]
if !ok {
sum = &ClassSummary{
Class: class,
Kernels: map[string]int{},
OSImages: map[string]int{},
Containerd: map[string]int{},
K3sVersions: map[string]int{},
PackageStats: map[string]map[string]int{},
}
result[class] = sum
}
sum.Nodes = append(sum.Nodes, s.Hostname)
if s.Kernel != "" {
sum.Kernels[s.Kernel]++
}
if s.OSImage != "" {
sum.OSImages[s.OSImage]++
}
if s.Containerd != "" {
sum.Containerd[s.Containerd]++
}
if s.K3sVersion != "" {
sum.K3sVersions[s.K3sVersion]++
}
for pkg, ver := range s.PackageSample {
if sum.PackageStats[pkg] == nil {
sum.PackageStats[pkg] = map[string]int{}
}
if ver != "" {
sum.PackageStats[pkg][ver]++
}
}
}
return result
}