@skyhook-io/k8s-ui 1.0.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.
Files changed (193) hide show
  1. package/package.json +63 -0
  2. package/src/components/dock/BottomDock.tsx +204 -0
  3. package/src/components/dock/DockContext.tsx +212 -0
  4. package/src/components/dock/TerminalTab.tsx +333 -0
  5. package/src/components/dock/index.ts +3 -0
  6. package/src/components/gitops/GitOpsActions.tsx +227 -0
  7. package/src/components/gitops/GitOpsStatusBadge.tsx +221 -0
  8. package/src/components/gitops/ManagedResourcesList.tsx +210 -0
  9. package/src/components/gitops/SyncCountdown.tsx +146 -0
  10. package/src/components/gitops/index.ts +4 -0
  11. package/src/components/logs/JsonLogLine.tsx +90 -0
  12. package/src/components/logs/LogCore.tsx +553 -0
  13. package/src/components/logs/LogToolbarSelects.tsx +74 -0
  14. package/src/components/logs/LogsViewer.tsx +146 -0
  15. package/src/components/logs/WorkloadLogsViewer.tsx +263 -0
  16. package/src/components/logs/index.ts +13 -0
  17. package/src/components/logs/useLogBuffer.ts +138 -0
  18. package/src/components/logs/useLogSearch.ts +151 -0
  19. package/src/components/logs/useLogStream.ts +61 -0
  20. package/src/components/resources/ResourcesView.tsx +5494 -0
  21. package/src/components/resources/index.ts +17 -0
  22. package/src/components/resources/renderers/AlertRenderer.tsx +166 -0
  23. package/src/components/resources/renderers/ArgoApplicationRenderer.tsx +233 -0
  24. package/src/components/resources/renderers/CNPGBackupRenderer.tsx +89 -0
  25. package/src/components/resources/renderers/CNPGClusterRenderer.tsx +194 -0
  26. package/src/components/resources/renderers/CNPGPoolerRenderer.tsx +79 -0
  27. package/src/components/resources/renderers/CNPGScheduledBackupRenderer.tsx +68 -0
  28. package/src/components/resources/renderers/CertificateRenderer.tsx +209 -0
  29. package/src/components/resources/renderers/CertificateRequestRenderer.tsx +123 -0
  30. package/src/components/resources/renderers/ChallengeRenderer.tsx +111 -0
  31. package/src/components/resources/renderers/ClusterComplianceReportRenderer.tsx +164 -0
  32. package/src/components/resources/renderers/ClusterExternalSecretRenderer.tsx +140 -0
  33. package/src/components/resources/renderers/ClusterIssuerRenderer.tsx +153 -0
  34. package/src/components/resources/renderers/ConfigAuditReportRenderer.tsx +221 -0
  35. package/src/components/resources/renderers/ConfigMapRenderer.tsx +124 -0
  36. package/src/components/resources/renderers/CronJobRenderer.tsx +86 -0
  37. package/src/components/resources/renderers/EventRenderer.tsx +175 -0
  38. package/src/components/resources/renderers/ExposedSecretReportRenderer.tsx +119 -0
  39. package/src/components/resources/renderers/ExternalSecretRenderer.tsx +172 -0
  40. package/src/components/resources/renderers/FluxHelmReleaseRenderer.tsx +242 -0
  41. package/src/components/resources/renderers/GRPCRouteRenderer.tsx +263 -0
  42. package/src/components/resources/renderers/GatewayClassRenderer.tsx +68 -0
  43. package/src/components/resources/renderers/GatewayRenderer.tsx +218 -0
  44. package/src/components/resources/renderers/GenericRenderer.tsx +476 -0
  45. package/src/components/resources/renderers/GitRepositoryRenderer.tsx +154 -0
  46. package/src/components/resources/renderers/HPARenderer.tsx +164 -0
  47. package/src/components/resources/renderers/HTTPRouteRenderer.tsx +303 -0
  48. package/src/components/resources/renderers/HelmRepositoryRenderer.tsx +167 -0
  49. package/src/components/resources/renderers/IngressClassRenderer.tsx +49 -0
  50. package/src/components/resources/renderers/IngressRenderer.tsx +104 -0
  51. package/src/components/resources/renderers/IstioAuthorizationPolicyRenderer.tsx +175 -0
  52. package/src/components/resources/renderers/IstioDestinationRuleRenderer.tsx +176 -0
  53. package/src/components/resources/renderers/IstioGatewayRenderer.tsx +125 -0
  54. package/src/components/resources/renderers/IstioPeerAuthenticationRenderer.tsx +84 -0
  55. package/src/components/resources/renderers/IstioServiceEntryRenderer.tsx +112 -0
  56. package/src/components/resources/renderers/IstioVirtualServiceRenderer.tsx +288 -0
  57. package/src/components/resources/renderers/JobRenderer.tsx +103 -0
  58. package/src/components/resources/renderers/KarpenterEC2NodeClassRenderer.tsx +157 -0
  59. package/src/components/resources/renderers/KarpenterNodeClaimRenderer.tsx +188 -0
  60. package/src/components/resources/renderers/KarpenterNodePoolRenderer.tsx +148 -0
  61. package/src/components/resources/renderers/KedaScaledJobRenderer.tsx +90 -0
  62. package/src/components/resources/renderers/KedaScaledObjectRenderer.tsx +136 -0
  63. package/src/components/resources/renderers/KedaTriggerAuthRenderer.tsx +151 -0
  64. package/src/components/resources/renderers/KnativeConfigurationRenderer.tsx +70 -0
  65. package/src/components/resources/renderers/KnativeEventingRenderer.tsx +309 -0
  66. package/src/components/resources/renderers/KnativeFlowRenderer.tsx +142 -0
  67. package/src/components/resources/renderers/KnativeNetworkingRenderer.tsx +232 -0
  68. package/src/components/resources/renderers/KnativeRevisionRenderer.tsx +97 -0
  69. package/src/components/resources/renderers/KnativeRouteRenderer.tsx +74 -0
  70. package/src/components/resources/renderers/KnativeServiceRenderer.tsx +138 -0
  71. package/src/components/resources/renderers/KnativeSourceRenderer.tsx +220 -0
  72. package/src/components/resources/renderers/KustomizationRenderer.tsx +151 -0
  73. package/src/components/resources/renderers/KyvernoPolicyReportRenderer.tsx +352 -0
  74. package/src/components/resources/renderers/LeaseRenderer.tsx +93 -0
  75. package/src/components/resources/renderers/NetworkPolicyRenderer.tsx +208 -0
  76. package/src/components/resources/renderers/NodeRenderer.tsx +282 -0
  77. package/src/components/resources/renderers/OCIRepositoryRenderer.tsx +153 -0
  78. package/src/components/resources/renderers/OrderRenderer.tsx +108 -0
  79. package/src/components/resources/renderers/PVCRenderer.tsx +98 -0
  80. package/src/components/resources/renderers/PersistentVolumeRenderer.tsx +138 -0
  81. package/src/components/resources/renderers/PodDisruptionBudgetRenderer.tsx +126 -0
  82. package/src/components/resources/renderers/PodMonitorRenderer.tsx +63 -0
  83. package/src/components/resources/renderers/PodRenderer.tsx +677 -0
  84. package/src/components/resources/renderers/PriorityClassRenderer.tsx +50 -0
  85. package/src/components/resources/renderers/PrometheusRuleRenderer.tsx +62 -0
  86. package/src/components/resources/renderers/ReplicaSetRenderer.tsx +71 -0
  87. package/src/components/resources/renderers/RoleBindingRenderer.tsx +97 -0
  88. package/src/components/resources/renderers/RoleRenderer.tsx +192 -0
  89. package/src/components/resources/renderers/RolloutRenderer.tsx +227 -0
  90. package/src/components/resources/renderers/RuntimeClassRenderer.tsx +75 -0
  91. package/src/components/resources/renderers/SbomReportRenderer.tsx +98 -0
  92. package/src/components/resources/renderers/SealedSecretRenderer.tsx +121 -0
  93. package/src/components/resources/renderers/SecretRenderer.tsx +321 -0
  94. package/src/components/resources/renderers/SecretStoreRenderer.tsx +111 -0
  95. package/src/components/resources/renderers/ServiceAccountRenderer.tsx +81 -0
  96. package/src/components/resources/renderers/ServiceMonitorRenderer.tsx +65 -0
  97. package/src/components/resources/renderers/ServiceRenderer.tsx +98 -0
  98. package/src/components/resources/renderers/SimpleRouteRenderer.tsx +195 -0
  99. package/src/components/resources/renderers/StorageClassRenderer.tsx +82 -0
  100. package/src/components/resources/renderers/TraefikIngressRouteRenderer.tsx +257 -0
  101. package/src/components/resources/renderers/VPARenderer.tsx +193 -0
  102. package/src/components/resources/renderers/VeleroBSLRenderer.tsx +73 -0
  103. package/src/components/resources/renderers/VeleroBackupRenderer.tsx +193 -0
  104. package/src/components/resources/renderers/VeleroRestoreRenderer.tsx +161 -0
  105. package/src/components/resources/renderers/VeleroScheduleRenderer.tsx +134 -0
  106. package/src/components/resources/renderers/VeleroVSLRenderer.tsx +36 -0
  107. package/src/components/resources/renderers/VulnerabilityReportRenderer.tsx +347 -0
  108. package/src/components/resources/renderers/WebhookConfigRenderer.tsx +156 -0
  109. package/src/components/resources/renderers/WorkflowRenderer.tsx +202 -0
  110. package/src/components/resources/renderers/WorkflowTemplateRenderer.tsx +91 -0
  111. package/src/components/resources/renderers/WorkloadRenderer.tsx +311 -0
  112. package/src/components/resources/renderers/argo-cells.tsx +118 -0
  113. package/src/components/resources/renderers/certmanager-cells.tsx +164 -0
  114. package/src/components/resources/renderers/cnpg-cells.tsx +161 -0
  115. package/src/components/resources/renderers/eso-cells.tsx +115 -0
  116. package/src/components/resources/renderers/flux-cells.tsx +253 -0
  117. package/src/components/resources/renderers/index.ts +105 -0
  118. package/src/components/resources/renderers/istio-cells.tsx +210 -0
  119. package/src/components/resources/renderers/karpenter-cells.tsx +107 -0
  120. package/src/components/resources/renderers/keda-cells.tsx +94 -0
  121. package/src/components/resources/renderers/knative-cells.tsx +396 -0
  122. package/src/components/resources/renderers/kyverno-cells.tsx +85 -0
  123. package/src/components/resources/renderers/prometheus-cells.tsx +74 -0
  124. package/src/components/resources/renderers/traefik-cells.tsx +120 -0
  125. package/src/components/resources/renderers/trivy-cells.tsx +153 -0
  126. package/src/components/resources/renderers/trivy-shared.tsx +67 -0
  127. package/src/components/resources/renderers/velero-cells.tsx +164 -0
  128. package/src/components/resources/resource-utils-argo.ts +155 -0
  129. package/src/components/resources/resource-utils-certmanager.ts +198 -0
  130. package/src/components/resources/resource-utils-cnpg.ts +344 -0
  131. package/src/components/resources/resource-utils-eso.ts +385 -0
  132. package/src/components/resources/resource-utils-flux.ts +186 -0
  133. package/src/components/resources/resource-utils-istio.ts +372 -0
  134. package/src/components/resources/resource-utils-karpenter.ts +150 -0
  135. package/src/components/resources/resource-utils-keda.ts +203 -0
  136. package/src/components/resources/resource-utils-knative.ts +218 -0
  137. package/src/components/resources/resource-utils-kyverno.ts +224 -0
  138. package/src/components/resources/resource-utils-prometheus.ts +159 -0
  139. package/src/components/resources/resource-utils-traefik.ts +180 -0
  140. package/src/components/resources/resource-utils-trivy.ts +146 -0
  141. package/src/components/resources/resource-utils-velero.ts +293 -0
  142. package/src/components/resources/resource-utils.ts +1558 -0
  143. package/src/components/shared/EditableYamlView.tsx +302 -0
  144. package/src/components/shared/ResourceActionsBar.tsx +924 -0
  145. package/src/components/shared/ResourceRendererDispatch.tsx +557 -0
  146. package/src/components/shared/index.ts +3 -0
  147. package/src/components/timeline/index.ts +1 -0
  148. package/src/components/timeline/shared.tsx +614 -0
  149. package/src/components/topology/GroupNode.tsx +198 -0
  150. package/src/components/topology/K8sResourceNode.tsx +440 -0
  151. package/src/components/topology/TopologyControls.tsx +62 -0
  152. package/src/components/topology/TopologyFilterSidebar.tsx +377 -0
  153. package/src/components/topology/TopologyGraph.tsx +748 -0
  154. package/src/components/topology/TopologySearch.tsx +304 -0
  155. package/src/components/topology/index.ts +7 -0
  156. package/src/components/topology/layout.ts +734 -0
  157. package/src/components/topology/layout.worker.ts +272 -0
  158. package/src/components/topology/topology.css +129 -0
  159. package/src/components/ui/CodeViewer.tsx +451 -0
  160. package/src/components/ui/ConfirmDialog.tsx +188 -0
  161. package/src/components/ui/ForceDeleteConfirmDialog.tsx +57 -0
  162. package/src/components/ui/HealthRing.tsx +72 -0
  163. package/src/components/ui/MetricsChart.tsx +259 -0
  164. package/src/components/ui/ResourceBar.tsx +68 -0
  165. package/src/components/ui/Toast.tsx +225 -0
  166. package/src/components/ui/Tooltip.tsx +165 -0
  167. package/src/components/ui/YamlEditor.tsx +280 -0
  168. package/src/components/ui/drawer-components.tsx +792 -0
  169. package/src/components/ui/index.ts +10 -0
  170. package/src/components/workload/ResourceDetailDrawer.tsx +158 -0
  171. package/src/components/workload/WorkloadView.tsx +1109 -0
  172. package/src/components/workload/index.ts +2 -0
  173. package/src/hooks/index.ts +9 -0
  174. package/src/hooks/useAnimatedUnmount.ts +30 -0
  175. package/src/hooks/useKeyboardShortcuts.tsx +336 -0
  176. package/src/hooks/useRefreshAnimation.ts +58 -0
  177. package/src/index.ts +35 -0
  178. package/src/types/core.ts +894 -0
  179. package/src/types/gitops.ts +458 -0
  180. package/src/types/index.ts +2 -0
  181. package/src/utils/animation.ts +40 -0
  182. package/src/utils/api-resources.ts +185 -0
  183. package/src/utils/badge-colors.ts +399 -0
  184. package/src/utils/context-name.ts +72 -0
  185. package/src/utils/download.ts +19 -0
  186. package/src/utils/format.ts +233 -0
  187. package/src/utils/index.ts +10 -0
  188. package/src/utils/log-format.ts +300 -0
  189. package/src/utils/navigation.ts +119 -0
  190. package/src/utils/resource-hierarchy.ts +630 -0
  191. package/src/utils/resource-icons.ts +206 -0
  192. package/src/vite-env.d.ts +1 -0
  193. package/tsconfig.json +24 -0
@@ -0,0 +1,142 @@
1
+ import { ListOrdered, GitFork } from 'lucide-react'
2
+ import { clsx } from 'clsx'
3
+ import { Section, PropertyList, Property, ConditionsSection, KnativeNotReadyBanner, ResourceLink } from '../../ui/drawer-components'
4
+ import { getKnativeConditionStatus } from '../resource-utils-knative'
5
+
6
+ interface RendererProps {
7
+ data: any
8
+ onNavigate?: (ref: { kind: string; namespace: string; name: string }) => void
9
+ }
10
+
11
+ function RefDisplay({ ref: destRef, ns, onNavigate }: { ref: any; ns: string; onNavigate?: RendererProps['onNavigate'] }) {
12
+ if (!destRef) return <span className="text-theme-text-tertiary">-</span>
13
+
14
+ if (destRef.ref) {
15
+ return (
16
+ <ResourceLink
17
+ name={destRef.ref.name}
18
+ kind={(destRef.ref.kind?.toLowerCase() || 'services') + (destRef.ref.kind?.toLowerCase().endsWith('s') ? '' : 's')}
19
+ namespace={destRef.ref.namespace || ns}
20
+ onNavigate={onNavigate}
21
+ />
22
+ )
23
+ }
24
+
25
+ if (destRef.uri) {
26
+ return <span className="text-theme-text-primary break-all text-xs">{destRef.uri}</span>
27
+ }
28
+
29
+ return <span className="text-theme-text-tertiary">-</span>
30
+ }
31
+
32
+ // ============================================================================
33
+ // Sequence
34
+ // ============================================================================
35
+
36
+ export function SequenceRenderer({ data, onNavigate }: RendererProps) {
37
+ const status = getKnativeConditionStatus(data)
38
+ const ns = data.metadata?.namespace || ''
39
+ const spec = data.spec || {}
40
+ const steps = spec.steps || []
41
+ const reply = spec.reply
42
+
43
+ return (
44
+ <>
45
+ <KnativeNotReadyBanner status={status} data={data} resourceType="Sequence" />
46
+
47
+ <Section title="Overview" icon={ListOrdered} defaultExpanded>
48
+ <PropertyList>
49
+ <Property label="Status" value={
50
+ <span className={clsx('px-2 py-0.5 rounded text-xs font-medium', status.color)}>
51
+ {status.text}
52
+ </span>
53
+ } />
54
+ <Property label="Steps" value={String(steps.length)} />
55
+ {reply && (
56
+ <Property label="Reply" value={
57
+ <RefDisplay ref={reply} ns={ns} onNavigate={onNavigate} />
58
+ } />
59
+ )}
60
+ </PropertyList>
61
+ </Section>
62
+
63
+ {steps.length > 0 && (
64
+ <Section title={`Steps (${steps.length})`} defaultExpanded>
65
+ <div className="space-y-2">
66
+ {steps.map((step: any, i: number) => (
67
+ <div key={i} className="bg-theme-elevated/30 rounded p-2 flex items-center gap-2">
68
+ <span className="text-xs font-medium text-theme-text-tertiary w-6 shrink-0">#{i + 1}</span>
69
+ <RefDisplay ref={step} ns={ns} onNavigate={onNavigate} />
70
+ </div>
71
+ ))}
72
+ </div>
73
+ </Section>
74
+ )}
75
+
76
+ <ConditionsSection conditions={data.status?.conditions || []} />
77
+ </>
78
+ )
79
+ }
80
+
81
+ // ============================================================================
82
+ // Parallel
83
+ // ============================================================================
84
+
85
+ export function ParallelRenderer({ data, onNavigate }: RendererProps) {
86
+ const status = getKnativeConditionStatus(data)
87
+ const ns = data.metadata?.namespace || ''
88
+ const spec = data.spec || {}
89
+ const branches = spec.branches || []
90
+ const reply = spec.reply
91
+
92
+ return (
93
+ <>
94
+ <KnativeNotReadyBanner status={status} data={data} resourceType="Parallel" />
95
+
96
+ <Section title="Overview" icon={GitFork} defaultExpanded>
97
+ <PropertyList>
98
+ <Property label="Status" value={
99
+ <span className={clsx('px-2 py-0.5 rounded text-xs font-medium', status.color)}>
100
+ {status.text}
101
+ </span>
102
+ } />
103
+ <Property label="Branches" value={String(branches.length)} />
104
+ {reply && (
105
+ <Property label="Reply" value={
106
+ <RefDisplay ref={reply} ns={ns} onNavigate={onNavigate} />
107
+ } />
108
+ )}
109
+ </PropertyList>
110
+ </Section>
111
+
112
+ {branches.length > 0 && (
113
+ <Section title={`Branches (${branches.length})`} defaultExpanded>
114
+ <div className="space-y-3">
115
+ {branches.map((branch: any, i: number) => (
116
+ <div key={i} className="bg-theme-elevated/30 rounded p-3">
117
+ <div className="text-sm font-medium text-theme-text-primary mb-2">Branch {i + 1}</div>
118
+ <PropertyList>
119
+ {branch.filter && (
120
+ <Property label="Filter" value={
121
+ <RefDisplay ref={branch.filter} ns={ns} onNavigate={onNavigate} />
122
+ } />
123
+ )}
124
+ <Property label="Subscriber" value={
125
+ <RefDisplay ref={branch.subscriber} ns={ns} onNavigate={onNavigate} />
126
+ } />
127
+ {branch.reply && (
128
+ <Property label="Reply" value={
129
+ <RefDisplay ref={branch.reply} ns={ns} onNavigate={onNavigate} />
130
+ } />
131
+ )}
132
+ </PropertyList>
133
+ </div>
134
+ ))}
135
+ </div>
136
+ </Section>
137
+ )}
138
+
139
+ <ConditionsSection conditions={data.status?.conditions || []} />
140
+ </>
141
+ )
142
+ }
@@ -0,0 +1,232 @@
1
+ import { Network, ShieldCheck, Server, Globe } from 'lucide-react'
2
+ import { clsx } from 'clsx'
3
+ import { Section, PropertyList, Property, ConditionsSection, KnativeNotReadyBanner, ResourceLink } from '../../ui/drawer-components'
4
+ import { getKnativeConditionStatus } from '../resource-utils-knative'
5
+
6
+ interface RendererProps {
7
+ data: any
8
+ onNavigate?: (ref: { kind: string; namespace: string; name: string }) => void
9
+ }
10
+
11
+ // ============================================================================
12
+ // KnativeIngress (Ingress from networking.internal.knative.dev)
13
+ // ============================================================================
14
+
15
+ export function KnativeIngressRenderer({ data }: RendererProps) {
16
+ const status = getKnativeConditionStatus(data)
17
+ const spec = data.spec || {}
18
+ const rules = spec.rules || []
19
+ const ingressClass = data.metadata?.annotations?.['networking.knative.dev/ingress.class']
20
+ const httpOption = spec.httpOption
21
+
22
+ return (
23
+ <>
24
+ <KnativeNotReadyBanner status={status} data={data} resourceType="Ingress" />
25
+
26
+ <Section title="Overview" icon={Network} defaultExpanded>
27
+ <PropertyList>
28
+ <Property label="Status" value={
29
+ <span className={clsx('px-2 py-0.5 rounded text-xs font-medium', status.color)}>
30
+ {status.text}
31
+ </span>
32
+ } />
33
+ <Property label="Ingress Class" value={ingressClass} />
34
+ <Property label="HTTP" value={httpOption} />
35
+ </PropertyList>
36
+ </Section>
37
+
38
+ {rules.length > 0 && (
39
+ <Section title={`Rules (${rules.length})`} defaultExpanded>
40
+ <div className="space-y-3">
41
+ {rules.map((rule: any, i: number) => (
42
+ <div key={i} className="bg-theme-elevated/30 rounded p-3">
43
+ <div className="flex flex-wrap gap-1 mb-2">
44
+ {(rule.hosts || []).map((host: string, hi: number) => (
45
+ <span key={hi} className="px-1.5 py-0.5 bg-blue-500/10 text-blue-400 rounded text-xs">
46
+ {host}
47
+ </span>
48
+ ))}
49
+ {rule.visibility && (
50
+ <span className="px-1.5 py-0.5 bg-theme-hover rounded text-[10px] text-theme-text-secondary">
51
+ {rule.visibility}
52
+ </span>
53
+ )}
54
+ </div>
55
+ {rule.http?.paths && rule.http.paths.length > 0 && (
56
+ <div className="space-y-1.5">
57
+ {rule.http.paths.map((path: any, pi: number) => (
58
+ <div key={pi} className="text-xs">
59
+ <span className="text-theme-text-tertiary">
60
+ {path.path || '/'}
61
+ </span>
62
+ {path.splits && path.splits.length > 0 && (
63
+ <div className="ml-3 mt-1 space-y-0.5">
64
+ {path.splits.map((split: any, si: number) => (
65
+ <div key={si} className="text-theme-text-secondary">
66
+ {split.serviceName}:{split.servicePort}
67
+ {split.percent !== undefined && (
68
+ <span className="text-theme-text-tertiary ml-1">({split.percent}%)</span>
69
+ )}
70
+ </div>
71
+ ))}
72
+ </div>
73
+ )}
74
+ </div>
75
+ ))}
76
+ </div>
77
+ )}
78
+ </div>
79
+ ))}
80
+ </div>
81
+ </Section>
82
+ )}
83
+
84
+ <ConditionsSection conditions={data.status?.conditions || []} />
85
+ </>
86
+ )
87
+ }
88
+
89
+ // ============================================================================
90
+ // KnativeCertificate (Certificate from networking.internal.knative.dev)
91
+ // ============================================================================
92
+
93
+ export function KnativeCertificateRenderer({ data }: RendererProps) {
94
+ const status = getKnativeConditionStatus(data)
95
+ const spec = data.spec || {}
96
+ const dnsNames = spec.dnsNames || []
97
+ const secretName = spec.secretName || data.status?.http01Challenges?.[0]?.secretName
98
+
99
+ return (
100
+ <>
101
+ <KnativeNotReadyBanner status={status} data={data} resourceType="Certificate" />
102
+
103
+ <Section title="Overview" icon={ShieldCheck} defaultExpanded>
104
+ <PropertyList>
105
+ <Property label="Status" value={
106
+ <span className={clsx('px-2 py-0.5 rounded text-xs font-medium', status.color)}>
107
+ {status.text}
108
+ </span>
109
+ } />
110
+ <Property label="Secret Name" value={secretName} />
111
+ <Property label="Domain" value={spec.domain} />
112
+ </PropertyList>
113
+ </Section>
114
+
115
+ {dnsNames.length > 0 && (
116
+ <Section title={`DNS Names (${dnsNames.length})`} defaultExpanded>
117
+ <div className="flex flex-wrap gap-1">
118
+ {dnsNames.map((name: string, i: number) => (
119
+ <span key={i} className="px-1.5 py-0.5 bg-theme-elevated rounded text-xs text-theme-text-secondary">
120
+ {name}
121
+ </span>
122
+ ))}
123
+ </div>
124
+ </Section>
125
+ )}
126
+
127
+ <ConditionsSection conditions={data.status?.conditions || []} />
128
+ </>
129
+ )
130
+ }
131
+
132
+ // ============================================================================
133
+ // ServerlessService (from networking.internal.knative.dev)
134
+ // ============================================================================
135
+
136
+ export function ServerlessServiceRenderer({ data, onNavigate }: RendererProps) {
137
+ const status = getKnativeConditionStatus(data)
138
+ const ns = data.metadata?.namespace || ''
139
+ const spec = data.spec || {}
140
+ const mode = spec.mode
141
+ const numActivators = spec.numActivators
142
+ const protocolType = spec.protocolType
143
+ const objectRef = spec.objectRef
144
+ const privateServiceName = data.status?.privateServiceName
145
+ const serviceName = data.status?.serviceName
146
+
147
+ return (
148
+ <>
149
+ <KnativeNotReadyBanner status={status} data={data} resourceType="ServerlessService" />
150
+
151
+ <Section title="Overview" icon={Server} defaultExpanded>
152
+ <PropertyList>
153
+ <Property label="Status" value={
154
+ <span className={clsx('px-2 py-0.5 rounded text-xs font-medium', status.color)}>
155
+ {status.text}
156
+ </span>
157
+ } />
158
+ <Property label="Mode" value={mode ? (
159
+ <span className={clsx(
160
+ 'px-2 py-0.5 rounded text-xs font-medium',
161
+ mode === 'Proxy' ? 'bg-yellow-500/20 text-yellow-400' : 'bg-green-500/20 text-green-400'
162
+ )}>
163
+ {mode}
164
+ </span>
165
+ ) : undefined} />
166
+ <Property label="Activators" value={numActivators != null ? String(numActivators) : undefined} />
167
+ <Property label="Protocol" value={protocolType} />
168
+ {objectRef && (
169
+ <Property label="Target" value={
170
+ <ResourceLink
171
+ name={objectRef.name}
172
+ kind={(objectRef.kind?.toLowerCase() || 'deployments') + 's'}
173
+ namespace={ns}
174
+ onNavigate={onNavigate}
175
+ />
176
+ } />
177
+ )}
178
+ {serviceName && <Property label="Public Service" value={serviceName} />}
179
+ {privateServiceName && <Property label="Private Service" value={privateServiceName} />}
180
+ </PropertyList>
181
+ </Section>
182
+
183
+ <ConditionsSection conditions={data.status?.conditions || []} />
184
+ </>
185
+ )
186
+ }
187
+
188
+ // ============================================================================
189
+ // DomainMapping (serving.knative.dev/v1beta1)
190
+ // ============================================================================
191
+
192
+ export function DomainMappingRenderer({ data, onNavigate }: RendererProps) {
193
+ const status = getKnativeConditionStatus(data)
194
+ const ns = data.metadata?.namespace || ''
195
+ const url = data.status?.url
196
+ const ref = data.spec?.ref
197
+ const tlsSecret = data.spec?.tls?.secretName
198
+
199
+ return (
200
+ <>
201
+ <KnativeNotReadyBanner status={status} data={data} resourceType="DomainMapping" />
202
+
203
+ <Section title="Overview" icon={Globe} defaultExpanded>
204
+ <PropertyList>
205
+ <Property label="Status" value={
206
+ <span className={clsx('px-2 py-0.5 rounded text-xs font-medium', status.color)}>
207
+ {status.text}
208
+ </span>
209
+ } />
210
+ <Property label="URL" value={url ? (
211
+ <a href={url} target="_blank" rel="noopener noreferrer" className="text-blue-400 hover:text-blue-300 break-all">
212
+ {url}
213
+ </a>
214
+ ) : undefined} />
215
+ {ref && (
216
+ <Property label="Target" value={
217
+ <ResourceLink
218
+ name={ref.name}
219
+ kind={(ref.kind?.toLowerCase() || 'services') + (ref.kind?.toLowerCase().endsWith('s') ? '' : 's')}
220
+ namespace={ns}
221
+ onNavigate={onNavigate}
222
+ />
223
+ } />
224
+ )}
225
+ {tlsSecret && <Property label="TLS Secret" value={tlsSecret} />}
226
+ </PropertyList>
227
+ </Section>
228
+
229
+ <ConditionsSection conditions={data.status?.conditions || []} />
230
+ </>
231
+ )
232
+ }
@@ -0,0 +1,97 @@
1
+ import { Container, Settings } from 'lucide-react'
2
+ import { clsx } from 'clsx'
3
+ import { Section, PropertyList, Property, ConditionsSection, KnativeNotReadyBanner } from '../../ui/drawer-components'
4
+ import { getRevisionStatus } from '../resource-utils-knative'
5
+
6
+ interface KnativeRevisionRendererProps {
7
+ data: any
8
+ onNavigate?: (ref: { kind: string; namespace: string; name: string }) => void
9
+ }
10
+
11
+ export function KnativeRevisionRenderer({ data }: KnativeRevisionRendererProps) {
12
+ const status = getRevisionStatus(data)
13
+ const spec = data.spec || {}
14
+ const containers = spec.containers || []
15
+ const containerConcurrency = spec.containerConcurrency
16
+ const timeoutSeconds = spec.timeoutSeconds
17
+ const serviceAccountName = spec.serviceAccountName
18
+
19
+ const firstContainer = containers[0] || {}
20
+ const image = firstContainer.image
21
+
22
+ // Runtime status
23
+ const actualReplicas = data.status?.actualReplicas
24
+ const desiredReplicas = data.status?.desiredReplicas
25
+ const routingState = data.metadata?.labels?.['serving.knative.dev/routingState']
26
+ const imageDigest = data.status?.containerStatuses?.[0]?.imageDigest
27
+
28
+ return (
29
+ <>
30
+ <KnativeNotReadyBanner status={status} data={data} resourceType="Revision" />
31
+
32
+ <Section title="Overview" icon={Settings} defaultExpanded>
33
+ <PropertyList>
34
+ <Property label="Status" value={
35
+ <span className={clsx('px-2 py-0.5 rounded text-xs font-medium', status.color)}>
36
+ {status.text}
37
+ </span>
38
+ } />
39
+ <Property label="Image" value={image} />
40
+ {imageDigest && <Property label="Image Digest" value={
41
+ <span className="text-xs font-mono text-theme-text-secondary break-all">{imageDigest}</span>
42
+ } />}
43
+ {routingState && <Property label="Routing" value={
44
+ <span className={clsx(
45
+ 'px-2 py-0.5 rounded text-xs font-medium',
46
+ routingState === 'active' ? 'bg-green-500/20 text-green-400' : 'bg-theme-hover text-theme-text-secondary'
47
+ )}>
48
+ {routingState}
49
+ </span>
50
+ } />}
51
+ {(actualReplicas != null || desiredReplicas != null) && (
52
+ <Property label="Replicas" value={`${actualReplicas ?? 0} / ${desiredReplicas ?? 0}`} />
53
+ )}
54
+ <Property label="Concurrency" value={containerConcurrency != null ? (containerConcurrency === 0 ? 'Unlimited' : String(containerConcurrency)) : undefined} />
55
+ <Property label="Timeout" value={timeoutSeconds != null ? `${timeoutSeconds}s` : undefined} />
56
+ <Property label="Service Account" value={serviceAccountName} />
57
+ </PropertyList>
58
+ </Section>
59
+
60
+ {containers.length > 0 && (
61
+ <Section title={`Containers (${containers.length})`} icon={Container} defaultExpanded>
62
+ <div className="space-y-2">
63
+ {containers.map((c: any, i: number) => (
64
+ <div key={i} className="bg-theme-elevated/30 rounded p-2 text-sm">
65
+ <div className="font-medium text-theme-text-primary">{c.name || 'container'}</div>
66
+ <div className="text-xs text-theme-text-secondary truncate" title={c.image}>{c.image}</div>
67
+ {c.ports && c.ports.length > 0 && (
68
+ <div className="text-xs text-theme-text-tertiary mt-1">
69
+ Ports: {c.ports.map((p: any) => `${p.containerPort}/${p.protocol || 'TCP'}`).join(', ')}
70
+ </div>
71
+ )}
72
+ {c.resources && (c.resources.requests || c.resources.limits) && (
73
+ <div className="text-xs text-theme-text-tertiary mt-1">
74
+ {c.resources.requests && (
75
+ <span>Requests: {Object.entries(c.resources.requests).map(([k, v]) => `${k}=${v}`).join(', ')}</span>
76
+ )}
77
+ {c.resources.requests && c.resources.limits && ' | '}
78
+ {c.resources.limits && (
79
+ <span>Limits: {Object.entries(c.resources.limits).map(([k, v]) => `${k}=${v}`).join(', ')}</span>
80
+ )}
81
+ </div>
82
+ )}
83
+ {c.env && c.env.length > 0 && (
84
+ <div className="text-xs text-theme-text-tertiary mt-1">
85
+ Env: {c.env.length} variable{c.env.length !== 1 ? 's' : ''}
86
+ </div>
87
+ )}
88
+ </div>
89
+ ))}
90
+ </div>
91
+ </Section>
92
+ )}
93
+
94
+ <ConditionsSection conditions={data.status?.conditions || []} />
95
+ </>
96
+ )
97
+ }
@@ -0,0 +1,74 @@
1
+ import { Route } from 'lucide-react'
2
+ import { clsx } from 'clsx'
3
+ import { Section, PropertyList, Property, ConditionsSection, KnativeNotReadyBanner, ResourceLink } from '../../ui/drawer-components'
4
+ import { getKnativeConditionStatus } from '../resource-utils-knative'
5
+
6
+ interface KnativeRouteRendererProps {
7
+ data: any
8
+ onNavigate?: (ref: { kind: string; namespace: string; name: string }) => void
9
+ }
10
+
11
+ export function KnativeRouteRenderer({ data, onNavigate }: KnativeRouteRendererProps) {
12
+ const status = getKnativeConditionStatus(data)
13
+ const traffic = data.status?.traffic || data.spec?.traffic || []
14
+ const ns = data.metadata?.namespace || ''
15
+ const url = data.status?.url || data.status?.address?.url
16
+
17
+ return (
18
+ <>
19
+ <KnativeNotReadyBanner status={status} data={data} resourceType="Route" />
20
+
21
+ <Section title="Overview" icon={Route} defaultExpanded>
22
+ <PropertyList>
23
+ <Property label="Status" value={
24
+ <span className={clsx('px-2 py-0.5 rounded text-xs font-medium', status.color)}>
25
+ {status.text}
26
+ </span>
27
+ } />
28
+ <Property label="URL" value={url ? (
29
+ <a href={url} target="_blank" rel="noopener noreferrer" className="text-blue-400 hover:text-blue-300 hover:underline break-all">
30
+ {url}
31
+ </a>
32
+ ) : undefined} />
33
+ </PropertyList>
34
+ </Section>
35
+
36
+ {traffic.length > 0 && (
37
+ <Section title={`Traffic Targets (${traffic.length})`} defaultExpanded>
38
+ <div className="space-y-2">
39
+ {traffic.map((t: any, i: number) => (
40
+ <div key={i} className="flex items-center gap-2 text-sm">
41
+ <div className="flex items-center gap-1 w-16 shrink-0">
42
+ <div className="flex-1 h-1.5 bg-theme-hover rounded-full overflow-hidden">
43
+ <div
44
+ className="h-full bg-blue-500 rounded-full"
45
+ style={{ width: `${t.percent || 0}%` }}
46
+ />
47
+ </div>
48
+ <span className="text-theme-text-secondary font-medium text-xs">{t.percent || 0}%</span>
49
+ </div>
50
+ {t.revisionName ? (
51
+ <ResourceLink
52
+ name={t.revisionName}
53
+ kind="revisions"
54
+ namespace={ns}
55
+ onNavigate={onNavigate}
56
+ />
57
+ ) : (
58
+ <span className="text-theme-text-secondary">{t.configurationName || (t.latestRevision ? '@latest' : '-')}</span>
59
+ )}
60
+ {t.tag && (
61
+ <span className="px-1.5 py-0.5 bg-theme-hover rounded text-[10px] text-theme-text-secondary">
62
+ tag: {t.tag}
63
+ </span>
64
+ )}
65
+ </div>
66
+ ))}
67
+ </div>
68
+ </Section>
69
+ )}
70
+
71
+ <ConditionsSection conditions={data.status?.conditions || []} />
72
+ </>
73
+ )
74
+ }