fix(workloads): resolve truenas as canonical platform source

This commit is contained in:
rcourtman
2026-03-29 22:45:56 +01:00
parent 0031105e43
commit a3b4390e4c
4 changed files with 50 additions and 3 deletions
@@ -1143,6 +1143,12 @@ may render friendly string keys, but membership checks against available
sources must normalize through the shared
`frontend-modern/src/utils/sourcePlatforms.ts` helper before consulting
`KnownSourcePlatform` sets.
That same shared source-platform boundary now also owns TrueNAS-backed hybrid
resources. When a canonical resource carries both `agent` and `truenas`
sources, `frontend-modern/src/utils/sourcePlatforms.ts` must still resolve the
platform as `truenas` and the source mode as `hybrid`, so workload and
infrastructure consumers do not collapse API-backed TrueNAS systems or apps
back onto the generic agent path just because host telemetry is also present.
The route file `frontend-modern/src/pages/Infrastructure.tsx` is now only the
navigation boundary for that surface; canonical infrastructure filter, search,
deep-link, and expansion state now live behind the dedicated infrastructure
@@ -137,6 +137,19 @@ describe('useWorkloads', () => {
{ ...sampleResource, id: 'vm-pve', sources: ['PROXMOX'] },
{ ...sampleResource, id: 'vm-pbs', sources: ['pbs'], name: 'vm-pbs' },
{ ...sampleResource, id: 'vm-pmg', sources: ['pmg'], name: 'vm-pmg' },
{
...sampleResource,
id: 'truenas-nextcloud',
type: 'app-container',
name: 'nextcloud',
status: 'healthy',
sources: ['agent', 'truenas'],
parentName: 'truenas-main',
docker: {
containerId: 'nextcloud-ctr',
image: 'ix-nextcloud:latest',
},
},
],
meta: { totalPages: 1 },
});
@@ -150,12 +163,13 @@ describe('useWorkloads', () => {
});
await flushAsync();
await waitForWorkloadCount(() => result!.workloads().length, 3);
await waitForWorkloadCount(() => result!.workloads().length, 4);
const byName = new Map(result!.workloads().map((workload) => [workload.name, workload]));
expect(byName.get('vm-101')?.platformType).toBe('proxmox-pve');
expect(byName.get('vm-pbs')?.platformType).toBe('proxmox-pbs');
expect(byName.get('vm-pmg')?.platformType).toBe('proxmox-pmg');
expect(byName.get('nextcloud')?.platformType).toBe('truenas');
dispose();
});
@@ -74,6 +74,7 @@ describe('sourcePlatforms', () => {
hasKubernetes: false,
hasPbs: true,
hasPmg: false,
hasTrueNAS: false,
});
});
@@ -85,6 +86,19 @@ describe('sourcePlatforms', () => {
hasKubernetes: false,
hasPbs: false,
hasPmg: false,
hasTrueNAS: false,
});
});
it('tracks TrueNAS as a canonical API-backed platform source', () => {
expect(readSourcePlatformFlags(['agent', 'truenas'])).toEqual({
hasAgent: true,
hasProxmox: false,
hasDocker: false,
hasKubernetes: false,
hasPbs: false,
hasPmg: false,
hasTrueNAS: true,
});
});
});
@@ -94,6 +108,7 @@ describe('sourcePlatforms', () => {
expect(resolvePlatformTypeFromSources(['agent', 'docker'])).toBe('docker');
expect(resolvePlatformTypeFromSources(['agent', 'pbs'])).toBe('proxmox-pbs');
expect(resolvePlatformTypeFromSources(['pmg', 'docker'])).toBe('proxmox-pmg');
expect(resolvePlatformTypeFromSources(['agent', 'truenas'])).toBe('truenas');
expect(resolvePlatformTypeFromSources(['agent'])).toBe('agent');
expect(resolvePlatformTypeFromSources(['custom-source'])).toBeUndefined();
});
@@ -104,6 +119,7 @@ describe('sourcePlatforms', () => {
expect(resolveSourceTypeFromSources(['agent'])).toBe('agent');
expect(resolveSourceTypeFromSources(['pve'])).toBe('api');
expect(resolveSourceTypeFromSources(['agent', 'proxmox'])).toBe('hybrid');
expect(resolveSourceTypeFromSources(['agent', 'truenas'])).toBe('hybrid');
expect(resolveSourceTypeFromSources(['custom-source'])).toBe('api');
});
});
+13 -2
View File
@@ -30,6 +30,7 @@ export interface SourcePlatformFlags {
hasKubernetes: boolean;
hasPbs: boolean;
hasPmg: boolean;
hasTrueNAS: boolean;
}
export const SOURCE_PLATFORM_PRESENTATION: Record<KnownSourcePlatform, SourcePlatformPresentation> =
@@ -141,6 +142,7 @@ export const readSourcePlatformFlags = (sources?: string[]): SourcePlatformFlags
hasKubernetes: false,
hasPbs: false,
hasPmg: false,
hasTrueNAS: false,
};
if (!sources || sources.length === 0) {
@@ -167,6 +169,9 @@ export const readSourcePlatformFlags = (sources?: string[]): SourcePlatformFlags
case 'proxmox-pmg':
flags.hasPmg = true;
break;
case 'truenas':
flags.hasTrueNAS = true;
break;
default:
break;
}
@@ -180,8 +185,9 @@ export const resolvePlatformTypeFromSources = (sources?: string[]): PlatformType
if (flags.hasProxmox) return 'proxmox-pve';
if (flags.hasPbs) return 'proxmox-pbs';
if (flags.hasPmg) return 'proxmox-pmg';
if (flags.hasDocker) return 'docker';
if (flags.hasTrueNAS) return 'truenas';
if (flags.hasKubernetes) return 'kubernetes';
if (flags.hasDocker) return 'docker';
if (flags.hasAgent) return 'agent';
return undefined;
};
@@ -189,7 +195,12 @@ export const resolvePlatformTypeFromSources = (sources?: string[]): PlatformType
export const resolveSourceTypeFromSources = (sources?: string[]): SourceType => {
const flags = readSourcePlatformFlags(sources);
const hasOther =
flags.hasProxmox || flags.hasDocker || flags.hasKubernetes || flags.hasPbs || flags.hasPmg;
flags.hasProxmox ||
flags.hasDocker ||
flags.hasKubernetes ||
flags.hasPbs ||
flags.hasPmg ||
flags.hasTrueNAS;
if (flags.hasAgent && hasOther) return 'hybrid';
if (flags.hasAgent) return 'agent';
return 'api';