Reduce complete broadcast conversion work without retaining frames

Borrow the converter-owned resource across field helpers and bypass encoding typed absent facets as discarded null. Preserve named nil collection marshalers, errors, detached output, all payload fields, metadata refresh, catalogues and same-generation History targets. Validate complete projections and encoded frames against the exact parent.

Contract-Neutral: Conversion work only; broadcast and REST payloads, identities, tenant routing, metadata and health freshness, alerts, catalogue references and History coordinates are unchanged.
Change-source: pulse-maintainer
This commit is contained in:
pulse-triage[bot]
2026-10-05 14:13:16 +01:00
parent 5b560521e2
commit eb26fbba05
5 changed files with 203 additions and 66 deletions
@@ -0,0 +1,120 @@
package monitoring
import (
"bytes"
"encoding/json"
"errors"
"math"
"testing"
"time"
"github.com/rcourtman/pulse-go-rewrite/internal/models"
"github.com/rcourtman/pulse-go-rewrite/internal/unifiedresources"
)
// These deliberately use named nil collections: a nil slice/map can still
// have a custom wire representation, unlike a nil pointer marshaler.
type projectionNilSlice []string
func (projectionNilSlice) MarshalJSON() ([]byte, error) { return []byte(`["custom"]`), nil }
type projectionNilMap map[string]string
func (projectionNilMap) MarshalJSON() ([]byte, error) { return []byte(`{"custom":true}`), nil }
type projectionInvalidJSON struct{}
func (projectionInvalidJSON) MarshalJSON() ([]byte, error) { return []byte(`{broken`), nil }
type projectionFailedJSON struct{}
func (projectionFailedJSON) MarshalJSON() ([]byte, error) {
return nil, errors.New("synthetic encode failure")
}
func projectionRawJSONReference(value any) json.RawMessage {
if value == nil {
return nil
}
encoded, err := json.Marshal(value)
if err != nil || string(encoded) == "null" {
return nil
}
return encoded
}
func TestBroadcastRawJSONPreservesAbsentEmptyAndFailureSemantics(t *testing.T) {
cases := []struct {
name string
value any
}{
{"untyped-nil", nil}, {"nil-facet", (*unifiedresources.K8sData)(nil)},
{"nil-slice", []string(nil)}, {"nil-map", map[string]string(nil)},
{"empty-slice", []string{}}, {"empty-map", map[string]string{}},
{"named-nil-slice-marshaler", projectionNilSlice(nil)},
{"named-nil-map-marshaler", projectionNilMap(nil)},
{"nil-pointer-marshaler", (*projectionNilSlice)(nil)},
{"invalid-json", projectionInvalidJSON{}}, {"encode-failure", projectionFailedJSON{}},
{"invalid-float", math.NaN()}, {"raw-null", json.RawMessage(`null`)},
{"unicode-html", map[string]string{"label": "<synthetic> & café \u2028"}},
{"facet", &unifiedresources.K8sData{ClusterID: "synthetic", Labels: map[string]string{"env": "test"}}},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
got, want := monitorRawJSON(tc.value), projectionRawJSONReference(tc.value)
if !bytes.Equal(got, want) || (got == nil) != (want == nil) {
t.Fatalf("raw JSON changed: got %q, want %q", got, want)
}
})
}
}
func TestBroadcastAbsentFacetsDoNotAllocateNull(t *testing.T) {
for _, value := range []any{(*unifiedresources.K8sData)(nil), (*unifiedresources.StorageMeta)(nil), []unifiedresources.ResourceIncident(nil)} {
allocations := testing.AllocsPerRun(100, func() {
if monitorRawJSON(value) != nil {
panic("absent facet became present")
}
})
if allocations != 0 {
t.Fatalf("absent %T allocated discarded JSON: %.0f", value, allocations)
}
}
}
func TestBroadcastConversionBorrowedHelpersKeepOutputOwned(t *testing.T) {
now := time.Date(2026, 10, 5, 10, 0, 0, 0, time.UTC)
temperature := 42.5
total, used := int64(1000), int64(250)
resource := unifiedresources.Resource{ID: "pod:synthetic", Type: unifiedresources.ResourceTypePod, Name: "synthetic", LastSeen: now,
Sources: []unifiedresources.DataSource{unifiedresources.SourceK8s}, Tags: []string{"public"},
Identity: unifiedresources.ResourceIdentity{Hostnames: []string{"synthetic"}, IPAddresses: []string{"192.0.2.1"}},
Metrics: &unifiedresources.ResourceMetrics{CPU: &unifiedresources.MetricValue{Percent: 0.25}, Memory: &unifiedresources.MetricValue{Total: &total, Used: &used}},
Kubernetes: &unifiedresources.K8sData{ClusterID: "synthetic", PodPhase: "Running", Labels: map[string]string{"env": "synthetic"}, Temperature: &temperature, UptimeSeconds: 60},
}
before, err := json.Marshal(resource)
if err != nil {
t.Fatal(err)
}
projected := models.ConvertResourceToFrontend(monitorResourceToConvertInput(resource))
projected.Tags[0] = "caller-change"
projected.Sources[0] = "caller-change"
projected.Labels["env"] = "caller-change"
projected.Identity.IPs[0] = "caller-change"
*projected.Temperature = 100
*projected.Uptime = 100
*projected.Memory.Total = 2000
*projected.Memory.Used = 1000
for _, raw := range []json.RawMessage{projected.Canonical, projected.Kubernetes, projected.MetricsTarget, projected.DiscoveryTarget, projected.Capabilities} {
if len(raw) > 0 {
raw[0] = 'x'
}
}
after, err := json.Marshal(resource)
if err != nil {
t.Fatal(err)
}
if !bytes.Equal(before, after) {
t.Fatal("converter or output caller mutated source resource")
}
}
@@ -2592,7 +2592,7 @@ func TestPollersHonorDisabledInstanceFlag(t *testing.T) {
func TestMonitorUptimeFallsBackToCanonicalResourceUptime(t *testing.T) {
t.Run("falls through to Resource.Uptime when no source carve-out is set", func(t *testing.T) {
resource := unifiedresources.Resource{Uptime: 123456}
got := monitorUptime(resource)
got := monitorUptime(&resource)
if got == nil || *got != 123456 {
t.Fatalf("monitorUptime() = %v, want 123456 from canonical Resource.Uptime", got)
}
@@ -2603,21 +2603,21 @@ func TestMonitorUptimeFallsBackToCanonicalResourceUptime(t *testing.T) {
Uptime: 999999,
Agent: &unifiedresources.AgentData{UptimeSeconds: 100},
}
got := monitorUptime(resource)
got := monitorUptime(&resource)
if got == nil || *got != 100 {
t.Fatalf("monitorUptime() = %v, want 100 from agent (precedence over canonical Uptime)", got)
}
resource.Agent = nil
resource.Proxmox = &unifiedresources.ProxmoxData{Uptime: 200}
got = monitorUptime(resource)
got = monitorUptime(&resource)
if got == nil || *got != 200 {
t.Fatalf("monitorUptime() = %v, want 200 from proxmox (precedence over canonical Uptime)", got)
}
})
t.Run("returns nil when nothing populates", func(t *testing.T) {
if got := monitorUptime(unifiedresources.Resource{}); got != nil {
if got := monitorUptime(&unifiedresources.Resource{}); got != nil {
t.Fatalf("monitorUptime() = %v, want nil when all sources empty", got)
}
})
@@ -209,7 +209,7 @@ func TestMonitorFrontendAndMetricHelpers(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := monitorFrontendResourceType(tt.resource); got != tt.want {
if got := monitorFrontendResourceType(&tt.resource); got != tt.want {
t.Fatalf("monitorFrontendResourceType() = %q, want %q", got, tt.want)
}
})
@@ -320,7 +320,7 @@ func TestMonitorFrontendAndMetricHelpers(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := monitorPlatformType(tt.resource, tt.resourceType); got != tt.want {
if got := monitorPlatformType(&tt.resource, tt.resourceType); got != tt.want {
t.Fatalf("monitorPlatformType() = %q, want %q", got, tt.want)
}
})
@@ -387,7 +387,7 @@ func TestMonitorFrontendAndMetricHelpers(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := monitorPlatformID(tt.resource, tt.resourceType); got != tt.want {
if got := monitorPlatformID(&tt.resource, tt.resourceType); got != tt.want {
t.Fatalf("monitorPlatformID() = %q, want %q", got, tt.want)
}
})
@@ -482,7 +482,7 @@ func TestMonitorFrontendAndMetricHelpers(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := monitorFrontendStatus(tt.resource, tt.resourceType); got != tt.want {
if got := monitorFrontendStatus(&tt.resource, tt.resourceType); got != tt.want {
t.Fatalf("monitorFrontendStatus() = %q, want %q", got, tt.want)
}
})
@@ -553,7 +553,7 @@ func TestMonitorPlatformData(t *testing.T) {
},
}
payload := decodePlatformDataPayload(t, monitorPlatformData(resource, "node", "ignored"))
payload := decodePlatformDataPayload(t, monitorPlatformData(&resource, "node", "ignored"))
if payload["instance"] != "pve-a" {
t.Fatalf("instance = %#v, want pve-a", payload["instance"])
}
@@ -584,7 +584,7 @@ func TestMonitorPlatformData(t *testing.T) {
},
}
payload := decodePlatformDataPayload(t, monitorPlatformData(resource, "vm", "ignored"))
payload := decodePlatformDataPayload(t, monitorPlatformData(&resource, "vm", "ignored"))
if payload["networkIn"] != float64(11) {
t.Fatalf("networkIn = %#v, want 11", payload["networkIn"])
}
@@ -614,7 +614,7 @@ func TestMonitorPlatformData(t *testing.T) {
},
}
payload := decodePlatformDataPayload(t, monitorPlatformData(resource, "pbs", "ignored"))
payload := decodePlatformDataPayload(t, monitorPlatformData(&resource, "pbs", "ignored"))
if payload["memoryUsed"] != float64(20) {
t.Fatalf("memoryUsed = %#v, want 20", payload["memoryUsed"])
}
@@ -630,7 +630,7 @@ func TestMonitorPlatformData(t *testing.T) {
ParentID: &parent,
}
storagePayload := decodePlatformDataPayload(t, monitorPlatformData(resource, "storage", "pve-a"))
storagePayload := decodePlatformDataPayload(t, monitorPlatformData(&resource, "storage", "pve-a"))
if storagePayload["instance"] != "pve-a" {
t.Fatalf("instance = %#v, want pve-a", storagePayload["instance"])
}
@@ -641,7 +641,7 @@ func TestMonitorPlatformData(t *testing.T) {
t.Fatalf("active = %#v, want true", storagePayload["active"])
}
poolPayload := decodePlatformDataPayload(t, monitorPlatformData(resource, "pool", "pve-a"))
poolPayload := decodePlatformDataPayload(t, monitorPlatformData(&resource, "pool", "pve-a"))
if poolPayload["active"] != true {
t.Fatalf("pool active = %#v, want true", poolPayload["active"])
}
@@ -667,7 +667,7 @@ func TestMonitorPlatformData(t *testing.T) {
},
}
payload := decodePlatformDataPayload(t, monitorPlatformData(resource, "storage", "ignored"))
payload := decodePlatformDataPayload(t, monitorPlatformData(&resource, "storage", "ignored"))
if payload["platform"] != "unraid" {
t.Fatalf("platform = %#v, want unraid", payload["platform"])
}
@@ -687,10 +687,10 @@ func TestMonitorPlatformData(t *testing.T) {
})
t.Run("nil payload branches", func(t *testing.T) {
if got := monitorPlatformData(unifiedresources.Resource{}, "agent", "id"); got != nil {
if got := monitorPlatformData(&unifiedresources.Resource{}, "agent", "id"); got != nil {
t.Fatalf("expected nil payload for agent without resource agent data, got %s", string(got))
}
if got := monitorPlatformData(unifiedresources.Resource{}, "unknown", "id"); got != nil {
if got := monitorPlatformData(&unifiedresources.Resource{}, "unknown", "id"); got != nil {
t.Fatalf("expected nil payload for unknown type, got %s", string(got))
}
})
+50 -33
View File
@@ -6554,17 +6554,17 @@ func validBroadcastMetricsTarget(
}
func monitorResourceToConvertInput(resource unifiedresources.Resource) models.ResourceConvertInput {
resourceType := monitorFrontendResourceType(resource)
resourceType := monitorFrontendResourceType(&resource)
if resource.DiscoveryTarget == nil {
resource.DiscoveryTarget = monitorDiscoveryTarget(resource, resourceType)
resource.DiscoveryTarget = monitorDiscoveryTarget(&resource, resourceType)
}
if resource.MetricsTarget == nil {
resource.MetricsTarget = monitorMetricsTarget(resource, resourceType)
resource.MetricsTarget = monitorMetricsTarget(&resource, resourceType)
}
unifiedresources.RefreshCanonicalMetadata(&resource)
slimResourceForBroadcast(&resource)
name, displayName := monitorFrontendNames(resource, resourceType)
platformID := monitorPlatformID(resource, resourceType)
name, displayName := monitorFrontendNames(&resource, resourceType)
platformID := monitorPlatformID(&resource, resourceType)
input := models.ResourceConvertInput{
ID: resource.ID,
@@ -6573,21 +6573,21 @@ func monitorResourceToConvertInput(resource unifiedresources.Resource) models.Re
Name: name,
DisplayName: displayName,
PlatformID: platformID,
PlatformType: monitorPlatformType(resource, resourceType),
PlatformType: monitorPlatformType(&resource, resourceType),
SourceType: monitorSourceType(resource.Sources),
Sources: monitorSourceKeys(resource.Sources),
ParentID: monitorStringValue(resource.ParentID),
ParentName: resource.ParentName,
ChildCount: resource.ChildCount,
ClusterID: monitorClusterID(resource),
Status: monitorFrontendStatus(resource, resourceType),
ClusterID: monitorClusterID(&resource),
Status: monitorFrontendStatus(&resource, resourceType),
CPU: monitorMetricInput(monitorMetricValue(resource.Metrics, func(metrics *unifiedresources.ResourceMetrics) *unifiedresources.MetricValue { return metrics.CPU })),
Memory: monitorMetricInput(monitorMetricValue(resource.Metrics, func(metrics *unifiedresources.ResourceMetrics) *unifiedresources.MetricValue { return metrics.Memory })),
Disk: monitorMetricInput(monitorMetricValue(resource.Metrics, func(metrics *unifiedresources.ResourceMetrics) *unifiedresources.MetricValue { return metrics.Disk })),
Temperature: monitorTemperature(resource),
Uptime: monitorUptime(resource),
Temperature: monitorTemperature(&resource),
Uptime: monitorUptime(&resource),
Tags: append([]string(nil), resource.Tags...),
Labels: monitorLabels(resource),
Labels: monitorLabels(&resource),
CustomURL: strings.TrimSpace(resource.CustomURL),
LastSeenUnix: monitorLastSeenUnix(resource.LastSeen),
Health: monitorRawJSON(resource.Health),
@@ -6601,7 +6601,7 @@ func monitorResourceToConvertInput(resource unifiedresources.Resource) models.Re
IncidentImpactSummary: resource.IncidentImpactSummary,
IncidentUrgency: resource.IncidentUrgency,
IncidentAction: resource.IncidentAction,
Identity: monitorIdentity(resource, name),
Identity: monitorIdentity(&resource, name),
DiscoveryTarget: monitorRawJSON(resource.DiscoveryTarget),
MetricsTarget: monitorRawJSON(resource.MetricsTarget),
Canonical: monitorRawJSON(resource.Canonical),
@@ -6625,7 +6625,7 @@ func monitorResourceToConvertInput(resource unifiedresources.Resource) models.Re
VMware: monitorRawJSON(resource.VMware),
Availability: monitorRawJSON(resource.Availability),
AvailabilityChecks: monitorRawJSON(resource.AvailabilityChecks),
PlatformData: monitorPlatformData(resource, resourceType, platformID),
PlatformData: monitorPlatformData(&resource, resourceType, platformID),
}
hasNetwork, rx, tx := monitorNetworkMetricInput(resource.Metrics)
@@ -6641,6 +6641,23 @@ func monitorRawJSON(value interface{}) json.RawMessage {
if value == nil {
return nil
}
// Optional facets arrive as typed nil pointers/slices in an interface.
// Marshaling "null" only to discard it costs one encode and allocation
// per absent facet, on every row and frame. Named slice/map marshalers
// still get their normal chance to emit a non-null representation.
v := reflect.ValueOf(value)
switch v.Kind() {
case reflect.Ptr:
if v.IsNil() {
return nil
}
case reflect.Slice, reflect.Map:
if v.IsNil() {
if _, custom := value.(json.Marshaler); !custom {
return nil
}
}
}
encoded, err := json.Marshal(value)
if err != nil || string(encoded) == "null" {
return nil
@@ -6708,7 +6725,7 @@ func capabilityCatalogID(encoded json.RawMessage) string {
return hex.EncodeToString(digest[:6])
}
func monitorDiscoveryTarget(resource unifiedresources.Resource, resourceType string) *unifiedresources.DiscoveryTarget {
func monitorDiscoveryTarget(resource *unifiedresources.Resource, resourceType string) *unifiedresources.DiscoveryTarget {
switch resourceType {
case "agent", "docker-host":
agentID := monitorAgentTargetID(resource)
@@ -6726,7 +6743,7 @@ func monitorDiscoveryTarget(resource unifiedresources.Resource, resourceType str
}
}
func monitorMetricsTarget(resource unifiedresources.Resource, resourceType string) *unifiedresources.MetricsTarget {
func monitorMetricsTarget(resource *unifiedresources.Resource, resourceType string) *unifiedresources.MetricsTarget {
switch resourceType {
case "agent", "docker-host":
agentID := monitorAgentTargetID(resource)
@@ -6742,7 +6759,7 @@ func monitorMetricsTarget(resource unifiedresources.Resource, resourceType strin
}
}
func monitorAgentTargetID(resource unifiedresources.Resource) string {
func monitorAgentTargetID(resource *unifiedresources.Resource) string {
if resource.Agent != nil {
if id := strings.TrimSpace(resource.Agent.AgentID); id != "" {
return id
@@ -6764,7 +6781,7 @@ func monitorAgentTargetID(resource unifiedresources.Resource) string {
return ""
}
func monitorTargetHostname(resource unifiedresources.Resource) string {
func monitorTargetHostname(resource *unifiedresources.Resource) string {
if resource.Agent != nil {
if hostname := strings.TrimSpace(resource.Agent.Hostname); hostname != "" {
return hostname
@@ -6788,19 +6805,19 @@ func monitorTargetHostname(resource unifiedresources.Resource) string {
return strings.TrimSpace(resource.Name)
}
func monitorFrontendResourceType(resource unifiedresources.Resource) string {
return string(unifiedresources.ContractResourceType(resource))
func monitorFrontendResourceType(resource *unifiedresources.Resource) string {
return string(unifiedresources.ContractResourceType(*resource))
}
func monitorFrontendNames(resource unifiedresources.Resource, resourceType string) (string, string) {
name := strings.TrimSpace(unifiedresources.ResourceDisplayName(resource))
func monitorFrontendNames(resource *unifiedresources.Resource, resourceType string) (string, string) {
name := strings.TrimSpace(unifiedresources.ResourceDisplayName(*resource))
if name == "" {
name = resource.ID
}
return name, name
}
func monitorPlatformType(resource unifiedresources.Resource, resourceType string) string {
func monitorPlatformType(resource *unifiedresources.Resource, resourceType string) string {
if resource.Proxmox != nil {
return "proxmox-pve"
}
@@ -6901,7 +6918,7 @@ func monitorStoragePlatformType(storage *unifiedresources.StorageMeta, sources [
}
}
func monitorPlatformID(resource unifiedresources.Resource, resourceType string) string {
func monitorPlatformID(resource *unifiedresources.Resource, resourceType string) string {
switch resourceType {
case "node", "vm", "system-container":
if resource.Proxmox != nil && strings.TrimSpace(resource.Proxmox.Instance) != "" {
@@ -6947,7 +6964,7 @@ func monitorPlatformID(resource unifiedresources.Resource, resourceType string)
return resource.ID
}
func monitorFrontendStatus(resource unifiedresources.Resource, resourceType string) string {
func monitorFrontendStatus(resource *unifiedresources.Resource, resourceType string) string {
switch resourceType {
case "app-container":
switch resource.Status {
@@ -7001,8 +7018,8 @@ func monitorIsWorkloadType(resourceType string) bool {
}
}
func monitorClusterID(resource unifiedresources.Resource) string {
if clusterID := strings.TrimSpace(unifiedresources.ResourceClusterName(resource)); clusterID != "" {
func monitorClusterID(resource *unifiedresources.Resource) string {
if clusterID := strings.TrimSpace(unifiedresources.ResourceClusterName(*resource)); clusterID != "" {
return clusterID
}
@@ -7079,7 +7096,7 @@ func monitorDiskIOMetricInput(metrics *unifiedresources.ResourceMetrics) (*int64
return read, write
}
func monitorTemperature(resource unifiedresources.Resource) *float64 {
func monitorTemperature(resource *unifiedresources.Resource) *float64 {
if resource.Agent != nil && resource.Agent.Temperature != nil {
value := *resource.Agent.Temperature
return &value
@@ -7099,7 +7116,7 @@ func monitorTemperature(resource unifiedresources.Resource) *float64 {
return nil
}
func monitorUptime(resource unifiedresources.Resource) *int64 {
func monitorUptime(resource *unifiedresources.Resource) *int64 {
if resource.Agent != nil && resource.Agent.UptimeSeconds > 0 {
value := resource.Agent.UptimeSeconds
return &value
@@ -7141,7 +7158,7 @@ func monitorUptime(resource unifiedresources.Resource) *int64 {
return nil
}
func monitorLabels(resource unifiedresources.Resource) map[string]string {
func monitorLabels(resource *unifiedresources.Resource) map[string]string {
if resource.Kubernetes == nil || len(resource.Kubernetes.Labels) == 0 {
return nil
}
@@ -7152,7 +7169,7 @@ func monitorLabels(resource unifiedresources.Resource) map[string]string {
return labels
}
func monitorIdentity(resource unifiedresources.Resource, fallbackName string) *models.ResourceIdentityInput {
func monitorIdentity(resource *unifiedresources.Resource, fallbackName string) *models.ResourceIdentityInput {
hostname := ""
if resource.Agent != nil {
hostname = strings.TrimSpace(resource.Agent.Hostname)
@@ -7199,7 +7216,7 @@ func monitorIdentity(resource unifiedresources.Resource, fallbackName string) *m
}
}
func monitorPlatformData(resource unifiedresources.Resource, resourceType string, platformID string) json.RawMessage {
func monitorPlatformData(resource *unifiedresources.Resource, resourceType string, platformID string) json.RawMessage {
var payload interface{}
switch resourceType {
@@ -7416,7 +7433,7 @@ func monitorAttachSourceKeys(payload interface{}, sources []unifiedresources.Dat
return payload
}
func monitorStoragePlatformData(resource unifiedresources.Resource, platformID string) map[string]interface{} {
func monitorStoragePlatformData(resource *unifiedresources.Resource, platformID string) map[string]interface{} {
nodeLabel := resource.ParentName
if nodeLabel == "" {
nodeLabel = monitorStringValue(resource.ParentID)
@@ -7507,7 +7524,7 @@ func convertProxmoxDisks(disks []unifiedresources.DiskInfo) []map[string]interfa
return out
}
func buildProxmoxVMPayload(resource unifiedresources.Resource) map[string]interface{} {
func buildProxmoxVMPayload(resource *unifiedresources.Resource) map[string]interface{} {
if resource.Proxmox == nil {
return nil
}
@@ -11,7 +11,7 @@ func ptrF64Coverage(v float64) *float64 { return &v }
func TestMonitorFrontendNamesAdditional(t *testing.T) {
t.Run("frontend names use canonical display name", func(t *testing.T) {
name, display := monitorFrontendNames(unifiedresources.Resource{
name, display := monitorFrontendNames(&unifiedresources.Resource{
ID: "node-1",
Name: "Node Friendly",
Proxmox: &unifiedresources.ProxmoxData{
@@ -28,7 +28,7 @@ func TestMonitorFrontendNamesAdditional(t *testing.T) {
})
t.Run("frontend names ignore source hostnames when a display name exists", func(t *testing.T) {
hostName, hostDisplay := monitorFrontendNames(unifiedresources.Resource{
hostName, hostDisplay := monitorFrontendNames(&unifiedresources.Resource{
ID: "host-1",
Name: "Friendly Host",
Agent: &unifiedresources.AgentData{
@@ -39,7 +39,7 @@ func TestMonitorFrontendNamesAdditional(t *testing.T) {
t.Fatalf("agent branch mismatch: name=%q display=%q", hostName, hostDisplay)
}
dockerName, dockerDisplay := monitorFrontendNames(unifiedresources.Resource{
dockerName, dockerDisplay := monitorFrontendNames(&unifiedresources.Resource{
ID: "docker-1",
Name: "Friendly Docker",
Docker: &unifiedresources.DockerData{
@@ -52,7 +52,7 @@ func TestMonitorFrontendNamesAdditional(t *testing.T) {
})
t.Run("falls back to id when display name is empty", func(t *testing.T) {
name, display := monitorFrontendNames(unifiedresources.Resource{
name, display := monitorFrontendNames(&unifiedresources.Resource{
ID: "fallback-id",
Name: " ",
}, "unknown")
@@ -74,31 +74,31 @@ func TestMonitorTemperatureAndUptimeAdditional(t *testing.T) {
Kubernetes: &unifiedresources.K8sData{Temperature: ptrF64Coverage(35)},
}
got := monitorTemperature(resource)
got := monitorTemperature(&resource)
if got == nil || *got != 50 {
t.Fatalf("temperature = %v, want 50 from agent", got)
}
resource.Agent = nil
got = monitorTemperature(resource)
got = monitorTemperature(&resource)
if got == nil || *got != 45 {
t.Fatalf("temperature = %v, want 45 from proxmox", got)
}
resource.Proxmox = nil
got = monitorTemperature(resource)
got = monitorTemperature(&resource)
if got == nil || *got != 40 {
t.Fatalf("temperature = %v, want 40 from docker", got)
}
resource.Docker = nil
got = monitorTemperature(resource)
got = monitorTemperature(&resource)
if got == nil || *got != 35 {
t.Fatalf("temperature = %v, want 35 from kubernetes", got)
}
resource.Kubernetes = nil
if got := monitorTemperature(resource); got != nil {
if got := monitorTemperature(&resource); got != nil {
t.Fatalf("temperature = %v, want nil when no source has temp", got)
}
})
@@ -113,19 +113,19 @@ func TestMonitorTemperatureAndUptimeAdditional(t *testing.T) {
PMG: &unifiedresources.PMGData{UptimeSeconds: 12},
}
got := monitorUptime(resource)
got := monitorUptime(&resource)
if got == nil || *got != 11 {
t.Fatalf("uptime = %v, want 11 from PBS", got)
}
resource.PBS.UptimeSeconds = 0
got = monitorUptime(resource)
got = monitorUptime(&resource)
if got == nil || *got != 12 {
t.Fatalf("uptime = %v, want 12 from PMG", got)
}
resource.PMG.UptimeSeconds = 0
if got := monitorUptime(resource); got != nil {
if got := monitorUptime(&resource); got != nil {
t.Fatalf("uptime = %v, want nil when all sources are zero", got)
}
})
@@ -133,7 +133,7 @@ func TestMonitorTemperatureAndUptimeAdditional(t *testing.T) {
func TestMonitorIdentityLabelsSourceTypeAndLastSeenAdditional(t *testing.T) {
t.Run("labels are copied and nil is preserved", func(t *testing.T) {
if got := monitorLabels(unifiedresources.Resource{}); got != nil {
if got := monitorLabels(&unifiedresources.Resource{}); got != nil {
t.Fatalf("monitorLabels() = %#v, want nil", got)
}
@@ -142,7 +142,7 @@ func TestMonitorIdentityLabelsSourceTypeAndLastSeenAdditional(t *testing.T) {
Labels: map[string]string{"env": "prod"},
},
}
labels := monitorLabels(resource)
labels := monitorLabels(&resource)
labels["env"] = "dev"
if resource.Kubernetes.Labels["env"] != "prod" {
t.Fatalf("expected labels to be copied, source mutated to %q", resource.Kubernetes.Labels["env"])
@@ -157,7 +157,7 @@ func TestMonitorIdentityLabelsSourceTypeAndLastSeenAdditional(t *testing.T) {
IPAddresses: []string{" 10.0.0.1 ", "", "10.0.0.2"},
},
}
identity := monitorIdentity(resource, "fallback-name")
identity := monitorIdentity(&resource, "fallback-name")
if identity == nil {
t.Fatal("expected non-nil identity")
}
@@ -171,7 +171,7 @@ func TestMonitorIdentityLabelsSourceTypeAndLastSeenAdditional(t *testing.T) {
t.Fatalf("ips = %#v, want trimmed non-empty entries", identity.IPs)
}
none := monitorIdentity(unifiedresources.Resource{}, "")
none := monitorIdentity(&unifiedresources.Resource{}, "")
if none != nil {
t.Fatalf("expected nil identity for empty input, got %#v", none)
}
@@ -204,7 +204,7 @@ func TestMonitorIdentityLabelsSourceTypeAndLastSeenAdditional(t *testing.T) {
})
t.Run("identity prefers direct source hostnames", func(t *testing.T) {
identity := monitorIdentity(unifiedresources.Resource{
identity := monitorIdentity(&unifiedresources.Resource{
Agent: &unifiedresources.AgentData{Hostname: "agent-host"},
Docker: &unifiedresources.DockerData{Hostname: "docker-host"},
Proxmox: &unifiedresources.ProxmoxData{NodeName: "proxmox-node"},