@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,293 @@
1
+ // Velero CRD utility functions
2
+
3
+ import type { StatusBadge } from './resource-utils'
4
+ import { healthColors, formatAge, formatDuration } from './resource-utils'
5
+
6
+ // ============================================================================
7
+ // BACKUP UTILITIES
8
+ // ============================================================================
9
+
10
+ export function getBackupStatus(resource: any): StatusBadge {
11
+ const phase = resource.status?.phase || ''
12
+
13
+ switch (phase) {
14
+ case 'Completed':
15
+ return { text: 'Completed', color: healthColors.healthy, level: 'healthy' }
16
+ case 'InProgress':
17
+ return { text: 'InProgress', color: healthColors.neutral, level: 'neutral' }
18
+ case 'Uploading':
19
+ return { text: 'Uploading', color: healthColors.neutral, level: 'neutral' }
20
+ case 'PartiallyFailed':
21
+ return { text: 'PartiallyFailed', color: healthColors.degraded, level: 'degraded' }
22
+ case 'Failed':
23
+ return { text: 'Failed', color: healthColors.unhealthy, level: 'unhealthy' }
24
+ case 'Deleting':
25
+ return { text: 'Deleting', color: healthColors.degraded, level: 'degraded' }
26
+ case 'New':
27
+ return { text: 'New', color: healthColors.unknown, level: 'unknown' }
28
+ default:
29
+ return { text: phase || 'Unknown', color: healthColors.unknown, level: 'unknown' }
30
+ }
31
+ }
32
+
33
+ export function getBackupStorageLocation(resource: any): string {
34
+ return resource.spec?.storageLocation || 'default'
35
+ }
36
+
37
+ export function getBackupIncludedNamespaces(resource: any): string[] {
38
+ return resource.spec?.includedNamespaces || []
39
+ }
40
+
41
+ export function getBackupExcludedNamespaces(resource: any): string[] {
42
+ return resource.spec?.excludedNamespaces || []
43
+ }
44
+
45
+ export function getBackupIncludedResources(resource: any): string[] {
46
+ return resource.spec?.includedResources || []
47
+ }
48
+
49
+ export function getBackupExcludedResources(resource: any): string[] {
50
+ return resource.spec?.excludedResources || []
51
+ }
52
+
53
+ export function getBackupDuration(resource: any): string {
54
+ const start = resource.status?.startTimestamp
55
+ const end = resource.status?.completionTimestamp
56
+ if (!start) return '-'
57
+ const startDate = new Date(start)
58
+ const endDate = end ? new Date(end) : new Date()
59
+ const diffMs = endDate.getTime() - startDate.getTime()
60
+ if (diffMs < 0) return '-'
61
+ return formatDuration(diffMs, true)
62
+ }
63
+
64
+ export function getBackupItemCount(resource: any): string {
65
+ const progress = resource.status?.progress
66
+ if (!progress) return '-'
67
+ const backed = progress.itemsBackedUp ?? 0
68
+ const total = progress.totalItems ?? 0
69
+ return `${backed}/${total}`
70
+ }
71
+
72
+ export function getBackupExpiry(resource: any): string {
73
+ const expiration = resource.status?.expiration
74
+ if (!expiration) return '-'
75
+ const expiryDate = new Date(expiration)
76
+ const now = new Date()
77
+ const diffMs = expiryDate.getTime() - now.getTime()
78
+ if (diffMs <= 0) return 'Expired'
79
+ return formatDuration(diffMs) + ' remaining'
80
+ }
81
+
82
+ export function getBackupErrors(resource: any): number {
83
+ return resource.status?.errors ?? 0
84
+ }
85
+
86
+ export function getBackupWarnings(resource: any): number {
87
+ return resource.status?.warnings ?? 0
88
+ }
89
+
90
+ export function getBackupValidationErrors(resource: any): string[] {
91
+ return resource.status?.validationErrors || []
92
+ }
93
+
94
+ export function getBackupTTL(resource: any): string {
95
+ return resource.spec?.ttl || '-'
96
+ }
97
+
98
+ export function getBackupSnapshotVolumes(resource: any): string {
99
+ const val = resource.spec?.snapshotVolumes
100
+ if (val === undefined || val === null) return 'default'
101
+ return val ? 'Yes' : 'No'
102
+ }
103
+
104
+ export function getBackupDefaultVolumesToFsBackup(resource: any): string {
105
+ const val = resource.spec?.defaultVolumesToFsBackup
106
+ if (val === undefined || val === null) return 'No'
107
+ return val ? 'Yes' : 'No'
108
+ }
109
+
110
+ export function getBackupVolumeSnapshotLocations(resource: any): string[] {
111
+ return resource.spec?.volumeSnapshotLocations || []
112
+ }
113
+
114
+ // ============================================================================
115
+ // RESTORE UTILITIES
116
+ // ============================================================================
117
+
118
+ export function getRestoreStatus(resource: any): StatusBadge {
119
+ const phase = resource.status?.phase || ''
120
+
121
+ switch (phase) {
122
+ case 'Completed':
123
+ return { text: 'Completed', color: healthColors.healthy, level: 'healthy' }
124
+ case 'InProgress':
125
+ return { text: 'InProgress', color: healthColors.neutral, level: 'neutral' }
126
+ case 'PartiallyFailed':
127
+ return { text: 'PartiallyFailed', color: healthColors.degraded, level: 'degraded' }
128
+ case 'Failed':
129
+ return { text: 'Failed', color: healthColors.unhealthy, level: 'unhealthy' }
130
+ case 'New':
131
+ return { text: 'New', color: healthColors.unknown, level: 'unknown' }
132
+ default:
133
+ return { text: phase || 'Unknown', color: healthColors.unknown, level: 'unknown' }
134
+ }
135
+ }
136
+
137
+ export function getRestoreBackupName(resource: any): string {
138
+ return resource.spec?.backupName || '-'
139
+ }
140
+
141
+ export function getRestoreIncludedNamespaces(resource: any): string[] {
142
+ return resource.spec?.includedNamespaces || []
143
+ }
144
+
145
+ export function getRestoreExcludedNamespaces(resource: any): string[] {
146
+ return resource.spec?.excludedNamespaces || []
147
+ }
148
+
149
+ export function getRestoreIncludedResources(resource: any): string[] {
150
+ return resource.spec?.includedResources || []
151
+ }
152
+
153
+ export function getRestoreExcludedResources(resource: any): string[] {
154
+ return resource.spec?.excludedResources || []
155
+ }
156
+
157
+ export function getRestoreDuration(resource: any): string {
158
+ const start = resource.status?.startTimestamp
159
+ const end = resource.status?.completionTimestamp
160
+ if (!start) return '-'
161
+ const startDate = new Date(start)
162
+ const endDate = end ? new Date(end) : new Date()
163
+ const diffMs = endDate.getTime() - startDate.getTime()
164
+ if (diffMs < 0) return '-'
165
+ return formatDuration(diffMs, true)
166
+ }
167
+
168
+ export function getRestoreErrors(resource: any): number {
169
+ return resource.status?.errors ?? 0
170
+ }
171
+
172
+ export function getRestoreWarnings(resource: any): number {
173
+ return resource.status?.warnings ?? 0
174
+ }
175
+
176
+ export function getRestorePVs(resource: any): string {
177
+ const val = resource.spec?.restorePVs
178
+ if (val === undefined || val === null) return 'default'
179
+ return val ? 'Yes' : 'No'
180
+ }
181
+
182
+ export function getRestoreExistingResourcePolicy(resource: any): string {
183
+ return resource.spec?.existingResourcePolicy || 'none'
184
+ }
185
+
186
+ // ============================================================================
187
+ // SCHEDULE UTILITIES
188
+ // ============================================================================
189
+
190
+ export function getScheduleStatus(resource: any): StatusBadge {
191
+ const phase = resource.status?.phase || ''
192
+ const isPaused = resource.spec?.paused === true
193
+
194
+ if (isPaused) {
195
+ return { text: 'Paused', color: healthColors.degraded, level: 'degraded' }
196
+ }
197
+
198
+ switch (phase) {
199
+ case 'Enabled':
200
+ return { text: 'Enabled', color: healthColors.healthy, level: 'healthy' }
201
+ case 'FailedValidation':
202
+ return { text: 'FailedValidation', color: healthColors.unhealthy, level: 'unhealthy' }
203
+ default:
204
+ return { text: phase || 'Unknown', color: healthColors.unknown, level: 'unknown' }
205
+ }
206
+ }
207
+
208
+ export function getScheduleCron(resource: any): string {
209
+ return resource.spec?.schedule || '-'
210
+ }
211
+
212
+ export function getScheduleLastBackup(resource: any): string {
213
+ const lastBackup = resource.status?.lastBackup
214
+ if (!lastBackup) return 'Never'
215
+ return formatAge(lastBackup)
216
+ }
217
+
218
+ export function getSchedulePaused(resource: any): boolean {
219
+ return resource.spec?.paused === true
220
+ }
221
+
222
+ export function getScheduleTemplate(resource: any): any {
223
+ return resource.spec?.template || {}
224
+ }
225
+
226
+ export function getScheduleUseOwnerReferences(resource: any): boolean {
227
+ return resource.spec?.useOwnerReferencesInBackup === true
228
+ }
229
+
230
+ // ============================================================================
231
+ // BACKUP STORAGE LOCATION UTILITIES
232
+ // ============================================================================
233
+
234
+ export function getBSLStatus(resource: any): StatusBadge {
235
+ const phase = resource.status?.phase || ''
236
+
237
+ switch (phase) {
238
+ case 'Available':
239
+ return { text: 'Available', color: healthColors.healthy, level: 'healthy' }
240
+ case 'Unavailable':
241
+ return { text: 'Unavailable', color: healthColors.unhealthy, level: 'unhealthy' }
242
+ default:
243
+ return { text: phase || 'Unknown', color: healthColors.unknown, level: 'unknown' }
244
+ }
245
+ }
246
+
247
+ export function getBSLProvider(resource: any): string {
248
+ return resource.spec?.provider || '-'
249
+ }
250
+
251
+ export function getBSLBucket(resource: any): string {
252
+ return resource.spec?.objectStorage?.bucket || '-'
253
+ }
254
+
255
+ export function getBSLPrefix(resource: any): string {
256
+ return resource.spec?.objectStorage?.prefix || '-'
257
+ }
258
+
259
+ export function getBSLRegion(resource: any): string {
260
+ return resource.spec?.config?.region || '-'
261
+ }
262
+
263
+ export function getBSLDefault(resource: any): boolean {
264
+ return resource.spec?.default === true
265
+ }
266
+
267
+ export function getBSLAccessMode(resource: any): string {
268
+ return resource.spec?.accessMode || 'ReadWrite'
269
+ }
270
+
271
+ export function getBSLLastValidation(resource: any): string {
272
+ const lastValidation = resource.status?.lastValidationTime
273
+ if (!lastValidation) return '-'
274
+ return formatAge(lastValidation)
275
+ }
276
+
277
+ export function getBSLLastSynced(resource: any): string {
278
+ const lastSynced = resource.status?.lastSyncedTime
279
+ if (!lastSynced) return '-'
280
+ return formatAge(lastSynced)
281
+ }
282
+
283
+ // ============================================================================
284
+ // VOLUME SNAPSHOT LOCATION UTILITIES
285
+ // ============================================================================
286
+
287
+ export function getVSLProvider(resource: any): string {
288
+ return resource.spec?.provider || '-'
289
+ }
290
+
291
+ export function getVSLConfig(resource: any): Record<string, string> {
292
+ return resource.spec?.config || {}
293
+ }