@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,138 @@
1
+ import { HardDrive, Link, Database, Server } from 'lucide-react'
2
+ import { clsx } from 'clsx'
3
+ import { Section, PropertyList, Property, ConditionsSection, AlertBanner, ResourceLink } from '../../ui/drawer-components'
4
+
5
+ interface PersistentVolumeRendererProps {
6
+ data: any
7
+ onNavigate?: (ref: { kind: string; namespace: string; name: string }) => void
8
+ }
9
+
10
+ const accessModeShorthand: Record<string, string> = {
11
+ ReadWriteOnce: 'RWO',
12
+ ReadOnlyMany: 'ROX',
13
+ ReadWriteMany: 'RWX',
14
+ ReadWriteOncePod: 'RWOP',
15
+ }
16
+
17
+ function formatAccessModes(modes: string[] | undefined): string | undefined {
18
+ if (!modes || modes.length === 0) return undefined
19
+ return modes.map(m => accessModeShorthand[m] || m).join(', ')
20
+ }
21
+
22
+ export function PersistentVolumeRenderer({ data, onNavigate }: PersistentVolumeRendererProps) {
23
+ const status = data.status || {}
24
+ const spec = data.spec || {}
25
+ const phase = status.phase
26
+
27
+ const claimRef = spec.claimRef
28
+ const csi = spec.csi
29
+ const nodeAffinity = spec.nodeAffinity
30
+
31
+ // Problem detection
32
+ const isFailed = phase === 'Failed'
33
+ const isReleased = phase === 'Released'
34
+
35
+ return (
36
+ <>
37
+ {/* Problem alerts */}
38
+ {isFailed && (
39
+ <AlertBanner
40
+ variant="error"
41
+ title="Issues Detected"
42
+ message="PV has failed"
43
+ />
44
+ )}
45
+
46
+ {isReleased && (
47
+ <AlertBanner
48
+ variant="warning"
49
+ title="Issues Detected"
50
+ message="PV is released but not yet available or reclaimed"
51
+ />
52
+ )}
53
+
54
+ {/* Status */}
55
+ <Section title="Status" icon={HardDrive}>
56
+ <PropertyList>
57
+ <Property
58
+ label="Phase"
59
+ value={
60
+ <span className={clsx(
61
+ (phase === 'Bound' || phase === 'Available') && 'text-green-400',
62
+ phase === 'Released' && 'text-yellow-400',
63
+ phase === 'Failed' && 'text-red-400',
64
+ )}>
65
+ {phase}
66
+ </span>
67
+ }
68
+ />
69
+ <Property label="Capacity" value={spec.capacity?.storage} />
70
+ <Property label="Access Modes" value={formatAccessModes(spec.accessModes)} />
71
+ <Property label="Volume Mode" value={spec.volumeMode} />
72
+ <Property
73
+ label="Reclaim Policy"
74
+ value={
75
+ spec.persistentVolumeReclaimPolicy ? (
76
+ <span className={clsx(
77
+ spec.persistentVolumeReclaimPolicy === 'Delete' && 'text-red-400',
78
+ spec.persistentVolumeReclaimPolicy === 'Retain' && 'text-green-400',
79
+ )}>
80
+ {spec.persistentVolumeReclaimPolicy}
81
+ </span>
82
+ ) : undefined
83
+ }
84
+ />
85
+ <Property label="Storage Class" value={
86
+ spec.storageClassName ? <ResourceLink name={spec.storageClassName} kind="storageclasses" namespace="" onNavigate={onNavigate} /> : undefined
87
+ } />
88
+ </PropertyList>
89
+ </Section>
90
+
91
+ {/* Claim Reference */}
92
+ {claimRef && (
93
+ <Section title="Claim" icon={Link}>
94
+ <PropertyList>
95
+ <Property label="Namespace" value={claimRef.namespace} />
96
+ <Property label="Name" value={
97
+ claimRef.name ? <ResourceLink name={claimRef.name} kind="persistentvolumeclaims" namespace={claimRef.namespace || ''} onNavigate={onNavigate} /> : undefined
98
+ } />
99
+ <Property label="UID" value={claimRef.uid} />
100
+ </PropertyList>
101
+ </Section>
102
+ )}
103
+
104
+ {/* CSI */}
105
+ {csi && (
106
+ <Section title="CSI" icon={Database}>
107
+ <PropertyList>
108
+ <Property label="Driver" value={csi.driver} />
109
+ <Property label="Volume Handle" value={csi.volumeHandle} />
110
+ <Property label="FS Type" value={csi.fsType} />
111
+ </PropertyList>
112
+ </Section>
113
+ )}
114
+
115
+ {/* Node Affinity */}
116
+ {nodeAffinity?.required?.nodeSelectorTerms && nodeAffinity.required.nodeSelectorTerms.length > 0 && (
117
+ <Section title="Node Affinity" icon={Server}>
118
+ <div className="space-y-2">
119
+ {nodeAffinity.required.nodeSelectorTerms.map((term: any, termIdx: number) => (
120
+ <div key={termIdx} className="space-y-1">
121
+ {term.matchExpressions?.map((expr: any, exprIdx: number) => (
122
+ <div key={exprIdx} className="flex flex-wrap gap-1">
123
+ <span className="px-2 py-0.5 bg-theme-elevated rounded text-xs text-theme-text-secondary">
124
+ {expr.key} {expr.operator} {expr.values?.join(', ')}
125
+ </span>
126
+ </div>
127
+ ))}
128
+ </div>
129
+ ))}
130
+ </div>
131
+ </Section>
132
+ )}
133
+
134
+ {/* Conditions */}
135
+ <ConditionsSection conditions={status.conditions} />
136
+ </>
137
+ )
138
+ }
@@ -0,0 +1,126 @@
1
+ import { Shield, Activity } from 'lucide-react'
2
+ import { clsx } from 'clsx'
3
+ import { Section, PropertyList, Property, ConditionsSection, KeyValueBadgeList, AlertBanner } from '../../ui/drawer-components'
4
+
5
+ interface PodDisruptionBudgetRendererProps {
6
+ data: any
7
+ }
8
+
9
+ export function PodDisruptionBudgetRenderer({ data }: PodDisruptionBudgetRendererProps) {
10
+ const spec = data.spec || {}
11
+ const status = data.status || {}
12
+ const matchLabels = spec.selector?.matchLabels || {}
13
+ const hasSelector = Object.keys(matchLabels).length > 0
14
+
15
+ // Determine budget type
16
+ const hasMaxUnavailable = spec.maxUnavailable !== undefined && spec.maxUnavailable !== null
17
+ const hasMinAvailable = spec.minAvailable !== undefined && spec.minAvailable !== null
18
+ const budgetType = hasMaxUnavailable ? 'Max Unavailable' : hasMinAvailable ? 'Min Available' : undefined
19
+ const budgetValue = hasMaxUnavailable ? spec.maxUnavailable : hasMinAvailable ? spec.minAvailable : undefined
20
+
21
+ // Problem detection
22
+ const disruptionsAllowed = status.disruptionsAllowed
23
+ const expectedPods = status.expectedPods
24
+ const currentHealthy = status.currentHealthy
25
+ const desiredHealthy = status.desiredHealthy
26
+
27
+ const noDisruptionsAllowed = disruptionsAllowed === 0 && expectedPods > 0
28
+ const insufficientHealthy = currentHealthy !== undefined && desiredHealthy !== undefined && currentHealthy < desiredHealthy
29
+
30
+ return (
31
+ <>
32
+ {/* Problem alerts */}
33
+ {insufficientHealthy && (
34
+ <AlertBanner
35
+ variant="error"
36
+ title="Issues Detected"
37
+ message={`Insufficient healthy pods (${currentHealthy} healthy, ${desiredHealthy} desired)`}
38
+ />
39
+ )}
40
+
41
+ {noDisruptionsAllowed && !insufficientHealthy && (
42
+ <AlertBanner
43
+ variant="warning"
44
+ title="Issues Detected"
45
+ message="No disruptions currently allowed"
46
+ />
47
+ )}
48
+
49
+ <Section title="Budget" icon={Shield}>
50
+ <PropertyList>
51
+ <Property label="Budget Type" value={budgetType} />
52
+ <Property label="Budget Value" value={budgetValue !== undefined ? String(budgetValue) : undefined} />
53
+ <Property
54
+ label="Disruptions"
55
+ value={
56
+ disruptionsAllowed !== undefined ? (
57
+ <span className={clsx(
58
+ disruptionsAllowed > 0 ? 'text-green-400' : 'text-red-400'
59
+ )}>
60
+ {disruptionsAllowed} allowed
61
+ </span>
62
+ ) : undefined
63
+ }
64
+ />
65
+ <Property label="Eviction Policy" value={spec.unhealthyPodEvictionPolicy} />
66
+ </PropertyList>
67
+ </Section>
68
+
69
+ <Section title="Pod Status" icon={Activity}>
70
+ <PropertyList>
71
+ <Property
72
+ label="Current Healthy"
73
+ value={
74
+ currentHealthy !== undefined ? (
75
+ <span className={clsx(
76
+ desiredHealthy !== undefined && currentHealthy >= desiredHealthy
77
+ ? 'text-green-400'
78
+ : 'text-red-400'
79
+ )}>
80
+ {currentHealthy}
81
+ </span>
82
+ ) : undefined
83
+ }
84
+ />
85
+ <Property label="Desired Healthy" value={desiredHealthy} />
86
+ <Property label="Expected Pods" value={expectedPods} />
87
+ </PropertyList>
88
+ {currentHealthy !== undefined && expectedPods !== undefined && expectedPods > 0 && (
89
+ <div className="mt-3 bg-theme-elevated/30 rounded p-2 text-sm">
90
+ <div className="flex items-center justify-between">
91
+ <span className="text-theme-text-secondary">Health</span>
92
+ <span className={clsx(
93
+ desiredHealthy !== undefined && currentHealthy >= desiredHealthy
94
+ ? 'text-green-400'
95
+ : 'text-red-400'
96
+ )}>
97
+ {currentHealthy}/{expectedPods} healthy
98
+ </span>
99
+ </div>
100
+ <div className="mt-2 h-2 bg-theme-hover rounded overflow-hidden">
101
+ <div
102
+ className={clsx(
103
+ 'h-full transition-all',
104
+ desiredHealthy !== undefined && currentHealthy >= desiredHealthy
105
+ ? 'bg-green-500'
106
+ : 'bg-red-500'
107
+ )}
108
+ style={{ width: `${Math.min(100, (currentHealthy / expectedPods) * 100)}%` }}
109
+ />
110
+ </div>
111
+ </div>
112
+ )}
113
+ </Section>
114
+
115
+ <Section title="Selector">
116
+ {hasSelector ? (
117
+ <KeyValueBadgeList items={matchLabels} />
118
+ ) : (
119
+ <div className="text-sm text-theme-text-tertiary">All pods in namespace</div>
120
+ )}
121
+ </Section>
122
+
123
+ <ConditionsSection conditions={status.conditions} />
124
+ </>
125
+ )
126
+ }
@@ -0,0 +1,63 @@
1
+ import { Radio } from 'lucide-react'
2
+ import { Section, PropertyList, Property, ConditionsSection, KeyValueBadgeList } from '../../ui/drawer-components'
3
+ import {
4
+ getPodMonitorEndpoints,
5
+ getPodMonitorNamespaceSelector,
6
+ } from '../resource-utils-prometheus'
7
+
8
+ interface PodMonitorRendererProps {
9
+ data: any
10
+ }
11
+
12
+ export function PodMonitorRenderer({ data }: PodMonitorRendererProps) {
13
+ const endpoints = getPodMonitorEndpoints(data)
14
+ const selector = data.spec?.selector?.matchLabels
15
+ const conditions = data.status?.conditions
16
+
17
+ return (
18
+ <>
19
+ <Section title="PodMonitor" icon={Radio}>
20
+ <PropertyList>
21
+ <Property label="Endpoints" value={String(endpoints.length)} />
22
+ <Property label="Namespace Scope" value={getPodMonitorNamespaceSelector(data)} />
23
+ <Property label="Sample Limit" value={data.spec?.sampleLimit ? String(data.spec.sampleLimit) : undefined} />
24
+ </PropertyList>
25
+ </Section>
26
+
27
+ {endpoints.length > 0 && (
28
+ <Section title={`Pod Metrics Endpoints (${endpoints.length})`} defaultExpanded>
29
+ <div className="space-y-2">
30
+ {endpoints.map((ep, i) => (
31
+ <div key={i} className="bg-theme-elevated/30 rounded p-2 text-sm">
32
+ <div className="flex items-center gap-2 flex-wrap">
33
+ {ep.port && (
34
+ <span className="text-theme-text-primary font-medium">{ep.port}</span>
35
+ )}
36
+ <span className="text-theme-text-secondary">{ep.path}</span>
37
+ {ep.interval && (
38
+ <span className="px-1.5 py-0.5 bg-theme-hover rounded text-xs text-theme-text-secondary">
39
+ every {ep.interval}
40
+ </span>
41
+ )}
42
+ {ep.scheme && ep.scheme !== 'http' && (
43
+ <span className="px-1.5 py-0.5 bg-theme-hover rounded text-xs text-theme-text-secondary">
44
+ {ep.scheme}
45
+ </span>
46
+ )}
47
+ </div>
48
+ </div>
49
+ ))}
50
+ </div>
51
+ </Section>
52
+ )}
53
+
54
+ {selector && Object.keys(selector).length > 0 && (
55
+ <Section title="Selector">
56
+ <KeyValueBadgeList items={selector} />
57
+ </Section>
58
+ )}
59
+
60
+ <ConditionsSection conditions={conditions} />
61
+ </>
62
+ )
63
+ }