@skyhook-io/k8s-ui 1.8.10 → 1.8.12

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.
Files changed (168) hide show
  1. package/package.json +7 -6
  2. package/src/assets/gitops/argocd.png +0 -0
  3. package/src/assets/gitops/flux.svg +7 -0
  4. package/src/components/applications/AppChips.tsx +10 -0
  5. package/src/components/applications/ApplicationDetail.test.tsx +697 -0
  6. package/src/components/applications/ApplicationDetail.tsx +3269 -474
  7. package/src/components/applications/ApplicationsView.tsx +62 -10
  8. package/src/components/applications/applications-view.test.tsx +47 -0
  9. package/src/components/applications/index.ts +1 -1
  10. package/src/components/audit/AuditAlerts.tsx +14 -10
  11. package/src/components/checks/ChecksView.tsx +2 -3
  12. package/src/components/checks/severity.ts +14 -10
  13. package/src/components/cluster-switcher/ClusterSwitcher.tsx +2 -2
  14. package/src/components/compare/CompareResourcePicker.tsx +2 -2
  15. package/src/components/gitops/GitOpsDetailLayout.tsx +13 -3
  16. package/src/components/gitops/GitOpsGraphFilterRail.tsx +2 -1
  17. package/src/components/gitops/GitOpsTableView.tsx +13 -6
  18. package/src/components/gitops/ManagedResourcesList.tsx +8 -11
  19. package/src/components/gitops/SyncCountdown.tsx +26 -17
  20. package/src/components/gitops/SyncOptionsDialog.test.ts +48 -0
  21. package/src/components/gitops/SyncOptionsDialog.tsx +190 -46
  22. package/src/components/gitops/insights/ArgoResourceDiff.tsx +172 -0
  23. package/src/components/gitops/insights/GitOpsInsightViews.tsx +474 -121
  24. package/src/components/gitops/insights/index.ts +1 -0
  25. package/src/components/gitops/insights/insights-helpers.test.ts +102 -1
  26. package/src/components/gitops/insights/insights-helpers.ts +74 -1
  27. package/src/components/gitops/tree/GitOpsTreeGraph.tsx +10 -2
  28. package/src/components/issues/IssuesView.tsx +91 -52
  29. package/src/components/issues/ResourceIssuesSection.test.tsx +39 -6
  30. package/src/components/issues/ResourceIssuesSection.tsx +46 -144
  31. package/src/components/issues/index.ts +3 -0
  32. package/src/components/issues/issue-timing.ts +53 -0
  33. package/src/components/issues/issues.test.ts +102 -1
  34. package/src/components/issues/severity.ts +3 -0
  35. package/src/components/logs/LogCore.tsx +14 -4
  36. package/src/components/logs/WorkloadLogsViewer.tsx +31 -6
  37. package/src/components/logs/useLogStream.ts +8 -1
  38. package/src/components/namespace-switcher/NamespacePicker.tsx +86 -107
  39. package/src/components/resources/ResourcesSidebar.test.tsx +71 -0
  40. package/src/components/resources/ResourcesSidebar.tsx +46 -46
  41. package/src/components/resources/ResourcesView.selected-kind.test.ts +143 -0
  42. package/src/components/resources/ResourcesView.tsx +233 -51
  43. package/src/components/resources/renderers/AWSMachineRenderer.tsx +3 -2
  44. package/src/components/resources/renderers/AWSManagedClusterRenderer.tsx +3 -2
  45. package/src/components/resources/renderers/AWSManagedControlPlaneRenderer.tsx +3 -2
  46. package/src/components/resources/renderers/AWSManagedMachinePoolRenderer.tsx +3 -2
  47. package/src/components/resources/renderers/AzureMachineRenderer.tsx +3 -2
  48. package/src/components/resources/renderers/AzureManagedControlPlaneRenderer.tsx +3 -2
  49. package/src/components/resources/renderers/AzureManagedMachinePoolRenderer.tsx +3 -2
  50. package/src/components/resources/renderers/CAPIClusterRenderer.tsx +3 -2
  51. package/src/components/resources/renderers/CAPIKubeadmControlPlaneRenderer.tsx +3 -2
  52. package/src/components/resources/renderers/CAPIMachineDeploymentRenderer.tsx +3 -2
  53. package/src/components/resources/renderers/CAPIMachineHealthCheckRenderer.tsx +3 -2
  54. package/src/components/resources/renderers/CAPIMachinePoolRenderer.tsx +3 -2
  55. package/src/components/resources/renderers/CAPIMachineRenderer.tsx +3 -2
  56. package/src/components/resources/renderers/CAPIMachineSetRenderer.tsx +3 -2
  57. package/src/components/resources/renderers/CertificateRenderer.tsx +3 -2
  58. package/src/components/resources/renderers/CertificateRequestRenderer.tsx +3 -2
  59. package/src/components/resources/renderers/ClusterComplianceReportRenderer.tsx +2 -2
  60. package/src/components/resources/renderers/CompositeRenderer.tsx +3 -2
  61. package/src/components/resources/renderers/CronWorkflowRenderer.tsx +99 -0
  62. package/src/components/resources/renderers/ExternalSecretRenderer.tsx +3 -2
  63. package/src/components/resources/renderers/GCPMachineRenderer.tsx +3 -2
  64. package/src/components/resources/renderers/GCPManagedControlPlaneRenderer.tsx +3 -2
  65. package/src/components/resources/renderers/GCPManagedMachinePoolRenderer.tsx +3 -2
  66. package/src/components/resources/renderers/GRPCRouteRenderer.tsx +7 -3
  67. package/src/components/resources/renderers/GatewayClassRenderer.tsx +3 -2
  68. package/src/components/resources/renderers/HTTPRouteRenderer.tsx +7 -3
  69. package/src/components/resources/renderers/JobRenderer.tsx +3 -1
  70. package/src/components/resources/renderers/KarpenterEC2NodeClassRenderer.tsx +3 -2
  71. package/src/components/resources/renderers/KarpenterNodeClaimRenderer.tsx +3 -2
  72. package/src/components/resources/renderers/KarpenterNodePoolRenderer.tsx +3 -2
  73. package/src/components/resources/renderers/KedaScaledJobRenderer.tsx +3 -2
  74. package/src/components/resources/renderers/KedaScaledObjectRenderer.tsx +3 -2
  75. package/src/components/resources/renderers/ManagedResourceRenderer.tsx +3 -2
  76. package/src/components/resources/renderers/PVCRenderer.tsx +3 -2
  77. package/src/components/resources/renderers/PrometheusRuleRenderer.tsx +2 -2
  78. package/src/components/resources/renderers/SbomReportRenderer.tsx +2 -2
  79. package/src/components/resources/renderers/SealedSecretRenderer.tsx +3 -2
  80. package/src/components/resources/renderers/SecretRenderer.tsx +2 -0
  81. package/src/components/resources/renderers/SecretStoreRenderer.tsx +3 -2
  82. package/src/components/resources/renderers/ServiceRenderer.tsx +58 -40
  83. package/src/components/resources/renderers/SimpleRouteRenderer.tsx +7 -3
  84. package/src/components/resources/renderers/VulnerabilityReportRenderer.tsx +2 -2
  85. package/src/components/resources/renderers/WorkflowRenderer.test.tsx +43 -0
  86. package/src/components/resources/renderers/WorkflowRenderer.tsx +60 -78
  87. package/src/components/resources/renderers/index.ts +1 -0
  88. package/src/components/resources/resource-utils-argo.test.ts +18 -1
  89. package/src/components/resources/resource-utils-argo.ts +8 -0
  90. package/src/components/resources/resource-utils-capi.ts +1 -1
  91. package/src/components/resources/resource-utils.ts +31 -0
  92. package/src/components/shared/DetailShell.tsx +2 -2
  93. package/src/components/shared/ResourceActionsBar.tsx +142 -111
  94. package/src/components/shared/ResourceRendererDispatch.tsx +33 -4
  95. package/src/components/shared/UnifiedDiff.tsx +51 -0
  96. package/src/components/shared/index.ts +1 -0
  97. package/src/components/timeline/TimelineList.tsx +375 -354
  98. package/src/components/timeline/TimelineStrip.test.tsx +194 -0
  99. package/src/components/timeline/TimelineStrip.tsx +836 -0
  100. package/src/components/timeline/TimelineSwimlanes.test.tsx +1028 -0
  101. package/src/components/timeline/TimelineSwimlanes.tsx +2498 -593
  102. package/src/components/timeline/TimelineToolbar.test.tsx +320 -0
  103. package/src/components/timeline/TimelineToolbar.tsx +759 -0
  104. package/src/components/timeline/TimelineToolbarState.test.tsx +88 -0
  105. package/src/components/timeline/index.ts +23 -0
  106. package/src/components/timeline/scrubber-math.test.ts +235 -0
  107. package/src/components/timeline/scrubber-math.ts +249 -0
  108. package/src/components/timeline/shared.test.tsx +219 -0
  109. package/src/components/timeline/shared.tsx +232 -447
  110. package/src/components/timeline/timeline-filters.test.ts +196 -0
  111. package/src/components/timeline/timeline-filters.ts +180 -0
  112. package/src/components/timeline/timeline-lane-sort.test.ts +97 -0
  113. package/src/components/timeline/timeline-lane-sort.ts +77 -0
  114. package/src/components/timeline/timeline-live.test.ts +131 -0
  115. package/src/components/timeline/timeline-live.ts +77 -0
  116. package/src/components/topology/GroupNode.tsx +9 -2
  117. package/src/components/topology/K8sResourceNode.test.ts +11 -0
  118. package/src/components/topology/K8sResourceNode.tsx +387 -243
  119. package/src/components/topology/TopologyBreadcrumb.tsx +30 -0
  120. package/src/components/topology/TopologyControls.tsx +3 -1
  121. package/src/components/topology/TopologyFilterSidebar.tsx +9 -0
  122. package/src/components/topology/TopologyGraph.tsx +149 -90
  123. package/src/components/topology/TopologyOverlayBar.tsx +30 -0
  124. package/src/components/topology/TopologySearch.tsx +25 -17
  125. package/src/components/topology/index.ts +2 -0
  126. package/src/components/topology/layout.ts +10 -2
  127. package/src/components/topology/topology.css +0 -92
  128. package/src/components/ui/Badge.tsx +6 -1
  129. package/src/components/ui/CodeViewer.tsx +2 -2
  130. package/src/components/ui/Collapse.tsx +59 -0
  131. package/src/components/ui/ConfirmDialog.tsx +7 -3
  132. package/src/components/ui/DialogPortal.tsx +31 -9
  133. package/src/components/ui/Input.tsx +24 -0
  134. package/src/components/ui/MultiSelectPicker.test.tsx +101 -0
  135. package/src/components/ui/MultiSelectPicker.tsx +167 -0
  136. package/src/components/ui/PaneLoader.tsx +10 -2
  137. package/src/components/ui/ResourceBar.tsx +68 -25
  138. package/src/components/ui/SearchBox.tsx +18 -4
  139. package/src/components/ui/SearchPillInput.tsx +2 -2
  140. package/src/components/ui/SelectMenu.tsx +81 -0
  141. package/src/components/ui/drawer-components.tsx +48 -32
  142. package/src/components/ui/index.ts +6 -0
  143. package/src/components/ui/severity-tone.ts +11 -4
  144. package/src/components/workload/ResourceDetailDrawer.tsx +6 -2
  145. package/src/components/workload/WorkloadView.tsx +2706 -475
  146. package/src/components/workload/index.ts +1 -1
  147. package/src/theme/tailwind-theme.css +1 -0
  148. package/src/theme/variables.css +2 -1
  149. package/src/types/core.ts +57 -4
  150. package/src/types/gitops-insights.ts +69 -1
  151. package/src/types/gitops.ts +3 -3
  152. package/src/utils/application-history.test.ts +538 -0
  153. package/src/utils/application-history.ts +257 -0
  154. package/src/utils/application-topology.test.ts +198 -0
  155. package/src/utils/application-topology.ts +261 -0
  156. package/src/utils/applications.test.ts +201 -1
  157. package/src/utils/applications.ts +1182 -393
  158. package/src/utils/index.ts +3 -0
  159. package/src/utils/navigation.test.ts +32 -1
  160. package/src/utils/navigation.ts +70 -0
  161. package/src/utils/resource-hierarchy.test.ts +1024 -1
  162. package/src/utils/resource-hierarchy.ts +925 -267
  163. package/src/utils/resource-icons.ts +2 -0
  164. package/src/utils/topology-neighborhood.test.ts +202 -1
  165. package/src/utils/topology-neighborhood.ts +194 -13
  166. package/src/utils/workflow-execution.test.ts +556 -0
  167. package/src/utils/workflow-execution.ts +814 -0
  168. package/src/utils/workload-colors.ts +2 -3
@@ -22,4 +22,7 @@ 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'
26
+ export * from './application-history'
25
27
  export * from './bulk-workload-actions'
28
+ 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
+ })
@@ -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
+ }