@skyhook-io/k8s-ui 1.4.2 → 1.5.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 (45) hide show
  1. package/package.json +31 -8
  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/hooks/useKeyboardShortcuts.tsx +19 -22
  43. package/src/types/core.ts +18 -2
  44. package/src/utils/api-resources.ts +4 -0
  45. package/src/utils/resource-icons.ts +35 -0
@@ -0,0 +1,102 @@
1
+ import { Server, Settings } from 'lucide-react'
2
+ import { Section, PropertyList, Property, ConditionsSection, AlertBanner } from '../../ui/drawer-components'
3
+ import { getCAPIConditions } from '../resource-utils-capi'
4
+ import { getGCPMMPStatus, getGCPMMPNodePoolName, getGCPMMPMachineType, getGCPMMPDiskInfo, getGCPMMPScaling, getGCPMMPImageType } from '../resource-utils-gcp-capi'
5
+
6
+ interface Props {
7
+ data: any
8
+ onNavigate?: (ref: { kind: string; namespace: string; name: string; group?: string }) => void
9
+ }
10
+
11
+ export function GCPManagedMachinePoolRenderer({ data }: Props) {
12
+ const spec = data.spec || {}
13
+ const status = data.status || {}
14
+ const conditions = getCAPIConditions(data)
15
+ const mmpStatus = getGCPMMPStatus(data)
16
+ const isFailed = mmpStatus.level === 'unhealthy'
17
+ const readyCond = conditions.find((c: any) => c.type === 'Ready')
18
+ const scaling = getGCPMMPScaling(data)
19
+ const management = spec.management || {}
20
+ const labels = spec.kubernetesLabels || {}
21
+ const taints = spec.kubernetesTaints || []
22
+ const locations = spec.nodeLocations || []
23
+
24
+ return (
25
+ <>
26
+ {isFailed && (
27
+ <AlertBanner variant="error" title="GKE Node Pool Not Ready" message={readyCond?.message || 'GCPManagedMachinePool is not ready.'} />
28
+ )}
29
+
30
+ <Section title="Overview" icon={Server}>
31
+ <PropertyList>
32
+ <Property label="Node Pool" value={getGCPMMPNodePoolName(data)} />
33
+ <Property label="Machine Type" value={getGCPMMPMachineType(data)} />
34
+ <Property label="Disk" value={getGCPMMPDiskInfo(data)} />
35
+ <Property label="Image Type" value={getGCPMMPImageType(data)} />
36
+ {spec.maxPodsPerNode != null && <Property label="Max Pods/Node" value={String(spec.maxPodsPerNode)} />}
37
+ </PropertyList>
38
+ </Section>
39
+
40
+ <Section title="Scaling" icon={Settings}>
41
+ <PropertyList>
42
+ <Property label="Autoscaling" value={scaling.autoscaling ? 'Enabled' : 'Disabled'} />
43
+ {scaling.autoscaling && <Property label="Min Nodes" value={String(scaling.min)} />}
44
+ {scaling.autoscaling && <Property label="Max Nodes" value={String(scaling.max)} />}
45
+ <Property label="Current Replicas" value={String(status.replicas ?? 0)} />
46
+ </PropertyList>
47
+ </Section>
48
+
49
+ {/* Management */}
50
+ {(management.autoRepair != null || management.autoUpgrade != null) && (
51
+ <Section title="Management" icon={Settings}>
52
+ <PropertyList>
53
+ {management.autoRepair != null && <Property label="Auto Repair" value={management.autoRepair ? 'Enabled' : 'Disabled'} />}
54
+ {management.autoUpgrade != null && <Property label="Auto Upgrade" value={management.autoUpgrade ? 'Enabled' : 'Disabled'} />}
55
+ </PropertyList>
56
+ </Section>
57
+ )}
58
+
59
+ {/* Locations */}
60
+ {locations.length > 0 && (
61
+ <Section title="Node Locations" icon={Server}>
62
+ <div className="flex flex-wrap gap-1">
63
+ {locations.map((loc: string) => (
64
+ <span key={loc} className="badge badge-sm bg-theme-elevated text-theme-text-secondary border-theme-border">{loc}</span>
65
+ ))}
66
+ </div>
67
+ </Section>
68
+ )}
69
+
70
+ {/* Labels */}
71
+ {Object.keys(labels).length > 0 && (
72
+ <Section title="Node Labels" icon={Settings}>
73
+ <div className="flex flex-wrap gap-1">
74
+ {Object.entries(labels).map(([k, v]) => (
75
+ <span key={k} className="badge badge-sm bg-theme-elevated text-theme-text-secondary border-theme-border text-[10px]">{k}={v as string}</span>
76
+ ))}
77
+ </div>
78
+ </Section>
79
+ )}
80
+
81
+ {/* Taints */}
82
+ {taints.length > 0 && (
83
+ <Section title="Taints" icon={Settings}>
84
+ <table className="w-full text-xs">
85
+ <thead><tr className="text-theme-text-tertiary"><th className="text-left font-medium py-1">Key</th><th className="text-left font-medium py-1">Value</th><th className="text-left font-medium py-1">Effect</th></tr></thead>
86
+ <tbody>
87
+ {taints.map((t: any, i: number) => (
88
+ <tr key={i} className="border-t border-theme-border">
89
+ <td className="py-1 text-theme-text-secondary">{t.key}</td>
90
+ <td className="py-1 text-theme-text-secondary">{t.value}</td>
91
+ <td className="py-1 text-theme-text-secondary">{t.effect}</td>
92
+ </tr>
93
+ ))}
94
+ </tbody>
95
+ </table>
96
+ </Section>
97
+ )}
98
+
99
+ <ConditionsSection conditions={conditions} />
100
+ </>
101
+ )
102
+ }
@@ -0,0 +1,117 @@
1
+ // AWS CAPI Infrastructure Provider cell components for ResourcesView table
2
+
3
+ import { clsx } from 'clsx'
4
+ import { Tooltip } from '../../ui/Tooltip'
5
+ import {
6
+ getAWSMCPStatus, getAWSMCPEKSClusterName, getAWSMCPRegion, getAWSMCPVersion,
7
+ getAWSMMPStatus, getAWSMMPInstanceType, getAWSMMPReplicas, getAWSMMPCapacityType,
8
+ getAWSMachineStatus, getAWSMachineInstanceType, getAWSMachineInstanceState, getAWSMachineInstanceID,
9
+ getAWSMTInstanceType, getAWSMTCapacity,
10
+ getAWSManagedClusterStatus, getAWSManagedClusterEndpoint,
11
+ } from '../resource-utils-aws-capi'
12
+
13
+ function StatusBadge({ resource, getStatus }: { resource: any; getStatus: (r: any) => { text: string; color: string } }) {
14
+ const status = getStatus(resource)
15
+ return (
16
+ <Tooltip content={status.text}>
17
+ <span className={clsx('badge truncate max-w-[140px]', status.color)}>{status.text}</span>
18
+ </Tooltip>
19
+ )
20
+ }
21
+
22
+ function TextCell({ value }: { value: string }) {
23
+ return <span className="text-sm text-theme-text-secondary">{value}</span>
24
+ }
25
+
26
+ function MonoCell({ value }: { value: string }) {
27
+ return (
28
+ <Tooltip content={value}>
29
+ <span className="text-xs text-theme-text-secondary font-mono truncate max-w-[180px] inline-block">{value}</span>
30
+ </Tooltip>
31
+ )
32
+ }
33
+
34
+ export function AWSManagedControlPlaneCell({ resource, column }: { resource: any; column: string }) {
35
+ switch (column) {
36
+ case 'status':
37
+ return <StatusBadge resource={resource} getStatus={getAWSMCPStatus} />
38
+ case 'eksCluster':
39
+ return <TextCell value={getAWSMCPEKSClusterName(resource)} />
40
+ case 'region':
41
+ return <TextCell value={getAWSMCPRegion(resource)} />
42
+ case 'version':
43
+ return <TextCell value={getAWSMCPVersion(resource)} />
44
+ default:
45
+ return <span className="text-sm text-theme-text-tertiary">-</span>
46
+ }
47
+ }
48
+
49
+ export function AWSManagedMachinePoolCell({ resource, column }: { resource: any; column: string }) {
50
+ switch (column) {
51
+ case 'status':
52
+ return <StatusBadge resource={resource} getStatus={getAWSMMPStatus} />
53
+ case 'instanceType':
54
+ return <TextCell value={getAWSMMPInstanceType(resource)} />
55
+ case 'replicas':
56
+ return <TextCell value={getAWSMMPReplicas(resource)} />
57
+ case 'capacityType': {
58
+ const ct = getAWSMMPCapacityType(resource)
59
+ return (
60
+ <span className={clsx('badge badge-sm', ct === 'spot'
61
+ ? 'bg-amber-100 text-amber-800 border-amber-300 dark:bg-amber-950/50 dark:text-amber-400 dark:border-amber-700/40'
62
+ : 'bg-sky-100 text-sky-700 border-sky-300 dark:bg-sky-950/50 dark:text-sky-400 dark:border-sky-700/40'
63
+ )}>{ct === 'onDemand' ? 'On-Demand' : ct}</span>
64
+ )
65
+ }
66
+ default:
67
+ return <span className="text-sm text-theme-text-tertiary">-</span>
68
+ }
69
+ }
70
+
71
+ export function AWSMachineCell({ resource, column }: { resource: any; column: string }) {
72
+ switch (column) {
73
+ case 'status':
74
+ return <StatusBadge resource={resource} getStatus={getAWSMachineStatus} />
75
+ case 'instanceType':
76
+ return <TextCell value={getAWSMachineInstanceType(resource)} />
77
+ case 'instanceState': {
78
+ const state = getAWSMachineInstanceState(resource)
79
+ return (
80
+ <span className={clsx('badge badge-sm', state === 'running'
81
+ ? 'status-healthy'
82
+ : state === 'pending' || state === 'stopping' || state === 'stopped'
83
+ ? 'status-degraded'
84
+ : state === 'terminated' || state === 'shutting-down'
85
+ ? 'status-unhealthy'
86
+ : 'status-neutral'
87
+ )}>{state}</span>
88
+ )
89
+ }
90
+ case 'instanceID':
91
+ return <MonoCell value={getAWSMachineInstanceID(resource)} />
92
+ default:
93
+ return <span className="text-sm text-theme-text-tertiary">-</span>
94
+ }
95
+ }
96
+
97
+ export function AWSMachineTemplateCell({ resource, column }: { resource: any; column: string }) {
98
+ switch (column) {
99
+ case 'instanceType':
100
+ return <TextCell value={getAWSMTInstanceType(resource)} />
101
+ case 'capacity':
102
+ return <TextCell value={getAWSMTCapacity(resource)} />
103
+ default:
104
+ return <span className="text-sm text-theme-text-tertiary">-</span>
105
+ }
106
+ }
107
+
108
+ export function AWSManagedClusterCell({ resource, column }: { resource: any; column: string }) {
109
+ switch (column) {
110
+ case 'status':
111
+ return <StatusBadge resource={resource} getStatus={getAWSManagedClusterStatus} />
112
+ case 'endpoint':
113
+ return <MonoCell value={getAWSManagedClusterEndpoint(resource)} />
114
+ default:
115
+ return <span className="text-sm text-theme-text-tertiary">-</span>
116
+ }
117
+ }
@@ -0,0 +1,83 @@
1
+ // Azure CAPI Infrastructure Provider cell components for ResourcesView table
2
+
3
+ import { Tooltip } from '../../ui/Tooltip'
4
+ import { clsx } from 'clsx'
5
+ import {
6
+ getAzureMCPStatus, getAzureMCPLocation, getAzureMCPVersion, getAzureMCPResourceGroup,
7
+ getAzureMMPStatus, getAzureMMPSKU, getAzureMMPMode, getAzureMMPReplicas, getAzureMMPScaleSetPriority,
8
+ getAzureMachineStatus, getAzureMachineVMSize,
9
+ getAzureMTVMSize,
10
+ getAzureManagedClusterStatus,
11
+ } from '../resource-utils-azure-capi'
12
+
13
+ function StatusBadge({ resource, getStatus }: { resource: any; getStatus: (r: any) => { text: string; color: string } }) {
14
+ const status = getStatus(resource)
15
+ return (
16
+ <Tooltip content={status.text}>
17
+ <span className={clsx('badge truncate max-w-[140px]', status.color)}>{status.text}</span>
18
+ </Tooltip>
19
+ )
20
+ }
21
+
22
+ function TextCell({ value }: { value: string }) {
23
+ return <span className="text-sm text-theme-text-secondary">{value}</span>
24
+ }
25
+
26
+ export function AzureManagedControlPlaneCell({ resource, column }: { resource: any; column: string }) {
27
+ switch (column) {
28
+ case 'status': return <StatusBadge resource={resource} getStatus={getAzureMCPStatus} />
29
+ case 'location': return <TextCell value={getAzureMCPLocation(resource)} />
30
+ case 'resourceGroup': return <TextCell value={getAzureMCPResourceGroup(resource)} />
31
+ case 'version': return <TextCell value={getAzureMCPVersion(resource)} />
32
+ default: return <span className="text-sm text-theme-text-tertiary">-</span>
33
+ }
34
+ }
35
+
36
+ export function AzureManagedMachinePoolCell({ resource, column }: { resource: any; column: string }) {
37
+ switch (column) {
38
+ case 'status': return <StatusBadge resource={resource} getStatus={getAzureMMPStatus} />
39
+ case 'sku': return <TextCell value={getAzureMMPSKU(resource)} />
40
+ case 'mode': {
41
+ const mode = getAzureMMPMode(resource)
42
+ return (
43
+ <span className={clsx('badge badge-sm', mode === 'System'
44
+ ? 'bg-purple-100 text-purple-800 border-purple-300 dark:bg-purple-950/50 dark:text-purple-400 dark:border-purple-700/40'
45
+ : 'bg-sky-100 text-sky-700 border-sky-300 dark:bg-sky-950/50 dark:text-sky-400 dark:border-sky-700/40'
46
+ )}>{mode}</span>
47
+ )
48
+ }
49
+ case 'replicas': return <TextCell value={getAzureMMPReplicas(resource)} />
50
+ case 'priority': {
51
+ const p = getAzureMMPScaleSetPriority(resource)
52
+ return (
53
+ <span className={clsx('badge badge-sm', p === 'Spot'
54
+ ? 'bg-amber-100 text-amber-800 border-amber-300 dark:bg-amber-950/50 dark:text-amber-400 dark:border-amber-700/40'
55
+ : 'bg-sky-100 text-sky-700 border-sky-300 dark:bg-sky-950/50 dark:text-sky-400 dark:border-sky-700/40'
56
+ )}>{p}</span>
57
+ )
58
+ }
59
+ default: return <span className="text-sm text-theme-text-tertiary">-</span>
60
+ }
61
+ }
62
+
63
+ export function AzureMachineCell({ resource, column }: { resource: any; column: string }) {
64
+ switch (column) {
65
+ case 'status': return <StatusBadge resource={resource} getStatus={getAzureMachineStatus} />
66
+ case 'vmSize': return <TextCell value={getAzureMachineVMSize(resource)} />
67
+ default: return <span className="text-sm text-theme-text-tertiary">-</span>
68
+ }
69
+ }
70
+
71
+ export function AzureMachineTemplateCell({ resource, column }: { resource: any; column: string }) {
72
+ switch (column) {
73
+ case 'vmSize': return <TextCell value={getAzureMTVMSize(resource)} />
74
+ default: return <span className="text-sm text-theme-text-tertiary">-</span>
75
+ }
76
+ }
77
+
78
+ export function AzureManagedClusterCell({ resource, column }: { resource: any; column: string }) {
79
+ switch (column) {
80
+ case 'status': return <StatusBadge resource={resource} getStatus={getAzureManagedClusterStatus} />
81
+ default: return <span className="text-sm text-theme-text-tertiary">-</span>
82
+ }
83
+ }
@@ -0,0 +1,158 @@
1
+ // Cluster API (CAPI) cell components for ResourcesView table
2
+
3
+ import { clsx } from 'clsx'
4
+ import { Tooltip } from '../../ui/Tooltip'
5
+ import {
6
+ getClusterStatus, getClusterClass, getClusterVersion, getClusterCPReplicas, getClusterWorkerReplicas,
7
+ getMachineStatus, getMachineRole, getMachineClusterName, getMachineNodeRef, getMachineVersion,
8
+ getMachineDeploymentStatus, getMachineDeploymentReplicas, getMachineDeploymentVersion,
9
+ getMachineSetStatus, getMachineSetReplicas,
10
+ getMachinePoolStatus, getMachinePoolReplicas,
11
+ getKCPStatus, getKCPReplicas, getKCPVersion, getKCPInitialized,
12
+ getClusterClassStatus,
13
+ getMachineHealthCheckStatus, getMachineHealthCheckHealthy, getMachineHealthCheckClusterName,
14
+ getClusterProvider,
15
+ } from '../resource-utils-capi'
16
+
17
+ function StatusBadge({ resource, getStatus }: { resource: any; getStatus: (r: any) => { text: string; color: string } }) {
18
+ const status = getStatus(resource)
19
+ return (
20
+ <Tooltip content={status.text}>
21
+ <span className={clsx('badge truncate max-w-[140px]', status.color)}>{status.text}</span>
22
+ </Tooltip>
23
+ )
24
+ }
25
+
26
+ function TextCell({ value }: { value: string }) {
27
+ return <span className="text-sm text-theme-text-secondary">{value}</span>
28
+ }
29
+
30
+ export function CAPIClusterCell({ resource, column }: { resource: any; column: string }) {
31
+ switch (column) {
32
+ case 'phase':
33
+ return <StatusBadge resource={resource} getStatus={getClusterStatus} />
34
+ case 'provider':
35
+ return <TextCell value={getClusterProvider(resource)} />
36
+ case 'class':
37
+ return <TextCell value={getClusterClass(resource)} />
38
+ case 'cpReplicas':
39
+ return <TextCell value={getClusterCPReplicas(resource)} />
40
+ case 'workerReplicas':
41
+ return <TextCell value={getClusterWorkerReplicas(resource)} />
42
+ case 'version':
43
+ return <TextCell value={getClusterVersion(resource)} />
44
+ default:
45
+ return <span className="text-sm text-theme-text-tertiary">-</span>
46
+ }
47
+ }
48
+
49
+ export function CAPIMachineCell({ resource, column }: { resource: any; column: string }) {
50
+ switch (column) {
51
+ case 'phase':
52
+ return <StatusBadge resource={resource} getStatus={getMachineStatus} />
53
+ case 'cluster':
54
+ return <TextCell value={getMachineClusterName(resource)} />
55
+ case 'role': {
56
+ const role = getMachineRole(resource)
57
+ return (
58
+ <span className={clsx('badge badge-sm', role === 'Control Plane'
59
+ ? 'bg-purple-100 text-purple-800 border-purple-300 dark:bg-purple-950/50 dark:text-purple-400 dark:border-purple-700/40'
60
+ : 'bg-sky-100 text-sky-700 border-sky-300 dark:bg-sky-950/50 dark:text-sky-400 dark:border-sky-700/40'
61
+ )}>{role}</span>
62
+ )
63
+ }
64
+ case 'node':
65
+ return <TextCell value={getMachineNodeRef(resource)} />
66
+ case 'version':
67
+ return <TextCell value={getMachineVersion(resource)} />
68
+ default:
69
+ return <span className="text-sm text-theme-text-tertiary">-</span>
70
+ }
71
+ }
72
+
73
+ export function CAPIMachineDeploymentCell({ resource, column }: { resource: any; column: string }) {
74
+ switch (column) {
75
+ case 'phase':
76
+ return <StatusBadge resource={resource} getStatus={getMachineDeploymentStatus} />
77
+ case 'cluster':
78
+ return <TextCell value={getMachineClusterName(resource)} />
79
+ case 'ready':
80
+ return <TextCell value={getMachineDeploymentReplicas(resource)} />
81
+ case 'version':
82
+ return <TextCell value={getMachineDeploymentVersion(resource)} />
83
+ default:
84
+ return <span className="text-sm text-theme-text-tertiary">-</span>
85
+ }
86
+ }
87
+
88
+ export function CAPIMachineSetCell({ resource, column }: { resource: any; column: string }) {
89
+ switch (column) {
90
+ case 'phase':
91
+ return <StatusBadge resource={resource} getStatus={getMachineSetStatus} />
92
+ case 'cluster':
93
+ return <TextCell value={getMachineClusterName(resource)} />
94
+ case 'ready':
95
+ return <TextCell value={getMachineSetReplicas(resource)} />
96
+ default:
97
+ return <span className="text-sm text-theme-text-tertiary">-</span>
98
+ }
99
+ }
100
+
101
+ export function CAPIMachinePoolCell({ resource, column }: { resource: any; column: string }) {
102
+ switch (column) {
103
+ case 'phase':
104
+ return <StatusBadge resource={resource} getStatus={getMachinePoolStatus} />
105
+ case 'cluster':
106
+ return <TextCell value={getMachineClusterName(resource)} />
107
+ case 'ready':
108
+ return <TextCell value={getMachinePoolReplicas(resource)} />
109
+ default:
110
+ return <span className="text-sm text-theme-text-tertiary">-</span>
111
+ }
112
+ }
113
+
114
+ export function CAPIKubeadmControlPlaneCell({ resource, column }: { resource: any; column: string }) {
115
+ switch (column) {
116
+ case 'status':
117
+ return <StatusBadge resource={resource} getStatus={getKCPStatus} />
118
+ case 'cluster':
119
+ return <TextCell value={getMachineClusterName(resource)} />
120
+ case 'ready':
121
+ return <TextCell value={getKCPReplicas(resource)} />
122
+ case 'initialized': {
123
+ const init = getKCPInitialized(resource)
124
+ return (
125
+ <span className={clsx('badge badge-sm', init
126
+ ? 'bg-emerald-100 text-emerald-800 border-emerald-300 dark:bg-emerald-950/50 dark:text-emerald-400 dark:border-emerald-700/40'
127
+ : 'bg-amber-100 text-amber-800 border-amber-300 dark:bg-amber-950/50 dark:text-amber-400 dark:border-amber-700/40'
128
+ )}>{init ? 'Yes' : 'No'}</span>
129
+ )
130
+ }
131
+ case 'version':
132
+ return <TextCell value={getKCPVersion(resource)} />
133
+ default:
134
+ return <span className="text-sm text-theme-text-tertiary">-</span>
135
+ }
136
+ }
137
+
138
+ export function CAPIClusterClassCell({ resource, column }: { resource: any; column: string }) {
139
+ switch (column) {
140
+ case 'status':
141
+ return <StatusBadge resource={resource} getStatus={getClusterClassStatus} />
142
+ default:
143
+ return <span className="text-sm text-theme-text-tertiary">-</span>
144
+ }
145
+ }
146
+
147
+ export function CAPIMachineHealthCheckCell({ resource, column }: { resource: any; column: string }) {
148
+ switch (column) {
149
+ case 'status':
150
+ return <StatusBadge resource={resource} getStatus={getMachineHealthCheckStatus} />
151
+ case 'cluster':
152
+ return <TextCell value={getMachineHealthCheckClusterName(resource)} />
153
+ case 'healthy':
154
+ return <TextCell value={getMachineHealthCheckHealthy(resource)} />
155
+ default:
156
+ return <span className="text-sm text-theme-text-tertiary">-</span>
157
+ }
158
+ }
@@ -0,0 +1,68 @@
1
+ // GCP CAPI Infrastructure Provider cell components for ResourcesView table
2
+
3
+ import { Tooltip } from '../../ui/Tooltip'
4
+ import { clsx } from 'clsx'
5
+ import {
6
+ getGCPMCPStatus, getGCPMCPClusterName, getGCPMCPProject, getGCPMCPLocation, getGCPMCPVersion,
7
+ getGCPMMPStatus, getGCPMMPMachineType, getGCPMMPReplicas,
8
+ getGCPMachineStatus, getGCPMachineInstanceType, getGCPMachineZone,
9
+ getGCPMTInstanceType,
10
+ getGCPManagedClusterStatus, getGCPManagedClusterProject,
11
+ } from '../resource-utils-gcp-capi'
12
+
13
+ function StatusBadge({ resource, getStatus }: { resource: any; getStatus: (r: any) => { text: string; color: string } }) {
14
+ const status = getStatus(resource)
15
+ return (
16
+ <Tooltip content={status.text}>
17
+ <span className={clsx('badge truncate max-w-[140px]', status.color)}>{status.text}</span>
18
+ </Tooltip>
19
+ )
20
+ }
21
+
22
+ function TextCell({ value }: { value: string }) {
23
+ return <span className="text-sm text-theme-text-secondary">{value}</span>
24
+ }
25
+
26
+ export function GCPManagedControlPlaneCell({ resource, column }: { resource: any; column: string }) {
27
+ switch (column) {
28
+ case 'status': return <StatusBadge resource={resource} getStatus={getGCPMCPStatus} />
29
+ case 'gkeCluster': return <TextCell value={getGCPMCPClusterName(resource)} />
30
+ case 'project': return <TextCell value={getGCPMCPProject(resource)} />
31
+ case 'location': return <TextCell value={getGCPMCPLocation(resource)} />
32
+ case 'version': return <TextCell value={getGCPMCPVersion(resource)} />
33
+ default: return <span className="text-sm text-theme-text-tertiary">-</span>
34
+ }
35
+ }
36
+
37
+ export function GCPManagedMachinePoolCell({ resource, column }: { resource: any; column: string }) {
38
+ switch (column) {
39
+ case 'status': return <StatusBadge resource={resource} getStatus={getGCPMMPStatus} />
40
+ case 'machineType': return <TextCell value={getGCPMMPMachineType(resource)} />
41
+ case 'replicas': return <TextCell value={getGCPMMPReplicas(resource)} />
42
+ default: return <span className="text-sm text-theme-text-tertiary">-</span>
43
+ }
44
+ }
45
+
46
+ export function GCPMachineCell({ resource, column }: { resource: any; column: string }) {
47
+ switch (column) {
48
+ case 'status': return <StatusBadge resource={resource} getStatus={getGCPMachineStatus} />
49
+ case 'instanceType': return <TextCell value={getGCPMachineInstanceType(resource)} />
50
+ case 'zone': return <TextCell value={getGCPMachineZone(resource)} />
51
+ default: return <span className="text-sm text-theme-text-tertiary">-</span>
52
+ }
53
+ }
54
+
55
+ export function GCPMachineTemplateCell({ resource, column }: { resource: any; column: string }) {
56
+ switch (column) {
57
+ case 'instanceType': return <TextCell value={getGCPMTInstanceType(resource)} />
58
+ default: return <span className="text-sm text-theme-text-tertiary">-</span>
59
+ }
60
+ }
61
+
62
+ export function GCPManagedClusterCell({ resource, column }: { resource: any; column: string }) {
63
+ switch (column) {
64
+ case 'status': return <StatusBadge resource={resource} getStatus={getGCPManagedClusterStatus} />
65
+ case 'project': return <TextCell value={getGCPManagedClusterProject(resource)} />
66
+ default: return <span className="text-sm text-theme-text-tertiary">-</span>
67
+ }
68
+ }
@@ -108,3 +108,28 @@ export * from './TraefikIngressRouteRenderer'
108
108
  export * from './traefik-cells'
109
109
  export * from './ContourHTTPProxyRenderer'
110
110
  export * from './contour-cells'
111
+ export * from './CAPIClusterRenderer'
112
+ export * from './CAPIMachineRenderer'
113
+ export * from './CAPIMachineDeploymentRenderer'
114
+ export * from './CAPIKubeadmControlPlaneRenderer'
115
+ export * from './capi-cells'
116
+ export * from './CAPIMachineSetRenderer'
117
+ export * from './CAPIMachinePoolRenderer'
118
+ export * from './CAPIClusterClassRenderer'
119
+ export * from './CAPIMachineHealthCheckRenderer'
120
+ export * from './CAPIMachineDrainRuleRenderer'
121
+ export * from './CAPIKubeadmConfigRenderer'
122
+ export * from './aws-capi-cells'
123
+ export * from './AWSManagedControlPlaneRenderer'
124
+ export * from './AWSManagedMachinePoolRenderer'
125
+ export * from './AWSMachineRenderer'
126
+ export * from './AWSMachineTemplateRenderer'
127
+ export * from './AWSManagedClusterRenderer'
128
+ export * from './gcp-capi-cells'
129
+ export * from './GCPManagedControlPlaneRenderer'
130
+ export * from './GCPManagedMachinePoolRenderer'
131
+ export * from './GCPMachineRenderer'
132
+ export * from './azure-capi-cells'
133
+ export * from './AzureManagedControlPlaneRenderer'
134
+ export * from './AzureManagedMachinePoolRenderer'
135
+ export * from './AzureMachineRenderer'