@skyhook-io/k8s-ui 1.4.2 → 1.4.3

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 (44) hide show
  1. package/package.json +1 -1
  2. package/src/components/resources/ResourcesView.tsx +267 -14
  3. package/src/components/resources/renderers/AWSMachineRenderer.tsx +96 -0
  4. package/src/components/resources/renderers/AWSMachineTemplateRenderer.tsx +39 -0
  5. package/src/components/resources/renderers/AWSManagedClusterRenderer.tsx +49 -0
  6. package/src/components/resources/renderers/AWSManagedControlPlaneRenderer.tsx +174 -0
  7. package/src/components/resources/renderers/AWSManagedMachinePoolRenderer.tsx +89 -0
  8. package/src/components/resources/renderers/AzureMachineRenderer.tsx +41 -0
  9. package/src/components/resources/renderers/AzureManagedControlPlaneRenderer.tsx +71 -0
  10. package/src/components/resources/renderers/AzureManagedMachinePoolRenderer.tsx +106 -0
  11. package/src/components/resources/renderers/CAPIClusterClassRenderer.tsx +156 -0
  12. package/src/components/resources/renderers/CAPIClusterRenderer.tsx +240 -0
  13. package/src/components/resources/renderers/CAPIKubeadmConfigRenderer.tsx +97 -0
  14. package/src/components/resources/renderers/CAPIKubeadmControlPlaneRenderer.tsx +124 -0
  15. package/src/components/resources/renderers/CAPIMachineDeploymentRenderer.tsx +128 -0
  16. package/src/components/resources/renderers/CAPIMachineDrainRuleRenderer.tsx +38 -0
  17. package/src/components/resources/renderers/CAPIMachineHealthCheckRenderer.tsx +146 -0
  18. package/src/components/resources/renderers/CAPIMachinePoolRenderer.tsx +92 -0
  19. package/src/components/resources/renderers/CAPIMachineRenderer.tsx +170 -0
  20. package/src/components/resources/renderers/CAPIMachineSetRenderer.tsx +101 -0
  21. package/src/components/resources/renderers/GCPMachineRenderer.tsx +53 -0
  22. package/src/components/resources/renderers/GCPManagedControlPlaneRenderer.tsx +75 -0
  23. package/src/components/resources/renderers/GCPManagedMachinePoolRenderer.tsx +102 -0
  24. package/src/components/resources/renderers/aws-capi-cells.tsx +117 -0
  25. package/src/components/resources/renderers/azure-capi-cells.tsx +83 -0
  26. package/src/components/resources/renderers/capi-cells.tsx +158 -0
  27. package/src/components/resources/renderers/gcp-capi-cells.tsx +68 -0
  28. package/src/components/resources/renderers/index.ts +25 -0
  29. package/src/components/resources/resource-utils-aws-capi.ts +211 -0
  30. package/src/components/resources/resource-utils-azure-capi.ts +123 -0
  31. package/src/components/resources/resource-utils-capi.ts +305 -0
  32. package/src/components/resources/resource-utils-gcp-capi.ts +130 -0
  33. package/src/components/shared/ResourceRendererDispatch.tsx +97 -2
  34. package/src/components/topology/K8sResourceNode.tsx +8 -0
  35. package/src/components/topology/TopologyControls.tsx +16 -0
  36. package/src/components/topology/TopologyFilterSidebar.tsx +15 -0
  37. package/src/components/topology/TopologyGraph.tsx +2 -1
  38. package/src/components/topology/layout.ts +11 -0
  39. package/src/components/topology/topology.css +29 -0
  40. package/src/components/ui/Badge.tsx +10 -0
  41. package/src/components/ui/drawer-components.tsx +54 -17
  42. package/src/types/core.ts +18 -2
  43. package/src/utils/api-resources.ts +4 -0
  44. package/src/utils/resource-icons.ts +35 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skyhook-io/k8s-ui",
3
- "version": "1.4.2",
3
+ "version": "1.4.3",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/skyhook-io/radar",
@@ -139,6 +139,10 @@ import { VirtualServiceCell, DestinationRuleCell, IstioGatewayCell, ServiceEntry
139
139
  import { KnativeServiceCell, ConfigurationCell as KnativeConfigurationCell, RevisionCell as KnativeRevisionCell, RouteCell as KnativeRouteCell, BrokerCell, TriggerCell, EventTypeCell, PingSourceCell, ApiServerSourceCell, ContainerSourceCell, SinkBindingCell, ChannelCell, InMemoryChannelCell, SubscriptionCell, SequenceCell, ParallelCell, DomainMappingCell, ServerlessServiceCell, KnativeIngressCell, KnativeCertificateCell } from './renderers/knative-cells'
140
140
  import { IngressRouteCell, MiddlewareCell, TraefikServiceCell, ServersTransportCell, TLSOptionCell } from './renderers/traefik-cells'
141
141
  import { HTTPProxyCell } from './renderers/contour-cells'
142
+ import { CAPIClusterCell, CAPIMachineCell, CAPIMachineDeploymentCell, CAPIMachineSetCell, CAPIMachinePoolCell, CAPIKubeadmControlPlaneCell, CAPIClusterClassCell, CAPIMachineHealthCheckCell } from './renderers/capi-cells'
143
+ import { AWSManagedControlPlaneCell, AWSManagedMachinePoolCell, AWSMachineCell, AWSMachineTemplateCell, AWSManagedClusterCell } from './renderers/aws-capi-cells'
144
+ import { GCPManagedControlPlaneCell, GCPManagedMachinePoolCell, GCPMachineCell, GCPMachineTemplateCell, GCPManagedClusterCell } from './renderers/gcp-capi-cells'
145
+ import { AzureManagedControlPlaneCell, AzureManagedMachinePoolCell, AzureMachineCell, AzureMachineTemplateCell, AzureManagedClusterCell } from './renderers/azure-capi-cells'
142
146
  import { useRegisterShortcut, useRegisterShortcuts } from '../../hooks/useKeyboardShortcuts'
143
147
  import { ResourcesSidebar } from './ResourcesSidebar'
144
148
  import type { SelectedKindInfo } from './ResourcesSidebar'
@@ -264,7 +268,7 @@ const KNOWN_COLUMNS: Record<string, Column[]> = {
264
268
  { key: 'rules', label: 'Rules', width: 'min-w-56', hideOnMobile: true },
265
269
  { key: 'tls', label: 'TLS', width: 'w-14 shrink-0' },
266
270
  { key: 'address', label: 'Address', width: 'min-w-32', hideOnMobile: true },
267
- { key: 'age', label: 'Age', width: 'w-16 shrink-0' },
271
+ { key: 'age', label: 'Age', width: 'w-20 shrink-0' },
268
272
  ],
269
273
  nodes: [
270
274
  { key: 'name', label: 'Name' },
@@ -969,7 +973,7 @@ const KNOWN_COLUMNS: Record<string, Column[]> = {
969
973
  // ============================================================================
970
974
  // CLOUDNATIVEPG (CNPG) POSTGRESQL
971
975
  // ============================================================================
972
- clusters: [
976
+ cnpgclusters: [
973
977
  { key: 'name', label: 'Name' },
974
978
  { key: 'namespace', label: 'Namespace', width: 'w-36' },
975
979
  { key: 'status', label: 'Status', width: 'w-28' },
@@ -1217,7 +1221,7 @@ const KNOWN_COLUMNS: Record<string, Column[]> = {
1217
1221
  { key: 'routes', label: 'Routes', width: 'min-w-48', hideOnMobile: true },
1218
1222
  { key: 'tls', label: 'TLS', width: 'w-14 shrink-0' },
1219
1223
  { key: 'middlewares', label: 'MW', width: 'w-14 shrink-0', tooltip: 'Unique middleware count' },
1220
- { key: 'age', label: 'Age', width: 'w-16 shrink-0' },
1224
+ { key: 'age', label: 'Age', width: 'w-20 shrink-0' },
1221
1225
  ],
1222
1226
  ingressroutetcps: [
1223
1227
  { key: 'name', label: 'Name', width: 'min-w-40' },
@@ -1227,58 +1231,249 @@ const KNOWN_COLUMNS: Record<string, Column[]> = {
1227
1231
  { key: 'routes', label: 'Routes', width: 'min-w-48', hideOnMobile: true },
1228
1232
  { key: 'tls', label: 'TLS', width: 'w-14 shrink-0' },
1229
1233
  { key: 'middlewares', label: 'MW', width: 'w-14 shrink-0', tooltip: 'Unique middleware count' },
1230
- { key: 'age', label: 'Age', width: 'w-16 shrink-0' },
1234
+ { key: 'age', label: 'Age', width: 'w-20 shrink-0' },
1231
1235
  ],
1232
1236
  ingressrouteudps: [
1233
1237
  { key: 'name', label: 'Name', width: 'min-w-40' },
1234
1238
  { key: 'namespace', label: 'Namespace', width: 'w-36 shrink-0' },
1235
1239
  { key: 'entrypoints', label: 'Entry Points', width: 'w-32 shrink-0' },
1236
1240
  { key: 'routes', label: 'Routes', width: 'min-w-48' },
1237
- { key: 'age', label: 'Age', width: 'w-16 shrink-0' },
1241
+ { key: 'age', label: 'Age', width: 'w-20 shrink-0' },
1238
1242
  ],
1239
1243
  middlewares: [
1240
1244
  { key: 'name', label: 'Name', width: 'min-w-40' },
1241
1245
  { key: 'namespace', label: 'Namespace', width: 'w-36 shrink-0' },
1242
1246
  { key: 'type', label: 'Type', width: 'w-32 shrink-0' },
1243
- { key: 'age', label: 'Age', width: 'w-16 shrink-0' },
1247
+ { key: 'age', label: 'Age', width: 'w-20 shrink-0' },
1244
1248
  ],
1245
1249
  middlewaretcps: [
1246
1250
  { key: 'name', label: 'Name', width: 'min-w-40' },
1247
1251
  { key: 'namespace', label: 'Namespace', width: 'w-36 shrink-0' },
1248
1252
  { key: 'type', label: 'Type', width: 'w-32 shrink-0' },
1249
- { key: 'age', label: 'Age', width: 'w-16 shrink-0' },
1253
+ { key: 'age', label: 'Age', width: 'w-20 shrink-0' },
1250
1254
  ],
1251
1255
  traefikservices: [
1252
1256
  { key: 'name', label: 'Name', width: 'min-w-40' },
1253
1257
  { key: 'namespace', label: 'Namespace', width: 'w-36 shrink-0' },
1254
1258
  { key: 'type', label: 'Type', width: 'w-36 shrink-0' },
1255
1259
  { key: 'targets', label: 'Targets', width: 'min-w-48' },
1256
- { key: 'age', label: 'Age', width: 'w-16 shrink-0' },
1260
+ { key: 'age', label: 'Age', width: 'w-20 shrink-0' },
1257
1261
  ],
1258
1262
  serverstransports: [
1259
1263
  { key: 'name', label: 'Name', width: 'min-w-40' },
1260
1264
  { key: 'namespace', label: 'Namespace', width: 'w-36 shrink-0' },
1261
1265
  { key: 'serverName', label: 'Server Name', width: 'w-40' },
1262
1266
  { key: 'insecure', label: 'Skip Verify', width: 'w-24 shrink-0' },
1263
- { key: 'age', label: 'Age', width: 'w-16 shrink-0' },
1267
+ { key: 'age', label: 'Age', width: 'w-20 shrink-0' },
1264
1268
  ],
1265
1269
  serverstransporttcps: [
1266
1270
  { key: 'name', label: 'Name', width: 'min-w-40' },
1267
1271
  { key: 'namespace', label: 'Namespace', width: 'w-36 shrink-0' },
1268
1272
  { key: 'serverName', label: 'Server Name', width: 'w-40' },
1269
1273
  { key: 'insecure', label: 'Skip Verify', width: 'w-24 shrink-0' },
1270
- { key: 'age', label: 'Age', width: 'w-16 shrink-0' },
1274
+ { key: 'age', label: 'Age', width: 'w-20 shrink-0' },
1271
1275
  ],
1272
1276
  tlsoptions: [
1273
1277
  { key: 'name', label: 'Name', width: 'min-w-40' },
1274
1278
  { key: 'namespace', label: 'Namespace', width: 'w-36 shrink-0' },
1275
1279
  { key: 'minVersion', label: 'Min TLS', width: 'w-24 shrink-0' },
1276
- { key: 'age', label: 'Age', width: 'w-16 shrink-0' },
1280
+ { key: 'age', label: 'Age', width: 'w-20 shrink-0' },
1277
1281
  ],
1278
1282
  tlsstores: [
1279
1283
  { key: 'name', label: 'Name', width: 'min-w-40' },
1280
1284
  { key: 'namespace', label: 'Namespace', width: 'w-36 shrink-0' },
1281
- { key: 'age', label: 'Age', width: 'w-16 shrink-0' },
1285
+ { key: 'age', label: 'Age', width: 'w-20 shrink-0' },
1286
+ ],
1287
+ // Cluster API (CAPI)
1288
+ capiclusters: [
1289
+ { key: 'name', label: 'Name', width: 'min-w-40' },
1290
+ { key: 'namespace', label: 'Namespace', width: 'w-36 shrink-0' },
1291
+ { key: 'provider', label: 'Provider', width: 'w-20 shrink-0' },
1292
+ { key: 'class', label: 'Class', width: 'w-32 shrink-0' },
1293
+ { key: 'cpReplicas', label: 'CP Ready', width: 'w-24 shrink-0', tooltip: 'Control plane replicas (ready/desired)' },
1294
+ { key: 'workerReplicas', label: 'Workers', width: 'w-20 shrink-0', tooltip: 'Worker replicas (ready/desired)' },
1295
+ { key: 'phase', label: 'Phase', width: 'w-28 shrink-0' },
1296
+ { key: 'version', label: 'Version', width: 'w-24 shrink-0' },
1297
+ { key: 'age', label: 'Age', width: 'w-20 shrink-0' },
1298
+ ],
1299
+ machinedeployments: [
1300
+ { key: 'name', label: 'Name', width: 'min-w-40' },
1301
+ { key: 'namespace', label: 'Namespace', width: 'w-36 shrink-0' },
1302
+ { key: 'cluster', label: 'Cluster', width: 'w-32 shrink-0' },
1303
+ { key: 'ready', label: 'Ready', width: 'w-20 shrink-0', tooltip: 'Ready replicas / desired' },
1304
+ { key: 'phase', label: 'Phase', width: 'w-28 shrink-0' },
1305
+ { key: 'version', label: 'Version', width: 'w-24 shrink-0' },
1306
+ { key: 'age', label: 'Age', width: 'w-20 shrink-0' },
1307
+ ],
1308
+ machines: [
1309
+ { key: 'name', label: 'Name', width: 'min-w-40' },
1310
+ { key: 'namespace', label: 'Namespace', width: 'w-36 shrink-0' },
1311
+ { key: 'cluster', label: 'Cluster', width: 'w-32 shrink-0' },
1312
+ { key: 'role', label: 'Role', width: 'w-28 shrink-0' },
1313
+ { key: 'phase', label: 'Phase', width: 'w-28 shrink-0' },
1314
+ { key: 'node', label: 'Node', width: 'w-32 shrink-0' },
1315
+ { key: 'version', label: 'Version', width: 'w-24 shrink-0' },
1316
+ { key: 'age', label: 'Age', width: 'w-20 shrink-0' },
1317
+ ],
1318
+ machinesets: [
1319
+ { key: 'name', label: 'Name', width: 'min-w-40' },
1320
+ { key: 'namespace', label: 'Namespace', width: 'w-36 shrink-0' },
1321
+ { key: 'cluster', label: 'Cluster', width: 'w-32 shrink-0' },
1322
+ { key: 'ready', label: 'Ready', width: 'w-20 shrink-0' },
1323
+ { key: 'phase', label: 'Phase', width: 'w-28 shrink-0' },
1324
+ { key: 'age', label: 'Age', width: 'w-20 shrink-0' },
1325
+ ],
1326
+ machinepools: [
1327
+ { key: 'name', label: 'Name', width: 'min-w-40' },
1328
+ { key: 'namespace', label: 'Namespace', width: 'w-36 shrink-0' },
1329
+ { key: 'cluster', label: 'Cluster', width: 'w-32 shrink-0' },
1330
+ { key: 'ready', label: 'Ready', width: 'w-20 shrink-0' },
1331
+ { key: 'phase', label: 'Phase', width: 'w-28 shrink-0' },
1332
+ { key: 'age', label: 'Age', width: 'w-20 shrink-0' },
1333
+ ],
1334
+ kubeadmcontrolplanes: [
1335
+ { key: 'name', label: 'Name', width: 'min-w-40' },
1336
+ { key: 'namespace', label: 'Namespace', width: 'w-36 shrink-0' },
1337
+ { key: 'cluster', label: 'Cluster', width: 'w-32 shrink-0' },
1338
+ { key: 'ready', label: 'Ready', width: 'w-20 shrink-0' },
1339
+ { key: 'initialized', label: 'Initialized', width: 'w-24 shrink-0' },
1340
+ { key: 'version', label: 'Version', width: 'w-24 shrink-0' },
1341
+ { key: 'age', label: 'Age', width: 'w-20 shrink-0' },
1342
+ ],
1343
+ clusterclasses: [
1344
+ { key: 'name', label: 'Name', width: 'min-w-40' },
1345
+ { key: 'namespace', label: 'Namespace', width: 'w-36 shrink-0' },
1346
+ { key: 'status', label: 'Status', width: 'w-28 shrink-0' },
1347
+ { key: 'age', label: 'Age', width: 'w-20 shrink-0' },
1348
+ ],
1349
+ machinehealthchecks: [
1350
+ { key: 'name', label: 'Name', width: 'min-w-40' },
1351
+ { key: 'namespace', label: 'Namespace', width: 'w-36 shrink-0' },
1352
+ { key: 'cluster', label: 'Cluster', width: 'w-32 shrink-0' },
1353
+ { key: 'healthy', label: 'Healthy', width: 'w-20 shrink-0', tooltip: 'Healthy machines / expected' },
1354
+ { key: 'status', label: 'Status', width: 'w-28 shrink-0' },
1355
+ { key: 'age', label: 'Age', width: 'w-20 shrink-0' },
1356
+ ],
1357
+ // AWS CAPI Infrastructure Provider
1358
+ awsmanagedcontrolplanes: [
1359
+ { key: 'name', label: 'Name', width: 'min-w-40' },
1360
+ { key: 'namespace', label: 'Namespace', width: 'w-36 shrink-0' },
1361
+ { key: 'eksCluster', label: 'EKS Cluster', width: 'w-36 shrink-0' },
1362
+ { key: 'region', label: 'Region', width: 'w-28 shrink-0' },
1363
+ { key: 'version', label: 'Version', width: 'w-24 shrink-0' },
1364
+ { key: 'status', label: 'Status', width: 'w-28 shrink-0' },
1365
+ { key: 'age', label: 'Age', width: 'w-20 shrink-0' },
1366
+ ],
1367
+ awsmanagedmachinepools: [
1368
+ { key: 'name', label: 'Name', width: 'min-w-40' },
1369
+ { key: 'namespace', label: 'Namespace', width: 'w-36 shrink-0' },
1370
+ { key: 'instanceType', label: 'Instance', width: 'w-28 shrink-0' },
1371
+ { key: 'replicas', label: 'Ready', width: 'w-20 shrink-0', tooltip: 'Ready replicas' },
1372
+ { key: 'capacityType', label: 'Capacity', width: 'w-28 shrink-0' },
1373
+ { key: 'status', label: 'Status', width: 'w-28 shrink-0' },
1374
+ { key: 'age', label: 'Age', width: 'w-20 shrink-0' },
1375
+ ],
1376
+ awsmachines: [
1377
+ { key: 'name', label: 'Name', width: 'min-w-40' },
1378
+ { key: 'namespace', label: 'Namespace', width: 'w-36 shrink-0' },
1379
+ { key: 'instanceType', label: 'Instance', width: 'w-28 shrink-0' },
1380
+ { key: 'instanceState', label: 'State', width: 'w-24 shrink-0' },
1381
+ { key: 'instanceID', label: 'Instance ID', width: 'w-40 shrink-0' },
1382
+ { key: 'status', label: 'Status', width: 'w-28 shrink-0' },
1383
+ { key: 'age', label: 'Age', width: 'w-20 shrink-0' },
1384
+ ],
1385
+ awsmachinetemplates: [
1386
+ { key: 'name', label: 'Name', width: 'min-w-40' },
1387
+ { key: 'namespace', label: 'Namespace', width: 'w-36 shrink-0' },
1388
+ { key: 'instanceType', label: 'Instance', width: 'w-28 shrink-0' },
1389
+ { key: 'capacity', label: 'Capacity', width: 'w-32 shrink-0', tooltip: 'Computed CPU/memory' },
1390
+ { key: 'age', label: 'Age', width: 'w-20 shrink-0' },
1391
+ ],
1392
+ awsmanagedclusters: [
1393
+ { key: 'name', label: 'Name', width: 'min-w-40' },
1394
+ { key: 'namespace', label: 'Namespace', width: 'w-36 shrink-0' },
1395
+ { key: 'endpoint', label: 'Endpoint', width: 'min-w-44' },
1396
+ { key: 'status', label: 'Status', width: 'w-28 shrink-0' },
1397
+ { key: 'age', label: 'Age', width: 'w-20 shrink-0' },
1398
+ ],
1399
+ // GCP CAPI Infrastructure Provider
1400
+ gcpmanagedcontrolplanes: [
1401
+ { key: 'name', label: 'Name', width: 'min-w-40' },
1402
+ { key: 'namespace', label: 'Namespace', width: 'w-36 shrink-0' },
1403
+ { key: 'gkeCluster', label: 'GKE Cluster', width: 'w-36 shrink-0' },
1404
+ { key: 'project', label: 'Project', width: 'w-36 shrink-0' },
1405
+ { key: 'location', label: 'Location', width: 'w-28 shrink-0' },
1406
+ { key: 'version', label: 'Version', width: 'w-24 shrink-0' },
1407
+ { key: 'status', label: 'Status', width: 'w-28 shrink-0' },
1408
+ { key: 'age', label: 'Age', width: 'w-20 shrink-0' },
1409
+ ],
1410
+ gcpmanagedmachinepools: [
1411
+ { key: 'name', label: 'Name', width: 'min-w-40' },
1412
+ { key: 'namespace', label: 'Namespace', width: 'w-36 shrink-0' },
1413
+ { key: 'machineType', label: 'Machine Type', width: 'w-32 shrink-0' },
1414
+ { key: 'replicas', label: 'Replicas', width: 'w-20 shrink-0' },
1415
+ { key: 'status', label: 'Status', width: 'w-28 shrink-0' },
1416
+ { key: 'age', label: 'Age', width: 'w-20 shrink-0' },
1417
+ ],
1418
+ gcpmachines: [
1419
+ { key: 'name', label: 'Name', width: 'min-w-40' },
1420
+ { key: 'namespace', label: 'Namespace', width: 'w-36 shrink-0' },
1421
+ { key: 'instanceType', label: 'Instance', width: 'w-28 shrink-0' },
1422
+ { key: 'zone', label: 'Zone', width: 'w-28 shrink-0' },
1423
+ { key: 'status', label: 'Status', width: 'w-28 shrink-0' },
1424
+ { key: 'age', label: 'Age', width: 'w-20 shrink-0' },
1425
+ ],
1426
+ gcpmachinetemplates: [
1427
+ { key: 'name', label: 'Name', width: 'min-w-40' },
1428
+ { key: 'namespace', label: 'Namespace', width: 'w-36 shrink-0' },
1429
+ { key: 'instanceType', label: 'Instance', width: 'w-28 shrink-0' },
1430
+ { key: 'age', label: 'Age', width: 'w-20 shrink-0' },
1431
+ ],
1432
+ gcpmanagedclusters: [
1433
+ { key: 'name', label: 'Name', width: 'min-w-40' },
1434
+ { key: 'namespace', label: 'Namespace', width: 'w-36 shrink-0' },
1435
+ { key: 'project', label: 'Project', width: 'w-36 shrink-0' },
1436
+ { key: 'status', label: 'Status', width: 'w-28 shrink-0' },
1437
+ { key: 'age', label: 'Age', width: 'w-20 shrink-0' },
1438
+ ],
1439
+ // Azure CAPI Infrastructure Provider
1440
+ azuremanagedcontrolplanes: [
1441
+ { key: 'name', label: 'Name', width: 'min-w-40' },
1442
+ { key: 'namespace', label: 'Namespace', width: 'w-36 shrink-0' },
1443
+ { key: 'location', label: 'Location', width: 'w-28 shrink-0' },
1444
+ { key: 'resourceGroup', label: 'Resource Group', width: 'w-40 shrink-0' },
1445
+ { key: 'version', label: 'Version', width: 'w-24 shrink-0' },
1446
+ { key: 'status', label: 'Status', width: 'w-28 shrink-0' },
1447
+ { key: 'age', label: 'Age', width: 'w-20 shrink-0' },
1448
+ ],
1449
+ azuremanagedmachinepools: [
1450
+ { key: 'name', label: 'Name', width: 'min-w-40' },
1451
+ { key: 'namespace', label: 'Namespace', width: 'w-36 shrink-0' },
1452
+ { key: 'sku', label: 'VM Size', width: 'w-32 shrink-0' },
1453
+ { key: 'mode', label: 'Mode', width: 'w-20 shrink-0' },
1454
+ { key: 'replicas', label: 'Replicas', width: 'w-20 shrink-0' },
1455
+ { key: 'priority', label: 'Priority', width: 'w-24 shrink-0' },
1456
+ { key: 'status', label: 'Status', width: 'w-28 shrink-0' },
1457
+ { key: 'age', label: 'Age', width: 'w-20 shrink-0' },
1458
+ ],
1459
+ azuremachines: [
1460
+ { key: 'name', label: 'Name', width: 'min-w-40' },
1461
+ { key: 'namespace', label: 'Namespace', width: 'w-36 shrink-0' },
1462
+ { key: 'vmSize', label: 'VM Size', width: 'w-32 shrink-0' },
1463
+ { key: 'status', label: 'Status', width: 'w-28 shrink-0' },
1464
+ { key: 'age', label: 'Age', width: 'w-20 shrink-0' },
1465
+ ],
1466
+ azuremachinetemplates: [
1467
+ { key: 'name', label: 'Name', width: 'min-w-40' },
1468
+ { key: 'namespace', label: 'Namespace', width: 'w-36 shrink-0' },
1469
+ { key: 'vmSize', label: 'VM Size', width: 'w-32 shrink-0' },
1470
+ { key: 'age', label: 'Age', width: 'w-20 shrink-0' },
1471
+ ],
1472
+ azuremanagedclusters: [
1473
+ { key: 'name', label: 'Name', width: 'min-w-40' },
1474
+ { key: 'namespace', label: 'Namespace', width: 'w-36 shrink-0' },
1475
+ { key: 'status', label: 'Status', width: 'w-28 shrink-0' },
1476
+ { key: 'age', label: 'Age', width: 'w-20 shrink-0' },
1282
1477
  ],
1283
1478
  // Contour
1284
1479
  httpproxies: [
@@ -1288,13 +1483,14 @@ const KNOWN_COLUMNS: Record<string, Column[]> = {
1288
1483
  { key: 'routes', label: 'Routes', width: 'w-20 shrink-0' },
1289
1484
  { key: 'includes', label: 'Includes', width: 'w-24 shrink-0' },
1290
1485
  { key: 'tls', label: 'TLS', width: 'w-14 shrink-0' },
1291
- { key: 'status', label: 'Status', width: 'w-24 shrink-0' },
1292
- { key: 'age', label: 'Age', width: 'w-16 shrink-0' },
1486
+ { key: 'status', label: 'Status', width: 'w-28 shrink-0' },
1487
+ { key: 'age', label: 'Age', width: 'w-20 shrink-0' },
1293
1488
  ],
1294
1489
  }
1295
1490
 
1296
1491
  // Map (plural, group) → KNOWN_COLUMNS key for kinds that collide with core K8s
1297
1492
  const GROUP_QUALIFIED_COLUMN_KEYS: Record<string, Record<string, string>> = {
1493
+ clusters: { 'postgresql.cnpg.io': 'cnpgclusters', 'cluster.x-k8s.io': 'capiclusters' },
1298
1494
  services: { 'serving.knative.dev': 'knativeservices' },
1299
1495
  configurations: { 'serving.knative.dev': 'knativeconfigurations' },
1300
1496
  revisions: { 'serving.knative.dev': 'knativerevisions' },
@@ -3804,6 +4000,7 @@ function CellContent({ resource, kind, column, group, majorityNodeMinorVersion }
3804
4000
  case 'backupstoragelocations':
3805
4001
  return <BackupStorageLocationCell resource={resource} column={column} />
3806
4002
  // CloudNativePG
4003
+ case 'cnpgclusters':
3807
4004
  case 'clusters':
3808
4005
  return <CNPGClusterCell resource={resource} column={column} />
3809
4006
  case 'scheduledbackups':
@@ -3885,6 +4082,62 @@ function CellContent({ resource, kind, column, group, majorityNodeMinorVersion }
3885
4082
  // Contour
3886
4083
  case 'httpproxies':
3887
4084
  return <HTTPProxyCell resource={resource} column={column} />
4085
+ // Cluster API (CAPI)
4086
+ case 'capiclusters':
4087
+ return <CAPIClusterCell resource={resource} column={column} />
4088
+ case 'machines':
4089
+ return <CAPIMachineCell resource={resource} column={column} />
4090
+ case 'machinedeployments':
4091
+ return <CAPIMachineDeploymentCell resource={resource} column={column} />
4092
+ case 'machinesets':
4093
+ return <CAPIMachineSetCell resource={resource} column={column} />
4094
+ case 'machinepools':
4095
+ return <CAPIMachinePoolCell resource={resource} column={column} />
4096
+ case 'kubeadmcontrolplanes':
4097
+ return <CAPIKubeadmControlPlaneCell resource={resource} column={column} />
4098
+ case 'clusterclasses':
4099
+ return <CAPIClusterClassCell resource={resource} column={column} />
4100
+ case 'machinehealthchecks':
4101
+ return <CAPIMachineHealthCheckCell resource={resource} column={column} />
4102
+ case 'machinedrainrules':
4103
+ case 'kubeadmconfigs':
4104
+ case 'kubeadmconfigtemplates':
4105
+ case 'kubeadmcontrolplanetemplates':
4106
+ // These use default columns — no custom cell renderer needed
4107
+ return <GenericCell resource={resource} column={column} />
4108
+ // AWS CAPI Infrastructure Provider
4109
+ case 'awsmanagedcontrolplanes':
4110
+ return <AWSManagedControlPlaneCell resource={resource} column={column} />
4111
+ case 'awsmanagedmachinepools':
4112
+ return <AWSManagedMachinePoolCell resource={resource} column={column} />
4113
+ case 'awsmachines':
4114
+ return <AWSMachineCell resource={resource} column={column} />
4115
+ case 'awsmachinetemplates':
4116
+ return <AWSMachineTemplateCell resource={resource} column={column} />
4117
+ case 'awsmanagedclusters':
4118
+ return <AWSManagedClusterCell resource={resource} column={column} />
4119
+ // GCP CAPI Infrastructure
4120
+ case 'gcpmanagedcontrolplanes':
4121
+ return <GCPManagedControlPlaneCell resource={resource} column={column} />
4122
+ case 'gcpmanagedmachinepools':
4123
+ return <GCPManagedMachinePoolCell resource={resource} column={column} />
4124
+ case 'gcpmachines':
4125
+ return <GCPMachineCell resource={resource} column={column} />
4126
+ case 'gcpmachinetemplates':
4127
+ return <GCPMachineTemplateCell resource={resource} column={column} />
4128
+ case 'gcpmanagedclusters':
4129
+ return <GCPManagedClusterCell resource={resource} column={column} />
4130
+ // Azure CAPI Infrastructure
4131
+ case 'azuremanagedcontrolplanes':
4132
+ return <AzureManagedControlPlaneCell resource={resource} column={column} />
4133
+ case 'azuremanagedmachinepools':
4134
+ return <AzureManagedMachinePoolCell resource={resource} column={column} />
4135
+ case 'azuremachines':
4136
+ return <AzureMachineCell resource={resource} column={column} />
4137
+ case 'azuremachinetemplates':
4138
+ return <AzureMachineTemplateCell resource={resource} column={column} />
4139
+ case 'azuremanagedclusters':
4140
+ return <AzureManagedClusterCell resource={resource} column={column} />
3888
4141
  default:
3889
4142
  // Generic cell for CRDs and unknown resources
3890
4143
  return <GenericCell resource={resource} column={column} />
@@ -0,0 +1,96 @@
1
+ import { Cpu, Network, Cloud } from 'lucide-react'
2
+ import { clsx } from 'clsx'
3
+ import { Section, PropertyList, Property, ConditionsSection, AlertBanner } from '../../ui/drawer-components'
4
+ import { getCAPIConditions } from '../resource-utils-capi'
5
+ import { getAWSMachineStatus, getAWSMachineInstanceType, getAWSMachineInstanceState, getAWSMachineInstanceID } from '../resource-utils-aws-capi'
6
+
7
+ interface Props {
8
+ data: any
9
+ onNavigate?: (ref: { kind: string; namespace: string; name: string; group?: string }) => void
10
+ }
11
+
12
+ export function AWSMachineRenderer({ data }: Props) {
13
+ const spec = data.spec || {}
14
+ const status = data.status || {}
15
+ const conditions = getCAPIConditions(data)
16
+
17
+ const machineStatus = getAWSMachineStatus(data)
18
+ const isFailed = machineStatus.level === 'unhealthy'
19
+ const readyCond = conditions.find((c: any) => c.type === 'Ready')
20
+
21
+ const instanceState = getAWSMachineInstanceState(data)
22
+ const addresses = status.addresses || []
23
+
24
+ return (
25
+ <>
26
+ {isFailed && (
27
+ <AlertBanner
28
+ variant="error"
29
+ title="AWS Machine Not Ready"
30
+ message={readyCond?.message || 'AWSMachine is not ready.'}
31
+ />
32
+ )}
33
+
34
+ <Section title="Instance" icon={Cloud}>
35
+ <PropertyList>
36
+ <Property label="Instance Type" value={getAWSMachineInstanceType(data)} />
37
+ <Property label="Instance ID" value={
38
+ <span className="font-mono text-[11px]">{getAWSMachineInstanceID(data)}</span>
39
+ } />
40
+ <Property label="State" value={
41
+ <span className={clsx('badge badge-sm', instanceState === 'running'
42
+ ? 'status-healthy'
43
+ : instanceState === 'pending' || instanceState === 'stopping' || instanceState === 'stopped'
44
+ ? 'status-degraded'
45
+ : instanceState === 'terminated' || instanceState === 'shutting-down'
46
+ ? 'status-unhealthy'
47
+ : 'status-neutral'
48
+ )}>{instanceState}</span>
49
+ } />
50
+ {spec.providerID && spec.providerID !== '-' && (
51
+ <Property label="Provider ID" value={
52
+ <span className="font-mono text-[10px] break-all">{spec.providerID}</span>
53
+ } />
54
+ )}
55
+ </PropertyList>
56
+ </Section>
57
+
58
+ <Section title="Configuration" icon={Cpu}>
59
+ <PropertyList>
60
+ {spec.iamInstanceProfile && <Property label="IAM Profile" value={spec.iamInstanceProfile} />}
61
+ {spec.sshKeyName && <Property label="SSH Key" value={spec.sshKeyName} />}
62
+ {spec.subnet?.id && (
63
+ <Property label="Subnet" value={<span className="font-mono text-[11px]">{spec.subnet.id}</span>} />
64
+ )}
65
+ {spec.cloudInit?.secureSecretsBackend && (
66
+ <Property label="Secrets Backend" value={spec.cloudInit.secureSecretsBackend} />
67
+ )}
68
+ </PropertyList>
69
+ </Section>
70
+
71
+ {/* Addresses */}
72
+ {addresses.length > 0 && (
73
+ <Section title="Addresses" icon={Network}>
74
+ <table className="w-full text-xs">
75
+ <thead>
76
+ <tr className="text-theme-text-tertiary">
77
+ <th className="text-left font-medium py-1">Type</th>
78
+ <th className="text-left font-medium py-1">Address</th>
79
+ </tr>
80
+ </thead>
81
+ <tbody>
82
+ {addresses.map((addr: any, i: number) => (
83
+ <tr key={i} className="border-t border-theme-border">
84
+ <td className="py-1 text-theme-text-secondary">{addr.type}</td>
85
+ <td className="py-1 text-theme-text-secondary font-mono">{addr.address}</td>
86
+ </tr>
87
+ ))}
88
+ </tbody>
89
+ </table>
90
+ </Section>
91
+ )}
92
+
93
+ <ConditionsSection conditions={conditions} />
94
+ </>
95
+ )
96
+ }
@@ -0,0 +1,39 @@
1
+ import { Cpu, Server } from 'lucide-react'
2
+ import { Section, PropertyList, Property } from '../../ui/drawer-components'
3
+ import { getAWSMTInstanceType } from '../resource-utils-aws-capi'
4
+
5
+ interface Props {
6
+ data: any
7
+ }
8
+
9
+ export function AWSMachineTemplateRenderer({ data }: Props) {
10
+ const templateSpec = data.spec?.template?.spec || {}
11
+ const status = data.status || {}
12
+
13
+ return (
14
+ <>
15
+ <Section title="Template Spec" icon={Cpu}>
16
+ <PropertyList>
17
+ <Property label="Instance Type" value={getAWSMTInstanceType(data)} />
18
+ {templateSpec.subnet?.id && (
19
+ <Property label="Subnet" value={<span className="font-mono text-[11px]">{templateSpec.subnet.id}</span>} />
20
+ )}
21
+ {templateSpec.iamInstanceProfile && <Property label="IAM Profile" value={templateSpec.iamInstanceProfile} />}
22
+ {templateSpec.sshKeyName && <Property label="SSH Key" value={templateSpec.sshKeyName} />}
23
+ </PropertyList>
24
+ </Section>
25
+
26
+ {/* Resolved capacity from status */}
27
+ {(status.capacity || status.nodeInfo) && (
28
+ <Section title="Resolved Info" icon={Server}>
29
+ <PropertyList>
30
+ {status.capacity?.cpu && <Property label="CPU" value={status.capacity.cpu} />}
31
+ {status.capacity?.memory && <Property label="Memory" value={status.capacity.memory} />}
32
+ {status.nodeInfo?.architecture && <Property label="Architecture" value={status.nodeInfo.architecture} />}
33
+ {status.nodeInfo?.operatingSystem && <Property label="OS" value={status.nodeInfo.operatingSystem} />}
34
+ </PropertyList>
35
+ </Section>
36
+ )}
37
+ </>
38
+ )
39
+ }
@@ -0,0 +1,49 @@
1
+ import { Globe, Server } from 'lucide-react'
2
+ import { Section, PropertyList, Property, ConditionsSection, AlertBanner } from '../../ui/drawer-components'
3
+ import { getCAPIConditions } from '../resource-utils-capi'
4
+ import { getAWSManagedClusterStatus, getAWSManagedClusterEndpoint, getAWSManagedClusterFailureDomains } from '../resource-utils-aws-capi'
5
+
6
+ interface Props {
7
+ data: any
8
+ }
9
+
10
+ export function AWSManagedClusterRenderer({ data }: Props) {
11
+ const conditions = getCAPIConditions(data)
12
+ const clusterStatus = getAWSManagedClusterStatus(data)
13
+ const isFailed = clusterStatus.level === 'unhealthy'
14
+ const readyCond = conditions.find((c: any) => c.type === 'Ready')
15
+ const failureDomains = getAWSManagedClusterFailureDomains(data)
16
+ const endpoint = getAWSManagedClusterEndpoint(data)
17
+
18
+ return (
19
+ <>
20
+ {isFailed && (
21
+ <AlertBanner
22
+ variant="error"
23
+ title="Managed Cluster Not Ready"
24
+ message={readyCond?.message || 'AWSManagedCluster is not ready.'}
25
+ />
26
+ )}
27
+
28
+ <Section title="Overview" icon={Globe}>
29
+ <PropertyList>
30
+ {endpoint !== '-' && (
31
+ <Property label="Endpoint" value={<span className="font-mono text-[10px] break-all">{endpoint}</span>} />
32
+ )}
33
+ </PropertyList>
34
+ </Section>
35
+
36
+ {failureDomains.length > 0 && (
37
+ <Section title="Failure Domains" icon={Server}>
38
+ <div className="flex flex-wrap gap-1">
39
+ {failureDomains.map((az) => (
40
+ <span key={az} className="badge badge-sm bg-theme-elevated text-theme-text-secondary border-theme-border">{az}</span>
41
+ ))}
42
+ </div>
43
+ </Section>
44
+ )}
45
+
46
+ <ConditionsSection conditions={conditions} />
47
+ </>
48
+ )
49
+ }