Move Kubernetes context helper into agent resources

This commit is contained in:
rcourtman 2026-03-19 20:10:37 +00:00
parent a3f24c304b
commit 96daee1173
5 changed files with 55 additions and 24 deletions

View file

@ -140,9 +140,10 @@ also routes its Kubernetes-cluster fallback through the same preferred
resource display contract, so navigation context does not leak raw
`displayName` values for governed clusters.
That same workloads-link path and the dashboard workload projection now also
share the canonical Kubernetes context prefix helper, so route labels and pod
grouping keep using the same cluster-context source of truth instead of
rebuilding the `clusterName`/`context`/`clusterId` prefix locally.
share the canonical Kubernetes context prefix helper in the shared
agent-resource layer, so route labels and pod grouping keep using the same
cluster-context source of truth instead of rebuilding the
`clusterName`/`context`/`clusterId` prefix locally.
The drawer's Kubernetes namespace/deployment tabs use the canonical
cluster-name helper for fetch keys, so the visible navigation label stays
separate from the backend cluster lookup contract.

View file

@ -297,9 +297,9 @@ The drawer's discovery mapper also reuses that helper for pod fallback agent
IDs, so the resource-detail path and the dashboard path stay aligned on the
same cluster-name source of truth.
The dashboard workload projection and workloads-link route helpers also share
the same Kubernetes context prefix helper, so pod grouping and cluster
navigation keep the same cluster-context prefix before any surface-specific
display fallback is applied.
the same Kubernetes context prefix helper in the shared agent-resource
layer, so pod grouping and cluster navigation keep the same cluster-context
prefix before any surface-specific display fallback is applied.
The unified-resource projection also reuses that same prefix helper for
projected Kubernetes `clusterId`, so the shared resource store stays aligned
with the dashboard and detail surfaces on the same canonical cluster-context

View file

@ -131,6 +131,19 @@ describe('agentResources', () => {
}),
),
).toBe('cluster-1');
expect(
getActionableKubernetesClusterIdFromResource(
makeResource({
type: 'k8s-cluster',
kubernetes: {
clusterName: 'cluster-a',
context: 'cluster-context',
clusterId: 'cluster-a-id',
},
}),
),
).toBe('cluster-a');
});
it('detects docker workloads scope from explicit docker facets instead of source lists', () => {

View file

@ -19,6 +19,23 @@ const AGENT_PROFILE_ASSIGNABLE_TYPES = new Set<ResourceType>([
const asRecord = (value: unknown): Record<string, unknown> | undefined =>
value && typeof value === 'object' ? (value as Record<string, unknown>) : undefined;
type KubernetesContextLike = {
clusterId?: string | null;
name?: string | null;
kubernetes?: {
clusterName?: string | null;
context?: string | null;
clusterId?: string | null;
} | null;
platformData?: {
kubernetes?: {
clusterName?: string | null;
context?: string | null;
clusterId?: string | null;
} | null;
} | null;
};
export const getPlatformDataRecord = (resource: Resource): Record<string, unknown> | undefined =>
resource.platformData ? (resource.platformData as Record<string, unknown>) : undefined;
@ -80,21 +97,30 @@ export const hasDockerWorkloadsScope = (resource: Resource): boolean => {
export const getActionableKubernetesClusterIdFromResource = (
resource: Resource,
): string | undefined => {
const platformData = getPlatformDataRecord(resource);
const kubernetes = asRecord(platformData?.kubernetes);
if (resource.discoveryTarget?.resourceType === 'pod' && resource.discoveryTarget.resourceId) {
return resource.discoveryTarget.resourceId;
}
return (
asTrimmedString(resource.kubernetes?.clusterId) ||
asTrimmedString(kubernetes?.clusterId) ||
asTrimmedString(platformData?.clusterId) ||
getPreferredResourceKubernetesContext(resource) ||
(resource.type === 'k8s-cluster' ? resource.id : undefined)
);
};
export const getPreferredResourceKubernetesContext = (
resource: KubernetesContextLike,
): string | undefined => {
return (
asTrimmedString(resource.kubernetes?.clusterName) ||
asTrimmedString(resource.kubernetes?.context) ||
asTrimmedString(resource.kubernetes?.clusterId) ||
asTrimmedString(resource.platformData?.kubernetes?.clusterName) ||
asTrimmedString(resource.platformData?.kubernetes?.context) ||
asTrimmedString(resource.platformData?.kubernetes?.clusterId) ||
asTrimmedString(resource.clusterId)
);
};
export const getMetricsChartKeyCandidatesFromResource = (resource: Resource): string[] => {
const candidates = [
asTrimmedString(resource.metricsTarget?.resourceId),

View file

@ -10,6 +10,7 @@ import {
getActionableAgentIdFromResource,
getActionableDockerRuntimeIdFromResource,
getActionableKubernetesClusterIdFromResource,
getPreferredResourceKubernetesContext,
getPlatformAgentRecord,
getPlatformDataRecord,
} from '@/utils/agentResources';
@ -318,6 +319,8 @@ export const getPreferredResourceHostname = (resource: Resource): string | undef
);
};
export { getPreferredResourceKubernetesContext };
export const getPreferredResourceClusterName = (
resource: ResourceClusterNameLike,
): string | undefined =>
@ -332,18 +335,6 @@ export const getPreferredResourceClusterName = (
);
})();
export const getPreferredResourceKubernetesContext = (
resource: ResourceClusterNameLike,
): string | undefined => {
const kubernetes = resource.kubernetes || resource.platformData?.kubernetes;
return (
asTrimmedString(kubernetes?.clusterName) ||
asTrimmedString(kubernetes?.context) ||
asTrimmedString(kubernetes?.clusterId) ||
asTrimmedString(resource.clusterId)
);
};
export const getPreferredResourceDisplayName = (resource: Resource): string =>
requiresGovernedResourceDisplay(resource.policy)
? getResourcePolicyDisplayLabel(resource)