Integrate published workload cluster labels without rewriting guest repairs

Preserve reviewed guest-observation ancestry and the human-authored vSphere label repair at the exact upstream frontier.

Change-source: pulse-maintainer
This commit is contained in:
pulse-triage[bot]
2026-10-05 00:07:43 +01:00
3 changed files with 99 additions and 3 deletions
@@ -0,0 +1,35 @@
{
"version": 1,
"base_sha": "f5157115b7b224000ef7035285d9ce64bbe60bb7",
"verified_at": "2026-10-04T22:46:28Z",
"result": "passed",
"changed_paths": [
"frontend-modern/src/hooks/useWorkloads.ts"
],
"content_sha256": {
"frontend-modern/src/hooks/useWorkloads.ts": "ef6459b28c2ce225e5f5ec56731f135b1a2b1788af40aad14724e108167d86ec"
},
"routes": [
"/vmware/overview",
"/proxmox/overview"
],
"viewports": [
{
"width": 1440,
"height": 1100
},
{
"width": 390,
"height": 844
}
],
"states": [
"Mock estate (PULSE_MOCK_MODE, 5 Proxmox nodes in one cluster, Lab vCenter with 7 ESXi hosts in Production Cluster and Edge Services). Before the fix every vSphere host group header carried a chip naming its first VM (esxi-01.lab.local [etl-batch-01]); after it each header names the host cluster and matches the hosts table Cluster column.",
"Proxmox overview group headers still render the node row with the Production West cluster chip and Agent badge, unchanged.",
"Phone width (390x844, touch, DPR 2): vSphere group headers show Production Cluster / Edge Services chips without truncation.",
"Unit proof: useWorkloads test fails on the old helper (Received etl-batch-01) and passes with the explicit cluster; a standalone Proxmox guest now has no cluster and labels its context with the instance."
],
"interactions": [
"Loaded each route signed in with Playwright Chromium at desktop and phone widths and inspected the screenshots; no console errors besides the dev-build update check."
]
}
@@ -1326,6 +1326,58 @@ describe('useWorkloads', () => {
dispose();
});
it('never labels a vSphere or standalone Proxmox workload as its own cluster', async () => {
apiFetchJSONMock.mockResolvedValueOnce({
data: [
{
...sampleResource,
id: 'vmware-vm-etl',
name: 'etl-batch-01',
sources: ['vmware'],
parentName: 'esxi-01.lab.local',
proxmox: undefined,
vmware: {
managedObjectId: 'vm-206',
runtimeHostName: 'esxi-01.lab.local',
clusterName: 'Production Cluster',
connectionName: 'Lab vCenter',
powerState: 'poweredOn',
},
},
{
...sampleResource,
id: 'pve-home-pve1-102',
name: 'standalone-vm',
vmid: 102,
instance: 'pve-home',
proxmox: {},
},
],
meta: { totalPages: 1 },
});
let dispose = () => {};
let result: ReturnType<UseWorkloadsModule['useWorkloads']> | undefined;
createRoot((d) => {
dispose = d;
const [enabled] = createSignal(true);
result = useWorkloads(enabled);
});
await flushAsync();
await waitForWorkloadCount(() => result!.workloads().length, 2);
const byName = new Map(result!.workloads().map((workload) => [workload.name, workload]));
expect(byName.get('etl-batch-01')?.clusterName).toBe('Production Cluster');
expect(byName.get('etl-batch-01')?.contextLabel).toBe('esxi-01.lab.local (Production Cluster)');
expect(byName.get('etl-batch-01')?.instance).toBe('Production Cluster');
expect(byName.get('standalone-vm')?.clusterName).toBeUndefined();
expect(byName.get('standalone-vm')?.contextLabel).toBe('pve1 (pve-home)');
expect(byName.get('standalone-vm')?.instance).toBe('pve-home');
dispose();
});
it('uses the shared cluster-name helper for proxmox workload labels', async () => {
apiFetchJSONMock.mockResolvedValueOnce({
data: [
+12 -3
View File
@@ -20,6 +20,7 @@ import {
getPreferredResourceClusterName,
getPreferredResourceKubernetesContext,
} from '@/utils/resourceIdentity';
import { getExplicitResourceClusterName } from '@/utils/agentResources';
import type { WorkloadGuest } from '@/types/workloads';
import type { HostRAIDArray } from '@/types/api';
import type {
@@ -448,6 +449,14 @@ const mapResourceToWorkload = (resource: APIResource): WorkloadGuest | null => {
'';
const kubernetesContext = getPreferredResourceKubernetesContext(resource);
const preferredClusterName = getPreferredResourceClusterName(resource);
// The preferred helper falls back to the resource's own name, which is the
// right label for a cluster resource but not for a workload: a vSphere VM
// or a standalone Proxmox guest would otherwise be labelled as its own
// cluster. Only an explicit cluster may become the workload's cluster.
const workloadClusterName =
(platformType === 'vmware-vsphere'
? resource.vmware?.clusterName?.trim() || undefined
: undefined) ?? getExplicitResourceClusterName(resource);
const instance =
vmwareInstance ??
resource.instance ??
@@ -638,7 +647,7 @@ const mapResourceToWorkload = (resource: APIResource): WorkloadGuest | null => {
workloadType === 'vm' || workloadType === 'system-container'
? node
? (() => {
const cluster = preferredClusterName || '';
const cluster = workloadClusterName || '';
if (cluster && cluster !== node) return `${node} (${cluster})`;
if (instance && instance !== node) return `${node} (${instance})`;
return node;
@@ -647,9 +656,9 @@ const mapResourceToWorkload = (resource: APIResource): WorkloadGuest | null => {
: workloadType === 'app-container'
? resource.parentName || resource.docker?.hostname
: workloadType === 'pod'
? preferredClusterName
? workloadClusterName
: undefined,
clusterName: preferredClusterName || undefined,
clusterName: workloadClusterName || undefined,
containerRuntime:
workloadType === 'app-container'
? (resource.docker?.runtime || '').trim() || undefined