@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
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@skyhook-io/k8s-ui",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.13.3",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/skyhook-io/radar",
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
"html-to-image": "^1.11.0",
|
|
72
72
|
"monaco-yaml": "5.5.1",
|
|
73
73
|
"react-virtuoso": "^4.18.11",
|
|
74
|
-
"shiki": "^4.2
|
|
74
|
+
"shiki": "^4.4.2"
|
|
75
75
|
},
|
|
76
76
|
"peerDependencies": {
|
|
77
77
|
"@xterm/addon-fit": ">=0.10.0",
|
|
@@ -88,7 +88,7 @@
|
|
|
88
88
|
"yaml": ">=2.0.0"
|
|
89
89
|
},
|
|
90
90
|
"devDependencies": {
|
|
91
|
-
"@types/node": "^26.
|
|
91
|
+
"@types/node": "^26.2.0",
|
|
92
92
|
"@types/react": "^19.2.18",
|
|
93
93
|
"@types/react-dom": "^19.2.3",
|
|
94
94
|
"@xterm/addon-fit": "^0.11.0",
|
|
@@ -98,7 +98,7 @@
|
|
|
98
98
|
"clsx": "^2.1.1",
|
|
99
99
|
"diff": "^9.0.0",
|
|
100
100
|
"elkjs": "^0.11.1",
|
|
101
|
-
"lucide-react": "^1.
|
|
101
|
+
"lucide-react": "^1.33.0",
|
|
102
102
|
"monaco-editor": "0.55.1",
|
|
103
103
|
"react": "^19.2.8",
|
|
104
104
|
"react-dom": "^19.2.8",
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
Boxes,
|
|
14
14
|
ChevronDown,
|
|
15
15
|
Clock3,
|
|
16
|
-
|
|
16
|
+
Coins,
|
|
17
17
|
ExternalLink,
|
|
18
18
|
GitCommit,
|
|
19
19
|
Layers,
|
|
@@ -988,7 +988,7 @@ function ApplicationViewTabs({
|
|
|
988
988
|
: "border-transparent text-theme-text-secondary hover:border-theme-border-light hover:text-theme-text-primary",
|
|
989
989
|
)}
|
|
990
990
|
>
|
|
991
|
-
<
|
|
991
|
+
<Coins className="h-4 w-4" />
|
|
992
992
|
Cost
|
|
993
993
|
</button>
|
|
994
994
|
)}
|
|
@@ -18,6 +18,9 @@ export interface ClusterSwitcherItem {
|
|
|
18
18
|
/** Raw context / display string. ClusterName collapses GKE/EKS/AKS
|
|
19
19
|
* shapes; user-named clusters pass through unchanged. */
|
|
20
20
|
name: string
|
|
21
|
+
/** Short qualifier rendered after the parsed name without affecting
|
|
22
|
+
* provider detection, e.g. a source suffix for colliding contexts. */
|
|
23
|
+
nameQualifier?: string
|
|
21
24
|
secondary?: string
|
|
22
25
|
badge?: string
|
|
23
26
|
/** Origin label, rendered as a folder-icon line under the name.
|
|
@@ -44,6 +47,8 @@ export interface ClusterSwitcherProps {
|
|
|
44
47
|
/** Raw context / display string. Pass it as-is — the trigger renders
|
|
45
48
|
* through ClusterName, which handles parse + provider badge + tooltip. */
|
|
46
49
|
currentName: string
|
|
50
|
+
/** Trigger-side counterpart to {@link ClusterSwitcherItem.nameQualifier}. */
|
|
51
|
+
currentNameQualifier?: string
|
|
47
52
|
/** Trigger-side counterpart to {@link ClusterSwitcherItem.sourceLabel}.
|
|
48
53
|
* Only pass when 2+ kubeconfig sources are loaded. */
|
|
49
54
|
currentSourceLabel?: string
|
|
@@ -80,6 +85,7 @@ const TRIGGER_NAME_MAX_WIDTH = 'max-w-[140px] sm:max-w-[220px] xl:max-w-[340px]'
|
|
|
80
85
|
export const ClusterSwitcher = forwardRef<ClusterSwitcherHandle, ClusterSwitcherProps>(({
|
|
81
86
|
currentId,
|
|
82
87
|
currentName,
|
|
88
|
+
currentNameQualifier,
|
|
83
89
|
currentSourceLabel,
|
|
84
90
|
items,
|
|
85
91
|
onSelect,
|
|
@@ -114,6 +120,7 @@ export const ClusterSwitcher = forwardRef<ClusterSwitcherHandle, ClusterSwitcher
|
|
|
114
120
|
if (!q) return true
|
|
115
121
|
return (
|
|
116
122
|
item.name.toLowerCase().includes(q) ||
|
|
123
|
+
item.nameQualifier?.toLowerCase().includes(q) ||
|
|
117
124
|
item.secondary?.toLowerCase().includes(q) ||
|
|
118
125
|
item.badge?.toLowerCase().includes(q) ||
|
|
119
126
|
item.sourceLabel?.toLowerCase().includes(q) ||
|
|
@@ -209,7 +216,7 @@ export const ClusterSwitcher = forwardRef<ClusterSwitcherHandle, ClusterSwitcher
|
|
|
209
216
|
disabled={disabled || loading}
|
|
210
217
|
className={
|
|
211
218
|
variant === 'segment'
|
|
212
|
-
? `flex items-center gap-1.5 px-3 py-1.5 h-full min-w-[150px] max-w-[264px] text-[13px] font-medium
|
|
219
|
+
? `flex items-center gap-1.5 px-3 py-1.5 h-full min-w-[150px] max-w-[264px] overflow-hidden text-[13px] font-medium
|
|
213
220
|
text-theme-text-primary hover:bg-theme-hover transition-colors cursor-pointer
|
|
214
221
|
disabled:opacity-50 disabled:cursor-not-allowed`
|
|
215
222
|
: `flex items-center gap-1.5 px-2.5 py-1.5 min-w-[140px]
|
|
@@ -236,12 +243,22 @@ export const ClusterSwitcher = forwardRef<ClusterSwitcherHandle, ClusterSwitcher
|
|
|
236
243
|
// context inline (per-row secondary line), and an extra hover
|
|
237
244
|
// tooltip would just overlap the search input.
|
|
238
245
|
<>
|
|
239
|
-
<
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
246
|
+
<span className={variant === 'segment' ? 'min-w-0 flex-1' : 'min-w-0'}>
|
|
247
|
+
<ClusterName
|
|
248
|
+
name={currentName}
|
|
249
|
+
fallbackBadge={<Server className="w-3.5 h-3.5 text-theme-text-secondary" />}
|
|
250
|
+
className={variant === 'segment' ? 'min-w-0 max-w-full' : TRIGGER_NAME_MAX_WIDTH}
|
|
251
|
+
noTooltip={isOpen}
|
|
252
|
+
/>
|
|
253
|
+
</span>
|
|
254
|
+
{currentNameQualifier && (
|
|
255
|
+
<span
|
|
256
|
+
className="shrink-0 max-w-[80px] truncate text-xs font-normal text-theme-text-tertiary"
|
|
257
|
+
title={currentNameQualifier}
|
|
258
|
+
>
|
|
259
|
+
{currentNameQualifier}
|
|
260
|
+
</span>
|
|
261
|
+
)}
|
|
245
262
|
{currentSourceLabel && (
|
|
246
263
|
// Icon-only on the trigger: long folder paths (the very case
|
|
247
264
|
// that motivates the chip) middle-truncate to something
|
|
@@ -358,6 +375,14 @@ export const ClusterSwitcher = forwardRef<ClusterSwitcherHandle, ClusterSwitcher
|
|
|
358
375
|
: 'text-theme-text-primary'
|
|
359
376
|
}`}
|
|
360
377
|
/>
|
|
378
|
+
{item.nameQualifier && (
|
|
379
|
+
<span
|
|
380
|
+
className="shrink-0 max-w-[120px] truncate text-xs font-normal text-theme-text-tertiary"
|
|
381
|
+
title={item.nameQualifier}
|
|
382
|
+
>
|
|
383
|
+
{item.nameQualifier}
|
|
384
|
+
</span>
|
|
385
|
+
)}
|
|
361
386
|
{item.badge && (
|
|
362
387
|
<span className="shrink-0 text-[10px] text-theme-text-tertiary bg-theme-elevated px-1 rounded">
|
|
363
388
|
{item.badge}
|
|
@@ -85,6 +85,7 @@ const CATEGORY_LABEL: Record<string, string> = {
|
|
|
85
85
|
volume_access_mode_conflict: 'Volume access conflict',
|
|
86
86
|
backup_failed: 'Backup failed',
|
|
87
87
|
backup_target_unavailable: 'Backup target unavailable',
|
|
88
|
+
backup_stalled: 'Backup not progressing',
|
|
88
89
|
job_failed: 'Job failed',
|
|
89
90
|
cronjob_failed: 'CronJob failed',
|
|
90
91
|
rollout_stalled: 'Rollout stalled',
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import { emptyKindNote } from './ResourcesView'
|
|
3
|
+
|
|
4
|
+
describe('emptyKindNote', () => {
|
|
5
|
+
it('explains that no UpdateRequest is the resting state, and that it looks the same as a rule that never ran', () => {
|
|
6
|
+
const note = emptyKindNote('UpdateRequest', 'kyverno.io')
|
|
7
|
+
expect(note).toContain('deleted seconds after')
|
|
8
|
+
expect(note).toContain('never ran')
|
|
9
|
+
})
|
|
10
|
+
|
|
11
|
+
it('says an absent EphemeralReport means the scan finished, not that nothing was checked', () => {
|
|
12
|
+
expect(emptyKindNote('EphemeralReport', 'reports.kyverno.io')).toContain('scan has finished')
|
|
13
|
+
expect(emptyKindNote('ClusterEphemeralReport', 'reports.kyverno.io')).toContain('scan has finished')
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
it('is case-insensitive on the kind, which arrives from a URL as often as from discovery', () => {
|
|
17
|
+
expect(emptyKindNote('updaterequest', 'kyverno.io')).toBeDefined()
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
// Same plural, different operator: Kyverno's group is what makes the note true.
|
|
21
|
+
it('says nothing about a kind of the same name from another group', () => {
|
|
22
|
+
expect(emptyKindNote('UpdateRequest', 'example.com')).toBeUndefined()
|
|
23
|
+
expect(emptyKindNote('EphemeralReport', '')).toBeUndefined()
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
it('says nothing about kinds with no such story', () => {
|
|
27
|
+
expect(emptyKindNote('Pod', '')).toBeUndefined()
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
// The table can be empty because the reader emptied it. Telling them none is
|
|
31
|
+
// normal then answers a question they did not ask, with their term still in
|
|
32
|
+
// the search box.
|
|
33
|
+
it('stays silent when the kind has rows and a filter is what emptied the table', () => {
|
|
34
|
+
expect(emptyKindNote('UpdateRequest', 'kyverno.io', 3)).toBeUndefined()
|
|
35
|
+
expect(emptyKindNote('EphemeralReport', 'reports.kyverno.io', 192)).toBeUndefined()
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
it('still speaks when the kind is genuinely empty', () => {
|
|
39
|
+
expect(emptyKindNote('UpdateRequest', 'kyverno.io', 0)).toBeDefined()
|
|
40
|
+
})
|
|
41
|
+
})
|