mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-07-09 16:00:59 +00:00
parent
c1d8cd8f11
commit
806fd7409c
6 changed files with 84 additions and 15 deletions
|
|
@ -30,6 +30,11 @@ healthy source is between normal poll cycles.
|
|||
Removed host-agent reconnect blocks are identity-scoped: matching may use the
|
||||
canonical host ID or token-qualified machine/hostname continuity, but must never
|
||||
block a distinct live host by hostname alone.
|
||||
Proxmox cluster node labels are monitoring-owned identity presentation:
|
||||
configured cluster labels must project into node display names as
|
||||
`cluster label (node name)` so duplicate node hostnames across clusters remain
|
||||
distinguishable, while `models.Node.Name` and `ProxmoxData.NodeName` keep the
|
||||
raw Proxmox node identity for linking, metrics, URLs, and actions.
|
||||
|
||||
## Canonical Files
|
||||
|
||||
|
|
|
|||
|
|
@ -1107,6 +1107,26 @@ func TestStoragePollingKeepsSharedStorageClusterStatusCanonical(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestMonitoringProxmoxClusterNodeDisplayNamesStayClusterQualified(t *testing.T) {
|
||||
data, err := os.ReadFile("monitor.go")
|
||||
if err != nil {
|
||||
t.Fatalf("failed to read monitor.go: %v", err)
|
||||
}
|
||||
source := string(data)
|
||||
|
||||
for _, snippet := range []string{
|
||||
"func getNodeDisplayName(instance *config.PVEInstance, nodeName string) string {",
|
||||
"clusterLabel := friendly",
|
||||
"clusterLabel = strings.TrimSpace(instance.ClusterName)",
|
||||
`return fmt.Sprintf("%s (%s)", clusterLabel, baseName)`,
|
||||
"return baseName",
|
||||
} {
|
||||
if !strings.Contains(source, snippet) {
|
||||
t.Fatalf("monitor.go must contain %q", snippet)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMonitoringTemperatureFallbackPrefersRecentAgentTelemetry(t *testing.T) {
|
||||
requiredSnippets := map[string][]string{
|
||||
"host_agent_temps.go": {
|
||||
|
|
|
|||
|
|
@ -136,14 +136,20 @@ func TestGetNodeDisplayName(t *testing.T) {
|
|||
// non-cluster: returns unknown-node when host is IP address
|
||||
{"host IP fallback to unknown-node", &config.PVEInstance{Name: "", Host: "https://192.168.1.100:8006"}, "", "unknown-node"},
|
||||
|
||||
// cluster: lookupClusterEndpointLabel result takes priority
|
||||
{"cluster host label", clusterInstance, "node1", "node1.local"},
|
||||
// cluster: configured instance label disambiguates the Proxmox node name
|
||||
{"cluster configured label", clusterInstance, "node1", "cluster (node1)"},
|
||||
|
||||
// cluster: falls back to baseName when no endpoint label
|
||||
{"cluster base fallback", clusterInstance, "node3", "node3"},
|
||||
// cluster: still uses configured label even when no endpoint label is present
|
||||
{"cluster base fallback", clusterInstance, "node3", "cluster (node3)"},
|
||||
|
||||
// cluster: falls back to nodeName (IP fallback via endpoint)
|
||||
{"cluster ip fallback", clusterInstance, "node2", "node2"},
|
||||
// cluster: keeps the node identity instead of substituting endpoint IP labels
|
||||
{"cluster ip fallback", clusterInstance, "node2", "cluster (node2)"},
|
||||
|
||||
// cluster: ClusterName backs the display label when the user-facing name is empty
|
||||
{"cluster name fallback", &config.PVEInstance{IsCluster: true, ClusterName: "detected-cluster"}, "node4", "detected-cluster (node4)"},
|
||||
|
||||
// cluster: do not duplicate the label when it already equals the node name
|
||||
{"cluster duplicate label", &config.PVEInstance{IsCluster: true, Name: "node5", ClusterName: "detected-cluster"}, "node5", "node5"},
|
||||
|
||||
// cluster: falls back to friendly name when baseName is "unknown-node"
|
||||
{"cluster friendly fallback", &config.PVEInstance{IsCluster: true, Name: "Cluster Name", ClusterEndpoints: []config.ClusterEndpoint{}}, "", "Cluster Name"},
|
||||
|
|
|
|||
|
|
@ -186,16 +186,27 @@ func getNodeDisplayName(instance *config.PVEInstance, nodeName string) string {
|
|||
friendly := strings.TrimSpace(instance.Name)
|
||||
|
||||
if instance.IsCluster {
|
||||
if endpointLabel := lookupClusterEndpointLabel(instance, nodeName); endpointLabel != "" {
|
||||
return endpointLabel
|
||||
clusterLabel := friendly
|
||||
if clusterLabel == "" {
|
||||
clusterLabel = strings.TrimSpace(instance.ClusterName)
|
||||
}
|
||||
|
||||
if baseName != "" && baseName != "unknown-node" {
|
||||
if clusterLabel != "" && !strings.EqualFold(clusterLabel, baseName) {
|
||||
return fmt.Sprintf("%s (%s)", clusterLabel, baseName)
|
||||
}
|
||||
return baseName
|
||||
}
|
||||
|
||||
if friendly != "" {
|
||||
return friendly
|
||||
if endpointLabel := lookupClusterEndpointLabel(instance, nodeName); endpointLabel != "" {
|
||||
if clusterLabel != "" && !strings.EqualFold(clusterLabel, endpointLabel) {
|
||||
return fmt.Sprintf("%s (%s)", clusterLabel, endpointLabel)
|
||||
}
|
||||
return endpointLabel
|
||||
}
|
||||
|
||||
if clusterLabel != "" {
|
||||
return clusterLabel
|
||||
}
|
||||
|
||||
return baseName
|
||||
|
|
|
|||
|
|
@ -354,8 +354,8 @@ func TestGetNodeDisplayName_FriendlyName(t *testing.T) {
|
|||
func TestGetNodeDisplayName_ClusterUsesNodeName(t *testing.T) {
|
||||
inst := &config.PVEInstance{Name: "cluster1", IsCluster: true}
|
||||
got := getNodeDisplayName(inst, "node1")
|
||||
if got != "node1" {
|
||||
t.Errorf("cluster mode should use node name, got %q", got)
|
||||
if got != "cluster1 (node1)" {
|
||||
t.Errorf("cluster mode should include configured cluster label, got %q", got)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -368,8 +368,7 @@ func TestGetNodeDisplayName_ClusterWithEndpointLabel(t *testing.T) {
|
|||
},
|
||||
}
|
||||
got := getNodeDisplayName(inst, "node1")
|
||||
// With matching endpoint, should still return node1 (or the endpoint label)
|
||||
if got == "" || got == "unknown-node" {
|
||||
t.Errorf("expected a valid display name for cluster node, got %q", got)
|
||||
if got != "cluster1 (node1)" {
|
||||
t.Errorf("expected cluster-qualified node display name, got %q", got)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,6 +39,34 @@ func TestResourceFromProxmoxNodeIncludesTemperature(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestResourceFromProxmoxNodeUsesDisplayNameWithoutChangingRawNodeIdentity(t *testing.T) {
|
||||
node := models.Node{
|
||||
ID: "pve-cluster-node01",
|
||||
Name: "node01",
|
||||
DisplayName: "PVE Cluster (node01)",
|
||||
ClusterName: "PVE Cluster",
|
||||
Status: "online",
|
||||
}
|
||||
|
||||
resource, identity := resourceFromProxmoxNode(node, nil)
|
||||
if resource.Name != "PVE Cluster (node01)" {
|
||||
t.Fatalf("resource.Name = %q, want cluster-qualified display label", resource.Name)
|
||||
}
|
||||
if resource.Proxmox == nil || resource.Proxmox.NodeName != "node01" {
|
||||
t.Fatalf("Proxmox.NodeName = %+v, want raw node identity node01", resource.Proxmox)
|
||||
}
|
||||
foundClusterIdentity := false
|
||||
for _, hostname := range identity.Hostnames {
|
||||
if hostname == "PVE Cluster:node01" {
|
||||
foundClusterIdentity = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !foundClusterIdentity {
|
||||
t.Fatalf("identity hostnames = %v, want cluster-qualified raw hostname identity", identity.Hostnames)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResourceFromDockerContainerAdvertisesLifecycleCapabilities(t *testing.T) {
|
||||
now := time.Now().UTC()
|
||||
host := models.DockerHost{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue