@skyhook-io/k8s-ui 1.8.9 → 1.8.11
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 -4
- package/src/assets/gitops/argocd.png +0 -0
- package/src/assets/gitops/flux.svg +7 -0
- package/src/components/applications/AppChips.tsx +10 -0
- package/src/components/applications/ApplicationDetail.test.tsx +569 -0
- package/src/components/applications/ApplicationDetail.tsx +2517 -450
- package/src/components/applications/ApplicationsList.tsx +4 -1
- package/src/components/applications/ApplicationsView.tsx +101 -18
- package/src/components/applications/applications-view.test.tsx +47 -0
- package/src/components/applications/index.ts +1 -1
- package/src/components/audit/AuditAlerts.tsx +14 -10
- package/src/components/checks/ChecksView.tsx +81 -51
- package/src/components/checks/severity.ts +39 -45
- package/src/components/cluster-switcher/ClusterSwitcher.tsx +2 -2
- package/src/components/compare/CompareResourcePicker.tsx +2 -2
- package/src/components/gitops/GitOpsGraphFilterRail.tsx +2 -1
- package/src/components/gitops/GitOpsTableView.tsx +14 -59
- package/src/components/gitops/ManagedResourcesList.tsx +8 -11
- package/src/components/gitops/SyncCountdown.tsx +26 -17
- package/src/components/gitops/SyncOptionsDialog.tsx +2 -2
- package/src/components/gitops/insights/GitOpsInsightViews.tsx +277 -104
- package/src/components/gitops/insights/insights-helpers.test.ts +86 -1
- package/src/components/gitops/insights/insights-helpers.ts +69 -1
- package/src/components/gitops/tree/GitOpsTreeGraph.tsx +5 -2
- package/src/components/issues/IssuesView.tsx +219 -143
- package/src/components/issues/ResourceIssuesSection.test.tsx +40 -0
- package/src/components/issues/ResourceIssuesSection.tsx +28 -128
- package/src/components/issues/index.ts +3 -2
- package/src/components/issues/issue-timing.ts +53 -0
- package/src/components/issues/issues.test.ts +146 -4
- package/src/components/issues/severity.ts +29 -32
- package/src/components/logs/LogCore.tsx +14 -4
- package/src/components/logs/WorkloadLogsViewer.tsx +31 -6
- package/src/components/logs/useLogStream.ts +8 -1
- package/src/components/namespace-switcher/NamespacePicker.tsx +86 -107
- package/src/components/resources/ResourcesSidebar.test.tsx +107 -0
- package/src/components/resources/ResourcesSidebar.tsx +70 -52
- package/src/components/resources/ResourcesView.selected-kind.test.ts +143 -0
- package/src/components/resources/ResourcesView.tsx +243 -53
- package/src/components/resources/renderers/ClusterComplianceReportRenderer.tsx +2 -2
- package/src/components/resources/renderers/CronWorkflowRenderer.tsx +99 -0
- package/src/components/resources/renderers/JobRenderer.tsx +3 -1
- package/src/components/resources/renderers/MetricsUnavailableNotice.tsx +47 -0
- package/src/components/resources/renderers/NodeRenderer.test.tsx +103 -0
- package/src/components/resources/renderers/NodeRenderer.tsx +20 -12
- package/src/components/resources/renderers/PVCRenderer.test.tsx +23 -0
- package/src/components/resources/renderers/PVCRenderer.tsx +2 -2
- package/src/components/resources/renderers/PodRenderer.test.tsx +101 -0
- package/src/components/resources/renderers/PodRenderer.tsx +81 -70
- package/src/components/resources/renderers/PrometheusRuleRenderer.tsx +2 -2
- package/src/components/resources/renderers/SbomReportRenderer.tsx +2 -2
- package/src/components/resources/renderers/SecretRenderer.tsx +2 -0
- package/src/components/resources/renderers/ServiceRenderer.tsx +58 -40
- package/src/components/resources/renderers/VulnerabilityReportRenderer.tsx +2 -2
- package/src/components/resources/renderers/WorkflowRenderer.test.tsx +43 -0
- package/src/components/resources/renderers/WorkflowRenderer.tsx +60 -78
- package/src/components/resources/renderers/index.ts +1 -0
- package/src/components/resources/resource-utils-capi.ts +1 -1
- package/src/components/resources/resource-utils.ts +31 -0
- package/src/components/shared/DetailShell.tsx +2 -2
- package/src/components/shared/ResourceActionsBar.tsx +140 -108
- package/src/components/shared/ResourceRendererDispatch.tsx +33 -4
- package/src/components/timeline/TimelineList.tsx +371 -354
- package/src/components/timeline/TimelineStrip.test.tsx +194 -0
- package/src/components/timeline/TimelineStrip.tsx +836 -0
- package/src/components/timeline/TimelineSwimlanes.test.tsx +1028 -0
- package/src/components/timeline/TimelineSwimlanes.tsx +2498 -593
- package/src/components/timeline/TimelineToolbar.test.tsx +320 -0
- package/src/components/timeline/TimelineToolbar.tsx +759 -0
- package/src/components/timeline/TimelineToolbarState.test.tsx +64 -0
- package/src/components/timeline/index.ts +23 -0
- package/src/components/timeline/scrubber-math.test.ts +235 -0
- package/src/components/timeline/scrubber-math.ts +249 -0
- package/src/components/timeline/shared.test.tsx +219 -0
- package/src/components/timeline/shared.tsx +232 -447
- package/src/components/timeline/timeline-filters.test.ts +196 -0
- package/src/components/timeline/timeline-filters.ts +180 -0
- package/src/components/timeline/timeline-lane-sort.test.ts +97 -0
- package/src/components/timeline/timeline-lane-sort.ts +77 -0
- package/src/components/timeline/timeline-live.test.ts +131 -0
- package/src/components/timeline/timeline-live.ts +77 -0
- package/src/components/topology/GroupNode.tsx +9 -2
- package/src/components/topology/K8sResourceNode.test.ts +11 -0
- package/src/components/topology/K8sResourceNode.tsx +387 -243
- package/src/components/topology/TopologyFilterSidebar.tsx +9 -0
- package/src/components/topology/TopologyGraph.tsx +89 -16
- package/src/components/topology/TopologySearch.tsx +2 -2
- package/src/components/topology/layout.ts +10 -2
- package/src/components/topology/topology.css +0 -92
- package/src/components/ui/Badge.tsx +5 -0
- package/src/components/ui/BoardSkeleton.tsx +47 -0
- package/src/components/ui/CardSection.tsx +117 -0
- package/src/components/ui/CodeViewer.tsx +2 -2
- package/src/components/ui/Collapse.tsx +59 -0
- package/src/components/ui/ConfirmDialog.tsx +7 -3
- package/src/components/ui/DialogPortal.tsx +31 -9
- package/src/components/ui/Input.tsx +24 -0
- package/src/components/ui/MultiSelectPicker.test.tsx +101 -0
- package/src/components/ui/MultiSelectPicker.tsx +167 -0
- package/src/components/ui/PaneLoader.tsx +10 -2
- package/src/components/ui/ResourceBar.tsx +68 -25
- package/src/components/ui/SearchBox.tsx +18 -4
- package/src/components/ui/SearchPillInput.tsx +2 -2
- package/src/components/ui/Toast.tsx +1 -1
- package/src/components/ui/drawer-components.tsx +39 -26
- package/src/components/ui/index.ts +6 -0
- package/src/components/ui/severity-tone.ts +63 -0
- package/src/components/workload/ResourceDetailDrawer.tsx +6 -2
- package/src/components/workload/WorkloadView.tsx +2682 -472
- package/src/components/workload/index.ts +1 -1
- package/src/theme/variables.css +15 -1
- package/src/types/core.ts +57 -4
- package/src/utils/api-resources.test.ts +54 -0
- package/src/utils/api-resources.ts +68 -1
- package/src/utils/application-topology.test.ts +198 -0
- package/src/utils/application-topology.ts +261 -0
- package/src/utils/applications.test.ts +167 -1
- package/src/utils/applications.ts +1157 -393
- package/src/utils/index.ts +2 -0
- package/src/utils/navigation.test.ts +32 -1
- package/src/utils/navigation.ts +70 -0
- package/src/utils/resource-hierarchy.test.ts +990 -1
- package/src/utils/resource-hierarchy.ts +905 -267
- package/src/utils/resource-icons.ts +2 -0
- package/src/utils/topology-neighborhood.test.ts +202 -1
- package/src/utils/topology-neighborhood.ts +194 -13
- package/src/utils/workflow-execution.test.ts +556 -0
- package/src/utils/workflow-execution.ts +814 -0
- package/src/utils/workload-colors.ts +2 -3
- package/tsconfig.json +2 -2
package/src/utils/index.ts
CHANGED
|
@@ -22,4 +22,6 @@ export * from './rbac-badges'
|
|
|
22
22
|
export * from './git-provider-urls'
|
|
23
23
|
export * from './applications'
|
|
24
24
|
export * from './topology-neighborhood'
|
|
25
|
+
export * from './application-topology'
|
|
25
26
|
export * from './bulk-workload-actions'
|
|
27
|
+
export * from './workflow-execution'
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, test, expect, afterEach } from 'vitest'
|
|
2
|
-
import { kindToPlural, pluralToKind, refToSelectedResource, initNavigationMap, resetNavigationMap } from './navigation'
|
|
2
|
+
import { kindToPlural, pluralToKind, refToSelectedResource, initNavigationMap, resetNavigationMap, laneId, laneResourceKey, groupQualifiesLaneId, parseLaneId } from './navigation'
|
|
3
3
|
|
|
4
4
|
afterEach(() => {
|
|
5
5
|
resetNavigationMap()
|
|
@@ -190,3 +190,34 @@ describe('refToSelectedResource', () => {
|
|
|
190
190
|
})
|
|
191
191
|
})
|
|
192
192
|
})
|
|
193
|
+
|
|
194
|
+
describe('lane identity helpers', () => {
|
|
195
|
+
test('groupQualifiesLaneId: only CRD groups qualify', () => {
|
|
196
|
+
expect(groupQualifiesLaneId('')).toBe(false) // core
|
|
197
|
+
expect(groupQualifiesLaneId(undefined)).toBe(false)
|
|
198
|
+
expect(groupQualifiesLaneId('apps')).toBe(false) // built-in
|
|
199
|
+
expect(groupQualifiesLaneId('batch')).toBe(false)
|
|
200
|
+
expect(groupQualifiesLaneId('networking.k8s.io')).toBe(false)
|
|
201
|
+
expect(groupQualifiesLaneId('postgresql.cnpg.io')).toBe(true)
|
|
202
|
+
expect(groupQualifiesLaneId('cluster.x-k8s.io')).toBe(true)
|
|
203
|
+
})
|
|
204
|
+
|
|
205
|
+
test('laneId: bare for core/built-in, qualified for CRD groups', () => {
|
|
206
|
+
expect(laneId('Pod', '', 'team-a', 'x')).toBe('Pod/team-a/x')
|
|
207
|
+
expect(laneId('Deployment', 'apps', 'ns', 'web')).toBe('Deployment/ns/web')
|
|
208
|
+
expect(laneId('Cluster', 'postgresql.cnpg.io', 'prod', 'main-db')).toBe('Cluster.postgresql.cnpg.io/prod/main-db')
|
|
209
|
+
})
|
|
210
|
+
|
|
211
|
+
test('laneResourceKey is always group-less', () => {
|
|
212
|
+
expect(laneResourceKey('Cluster', 'prod', 'main-db')).toBe('Cluster/prod/main-db')
|
|
213
|
+
expect(laneResourceKey('Pod', 'team-a', 'x')).toBe('Pod/team-a/x')
|
|
214
|
+
})
|
|
215
|
+
|
|
216
|
+
test('parseLaneId round-trips both bare and qualified ids', () => {
|
|
217
|
+
expect(parseLaneId('Pod/team-a/x')).toEqual({ kind: 'Pod', group: '', namespace: 'team-a', name: 'x' })
|
|
218
|
+
expect(parseLaneId('Cluster.postgresql.cnpg.io/prod/main-db')).toEqual({
|
|
219
|
+
kind: 'Cluster', group: 'postgresql.cnpg.io', namespace: 'prod', name: 'main-db',
|
|
220
|
+
})
|
|
221
|
+
expect(parseLaneId('bogus')).toBeNull()
|
|
222
|
+
})
|
|
223
|
+
})
|
package/src/utils/navigation.ts
CHANGED
|
@@ -25,6 +25,10 @@ const BUILTIN_PLURAL_TO_KIND: Record<string, string> = {
|
|
|
25
25
|
nodes: 'Node',
|
|
26
26
|
jobs: 'Job',
|
|
27
27
|
cronjobs: 'CronJob',
|
|
28
|
+
workflows: 'Workflow',
|
|
29
|
+
cronworkflows: 'CronWorkflow',
|
|
30
|
+
workflowtemplates: 'WorkflowTemplate',
|
|
31
|
+
clusterworkflowtemplates: 'ClusterWorkflowTemplate',
|
|
28
32
|
horizontalpodautoscalers: 'HorizontalPodAutoscaler',
|
|
29
33
|
persistentvolumeclaims: 'PersistentVolumeClaim',
|
|
30
34
|
persistentvolumes: 'PersistentVolume',
|
|
@@ -158,3 +162,69 @@ export function apiVersionToGroup(apiVersion?: string | null): string {
|
|
|
158
162
|
const i = apiVersion.indexOf('/')
|
|
159
163
|
return i === -1 ? '' : apiVersion.slice(0, i)
|
|
160
164
|
}
|
|
165
|
+
|
|
166
|
+
// -----------------------------------------------------------------------------
|
|
167
|
+
// Timeline lane identity. A lane's id includes the API group so two CRDs that
|
|
168
|
+
// share a kind name across vendors (CAPI `Cluster` in cluster.x-k8s.io vs CNPG
|
|
169
|
+
// `Cluster` in postgresql.cnpg.io) can never merge into one row. The group is an
|
|
170
|
+
// INTERNAL identity component only — it never surfaces in the UI except the rare
|
|
171
|
+
// on-screen collision chip (see collidingLaneKeys in resource-hierarchy).
|
|
172
|
+
// -----------------------------------------------------------------------------
|
|
173
|
+
|
|
174
|
+
// Built-in Kubernetes API groups. Their kind names are globally reserved and
|
|
175
|
+
// never collide across vendors, so their lanes keep the bare `Kind/ns/name` id.
|
|
176
|
+
// This keeps existing pins, ?event= URLs, and the applications byResource join
|
|
177
|
+
// byte-stable for all core/built-in resources (Pod, Deployment, Job, …) — only
|
|
178
|
+
// CRD-group lanes get a group-qualified id, so ONLY CRD pins are affected.
|
|
179
|
+
const BUILTIN_API_GROUPS: ReadonlySet<string> = new Set([
|
|
180
|
+
'', // core (v1)
|
|
181
|
+
'apps', 'batch', 'autoscaling', 'policy',
|
|
182
|
+
'networking.k8s.io', 'storage.k8s.io', 'scheduling.k8s.io',
|
|
183
|
+
'coordination.k8s.io', 'node.k8s.io', 'discovery.k8s.io',
|
|
184
|
+
'rbac.authorization.k8s.io', 'admissionregistration.k8s.io',
|
|
185
|
+
'authentication.k8s.io', 'authorization.k8s.io', 'certificates.k8s.io',
|
|
186
|
+
'apiextensions.k8s.io', 'apiregistration.k8s.io', 'events.k8s.io',
|
|
187
|
+
'flowcontrol.apiserver.k8s.io',
|
|
188
|
+
])
|
|
189
|
+
|
|
190
|
+
/** Whether a resource's API group must appear in its lane id to prevent a
|
|
191
|
+
* cross-group merge. Built-in groups never collide, so they stay bare. */
|
|
192
|
+
export function groupQualifiesLaneId(group: string | undefined): boolean {
|
|
193
|
+
return !!group && !BUILTIN_API_GROUPS.has(group)
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/** Canonical timeline lane id. Group-qualified only for CRD groups
|
|
197
|
+
* (`Cluster.postgresql.cnpg.io/prod/db`); bare for built-in/core groups
|
|
198
|
+
* (`Pod/team-a/x`, `Deployment/ns/web`) so those ids stay exactly as before. */
|
|
199
|
+
export function laneId(kind: string, group: string | undefined, namespace: string, name: string): string {
|
|
200
|
+
const g = groupQualifiesLaneId(group) ? `.${group}` : ''
|
|
201
|
+
return `${kind}${g}/${namespace}/${name}`
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/** The group-less resource key (`Kind/ns/name`) — the join key for group-less
|
|
205
|
+
* server payloads (applications byResource, AppRow workloads) and group-less
|
|
206
|
+
* references (owner refs, K8s-event involvedObject, topology node ids). For a
|
|
207
|
+
* built-in-group lane this equals its id; for a CRD lane it's the id minus the
|
|
208
|
+
* `.group` segment. */
|
|
209
|
+
export function laneResourceKey(kind: string, namespace: string, name: string): string {
|
|
210
|
+
return `${kind}/${namespace}/${name}`
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/** Recover {kind, group, namespace, name} from a lane id. The kind segment may
|
|
214
|
+
* carry a `.group` suffix (CRD lanes). Kind names never contain '.', and a
|
|
215
|
+
* qualifying group always does, so the first '.' in the kind segment splits
|
|
216
|
+
* them; ns and name never contain '/', so the first two '/' bound the rest. */
|
|
217
|
+
export function parseLaneId(id: string): { kind: string; group: string; namespace: string; name: string } | null {
|
|
218
|
+
const s1 = id.indexOf('/')
|
|
219
|
+
if (s1 < 0) return null
|
|
220
|
+
const s2 = id.indexOf('/', s1 + 1)
|
|
221
|
+
if (s2 < 0) return null
|
|
222
|
+
const kindSeg = id.slice(0, s1)
|
|
223
|
+
const dot = kindSeg.indexOf('.')
|
|
224
|
+
return {
|
|
225
|
+
kind: dot < 0 ? kindSeg : kindSeg.slice(0, dot),
|
|
226
|
+
group: dot < 0 ? '' : kindSeg.slice(dot + 1),
|
|
227
|
+
namespace: id.slice(s1 + 1, s2),
|
|
228
|
+
name: id.slice(s2 + 1),
|
|
229
|
+
}
|
|
230
|
+
}
|