@skyhook-io/k8s-ui 1.12.0 → 1.13.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +4 -4
- package/src/components/applications/ApplicationDetail.tsx +2 -2
- package/src/components/cluster-switcher/ClusterSwitcher.tsx +32 -7
- package/src/components/issues/severity.ts +1 -0
- package/src/components/resources/ResourcesView.empty-note.test.ts +41 -0
- package/src/components/resources/ResourcesView.tsx +419 -9
- package/src/components/resources/index.ts +27 -0
- package/src/components/resources/kyverno-legacy-action.test.ts +98 -0
- package/src/components/resources/renderers/AnalysisRunRenderer.test.tsx +241 -0
- package/src/components/resources/renderers/AnalysisRunRenderer.tsx +166 -0
- package/src/components/resources/renderers/CNPGBackupRenderer.tsx +31 -2
- package/src/components/resources/renderers/CNPGClusterRenderer.test.tsx +33 -0
- package/src/components/resources/renderers/CNPGClusterRenderer.tsx +47 -4
- package/src/components/resources/renderers/CNPGDeclarativeRenderer.tsx +243 -0
- package/src/components/resources/renderers/CNPGObjectStoreRenderer.test.tsx +99 -0
- package/src/components/resources/renderers/CNPGObjectStoreRenderer.tsx +235 -0
- package/src/components/resources/renderers/CNPGScheduledBackupRenderer.tsx +23 -1
- package/src/components/resources/renderers/CNPGShared.tsx +27 -0
- package/src/components/resources/renderers/CalicoHostEndpointRenderer.tsx +71 -0
- package/src/components/resources/renderers/CalicoIPPoolRenderer.tsx +32 -0
- package/src/components/resources/renderers/CalicoNetworkPolicyDiagram.test.tsx +205 -0
- package/src/components/resources/renderers/CalicoNetworkPolicyDiagram.tsx +537 -0
- package/src/components/resources/renderers/CalicoNetworkPolicyRenderer.test.tsx +223 -0
- package/src/components/resources/renderers/CalicoNetworkPolicyRenderer.tsx +670 -0
- package/src/components/resources/renderers/CalicoTierRenderer.tsx +19 -0
- package/src/components/resources/renderers/KyvernoCELPolicyRenderers.tsx +13 -6
- package/src/components/resources/renderers/KyvernoExceptionRenderers.tsx +3 -2
- package/src/components/resources/renderers/KyvernoGlobalContextRenderer.test.ts +31 -0
- package/src/components/resources/renderers/KyvernoGlobalContextRenderer.tsx +124 -0
- package/src/components/resources/renderers/KyvernoPolicyReportRenderer.tsx +28 -2
- package/src/components/resources/renderers/KyvernoQueueRenderers.tsx +303 -0
- package/src/components/resources/renderers/LookupFailureNote.test.tsx +60 -0
- package/src/components/resources/renderers/LookupFailureNote.tsx +42 -0
- package/src/components/resources/renderers/NamespaceRenderer.test.ts +30 -0
- package/src/components/resources/renderers/NamespaceRenderer.tsx +7 -3
- package/src/components/resources/renderers/NetworkPolicyDiagram.tsx +27 -26
- package/src/components/resources/renderers/NetworkPolicyRenderer.tsx +6 -3
- package/src/components/resources/renderers/PolicyCoverageSection.test.tsx +348 -0
- package/src/components/resources/renderers/PolicyCoverageSection.tsx +939 -0
- package/src/components/resources/renderers/PolicySection.test.tsx +59 -2
- package/src/components/resources/renderers/PolicySection.tsx +32 -5
- package/src/components/resources/renderers/RolloutRenderer.test.tsx +491 -0
- package/src/components/resources/renderers/RolloutRenderer.tsx +391 -92
- package/src/components/resources/renderers/VeleroBSLRenderer.test.tsx +374 -0
- package/src/components/resources/renderers/VeleroBSLRenderer.tsx +179 -3
- package/src/components/resources/renderers/VeleroBackupRenderer.test.tsx +221 -0
- package/src/components/resources/renderers/VeleroBackupRenderer.tsx +119 -6
- package/src/components/resources/renderers/VeleroBackupRepositoryRenderer.test.tsx +69 -0
- package/src/components/resources/renderers/VeleroBackupRepositoryRenderer.tsx +96 -0
- package/src/components/resources/renderers/VeleroRestoreRenderer.test.tsx +55 -0
- package/src/components/resources/renderers/VeleroRestoreRenderer.tsx +22 -4
- package/src/components/resources/renderers/VeleroRunMessages.test.tsx +152 -0
- package/src/components/resources/renderers/VeleroRunMessages.tsx +139 -0
- package/src/components/resources/renderers/VeleroScheduleRenderer.test.tsx +88 -0
- package/src/components/resources/renderers/VeleroScheduleRenderer.tsx +16 -6
- package/src/components/resources/renderers/calico-cells.tsx +177 -0
- package/src/components/resources/renderers/cnpg-cells.tsx +100 -0
- package/src/components/resources/renderers/index.ts +16 -1
- package/src/components/resources/renderers/kyverno-cells.tsx +81 -0
- package/src/components/resources/renderers/network-policy-peer-styles.ts +25 -0
- package/src/components/resources/renderers/velero-cells.tsx +29 -7
- package/src/components/resources/renderers/velero-dead-ends.test.tsx +142 -0
- package/src/components/resources/resource-utils-calico.test.ts +215 -0
- package/src/components/resources/resource-utils-calico.ts +261 -0
- package/src/components/resources/resource-utils-cnpg-declarative.test.ts +104 -0
- package/src/components/resources/resource-utils-cnpg-objectstore.test.ts +122 -0
- package/src/components/resources/resource-utils-cnpg.test.ts +54 -0
- package/src/components/resources/resource-utils-cnpg.ts +264 -3
- package/src/components/resources/resource-utils-kyverno-modern.ts +24 -0
- package/src/components/resources/resource-utils-kyverno-queue.test.ts +164 -0
- package/src/components/resources/resource-utils-kyverno-queue.ts +198 -0
- package/src/components/resources/resource-utils-kyverno.ts +43 -7
- package/src/components/resources/resource-utils-velero.test.ts +26 -0
- package/src/components/resources/resource-utils-velero.ts +68 -0
- package/src/components/resources/resource-utils.ts +98 -0
- package/src/components/shared/ResourceActionsBar.tsx +101 -16
- package/src/components/shared/ResourceRendererDispatch.test.tsx +379 -3
- package/src/components/shared/ResourceRendererDispatch.tsx +199 -22
- package/src/components/shared/index.ts +1 -1
- package/src/components/shared/revision-role-badges.test.ts +120 -0
- package/src/components/topology/K8sResourceNode.test.ts +10 -0
- package/src/components/topology/K8sResourceNode.tsx +22 -0
- package/src/components/topology/TopologyFilterSidebar.test.tsx +31 -0
- package/src/components/topology/TopologyFilterSidebar.tsx +5 -0
- package/src/components/topology/TopologyGraph.tsx +6 -6
- package/src/components/topology/TopologySearch.tsx +7 -0
- package/src/components/topology/layout.ts +3 -0
- package/src/components/trace/ReachabilityView.tsx +1 -0
- package/src/components/trace/TracePanel.tsx +13 -2
- package/src/components/trace/reachFixtures.ts +26 -1
- package/src/components/trace/reachGraphModel.test.ts +20 -0
- package/src/components/trace/reachGraphModel.ts +8 -1
- package/src/components/trace/reachOrigins.test.ts +31 -0
- package/src/components/trace/reachOrigins.ts +11 -1
- package/src/components/ui/Badge.tsx +10 -0
- package/src/components/ui/InClusterConsentDialog.tsx +5 -4
- package/src/components/ui/ScheduleValue.test.tsx +80 -0
- package/src/components/ui/ScheduleValue.tsx +85 -0
- package/src/components/ui/SelectMenu.tsx +202 -28
- package/src/components/ui/drawer-components.test.tsx +17 -1
- package/src/components/ui/drawer-components.tsx +9 -2
- package/src/components/ui/index.ts +2 -0
- package/src/components/workload/WorkloadView.tsx +5 -2
- package/src/types/core.ts +36 -4
- package/src/types/policy.ts +153 -2
- package/src/utils/clipboard.test.ts +86 -0
- package/src/utils/clipboard.ts +50 -0
- package/src/utils/extended-resources.ts +4 -7
- package/src/utils/format.test.ts +83 -1
- package/src/utils/format.ts +80 -1
- package/src/utils/inClusterConsent.test.ts +9 -0
- package/src/utils/inClusterConsent.ts +9 -9
- package/src/utils/index.ts +1 -0
- package/src/utils/navigation.test.ts +5 -0
- package/src/utils/navigation.ts +5 -0
- package/src/utils/resource-icons.test.ts +49 -2
- package/src/utils/resource-icons.ts +29 -2
|
@@ -35,6 +35,7 @@ import type { SelectedResource, APIResource } from '../../types'
|
|
|
35
35
|
import { isForbiddenError } from '../../types/fetch-error'
|
|
36
36
|
import type { NavigateToResource } from '../../utils/navigation'
|
|
37
37
|
import { categorizeResources, CORE_RESOURCES, findAPIResourceForRoute } from '../../utils/api-resources'
|
|
38
|
+
import { copyText } from '../../utils/clipboard'
|
|
38
39
|
import {
|
|
39
40
|
getPodStatus,
|
|
40
41
|
getPodRestarts,
|
|
@@ -79,6 +80,8 @@ import {
|
|
|
79
80
|
getPVCCapacity,
|
|
80
81
|
getPVCAccessModes,
|
|
81
82
|
getRolloutStatus,
|
|
83
|
+
getAnalysisRunStatus,
|
|
84
|
+
summarizeAnalysisMetrics,
|
|
82
85
|
getRolloutStrategy,
|
|
83
86
|
getRolloutReady,
|
|
84
87
|
getRolloutStep,
|
|
@@ -137,6 +140,7 @@ import {
|
|
|
137
140
|
import { SEVERITY_BADGE, EVENT_TYPE_COLORS } from '../../utils/badge-colors'
|
|
138
141
|
import { pluralize } from '../../utils/pluralize'
|
|
139
142
|
import { getPodGpuCount, getNodeGpuCount } from '../../utils/extended-resources'
|
|
143
|
+
import { parseQuantityToNumber } from '../../utils/format'
|
|
140
144
|
import { type CustomColumnDef, type CustomColumnSource, customColumnKey, readCustomColumnValue, sanitizeCustomColumnDefs } from '../../utils/custom-columns'
|
|
141
145
|
import { FreshnessControl, type FreshnessConnection } from '../ui/FreshnessControl'
|
|
142
146
|
import { Tooltip } from '../ui/Tooltip'
|
|
@@ -152,14 +156,17 @@ import { ScaledObjectCell, ScaledJobCell, TriggerAuthenticationCell, ClusterTrig
|
|
|
152
156
|
import { ResourceClaimCell, ResourceClaimTemplateCell, DeviceClassCell, ResourceSliceCell } from './renderers/dra-cells'
|
|
153
157
|
import { NvidiaClusterPolicyCell, NvidiaDriverCell } from './renderers/nvidia-cells'
|
|
154
158
|
import { ServiceMonitorCell, PrometheusRuleCell, PodMonitorCell } from './renderers/prometheus-cells'
|
|
155
|
-
import { PolicyReportCell, ClusterPolicyReportCell, KyvernoPolicyCell, ClusterPolicyCell
|
|
159
|
+
import { PolicyReportCell, ClusterPolicyReportCell, KyvernoPolicyCell, ClusterPolicyCell,
|
|
160
|
+
KyvernoUpdateRequestCell,
|
|
161
|
+
KyvernoEphemeralReportCell,
|
|
162
|
+
} from './renderers/kyverno-cells'
|
|
156
163
|
import { KyvernoModernPolicyCell, KyvernoPolicyExceptionCell, KyvernoCleanupPolicyCell } from './renderers/kyverno-modern-cells'
|
|
157
164
|
import { KYVERNO_MODERN_PLURALS, isModernKyvernoPolicy } from './resource-utils-kyverno-modern'
|
|
158
165
|
import { isAnyKyvernoPolicyException } from './resource-utils-kyverno-exceptions'
|
|
159
166
|
import { ExternalSecretCell, ClusterExternalSecretCell, SecretStoreCell, ClusterSecretStoreCell } from './renderers/eso-cells'
|
|
160
167
|
import { BackupCell, RestoreCell, ScheduleCell, BackupStorageLocationCell, VolumeSnapshotLocationCell, BackupRepositoryCell } from './renderers/velero-cells'
|
|
161
168
|
import { isVeleroResource } from './resource-utils-velero'
|
|
162
|
-
import { CNPGClusterCell, CNPGBackupCell, CNPGScheduledBackupCell, CNPGPoolerCell } from './renderers/cnpg-cells'
|
|
169
|
+
import { CNPGClusterCell, CNPGBackupCell, CNPGScheduledBackupCell, CNPGPoolerCell, CNPGObjectStoreCell, CNPGDeclarativeCell, CNPGImageCatalogCell } from './renderers/cnpg-cells'
|
|
163
170
|
import { isApiGroup, CNPG_GROUP } from './resource-utils-cnpg'
|
|
164
171
|
import { ManagedResourceCell, CompositeResourceCell, CrossplaneProviderCell, CrossplaneProviderConfigCell, CompositionCell, XRDCell } from './renderers/crossplane-cells'
|
|
165
172
|
import { isManagedResource, isComposite } from './resource-utils-crossplane'
|
|
@@ -171,6 +178,8 @@ import { CAPIClusterCell, CAPIMachineCell, CAPIMachineDeploymentCell, CAPIMachin
|
|
|
171
178
|
import { AWSManagedControlPlaneCell, AWSManagedMachinePoolCell, AWSMachineCell, AWSMachineTemplateCell, AWSManagedClusterCell } from './renderers/aws-capi-cells'
|
|
172
179
|
import { GCPManagedControlPlaneCell, GCPManagedMachinePoolCell, GCPMachineCell, GCPMachineTemplateCell, GCPManagedClusterCell } from './renderers/gcp-capi-cells'
|
|
173
180
|
import { AzureManagedControlPlaneCell, AzureManagedMachinePoolCell, AzureMachineCell, AzureMachineTemplateCell, AzureManagedClusterCell } from './renderers/azure-capi-cells'
|
|
181
|
+
import { CalicoInfraCell, CalicoPolicyCell } from './renderers/calico-cells'
|
|
182
|
+
import { isCalicoPolicyResource, isCoreNetworkPolicyKind } from './resource-utils-calico'
|
|
174
183
|
import { useRegisterShortcut, useRegisterShortcuts } from '../../hooks/useKeyboardShortcuts'
|
|
175
184
|
import { ResourcesSidebar } from './ResourcesSidebar'
|
|
176
185
|
import type { SelectedKindInfo } from './ResourcesSidebar'
|
|
@@ -274,10 +283,14 @@ function buildCustomColumn(d: CustomColumnDef): ExtraColumn {
|
|
|
274
283
|
}
|
|
275
284
|
|
|
276
285
|
// Tailwind width class → pixel minimum mapping for CSS Grid column sizing
|
|
286
|
+
// A width class missing from this map falls back to 80px, and nothing says so —
|
|
287
|
+
// the column just renders narrow enough to truncate its header. Keep the whole
|
|
288
|
+
// Tailwind step range present rather than only the sizes in use today.
|
|
277
289
|
const TAILWIND_WIDTH_TO_PX: Record<string, number> = {
|
|
278
290
|
'w-12': 48, 'w-14': 56, 'w-16': 64, 'w-20': 80, 'w-24': 96,
|
|
279
291
|
'w-28': 112, 'w-32': 128, 'w-36': 144, 'w-40': 160, 'w-44': 176,
|
|
280
|
-
'w-48': 192, 'w-56': 224, 'w-64': 256,
|
|
292
|
+
'w-48': 192, 'w-52': 208, 'w-56': 224, 'w-60': 240, 'w-64': 256,
|
|
293
|
+
'w-72': 288, 'w-80': 320, 'w-96': 384,
|
|
281
294
|
}
|
|
282
295
|
|
|
283
296
|
const COMPARE_COLUMN_WIDTH = 36
|
|
@@ -296,6 +309,30 @@ function getColumnMinWidth(col: Column): number {
|
|
|
296
309
|
}
|
|
297
310
|
|
|
298
311
|
// Default columns for unknown resource types (CRDs)
|
|
312
|
+
/**
|
|
313
|
+
* Why a list of this kind being empty is not the answer it looks like.
|
|
314
|
+
*
|
|
315
|
+
* Kyverno's two working records are garbage-collected within seconds of
|
|
316
|
+
* finishing, so "none" is the resting state of a healthy cluster — and for
|
|
317
|
+
* UpdateRequest it is ALSO what you see when a generate rule never fired at
|
|
318
|
+
* all. Those are opposite conclusions and a bare "No X found" renders them
|
|
319
|
+
* identically.
|
|
320
|
+
*/
|
|
321
|
+
export function emptyKindNote(kind: string, group?: string, unfilteredTotal = 0): string | undefined {
|
|
322
|
+
// A search or column filter emptying the table is the reader's own doing.
|
|
323
|
+
// Explaining that none is the resting state then answers a question they did
|
|
324
|
+
// not ask, while their own term is still in the box.
|
|
325
|
+
if (unfilteredTotal > 0) return undefined
|
|
326
|
+
const g = group ?? ''
|
|
327
|
+
if (kind.toLowerCase() === 'updaterequest' && g === 'kyverno.io') {
|
|
328
|
+
return 'These are deleted seconds after the work completes, so none is the normal resting state. It also looks like this if a generate or mutate-existing rule never ran — check the policy itself to tell the two apart.'
|
|
329
|
+
}
|
|
330
|
+
if ((kind.toLowerCase() === 'ephemeralreport' || kind.toLowerCase() === 'clusterephemeralreport') && g === 'reports.kyverno.io') {
|
|
331
|
+
return 'These exist only between a background scan and the PolicyReport it becomes, so none means the scan has finished rather than that nothing was checked.'
|
|
332
|
+
}
|
|
333
|
+
return undefined
|
|
334
|
+
}
|
|
335
|
+
|
|
299
336
|
const DEFAULT_COLUMNS: Column[] = [
|
|
300
337
|
{ key: 'name', label: 'Name' },
|
|
301
338
|
{ key: 'namespace', label: 'Namespace', width: 'w-48' },
|
|
@@ -464,6 +501,14 @@ const KNOWN_COLUMNS: Record<string, Column[]> = {
|
|
|
464
501
|
{ key: 'images', label: 'Images', width: 'w-48', hideOnMobile: true },
|
|
465
502
|
{ key: 'age', label: 'Age', width: 'w-24' },
|
|
466
503
|
],
|
|
504
|
+
analysisruns: [
|
|
505
|
+
{ key: 'name', label: 'Name' },
|
|
506
|
+
{ key: 'namespace', label: 'Namespace', width: 'w-48' },
|
|
507
|
+
{ key: 'status', label: 'Phase', width: 'w-28' },
|
|
508
|
+
{ key: 'trigger', label: 'Trigger', width: 'w-32', tooltip: 'Which part of the Rollout started this run' },
|
|
509
|
+
{ key: 'metrics', label: 'Metrics', width: 'w-40', hideOnMobile: true, tooltip: 'Per-metric verdicts' },
|
|
510
|
+
{ key: 'age', label: 'Age', width: 'w-24' },
|
|
511
|
+
],
|
|
467
512
|
workflows: [
|
|
468
513
|
{ key: 'name', label: 'Name' },
|
|
469
514
|
{ key: 'namespace', label: 'Namespace', width: 'w-48' },
|
|
@@ -913,6 +958,88 @@ const KNOWN_COLUMNS: Record<string, Column[]> = {
|
|
|
913
958
|
{ key: 'rules', label: 'Rules', width: 'w-24', tooltip: 'Ingress / Egress rule count' },
|
|
914
959
|
{ key: 'age', label: 'Age', width: 'w-24' },
|
|
915
960
|
],
|
|
961
|
+
caliconetworkpolicies: [
|
|
962
|
+
{ key: 'name', label: 'Name' },
|
|
963
|
+
{ key: 'namespace', label: 'Namespace', width: 'w-36' },
|
|
964
|
+
{ key: 'selector', label: 'Selector', width: 'w-48' },
|
|
965
|
+
{ key: 'namespaceSelector', label: 'Namespace Selector', width: 'w-48', defaultVisible: false },
|
|
966
|
+
{ key: 'serviceAccountSelector', label: 'Service Account Selector', width: 'w-48', defaultVisible: false },
|
|
967
|
+
{ key: 'tier', label: 'Tier', width: 'w-28' },
|
|
968
|
+
{ key: 'order', label: 'Order', width: 'w-24' },
|
|
969
|
+
{ key: 'types', label: 'Types', width: 'w-28' },
|
|
970
|
+
{ key: 'rules', label: 'Rules', width: 'w-24', tooltip: 'Ingress / Egress rule count' },
|
|
971
|
+
{ key: 'age', label: 'Age', width: 'w-24' },
|
|
972
|
+
],
|
|
973
|
+
calicoglobalnetworkpolicies: [
|
|
974
|
+
{ key: 'name', label: 'Name' },
|
|
975
|
+
{ key: 'selector', label: 'Selector', width: 'w-48' },
|
|
976
|
+
{ key: 'namespaceSelector', label: 'Namespace Selector', width: 'w-48', defaultVisible: false },
|
|
977
|
+
{ key: 'serviceAccountSelector', label: 'Service Account Selector', width: 'w-48', defaultVisible: false },
|
|
978
|
+
{ key: 'tier', label: 'Tier', width: 'w-28' },
|
|
979
|
+
{ key: 'order', label: 'Order', width: 'w-24' },
|
|
980
|
+
{ key: 'types', label: 'Types', width: 'w-28' },
|
|
981
|
+
{ key: 'rules', label: 'Rules', width: 'w-24', tooltip: 'Ingress / Egress rule count' },
|
|
982
|
+
{ key: 'age', label: 'Age', width: 'w-24' },
|
|
983
|
+
],
|
|
984
|
+
calicostagednetworkpolicies: [
|
|
985
|
+
{ key: 'name', label: 'Name' },
|
|
986
|
+
{ key: 'namespace', label: 'Namespace', width: 'w-36' },
|
|
987
|
+
{ key: 'selector', label: 'Selector', width: 'w-48' },
|
|
988
|
+
{ key: 'namespaceSelector', label: 'Namespace Selector', width: 'w-48', defaultVisible: false },
|
|
989
|
+
{ key: 'serviceAccountSelector', label: 'Service Account Selector', width: 'w-48', defaultVisible: false },
|
|
990
|
+
{ key: 'tier', label: 'Tier', width: 'w-28' },
|
|
991
|
+
{ key: 'order', label: 'Order', width: 'w-24' },
|
|
992
|
+
{ key: 'stagedAction', label: 'Staged Action', width: 'w-32' },
|
|
993
|
+
{ key: 'types', label: 'Types', width: 'w-28' },
|
|
994
|
+
{ key: 'rules', label: 'Rules', width: 'w-24', tooltip: 'Ingress / Egress rule count' },
|
|
995
|
+
{ key: 'age', label: 'Age', width: 'w-24' },
|
|
996
|
+
],
|
|
997
|
+
calicostagedglobalnetworkpolicies: [
|
|
998
|
+
{ key: 'name', label: 'Name' },
|
|
999
|
+
{ key: 'selector', label: 'Selector', width: 'w-48' },
|
|
1000
|
+
{ key: 'namespaceSelector', label: 'Namespace Selector', width: 'w-48', defaultVisible: false },
|
|
1001
|
+
{ key: 'serviceAccountSelector', label: 'Service Account Selector', width: 'w-48', defaultVisible: false },
|
|
1002
|
+
{ key: 'tier', label: 'Tier', width: 'w-28' },
|
|
1003
|
+
{ key: 'order', label: 'Order', width: 'w-24' },
|
|
1004
|
+
{ key: 'stagedAction', label: 'Staged Action', width: 'w-32' },
|
|
1005
|
+
{ key: 'types', label: 'Types', width: 'w-28' },
|
|
1006
|
+
{ key: 'rules', label: 'Rules', width: 'w-24', tooltip: 'Ingress / Egress rule count' },
|
|
1007
|
+
{ key: 'age', label: 'Age', width: 'w-24' },
|
|
1008
|
+
],
|
|
1009
|
+
calicoippools: [
|
|
1010
|
+
{ key: 'name', label: 'Name' },
|
|
1011
|
+
{ key: 'cidr', label: 'CIDR', width: 'w-44' },
|
|
1012
|
+
{ key: 'blockSize', label: 'Block Size', width: 'w-28' },
|
|
1013
|
+
{ key: 'encapsulation', label: 'Encapsulation', width: 'w-36' },
|
|
1014
|
+
{ key: 'natOutgoing', label: 'NAT Outgoing', width: 'w-32' },
|
|
1015
|
+
{ key: 'disabled', label: 'Disabled', width: 'w-28' },
|
|
1016
|
+
{ key: 'allowedUses', label: 'Allowed Uses', width: 'w-40', defaultVisible: false },
|
|
1017
|
+
{ key: 'nodeSelector', label: 'Node Selector', width: 'w-48', defaultVisible: false },
|
|
1018
|
+
{ key: 'age', label: 'Age', width: 'w-24' },
|
|
1019
|
+
],
|
|
1020
|
+
calicohostendpoints: [
|
|
1021
|
+
{ key: 'name', label: 'Name' },
|
|
1022
|
+
{ key: 'node', label: 'Node', width: 'w-48' },
|
|
1023
|
+
{ key: 'interfaceName', label: 'Interface', width: 'w-32' },
|
|
1024
|
+
{ key: 'expectedIPs', label: 'Expected IPs', width: 'w-48' },
|
|
1025
|
+
{ key: 'profiles', label: 'Profiles', width: 'w-48', defaultVisible: false },
|
|
1026
|
+
{ key: 'age', label: 'Age', width: 'w-24' },
|
|
1027
|
+
],
|
|
1028
|
+
calicotiers: [
|
|
1029
|
+
{ key: 'name', label: 'Name' },
|
|
1030
|
+
{ key: 'order', label: 'Order', width: 'w-24' },
|
|
1031
|
+
{ key: 'defaultAction', label: 'Default Action', width: 'w-36' },
|
|
1032
|
+
{ key: 'age', label: 'Age', width: 'w-24' },
|
|
1033
|
+
],
|
|
1034
|
+
calicostagedkubernetesnetworkpolicies: [
|
|
1035
|
+
{ key: 'name', label: 'Name' },
|
|
1036
|
+
{ key: 'namespace', label: 'Namespace', width: 'w-36' },
|
|
1037
|
+
{ key: 'selector', label: 'Pod Selector', width: 'w-48' },
|
|
1038
|
+
{ key: 'stagedAction', label: 'Staged Action', width: 'w-32' },
|
|
1039
|
+
{ key: 'types', label: 'Types', width: 'w-28' },
|
|
1040
|
+
{ key: 'rules', label: 'Rules', width: 'w-24', tooltip: 'Ingress / Egress rule count' },
|
|
1041
|
+
{ key: 'age', label: 'Age', width: 'w-24' },
|
|
1042
|
+
],
|
|
916
1043
|
poddisruptionbudgets: [
|
|
917
1044
|
{ key: 'name', label: 'Name' },
|
|
918
1045
|
{ key: 'namespace', label: 'Namespace', width: 'w-48' },
|
|
@@ -1305,6 +1432,92 @@ const KNOWN_COLUMNS: Record<string, Column[]> = {
|
|
|
1305
1432
|
// than an absent one — the reader can't tell which meaning they're getting.
|
|
1306
1433
|
{ key: 'age', label: 'Age', width: 'w-24' },
|
|
1307
1434
|
],
|
|
1435
|
+
// `databases`, `publications` and `subscriptions` are crowded plurals — other
|
|
1436
|
+
// database operators ship all three, and Knative owns the unqualified
|
|
1437
|
+
// `subscriptions` set. Keyed under cnpg* and reached only through
|
|
1438
|
+
// GROUP_QUALIFIED_COLUMN_KEYS, so a foreign CRD gets the generic columns
|
|
1439
|
+
// instead of a Cluster column it can never fill.
|
|
1440
|
+
// Kyverno's working records. Both are keyed by things the reader has to see
|
|
1441
|
+
// to know whether anything is wrong: which policy queued the work and what it
|
|
1442
|
+
// was queued against, and which resource a scan is about.
|
|
1443
|
+
updaterequests: [
|
|
1444
|
+
{ key: 'name', label: 'Name' },
|
|
1445
|
+
{ key: 'namespace', label: 'Namespace', width: 'w-32' },
|
|
1446
|
+
{ key: 'status', label: 'State', width: 'w-28' },
|
|
1447
|
+
{ key: 'type', label: 'Type', width: 'w-24' },
|
|
1448
|
+
{ key: 'policy', label: 'Policy', width: 'w-52' },
|
|
1449
|
+
{ key: 'triggers', label: 'Triggered By', width: 'w-56' },
|
|
1450
|
+
{ key: 'age', label: 'Age', width: 'w-24' },
|
|
1451
|
+
],
|
|
1452
|
+
ephemeralreports: [
|
|
1453
|
+
{ key: 'name', label: 'Name' },
|
|
1454
|
+
{ key: 'namespace', label: 'Namespace', width: 'w-32' },
|
|
1455
|
+
{ key: 'status', label: 'Outcome', width: 'w-28' },
|
|
1456
|
+
{ key: 'subject', label: 'About', width: 'w-56' },
|
|
1457
|
+
{ key: 'source', label: 'Produced By', width: 'w-36' },
|
|
1458
|
+
{ key: 'results', label: 'Results', width: 'w-24' },
|
|
1459
|
+
{ key: 'age', label: 'Age', width: 'w-24' },
|
|
1460
|
+
],
|
|
1461
|
+
clusterephemeralreports: [
|
|
1462
|
+
{ key: 'name', label: 'Name' },
|
|
1463
|
+
{ key: 'status', label: 'Outcome', width: 'w-28' },
|
|
1464
|
+
{ key: 'subject', label: 'About', width: 'w-56' },
|
|
1465
|
+
{ key: 'source', label: 'Produced By', width: 'w-36' },
|
|
1466
|
+
{ key: 'results', label: 'Results', width: 'w-24' },
|
|
1467
|
+
{ key: 'age', label: 'Age', width: 'w-24' },
|
|
1468
|
+
],
|
|
1469
|
+
cnpgdatabases: [
|
|
1470
|
+
{ key: 'name', label: 'Name' },
|
|
1471
|
+
{ key: 'namespace', label: 'Namespace', width: 'w-36' },
|
|
1472
|
+
{ key: 'status', label: 'Applied', width: 'w-32' },
|
|
1473
|
+
{ key: 'cluster', label: 'Cluster', width: 'w-36' },
|
|
1474
|
+
{ key: 'target', label: 'Database', width: 'w-40' },
|
|
1475
|
+
{ key: 'message', label: 'Message', width: 'w-64' },
|
|
1476
|
+
{ key: 'age', label: 'Age', width: 'w-24' },
|
|
1477
|
+
],
|
|
1478
|
+
cnpgpublications: [
|
|
1479
|
+
{ key: 'name', label: 'Name' },
|
|
1480
|
+
{ key: 'namespace', label: 'Namespace', width: 'w-36' },
|
|
1481
|
+
{ key: 'status', label: 'Applied', width: 'w-32' },
|
|
1482
|
+
{ key: 'cluster', label: 'Cluster', width: 'w-36' },
|
|
1483
|
+
{ key: 'dbname', label: 'In Database', width: 'w-40' },
|
|
1484
|
+
{ key: 'message', label: 'Message', width: 'w-64' },
|
|
1485
|
+
{ key: 'age', label: 'Age', width: 'w-24' },
|
|
1486
|
+
],
|
|
1487
|
+
cnpgsubscriptions: [
|
|
1488
|
+
{ key: 'name', label: 'Name' },
|
|
1489
|
+
{ key: 'namespace', label: 'Namespace', width: 'w-36' },
|
|
1490
|
+
{ key: 'status', label: 'Applied', width: 'w-32' },
|
|
1491
|
+
{ key: 'cluster', label: 'Cluster', width: 'w-36' },
|
|
1492
|
+
{ key: 'dbname', label: 'In Database', width: 'w-40' },
|
|
1493
|
+
{ key: 'message', label: 'Message', width: 'w-64' },
|
|
1494
|
+
{ key: 'age', label: 'Age', width: 'w-24' },
|
|
1495
|
+
],
|
|
1496
|
+
cnpgimagecatalogs: [
|
|
1497
|
+
{ key: 'name', label: 'Name' },
|
|
1498
|
+
{ key: 'namespace', label: 'Namespace', width: 'w-36' },
|
|
1499
|
+
{ key: 'majors', label: 'Major Versions', width: 'w-40' },
|
|
1500
|
+
{ key: 'images', label: 'Images', width: 'w-24' },
|
|
1501
|
+
{ key: 'age', label: 'Age', width: 'w-24' },
|
|
1502
|
+
],
|
|
1503
|
+
cnpgclusterimagecatalogs: [
|
|
1504
|
+
{ key: 'name', label: 'Name' },
|
|
1505
|
+
{ key: 'majors', label: 'Major Versions', width: 'w-40' },
|
|
1506
|
+
{ key: 'images', label: 'Images', width: 'w-24' },
|
|
1507
|
+
{ key: 'age', label: 'Age', width: 'w-24' },
|
|
1508
|
+
],
|
|
1509
|
+
barmanobjectstores: [
|
|
1510
|
+
{ key: 'name', label: 'Name' },
|
|
1511
|
+
{ key: 'namespace', label: 'Namespace', width: 'w-36' },
|
|
1512
|
+
{ key: 'status', label: 'Status', width: 'w-40' },
|
|
1513
|
+
// Sized rather than flexible: every sibling table gives its long value a
|
|
1514
|
+
// fixed width, and leaving two columns unsized let Name absorb the row at
|
|
1515
|
+
// 1920px — truncating the destination and pushing Retention off-screen.
|
|
1516
|
+
{ key: 'destination', label: 'Destination', width: 'w-64' },
|
|
1517
|
+
{ key: 'servers', label: 'Servers', width: 'w-32' },
|
|
1518
|
+
{ key: 'retention', label: 'Retention', width: 'w-28' },
|
|
1519
|
+
{ key: 'age', label: 'Age', width: 'w-24' },
|
|
1520
|
+
],
|
|
1308
1521
|
cnpgbackups: [
|
|
1309
1522
|
{ key: 'name', label: 'Name' },
|
|
1310
1523
|
{ key: 'namespace', label: 'Namespace', width: 'w-36' },
|
|
@@ -1499,7 +1712,10 @@ const KNOWN_COLUMNS: Record<string, Column[]> = {
|
|
|
1499
1712
|
{ key: 'address', label: 'Address', width: 'w-56' },
|
|
1500
1713
|
{ key: 'age', label: 'Age', width: 'w-24' },
|
|
1501
1714
|
],
|
|
1502
|
-
|
|
1715
|
+
// Keyed under knative*, reached only through GROUP_QUALIFIED_COLUMN_KEYS, so a
|
|
1716
|
+
// third operator's `subscriptions` gets the generic columns instead of Channel
|
|
1717
|
+
// and Subscriber it can never fill.
|
|
1718
|
+
knativesubscriptions: [
|
|
1503
1719
|
{ key: 'name', label: 'Name' },
|
|
1504
1720
|
{ key: 'namespace', label: 'Namespace', width: 'w-36' },
|
|
1505
1721
|
{ key: 'status', label: 'Status', width: 'w-28' },
|
|
@@ -1869,6 +2085,16 @@ const KNOWN_COLUMNS: Record<string, Column[]> = {
|
|
|
1869
2085
|
|
|
1870
2086
|
// Map (plural, group) → KNOWN_COLUMNS key for kinds that collide with core K8s
|
|
1871
2087
|
const GROUP_QUALIFIED_COLUMN_KEYS: Record<string, Record<string, string>> = {
|
|
2088
|
+
networkpolicy: {
|
|
2089
|
+
'networking.k8s.io': 'networkpolicies',
|
|
2090
|
+
'projectcalico.org': 'caliconetworkpolicies',
|
|
2091
|
+
'crd.projectcalico.org': 'caliconetworkpolicies',
|
|
2092
|
+
},
|
|
2093
|
+
networkpolicies: {
|
|
2094
|
+
'networking.k8s.io': 'networkpolicies',
|
|
2095
|
+
'projectcalico.org': 'caliconetworkpolicies',
|
|
2096
|
+
'crd.projectcalico.org': 'caliconetworkpolicies',
|
|
2097
|
+
},
|
|
1872
2098
|
clusters: { 'postgresql.cnpg.io': 'cnpgclusters', 'cluster.x-k8s.io': 'capiclusters' },
|
|
1873
2099
|
// Velero owns the unqualified `backups` column set; CNPG Backups carry a
|
|
1874
2100
|
// completely different shape (cluster + method, no storage location/expiry).
|
|
@@ -1882,8 +2108,81 @@ const GROUP_QUALIFIED_COLUMN_KEYS: Record<string, Record<string, string>> = {
|
|
|
1882
2108
|
certificates: { 'networking.internal.knative.dev': 'knativecertificates' },
|
|
1883
2109
|
restores: { 'velero.io': 'velerorestores' },
|
|
1884
2110
|
schedules: { 'velero.io': 'veleroschedules' },
|
|
2111
|
+
// CNPG's declarative objects. Knative owns the unqualified `subscriptions`
|
|
2112
|
+
// set, and `databases` / `publications` are shipped by several database
|
|
2113
|
+
// operators — none of which have a CNPG Cluster to point at.
|
|
2114
|
+
databases: { 'postgresql.cnpg.io': 'cnpgdatabases' },
|
|
2115
|
+
publications: { 'postgresql.cnpg.io': 'cnpgpublications' },
|
|
2116
|
+
subscriptions: {
|
|
2117
|
+
'postgresql.cnpg.io': 'cnpgsubscriptions',
|
|
2118
|
+
'messaging.knative.dev': 'knativesubscriptions',
|
|
2119
|
+
},
|
|
2120
|
+
imagecatalogs: { 'postgresql.cnpg.io': 'cnpgimagecatalogs' },
|
|
2121
|
+
clusterimagecatalogs: { 'postgresql.cnpg.io': 'cnpgclusterimagecatalogs' },
|
|
2122
|
+
objectstores: { 'barmancloud.cnpg.io': 'barmanobjectstores' },
|
|
2123
|
+
ippools: {
|
|
2124
|
+
'projectcalico.org': 'calicoippools',
|
|
2125
|
+
'crd.projectcalico.org': 'calicoippools',
|
|
2126
|
+
},
|
|
2127
|
+
hostendpoints: {
|
|
2128
|
+
'projectcalico.org': 'calicohostendpoints',
|
|
2129
|
+
'crd.projectcalico.org': 'calicohostendpoints',
|
|
2130
|
+
},
|
|
2131
|
+
tiers: {
|
|
2132
|
+
'projectcalico.org': 'calicotiers',
|
|
2133
|
+
'crd.projectcalico.org': 'calicotiers',
|
|
2134
|
+
},
|
|
2135
|
+
globalnetworkpolicies: {
|
|
2136
|
+
'projectcalico.org': 'calicoglobalnetworkpolicies',
|
|
2137
|
+
'crd.projectcalico.org': 'calicoglobalnetworkpolicies',
|
|
2138
|
+
},
|
|
2139
|
+
globalnetworkpolicy: {
|
|
2140
|
+
'projectcalico.org': 'calicoglobalnetworkpolicies',
|
|
2141
|
+
'crd.projectcalico.org': 'calicoglobalnetworkpolicies',
|
|
2142
|
+
},
|
|
2143
|
+
stagednetworkpolicies: {
|
|
2144
|
+
'projectcalico.org': 'calicostagednetworkpolicies',
|
|
2145
|
+
'crd.projectcalico.org': 'calicostagednetworkpolicies',
|
|
2146
|
+
},
|
|
2147
|
+
stagednetworkpolicy: {
|
|
2148
|
+
'projectcalico.org': 'calicostagednetworkpolicies',
|
|
2149
|
+
'crd.projectcalico.org': 'calicostagednetworkpolicies',
|
|
2150
|
+
},
|
|
2151
|
+
stagedglobalnetworkpolicies: {
|
|
2152
|
+
'projectcalico.org': 'calicostagedglobalnetworkpolicies',
|
|
2153
|
+
'crd.projectcalico.org': 'calicostagedglobalnetworkpolicies',
|
|
2154
|
+
},
|
|
2155
|
+
stagedglobalnetworkpolicy: {
|
|
2156
|
+
'projectcalico.org': 'calicostagedglobalnetworkpolicies',
|
|
2157
|
+
'crd.projectcalico.org': 'calicostagedglobalnetworkpolicies',
|
|
2158
|
+
},
|
|
2159
|
+
stagedkubernetesnetworkpolicies: {
|
|
2160
|
+
'projectcalico.org': 'calicostagedkubernetesnetworkpolicies',
|
|
2161
|
+
'crd.projectcalico.org': 'calicostagedkubernetesnetworkpolicies',
|
|
2162
|
+
},
|
|
2163
|
+
stagedkubernetesnetworkpolicy: {
|
|
2164
|
+
'projectcalico.org': 'calicostagedkubernetesnetworkpolicies',
|
|
2165
|
+
'crd.projectcalico.org': 'calicostagedkubernetesnetworkpolicies',
|
|
2166
|
+
},
|
|
1885
2167
|
}
|
|
1886
2168
|
|
|
2169
|
+
const GROUP_QUALIFIED_ONLY_COLUMN_KEYS = new Set([
|
|
2170
|
+
'networkpolicy', 'networkpolicies',
|
|
2171
|
+
// Other projects serve their own IPPool CRD, so only a Calico group earns the
|
|
2172
|
+
// Calico columns.
|
|
2173
|
+
'ippool', 'ippools',
|
|
2174
|
+
'globalnetworkpolicy', 'globalnetworkpolicies',
|
|
2175
|
+
'stagednetworkpolicy', 'stagednetworkpolicies',
|
|
2176
|
+
'stagedglobalnetworkpolicy', 'stagedglobalnetworkpolicies',
|
|
2177
|
+
'stagedkubernetesnetworkpolicy', 'stagedkubernetesnetworkpolicies',
|
|
2178
|
+
])
|
|
2179
|
+
const CALICO_ONLY_COLUMN_KEYS = new Set([
|
|
2180
|
+
'globalnetworkpolicy', 'globalnetworkpolicies',
|
|
2181
|
+
'stagednetworkpolicy', 'stagednetworkpolicies',
|
|
2182
|
+
'stagedglobalnetworkpolicy', 'stagedglobalnetworkpolicies',
|
|
2183
|
+
'stagedkubernetesnetworkpolicy', 'stagedkubernetesnetworkpolicies',
|
|
2184
|
+
])
|
|
2185
|
+
|
|
1887
2186
|
// Normalize a kind name to its plural API form used in KNOWN_COLUMNS keys.
|
|
1888
2187
|
// Handles CRD singular names from URLs: 'ScaledObject' → 'scaledobjects', 'NodePool' → 'nodepools'
|
|
1889
2188
|
// When group is provided, resolves collisions (e.g., 'services' + 'serving.knative.dev' → 'knativeservices')
|
|
@@ -1893,6 +2192,8 @@ function normalizeKindToPlural(kind: string, group?: string): string {
|
|
|
1893
2192
|
if (group && GROUP_QUALIFIED_COLUMN_KEYS[lower]?.[group]) {
|
|
1894
2193
|
return GROUP_QUALIFIED_COLUMN_KEYS[lower][group]
|
|
1895
2194
|
}
|
|
2195
|
+
if (group && GROUP_QUALIFIED_ONLY_COLUMN_KEYS.has(lower)) return `__generic_${lower}`
|
|
2196
|
+
if (CALICO_ONLY_COLUMN_KEYS.has(lower)) return `__generic_${lower}`
|
|
1896
2197
|
if (KNOWN_COLUMNS[lower]) return lower
|
|
1897
2198
|
// Try adding 's' but avoid double-s (e.g., "ingress" → "ingresss")
|
|
1898
2199
|
if (!lower.endsWith('s') && KNOWN_COLUMNS[lower + 's']) return lower + 's'
|
|
@@ -4928,6 +5229,11 @@ export function ResourcesView({
|
|
|
4928
5229
|
) : filteredResources.length === 0 ? (
|
|
4929
5230
|
<div className="absolute inset-0 flex flex-col items-center justify-center text-theme-text-tertiary">
|
|
4930
5231
|
<p>No {selectedKind.kind} found</p>
|
|
5232
|
+
{emptyKindNote(selectedKind.kind, selectedKind.group, resources?.length ?? 0) && (
|
|
5233
|
+
<p className="text-xs mt-2 max-w-md text-center text-theme-text-disabled">
|
|
5234
|
+
{emptyKindNote(selectedKind.kind, selectedKind.group, resources?.length ?? 0)}
|
|
5235
|
+
</p>
|
|
5236
|
+
)}
|
|
4931
5237
|
{searchTerm && (
|
|
4932
5238
|
<button
|
|
4933
5239
|
onClick={() => {
|
|
@@ -5534,10 +5840,11 @@ function CopyNameButton({ name }: { name: string }) {
|
|
|
5534
5840
|
<button
|
|
5535
5841
|
onClick={(e) => {
|
|
5536
5842
|
e.stopPropagation()
|
|
5537
|
-
|
|
5843
|
+
void copyText(name).then((didCopy) => {
|
|
5844
|
+
if (!didCopy) return
|
|
5538
5845
|
setCopied(true)
|
|
5539
5846
|
setTimeout(() => setCopied(false), 1500)
|
|
5540
|
-
})
|
|
5847
|
+
})
|
|
5541
5848
|
}}
|
|
5542
5849
|
className="shrink-0 p-0.5 text-theme-text-tertiary hover:text-theme-text-primary opacity-0 group-hover/row:opacity-100 transition-opacity"
|
|
5543
5850
|
title="Copy name"
|
|
@@ -5692,6 +5999,8 @@ function CellContent({ resource, kind, column, group, majorityNodeMinorVersion,
|
|
|
5692
5999
|
return <PVCCell resource={resource} column={column} />
|
|
5693
6000
|
case 'rollouts':
|
|
5694
6001
|
return <RolloutCell resource={resource} column={column} />
|
|
6002
|
+
case 'analysisruns':
|
|
6003
|
+
return <AnalysisRunCell resource={resource} column={column} />
|
|
5695
6004
|
case 'workflows':
|
|
5696
6005
|
return <WorkflowCell resource={resource} column={column} />
|
|
5697
6006
|
case 'cronworkflows':
|
|
@@ -5731,7 +6040,21 @@ function CellContent({ resource, kind, column, group, majorityNodeMinorVersion,
|
|
|
5731
6040
|
case 'clusterworkflowtemplates':
|
|
5732
6041
|
return <WorkflowTemplateCell resource={resource} column={column} />
|
|
5733
6042
|
case 'networkpolicies':
|
|
6043
|
+
if (!isCoreNetworkPolicyKind(resource.kind ?? kind, resource.apiVersion, group)) {
|
|
6044
|
+
return <GenericCell resource={resource} column={column} />
|
|
6045
|
+
}
|
|
5734
6046
|
return <NetworkPolicyCell resource={resource} column={column} />
|
|
6047
|
+
case 'calicoippools':
|
|
6048
|
+
case 'calicohostendpoints':
|
|
6049
|
+
case 'calicotiers':
|
|
6050
|
+
return <CalicoInfraCell resource={resource} column={column} />
|
|
6051
|
+
case 'caliconetworkpolicies':
|
|
6052
|
+
case 'calicoglobalnetworkpolicies':
|
|
6053
|
+
case 'calicostagednetworkpolicies':
|
|
6054
|
+
case 'calicostagedglobalnetworkpolicies':
|
|
6055
|
+
case 'calicostagedkubernetesnetworkpolicies':
|
|
6056
|
+
if (!isCalicoPolicyResource(resource)) return <GenericCell resource={resource} column={column} />
|
|
6057
|
+
return <CalicoPolicyCell resource={resource} column={column} />
|
|
5735
6058
|
case 'poddisruptionbudgets':
|
|
5736
6059
|
return <PDBCell resource={resource} column={column} />
|
|
5737
6060
|
case 'serviceaccounts':
|
|
@@ -5848,6 +6171,42 @@ function CellContent({ resource, kind, column, group, majorityNodeMinorVersion,
|
|
|
5848
6171
|
case 'clustersecretstores':
|
|
5849
6172
|
return <ClusterSecretStoreCell resource={resource} column={column} />
|
|
5850
6173
|
// Velero
|
|
6174
|
+
// The cnpg* keys come from GROUP_QUALIFIED_COLUMN_KEYS; the unqualified
|
|
6175
|
+
// plurals below are reached when the caller had no group to resolve with,
|
|
6176
|
+
// and stay group-guarded so a foreign CRD is not read as CNPG.
|
|
6177
|
+
case 'updaterequests':
|
|
6178
|
+
return <KyvernoUpdateRequestCell resource={resource} column={column} />
|
|
6179
|
+
case 'ephemeralreports':
|
|
6180
|
+
case 'clusterephemeralreports':
|
|
6181
|
+
return <KyvernoEphemeralReportCell resource={resource} column={column} />
|
|
6182
|
+
case 'cnpgdatabases':
|
|
6183
|
+
case 'cnpgpublications':
|
|
6184
|
+
case 'cnpgsubscriptions':
|
|
6185
|
+
return <CNPGDeclarativeCell resource={resource} column={column} />
|
|
6186
|
+
case 'databases':
|
|
6187
|
+
case 'publications':
|
|
6188
|
+
if (isApiGroup(resource.apiVersion, CNPG_GROUP)) {
|
|
6189
|
+
return <CNPGDeclarativeCell resource={resource} column={column} />
|
|
6190
|
+
}
|
|
6191
|
+
return <GenericCell resource={resource} column={column} />
|
|
6192
|
+
case 'cnpgimagecatalogs':
|
|
6193
|
+
case 'cnpgclusterimagecatalogs':
|
|
6194
|
+
return <CNPGImageCatalogCell resource={resource} column={column} />
|
|
6195
|
+
case 'imagecatalogs':
|
|
6196
|
+
case 'clusterimagecatalogs':
|
|
6197
|
+
if (isApiGroup(resource.apiVersion, CNPG_GROUP)) {
|
|
6198
|
+
return <CNPGImageCatalogCell resource={resource} column={column} />
|
|
6199
|
+
}
|
|
6200
|
+
return <GenericCell resource={resource} column={column} />
|
|
6201
|
+
case 'barmanobjectstores':
|
|
6202
|
+
return <CNPGObjectStoreCell resource={resource} column={column} />
|
|
6203
|
+
case 'objectstores':
|
|
6204
|
+
// Group-guarded: another operator could serve an `objectstores` plural,
|
|
6205
|
+
// and it would have no recovery window to report.
|
|
6206
|
+
if (isApiGroup(resource.apiVersion, 'barmancloud.cnpg.io')) {
|
|
6207
|
+
return <CNPGObjectStoreCell resource={resource} column={column} />
|
|
6208
|
+
}
|
|
6209
|
+
return <GenericCell resource={resource} column={column} />
|
|
5851
6210
|
case 'cnpgbackups':
|
|
5852
6211
|
return <CNPGBackupCell resource={resource} column={column} />
|
|
5853
6212
|
case 'backups':
|
|
@@ -5936,8 +6295,19 @@ function CellContent({ resource, kind, column, group, majorityNodeMinorVersion,
|
|
|
5936
6295
|
return <ChannelCell resource={resource} column={column} />
|
|
5937
6296
|
case 'inmemorychannels':
|
|
5938
6297
|
return <InMemoryChannelCell resource={resource} column={column} />
|
|
5939
|
-
case '
|
|
6298
|
+
case 'knativesubscriptions':
|
|
5940
6299
|
return <SubscriptionCell resource={resource} column={column} />
|
|
6300
|
+
case 'subscriptions':
|
|
6301
|
+
// Shared plural, and not only by two: CNPG declares one, Knative declares
|
|
6302
|
+
// one, and a third operator's would be read as Knative's — Channel and
|
|
6303
|
+
// Subscriber blank on every row — unless both are matched positively.
|
|
6304
|
+
if (isApiGroup(resource.apiVersion, CNPG_GROUP)) {
|
|
6305
|
+
return <CNPGDeclarativeCell resource={resource} column={column} />
|
|
6306
|
+
}
|
|
6307
|
+
if (isApiGroup(resource.apiVersion, 'messaging.knative.dev')) {
|
|
6308
|
+
return <SubscriptionCell resource={resource} column={column} />
|
|
6309
|
+
}
|
|
6310
|
+
return <GenericCell resource={resource} column={column} />
|
|
5941
6311
|
// Knative Flows
|
|
5942
6312
|
case 'sequences':
|
|
5943
6313
|
return <SequenceCell resource={resource} column={column} />
|
|
@@ -7151,8 +7521,10 @@ function NodeCell({ resource, column, majorityNodeMinorVersion }: { resource: an
|
|
|
7151
7521
|
const allocatable = resource.status?.allocatable?.pods
|
|
7152
7522
|
const podCount = m?.podCount ?? 0
|
|
7153
7523
|
if (!allocatable) return <span className="text-sm text-theme-text-tertiary font-mono">{podCount || '-'}</span>
|
|
7154
|
-
|
|
7155
|
-
|
|
7524
|
+
// Allocatable pods is a Quantity, so a 1000-pod node reports "1k" —
|
|
7525
|
+
// a raw-integer read would see 1 and peg the bar at 21600%.
|
|
7526
|
+
const max = parseQuantityToNumber(allocatable)
|
|
7527
|
+
if (!Number.isFinite(max) || max <= 0) return <span className="text-sm text-theme-text-tertiary font-mono">{podCount || '-'}</span>
|
|
7156
7528
|
const pct = (podCount / max) * 100
|
|
7157
7529
|
return <ResourceBar used={String(podCount)} total={String(max)} percent={pct} colorScheme="count" />
|
|
7158
7530
|
}
|
|
@@ -7240,6 +7612,44 @@ function RolloutCell({ resource, column }: { resource: any; column: string }) {
|
|
|
7240
7612
|
}
|
|
7241
7613
|
}
|
|
7242
7614
|
|
|
7615
|
+
function AnalysisRunCell({ resource, column }: { resource: any; column: string }) {
|
|
7616
|
+
switch (column) {
|
|
7617
|
+
case 'status': {
|
|
7618
|
+
const status = getAnalysisRunStatus(resource)
|
|
7619
|
+
return <span className={clsx('badge', status.color)}>{status.text}</span>
|
|
7620
|
+
}
|
|
7621
|
+
case 'trigger': {
|
|
7622
|
+
const trigger = resource.metadata?.labels?.['rollout-type']
|
|
7623
|
+
const step = resource.metadata?.labels?.['step-index']
|
|
7624
|
+
if (!trigger) return <span className="text-sm text-theme-text-tertiary">-</span>
|
|
7625
|
+
return (
|
|
7626
|
+
<span className="text-sm text-theme-text-secondary">
|
|
7627
|
+
{trigger}
|
|
7628
|
+
{step ? ` (step ${step})` : ''}
|
|
7629
|
+
</span>
|
|
7630
|
+
)
|
|
7631
|
+
}
|
|
7632
|
+
case 'metrics': {
|
|
7633
|
+
const results: any[] = resource.status?.metricResults || []
|
|
7634
|
+
if (results.length === 0) return <span className="text-sm text-theme-text-tertiary">-</span>
|
|
7635
|
+
const { total, passing, notPassing } = summarizeAnalysisMetrics(resource)
|
|
7636
|
+
return (
|
|
7637
|
+
<Tooltip
|
|
7638
|
+
content={results
|
|
7639
|
+
.map((m) => `${m.name}: ${m.phase || 'Unknown'}${m.dryRun ? ' (dry-run)' : ''}`)
|
|
7640
|
+
.join('\n')}
|
|
7641
|
+
>
|
|
7642
|
+
<span className={clsx('text-sm', notPassing > 0 ? 'text-amber-400' : 'text-theme-text-secondary')}>
|
|
7643
|
+
{notPassing > 0 ? `${notPassing}/${total} not passing` : `${passing}/${total} passing`}
|
|
7644
|
+
</span>
|
|
7645
|
+
</Tooltip>
|
|
7646
|
+
)
|
|
7647
|
+
}
|
|
7648
|
+
default:
|
|
7649
|
+
return <span className="text-sm text-theme-text-tertiary">-</span>
|
|
7650
|
+
}
|
|
7651
|
+
}
|
|
7652
|
+
|
|
7243
7653
|
function WorkflowCell({ resource, column }: { resource: any; column: string }) {
|
|
7244
7654
|
switch (column) {
|
|
7245
7655
|
case 'status': {
|
|
@@ -3,6 +3,33 @@ export * from './resource-utils-hpa'
|
|
|
3
3
|
export * from './resource-utils-argo'
|
|
4
4
|
export * from './resource-utils-certmanager'
|
|
5
5
|
export * from './resource-utils-cnpg'
|
|
6
|
+
export {
|
|
7
|
+
CALICO_GROUPS,
|
|
8
|
+
type CalicoApiGroup,
|
|
9
|
+
isCalicoApiGroup,
|
|
10
|
+
isCalicoApiVersion,
|
|
11
|
+
isCalicoPolicyKind,
|
|
12
|
+
isCalicoNetworkPolicyKind,
|
|
13
|
+
isCalicoStagedKubernetesNetworkPolicyKind,
|
|
14
|
+
formatKubernetesLabelSelector,
|
|
15
|
+
isCalicoPolicyResource,
|
|
16
|
+
isCoreNetworkPolicyApiVersion,
|
|
17
|
+
isCoreNetworkPolicyResource,
|
|
18
|
+
isCoreNetworkPolicyKind,
|
|
19
|
+
getCalicoPolicyKindLabel,
|
|
20
|
+
getCalicoPolicyTypes,
|
|
21
|
+
getCalicoPolicyRuleCount,
|
|
22
|
+
getCalicoPolicySelector,
|
|
23
|
+
getCalicoIPPoolAllowedUses,
|
|
24
|
+
getCalicoIPPoolBlockSize,
|
|
25
|
+
getCalicoIPPoolEncapsulation,
|
|
26
|
+
getCalicoStagedAction,
|
|
27
|
+
isCalicoStagedDeletion,
|
|
28
|
+
isCalicoStagedIgnored,
|
|
29
|
+
CALICO_SELECTOR_NOT_APPLICABLE,
|
|
30
|
+
getCalicoPolicyNamespaceSelector,
|
|
31
|
+
getCalicoPolicyServiceAccountSelector,
|
|
32
|
+
} from './resource-utils-calico'
|
|
6
33
|
export * from './resource-utils-crossplane'
|
|
7
34
|
export * from './resource-utils-eso'
|
|
8
35
|
export * from './resource-utils-flux'
|