@skyhook-io/k8s-ui 1.10.4 → 1.11.0
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 +5 -5
- package/src/components/applications/ApplicationDetail.test.tsx +46 -0
- package/src/components/applications/ApplicationDetail.tsx +14 -15
- package/src/components/issues/IssuesView.tsx +9 -0
- package/src/components/issues/diagnostic.ts +3 -0
- package/src/components/issues/issues.test.ts +11 -0
- package/src/components/issues/severity.ts +3 -0
- package/src/components/issues/types.ts +3 -0
- package/src/components/resources/ResourcesSidebar.tsx +1 -1
- package/src/components/resources/ResourcesView.tsx +259 -30
- package/src/components/resources/index.ts +2 -0
- package/src/components/resources/kyverno-cell-gating.test.ts +93 -0
- package/src/components/resources/kyverno-modern-posture.test.ts +290 -0
- package/src/components/resources/renderers/CNPGClusterRenderer.test.tsx +85 -0
- package/src/components/resources/renderers/CNPGClusterRenderer.tsx +109 -9
- package/src/components/resources/renderers/CNPGPoolerRenderer.tsx +8 -4
- package/src/components/resources/renderers/EventRenderer.test.tsx +23 -0
- package/src/components/resources/renderers/EventRenderer.tsx +10 -18
- package/src/components/resources/renderers/KyvernoCELPolicyRenderers.tsx +317 -0
- package/src/components/resources/renderers/KyvernoExceptionRenderers.tsx +264 -0
- package/src/components/resources/renderers/KyvernoPolicyShared.tsx +212 -0
- package/src/components/resources/renderers/VeleroBSLRenderer.tsx +2 -4
- package/src/components/resources/renderers/VeleroBackupRenderer.tsx +32 -9
- package/src/components/resources/renderers/VeleroRestoreRenderer.tsx +30 -9
- package/src/components/resources/renderers/VeleroScheduleRenderer.tsx +12 -6
- package/src/components/resources/renderers/badge-no-handrolled.test.tsx +1 -1
- package/src/components/resources/renderers/cnpg-cells.tsx +37 -2
- package/src/components/resources/renderers/index.ts +4 -0
- package/src/components/resources/renderers/kyverno-modern-cells.tsx +152 -0
- package/src/components/resources/renderers/velero-cells.tsx +128 -9
- package/src/components/resources/renderers/velero-phase-recovery.test.tsx +79 -0
- package/src/components/resources/resource-utils-cnpg.golden.test.ts +112 -0
- package/src/components/resources/resource-utils-cnpg.test.ts +527 -1
- package/src/components/resources/resource-utils-cnpg.ts +373 -56
- package/src/components/resources/resource-utils-kyverno-exceptions.ts +182 -0
- package/src/components/resources/resource-utils-kyverno-modern.ts +588 -0
- package/src/components/resources/resource-utils-velero.test.ts +237 -0
- package/src/components/resources/resource-utils-velero.ts +214 -22
- package/src/components/resources/resource-utils.ts +70 -3
- package/src/components/shared/ResourceActionsBar.tsx +3 -1
- package/src/components/shared/ResourceRendererDispatch.test.tsx +119 -1
- package/src/components/shared/ResourceRendererDispatch.tsx +116 -22
- package/src/components/topology/K8sResourceNode.tsx +11 -0
- package/src/components/topology/TopologyGraph.tsx +85 -5
- package/src/components/trace/ReachabilityGraph.tsx +517 -0
- package/src/components/trace/ReachabilityView.tsx +1173 -0
- package/src/components/trace/TracePanel.test.ts +172 -0
- package/src/components/trace/TracePanel.tsx +558 -0
- package/src/components/trace/TraceSummary.test.ts +213 -0
- package/src/components/trace/TraceSummary.tsx +168 -0
- package/src/components/trace/inClusterSummary.test.ts +98 -0
- package/src/components/trace/inClusterSummary.ts +81 -0
- package/src/components/trace/index.ts +19 -0
- package/src/components/trace/podReach.test.ts +71 -0
- package/src/components/trace/podReach.ts +37 -0
- package/src/components/trace/probe-display.test.ts +107 -0
- package/src/components/trace/probe-display.ts +37 -0
- package/src/components/trace/problemRows.test.ts +107 -0
- package/src/components/trace/reachFixtures.ts +261 -0
- package/src/components/trace/reachGraphModel.test.ts +1423 -0
- package/src/components/trace/reachGraphModel.ts +1521 -0
- package/src/components/trace/reachInspector.test.ts +892 -0
- package/src/components/trace/reachInspector.ts +797 -0
- package/src/components/trace/reachMarks.test.ts +698 -0
- package/src/components/trace/reachMarks.ts +623 -0
- package/src/components/trace/reachOrigins.test.ts +392 -0
- package/src/components/trace/reachOrigins.ts +449 -0
- package/src/components/trace/reachVerdict.test.ts +537 -0
- package/src/components/trace/reachVerdict.ts +601 -0
- package/src/components/trace/traceFingerprint.test.ts +214 -0
- package/src/components/trace/traceFingerprint.ts +122 -0
- package/src/components/trace/traceToSubgraph.test.ts +623 -0
- package/src/components/trace/traceToSubgraph.ts +463 -0
- package/src/components/trace/types.ts +414 -0
- package/src/components/ui/Badge.tsx +36 -0
- package/src/components/ui/ForceDeleteConfirmDialog.tsx +12 -1
- package/src/components/ui/InClusterConsentDialog.test.tsx +83 -0
- package/src/components/ui/InClusterConsentDialog.tsx +141 -0
- package/src/components/ui/index.ts +1 -0
- package/src/components/workload/WorkloadView.tsx +58 -5
- package/src/components/workload/index.ts +1 -1
- package/src/components/workload/reachabilityTab.test.ts +47 -0
- package/src/index.ts +5 -0
- package/src/theme/components.css +64 -0
- package/src/theme/variables.css +5 -0
- package/src/types/core.ts +8 -0
- package/src/utils/api-resources.ts +2 -0
- package/src/utils/application-history.test.ts +1 -1
- package/src/utils/applications.test.ts +63 -1
- package/src/utils/applications.ts +27 -0
- package/src/utils/inClusterConsent.test.ts +109 -0
- package/src/utils/inClusterConsent.ts +72 -0
- package/src/utils/index.ts +1 -0
- package/src/utils/navigation.test.ts +61 -0
- package/src/utils/navigation.ts +11 -9
- package/src/utils/pluralize.test.ts +80 -1
- package/src/utils/pluralize.ts +34 -0
- package/src/utils/resource-icons.test.ts +33 -0
- package/src/utils/resource-icons.ts +65 -2
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
// PolicyException + CleanupPolicy accessors.
|
|
2
|
+
//
|
|
3
|
+
// PolicyException is served by BOTH Kyverno API families under the same Kind
|
|
4
|
+
// and the same plural, with genuinely different spec shapes:
|
|
5
|
+
//
|
|
6
|
+
// kyverno.io/v2 spec.exceptions[].{policyName, ruleNames[]}, spec.match, spec.conditions, spec.background
|
|
7
|
+
// policies.kyverno.io/v1 spec.policyRefs[].{kind, name}, spec.matchConditions[], spec.reportResult, spec.images
|
|
8
|
+
//
|
|
9
|
+
// So every accessor here is group-qualified. Reading `spec.exceptions` off a
|
|
10
|
+
// modern object (or `spec.policyRefs` off a legacy one) silently yields
|
|
11
|
+
// nothing, which on THIS surface means "no policies are excepted" — the exact
|
|
12
|
+
// opposite of the truth for an object that exempts a workload from
|
|
13
|
+
// enforcement.
|
|
14
|
+
|
|
15
|
+
import type { StatusBadge } from './resource-utils'
|
|
16
|
+
import { healthColors } from './resource-utils'
|
|
17
|
+
|
|
18
|
+
export const KYVERNO_LEGACY_GROUP = 'kyverno.io'
|
|
19
|
+
export const KYVERNO_MODERN_GROUP_PREFIX = 'policies.kyverno.io/'
|
|
20
|
+
|
|
21
|
+
export function isLegacyKyvernoPolicyException(resource: any): boolean {
|
|
22
|
+
return typeof resource?.apiVersion === 'string' && resource.apiVersion.startsWith(`${KYVERNO_LEGACY_GROUP}/`)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function isModernKyvernoPolicyException(resource: any): boolean {
|
|
26
|
+
return typeof resource?.apiVersion === 'string' && resource.apiVersion.startsWith(KYVERNO_MODERN_GROUP_PREFIX)
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** Either family — the guard dispatch uses before rendering a PolicyException. */
|
|
30
|
+
export function isAnyKyvernoPolicyException(resource: any): boolean {
|
|
31
|
+
return isLegacyKyvernoPolicyException(resource) || isModernKyvernoPolicyException(resource)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** One excepted policy, normalized across both spec shapes. */
|
|
35
|
+
export interface KyvernoExceptedPolicy {
|
|
36
|
+
/** Policy object name. */
|
|
37
|
+
name: string
|
|
38
|
+
/**
|
|
39
|
+
* Rule names excepted within that policy (legacy only — the modern family
|
|
40
|
+
* exempts whole policies, since CEL policies have no named rules).
|
|
41
|
+
*/
|
|
42
|
+
ruleNames: string[]
|
|
43
|
+
/**
|
|
44
|
+
* Policy Kind being referenced (modern only). Load-bearing because
|
|
45
|
+
* policyRefs can point at ValidatingPolicy or ImageValidatingPolicy and the
|
|
46
|
+
* name alone doesn't say which.
|
|
47
|
+
*/
|
|
48
|
+
kind: string
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function getKyvernoExceptedPolicies(resource: any): KyvernoExceptedPolicy[] {
|
|
52
|
+
if (isModernKyvernoPolicyException(resource)) {
|
|
53
|
+
const refs = resource?.spec?.policyRefs
|
|
54
|
+
if (!Array.isArray(refs)) return []
|
|
55
|
+
return refs.map((r: any) => ({
|
|
56
|
+
name: r?.name || '',
|
|
57
|
+
kind: r?.kind || '',
|
|
58
|
+
ruleNames: [],
|
|
59
|
+
}))
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const exceptions = resource?.spec?.exceptions
|
|
63
|
+
if (!Array.isArray(exceptions)) return []
|
|
64
|
+
return exceptions.map((e: any) => ({
|
|
65
|
+
name: e?.policyName || '',
|
|
66
|
+
kind: '',
|
|
67
|
+
ruleNames: Array.isArray(e?.ruleNames) ? e.ruleNames.filter((r: unknown): r is string => typeof r === 'string') : [],
|
|
68
|
+
}))
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* The legacy `spec.match` block (any/all → resources). Absent on the modern
|
|
73
|
+
* family, which scopes via matchConditions instead.
|
|
74
|
+
*/
|
|
75
|
+
export function getKyvernoExceptionMatch(resource: any): any {
|
|
76
|
+
return isLegacyKyvernoPolicyException(resource) ? resource?.spec?.match : undefined
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export interface KyvernoNamedCEL {
|
|
80
|
+
name: string
|
|
81
|
+
expression: string
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* CEL conditions narrowing the exception. Both families have them under
|
|
86
|
+
* different keys: legacy `spec.conditions` (which is Kyverno's own
|
|
87
|
+
* any/all condition DSL, not CEL) versus modern `spec.matchConditions` (CEL).
|
|
88
|
+
* Only the modern one is a named-expression list; the legacy block is returned
|
|
89
|
+
* raw by getKyvernoExceptionLegacyConditions.
|
|
90
|
+
*/
|
|
91
|
+
export function getKyvernoExceptionMatchConditions(resource: any): KyvernoNamedCEL[] {
|
|
92
|
+
if (!isModernKyvernoPolicyException(resource)) return []
|
|
93
|
+
const conditions = resource?.spec?.matchConditions
|
|
94
|
+
if (!Array.isArray(conditions)) return []
|
|
95
|
+
return conditions.map((c: any) => ({ name: c?.name || '', expression: c?.expression || '' }))
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export function getKyvernoExceptionLegacyConditions(resource: any): any {
|
|
99
|
+
return isLegacyKyvernoPolicyException(resource) ? resource?.spec?.conditions : undefined
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/** Modern only: what result the excepted resource is reported as. */
|
|
103
|
+
export function getKyvernoExceptionReportResult(resource: any): string {
|
|
104
|
+
return isModernKyvernoPolicyException(resource) ? resource?.spec?.reportResult || '' : ''
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* True when the exception names no policy at all. Both shapes can express it,
|
|
109
|
+
* and it means the exception applies to every policy in scope — the widest
|
|
110
|
+
* possible exemption, and worth flagging.
|
|
111
|
+
*/
|
|
112
|
+
export function isBlanketKyvernoException(resource: any): boolean {
|
|
113
|
+
return getKyvernoExceptedPolicies(resource).length === 0
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export function getKyvernoPolicyExceptionStatus(resource: any): StatusBadge {
|
|
117
|
+
const count = getKyvernoExceptedPolicies(resource).length
|
|
118
|
+
if (count === 0) {
|
|
119
|
+
return { text: 'All policies', color: healthColors.alert, level: 'alert' }
|
|
120
|
+
}
|
|
121
|
+
return {
|
|
122
|
+
text: count === 1 ? '1 policy' : `${count} policies`,
|
|
123
|
+
color: healthColors.neutral,
|
|
124
|
+
level: 'neutral',
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// ============================================================================
|
|
129
|
+
// CLEANUP POLICY (kyverno.io/v2 — deprecated in 1.18 in favour of DeletingPolicy)
|
|
130
|
+
// ============================================================================
|
|
131
|
+
|
|
132
|
+
export function getKyvernoCleanupSchedule(resource: any): string {
|
|
133
|
+
return resource?.spec?.schedule || ''
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export function getKyvernoCleanupPropagationPolicy(resource: any): string {
|
|
137
|
+
return resource?.spec?.deletionPropagationPolicy || ''
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export function getKyvernoCleanupLastExecution(resource: any): string {
|
|
141
|
+
return resource?.status?.lastExecutionTime || ''
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export function getKyvernoCleanupConditions(resource: any): any {
|
|
145
|
+
return resource?.spec?.conditions
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export function getKyvernoCleanupMatch(resource: any): any {
|
|
149
|
+
return resource?.spec?.match
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export function getKyvernoCleanupExclude(resource: any): any {
|
|
153
|
+
return resource?.spec?.exclude
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Kinds a cleanup policy matches, flattened out of the any/all match block for
|
|
158
|
+
* a one-line summary. This is a delete-on-schedule object, so "what does it
|
|
159
|
+
* delete" is the only question that matters at a glance.
|
|
160
|
+
*/
|
|
161
|
+
export function getKyvernoCleanupMatchedKinds(resource: any): string[] {
|
|
162
|
+
const kinds = new Set<string>()
|
|
163
|
+
const collect = (block: any) => {
|
|
164
|
+
if (!Array.isArray(block)) return
|
|
165
|
+
for (const entry of block) {
|
|
166
|
+
const entryKinds = entry?.resources?.kinds
|
|
167
|
+
if (Array.isArray(entryKinds)) {
|
|
168
|
+
for (const k of entryKinds) if (typeof k === 'string') kinds.add(k)
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
collect(resource?.spec?.match?.any)
|
|
173
|
+
collect(resource?.spec?.match?.all)
|
|
174
|
+
return Array.from(kinds)
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export function getKyvernoCleanupPolicyStatus(resource: any): StatusBadge {
|
|
178
|
+
if (!getKyvernoCleanupSchedule(resource)) {
|
|
179
|
+
return { text: 'No schedule', color: healthColors.unknown, level: 'unknown' }
|
|
180
|
+
}
|
|
181
|
+
return { text: 'Scheduled', color: healthColors.alert, level: 'alert' }
|
|
182
|
+
}
|