@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.
- package/package.json +63 -0
- package/src/components/dock/BottomDock.tsx +204 -0
- package/src/components/dock/DockContext.tsx +212 -0
- package/src/components/dock/TerminalTab.tsx +333 -0
- package/src/components/dock/index.ts +3 -0
- package/src/components/gitops/GitOpsActions.tsx +227 -0
- package/src/components/gitops/GitOpsStatusBadge.tsx +221 -0
- package/src/components/gitops/ManagedResourcesList.tsx +210 -0
- package/src/components/gitops/SyncCountdown.tsx +146 -0
- package/src/components/gitops/index.ts +4 -0
- package/src/components/logs/JsonLogLine.tsx +90 -0
- package/src/components/logs/LogCore.tsx +553 -0
- package/src/components/logs/LogToolbarSelects.tsx +74 -0
- package/src/components/logs/LogsViewer.tsx +146 -0
- package/src/components/logs/WorkloadLogsViewer.tsx +263 -0
- package/src/components/logs/index.ts +13 -0
- package/src/components/logs/useLogBuffer.ts +138 -0
- package/src/components/logs/useLogSearch.ts +151 -0
- package/src/components/logs/useLogStream.ts +61 -0
- package/src/components/resources/ResourcesView.tsx +5494 -0
- package/src/components/resources/index.ts +17 -0
- package/src/components/resources/renderers/AlertRenderer.tsx +166 -0
- package/src/components/resources/renderers/ArgoApplicationRenderer.tsx +233 -0
- package/src/components/resources/renderers/CNPGBackupRenderer.tsx +89 -0
- package/src/components/resources/renderers/CNPGClusterRenderer.tsx +194 -0
- package/src/components/resources/renderers/CNPGPoolerRenderer.tsx +79 -0
- package/src/components/resources/renderers/CNPGScheduledBackupRenderer.tsx +68 -0
- package/src/components/resources/renderers/CertificateRenderer.tsx +209 -0
- package/src/components/resources/renderers/CertificateRequestRenderer.tsx +123 -0
- package/src/components/resources/renderers/ChallengeRenderer.tsx +111 -0
- package/src/components/resources/renderers/ClusterComplianceReportRenderer.tsx +164 -0
- package/src/components/resources/renderers/ClusterExternalSecretRenderer.tsx +140 -0
- package/src/components/resources/renderers/ClusterIssuerRenderer.tsx +153 -0
- package/src/components/resources/renderers/ConfigAuditReportRenderer.tsx +221 -0
- package/src/components/resources/renderers/ConfigMapRenderer.tsx +124 -0
- package/src/components/resources/renderers/CronJobRenderer.tsx +86 -0
- package/src/components/resources/renderers/EventRenderer.tsx +175 -0
- package/src/components/resources/renderers/ExposedSecretReportRenderer.tsx +119 -0
- package/src/components/resources/renderers/ExternalSecretRenderer.tsx +172 -0
- package/src/components/resources/renderers/FluxHelmReleaseRenderer.tsx +242 -0
- package/src/components/resources/renderers/GRPCRouteRenderer.tsx +263 -0
- package/src/components/resources/renderers/GatewayClassRenderer.tsx +68 -0
- package/src/components/resources/renderers/GatewayRenderer.tsx +218 -0
- package/src/components/resources/renderers/GenericRenderer.tsx +476 -0
- package/src/components/resources/renderers/GitRepositoryRenderer.tsx +154 -0
- package/src/components/resources/renderers/HPARenderer.tsx +164 -0
- package/src/components/resources/renderers/HTTPRouteRenderer.tsx +303 -0
- package/src/components/resources/renderers/HelmRepositoryRenderer.tsx +167 -0
- package/src/components/resources/renderers/IngressClassRenderer.tsx +49 -0
- package/src/components/resources/renderers/IngressRenderer.tsx +104 -0
- package/src/components/resources/renderers/IstioAuthorizationPolicyRenderer.tsx +175 -0
- package/src/components/resources/renderers/IstioDestinationRuleRenderer.tsx +176 -0
- package/src/components/resources/renderers/IstioGatewayRenderer.tsx +125 -0
- package/src/components/resources/renderers/IstioPeerAuthenticationRenderer.tsx +84 -0
- package/src/components/resources/renderers/IstioServiceEntryRenderer.tsx +112 -0
- package/src/components/resources/renderers/IstioVirtualServiceRenderer.tsx +288 -0
- package/src/components/resources/renderers/JobRenderer.tsx +103 -0
- package/src/components/resources/renderers/KarpenterEC2NodeClassRenderer.tsx +157 -0
- package/src/components/resources/renderers/KarpenterNodeClaimRenderer.tsx +188 -0
- package/src/components/resources/renderers/KarpenterNodePoolRenderer.tsx +148 -0
- package/src/components/resources/renderers/KedaScaledJobRenderer.tsx +90 -0
- package/src/components/resources/renderers/KedaScaledObjectRenderer.tsx +136 -0
- package/src/components/resources/renderers/KedaTriggerAuthRenderer.tsx +151 -0
- package/src/components/resources/renderers/KnativeConfigurationRenderer.tsx +70 -0
- package/src/components/resources/renderers/KnativeEventingRenderer.tsx +309 -0
- package/src/components/resources/renderers/KnativeFlowRenderer.tsx +142 -0
- package/src/components/resources/renderers/KnativeNetworkingRenderer.tsx +232 -0
- package/src/components/resources/renderers/KnativeRevisionRenderer.tsx +97 -0
- package/src/components/resources/renderers/KnativeRouteRenderer.tsx +74 -0
- package/src/components/resources/renderers/KnativeServiceRenderer.tsx +138 -0
- package/src/components/resources/renderers/KnativeSourceRenderer.tsx +220 -0
- package/src/components/resources/renderers/KustomizationRenderer.tsx +151 -0
- package/src/components/resources/renderers/KyvernoPolicyReportRenderer.tsx +352 -0
- package/src/components/resources/renderers/LeaseRenderer.tsx +93 -0
- package/src/components/resources/renderers/NetworkPolicyRenderer.tsx +208 -0
- package/src/components/resources/renderers/NodeRenderer.tsx +282 -0
- package/src/components/resources/renderers/OCIRepositoryRenderer.tsx +153 -0
- package/src/components/resources/renderers/OrderRenderer.tsx +108 -0
- package/src/components/resources/renderers/PVCRenderer.tsx +98 -0
- package/src/components/resources/renderers/PersistentVolumeRenderer.tsx +138 -0
- package/src/components/resources/renderers/PodDisruptionBudgetRenderer.tsx +126 -0
- package/src/components/resources/renderers/PodMonitorRenderer.tsx +63 -0
- package/src/components/resources/renderers/PodRenderer.tsx +677 -0
- package/src/components/resources/renderers/PriorityClassRenderer.tsx +50 -0
- package/src/components/resources/renderers/PrometheusRuleRenderer.tsx +62 -0
- package/src/components/resources/renderers/ReplicaSetRenderer.tsx +71 -0
- package/src/components/resources/renderers/RoleBindingRenderer.tsx +97 -0
- package/src/components/resources/renderers/RoleRenderer.tsx +192 -0
- package/src/components/resources/renderers/RolloutRenderer.tsx +227 -0
- package/src/components/resources/renderers/RuntimeClassRenderer.tsx +75 -0
- package/src/components/resources/renderers/SbomReportRenderer.tsx +98 -0
- package/src/components/resources/renderers/SealedSecretRenderer.tsx +121 -0
- package/src/components/resources/renderers/SecretRenderer.tsx +321 -0
- package/src/components/resources/renderers/SecretStoreRenderer.tsx +111 -0
- package/src/components/resources/renderers/ServiceAccountRenderer.tsx +81 -0
- package/src/components/resources/renderers/ServiceMonitorRenderer.tsx +65 -0
- package/src/components/resources/renderers/ServiceRenderer.tsx +98 -0
- package/src/components/resources/renderers/SimpleRouteRenderer.tsx +195 -0
- package/src/components/resources/renderers/StorageClassRenderer.tsx +82 -0
- package/src/components/resources/renderers/TraefikIngressRouteRenderer.tsx +257 -0
- package/src/components/resources/renderers/VPARenderer.tsx +193 -0
- package/src/components/resources/renderers/VeleroBSLRenderer.tsx +73 -0
- package/src/components/resources/renderers/VeleroBackupRenderer.tsx +193 -0
- package/src/components/resources/renderers/VeleroRestoreRenderer.tsx +161 -0
- package/src/components/resources/renderers/VeleroScheduleRenderer.tsx +134 -0
- package/src/components/resources/renderers/VeleroVSLRenderer.tsx +36 -0
- package/src/components/resources/renderers/VulnerabilityReportRenderer.tsx +347 -0
- package/src/components/resources/renderers/WebhookConfigRenderer.tsx +156 -0
- package/src/components/resources/renderers/WorkflowRenderer.tsx +202 -0
- package/src/components/resources/renderers/WorkflowTemplateRenderer.tsx +91 -0
- package/src/components/resources/renderers/WorkloadRenderer.tsx +311 -0
- package/src/components/resources/renderers/argo-cells.tsx +118 -0
- package/src/components/resources/renderers/certmanager-cells.tsx +164 -0
- package/src/components/resources/renderers/cnpg-cells.tsx +161 -0
- package/src/components/resources/renderers/eso-cells.tsx +115 -0
- package/src/components/resources/renderers/flux-cells.tsx +253 -0
- package/src/components/resources/renderers/index.ts +105 -0
- package/src/components/resources/renderers/istio-cells.tsx +210 -0
- package/src/components/resources/renderers/karpenter-cells.tsx +107 -0
- package/src/components/resources/renderers/keda-cells.tsx +94 -0
- package/src/components/resources/renderers/knative-cells.tsx +396 -0
- package/src/components/resources/renderers/kyverno-cells.tsx +85 -0
- package/src/components/resources/renderers/prometheus-cells.tsx +74 -0
- package/src/components/resources/renderers/traefik-cells.tsx +120 -0
- package/src/components/resources/renderers/trivy-cells.tsx +153 -0
- package/src/components/resources/renderers/trivy-shared.tsx +67 -0
- package/src/components/resources/renderers/velero-cells.tsx +164 -0
- package/src/components/resources/resource-utils-argo.ts +155 -0
- package/src/components/resources/resource-utils-certmanager.ts +198 -0
- package/src/components/resources/resource-utils-cnpg.ts +344 -0
- package/src/components/resources/resource-utils-eso.ts +385 -0
- package/src/components/resources/resource-utils-flux.ts +186 -0
- package/src/components/resources/resource-utils-istio.ts +372 -0
- package/src/components/resources/resource-utils-karpenter.ts +150 -0
- package/src/components/resources/resource-utils-keda.ts +203 -0
- package/src/components/resources/resource-utils-knative.ts +218 -0
- package/src/components/resources/resource-utils-kyverno.ts +224 -0
- package/src/components/resources/resource-utils-prometheus.ts +159 -0
- package/src/components/resources/resource-utils-traefik.ts +180 -0
- package/src/components/resources/resource-utils-trivy.ts +146 -0
- package/src/components/resources/resource-utils-velero.ts +293 -0
- package/src/components/resources/resource-utils.ts +1558 -0
- package/src/components/shared/EditableYamlView.tsx +302 -0
- package/src/components/shared/ResourceActionsBar.tsx +924 -0
- package/src/components/shared/ResourceRendererDispatch.tsx +557 -0
- package/src/components/shared/index.ts +3 -0
- package/src/components/timeline/index.ts +1 -0
- package/src/components/timeline/shared.tsx +614 -0
- package/src/components/topology/GroupNode.tsx +198 -0
- package/src/components/topology/K8sResourceNode.tsx +440 -0
- package/src/components/topology/TopologyControls.tsx +62 -0
- package/src/components/topology/TopologyFilterSidebar.tsx +377 -0
- package/src/components/topology/TopologyGraph.tsx +748 -0
- package/src/components/topology/TopologySearch.tsx +304 -0
- package/src/components/topology/index.ts +7 -0
- package/src/components/topology/layout.ts +734 -0
- package/src/components/topology/layout.worker.ts +272 -0
- package/src/components/topology/topology.css +129 -0
- package/src/components/ui/CodeViewer.tsx +451 -0
- package/src/components/ui/ConfirmDialog.tsx +188 -0
- package/src/components/ui/ForceDeleteConfirmDialog.tsx +57 -0
- package/src/components/ui/HealthRing.tsx +72 -0
- package/src/components/ui/MetricsChart.tsx +259 -0
- package/src/components/ui/ResourceBar.tsx +68 -0
- package/src/components/ui/Toast.tsx +225 -0
- package/src/components/ui/Tooltip.tsx +165 -0
- package/src/components/ui/YamlEditor.tsx +280 -0
- package/src/components/ui/drawer-components.tsx +792 -0
- package/src/components/ui/index.ts +10 -0
- package/src/components/workload/ResourceDetailDrawer.tsx +158 -0
- package/src/components/workload/WorkloadView.tsx +1109 -0
- package/src/components/workload/index.ts +2 -0
- package/src/hooks/index.ts +9 -0
- package/src/hooks/useAnimatedUnmount.ts +30 -0
- package/src/hooks/useKeyboardShortcuts.tsx +336 -0
- package/src/hooks/useRefreshAnimation.ts +58 -0
- package/src/index.ts +35 -0
- package/src/types/core.ts +894 -0
- package/src/types/gitops.ts +458 -0
- package/src/types/index.ts +2 -0
- package/src/utils/animation.ts +40 -0
- package/src/utils/api-resources.ts +185 -0
- package/src/utils/badge-colors.ts +399 -0
- package/src/utils/context-name.ts +72 -0
- package/src/utils/download.ts +19 -0
- package/src/utils/format.ts +233 -0
- package/src/utils/index.ts +10 -0
- package/src/utils/log-format.ts +300 -0
- package/src/utils/navigation.ts +119 -0
- package/src/utils/resource-hierarchy.ts +630 -0
- package/src/utils/resource-icons.ts +206 -0
- package/src/vite-env.d.ts +1 -0
- package/tsconfig.json +24 -0
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { Globe, Layers, Container } from 'lucide-react'
|
|
2
|
+
import { clsx } from 'clsx'
|
|
3
|
+
import { Section, PropertyList, Property, ConditionsSection, KnativeNotReadyBanner, ResourceLink } from '../../ui/drawer-components'
|
|
4
|
+
import { getKnativeConditionStatus } from '../resource-utils-knative'
|
|
5
|
+
|
|
6
|
+
interface KnativeServiceRendererProps {
|
|
7
|
+
data: any
|
|
8
|
+
onNavigate?: (ref: { kind: string; namespace: string; name: string }) => void
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function KnativeServiceRenderer({ data, onNavigate }: KnativeServiceRendererProps) {
|
|
12
|
+
const status = getKnativeConditionStatus(data)
|
|
13
|
+
const ns = data.metadata?.namespace || ''
|
|
14
|
+
const url = data.status?.url
|
|
15
|
+
const traffic = data.status?.traffic || []
|
|
16
|
+
const templateSpec = data.spec?.template?.spec || {}
|
|
17
|
+
const containers = templateSpec.containers || []
|
|
18
|
+
const templateAnnotations = data.spec?.template?.metadata?.annotations || {}
|
|
19
|
+
|
|
20
|
+
const latestReady = data.status?.latestReadyRevisionName
|
|
21
|
+
const latestCreated = data.status?.latestCreatedRevisionName
|
|
22
|
+
const generation = data.metadata?.generation
|
|
23
|
+
|
|
24
|
+
// Autoscaling config from template annotations
|
|
25
|
+
const minScale = templateAnnotations['autoscaling.knative.dev/minScale']
|
|
26
|
+
const maxScale = templateAnnotations['autoscaling.knative.dev/maxScale']
|
|
27
|
+
const concurrency = templateSpec.containerConcurrency
|
|
28
|
+
const timeoutSeconds = templateSpec.timeoutSeconds
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<>
|
|
32
|
+
<KnativeNotReadyBanner status={status} data={data} resourceType="Service" />
|
|
33
|
+
|
|
34
|
+
<Section title="Overview" icon={Globe} defaultExpanded>
|
|
35
|
+
<PropertyList>
|
|
36
|
+
<Property label="Status" value={
|
|
37
|
+
<span className={clsx('px-2 py-0.5 rounded text-xs font-medium', status.color)}>
|
|
38
|
+
{status.text}
|
|
39
|
+
</span>
|
|
40
|
+
} />
|
|
41
|
+
<Property label="URL" value={url ? (
|
|
42
|
+
<a href={url} target="_blank" rel="noopener noreferrer" className="text-blue-400 hover:text-blue-300 hover:underline break-all">
|
|
43
|
+
{url}
|
|
44
|
+
</a>
|
|
45
|
+
) : undefined} />
|
|
46
|
+
<Property label="Latest Ready" value={latestReady ? (
|
|
47
|
+
<ResourceLink
|
|
48
|
+
name={latestReady}
|
|
49
|
+
kind="revisions"
|
|
50
|
+
namespace={ns}
|
|
51
|
+
onNavigate={onNavigate}
|
|
52
|
+
/>
|
|
53
|
+
) : '-'} />
|
|
54
|
+
<Property label="Latest Created" value={latestCreated ? (
|
|
55
|
+
<ResourceLink
|
|
56
|
+
name={latestCreated}
|
|
57
|
+
kind="revisions"
|
|
58
|
+
namespace={ns}
|
|
59
|
+
onNavigate={onNavigate}
|
|
60
|
+
/>
|
|
61
|
+
) : '-'} />
|
|
62
|
+
<Property label="Generation" value={generation} />
|
|
63
|
+
</PropertyList>
|
|
64
|
+
</Section>
|
|
65
|
+
|
|
66
|
+
{(minScale || maxScale || concurrency != null || timeoutSeconds != null) && (
|
|
67
|
+
<Section title="Scaling & Configuration" defaultExpanded>
|
|
68
|
+
<PropertyList>
|
|
69
|
+
{minScale && <Property label="Min Scale" value={minScale} />}
|
|
70
|
+
{maxScale && <Property label="Max Scale" value={maxScale} />}
|
|
71
|
+
<Property label="Concurrency" value={concurrency != null ? (concurrency === 0 ? 'Unlimited' : String(concurrency)) : undefined} />
|
|
72
|
+
<Property label="Timeout" value={timeoutSeconds != null ? `${timeoutSeconds}s` : undefined} />
|
|
73
|
+
</PropertyList>
|
|
74
|
+
</Section>
|
|
75
|
+
)}
|
|
76
|
+
|
|
77
|
+
{traffic.length > 0 && (
|
|
78
|
+
<Section title={`Traffic (${traffic.length} targets)`} icon={Layers} defaultExpanded>
|
|
79
|
+
<div className="space-y-2">
|
|
80
|
+
{traffic.map((t: any, i: number) => (
|
|
81
|
+
<div key={i} className="flex items-center gap-2 text-sm">
|
|
82
|
+
<div className="flex items-center gap-1 w-16 shrink-0">
|
|
83
|
+
<div className="flex-1 h-1.5 bg-theme-hover rounded-full overflow-hidden">
|
|
84
|
+
<div
|
|
85
|
+
className="h-full bg-blue-500 rounded-full"
|
|
86
|
+
style={{ width: `${t.percent || 0}%` }}
|
|
87
|
+
/>
|
|
88
|
+
</div>
|
|
89
|
+
<span className="text-theme-text-secondary font-medium text-xs">{t.percent || 0}%</span>
|
|
90
|
+
</div>
|
|
91
|
+
{t.revisionName ? (
|
|
92
|
+
<ResourceLink
|
|
93
|
+
name={t.revisionName}
|
|
94
|
+
kind="revisions"
|
|
95
|
+
namespace={ns}
|
|
96
|
+
onNavigate={onNavigate}
|
|
97
|
+
/>
|
|
98
|
+
) : (
|
|
99
|
+
<span className="text-theme-text-secondary">{t.latestRevision ? '@latest' : '-'}</span>
|
|
100
|
+
)}
|
|
101
|
+
{t.tag && (
|
|
102
|
+
<span className="px-1.5 py-0.5 bg-theme-hover rounded text-[10px] text-theme-text-secondary">
|
|
103
|
+
tag: {t.tag}
|
|
104
|
+
</span>
|
|
105
|
+
)}
|
|
106
|
+
{t.url && (
|
|
107
|
+
<a href={t.url} target="_blank" rel="noopener noreferrer" className="text-blue-400 hover:text-blue-300 text-xs">
|
|
108
|
+
{t.tag || 'link'}
|
|
109
|
+
</a>
|
|
110
|
+
)}
|
|
111
|
+
</div>
|
|
112
|
+
))}
|
|
113
|
+
</div>
|
|
114
|
+
</Section>
|
|
115
|
+
)}
|
|
116
|
+
|
|
117
|
+
{containers.length > 0 && (
|
|
118
|
+
<Section title="Template" icon={Container} defaultExpanded>
|
|
119
|
+
<div className="space-y-2">
|
|
120
|
+
{containers.map((c: any, i: number) => (
|
|
121
|
+
<div key={i} className="bg-theme-elevated/30 rounded p-2 text-sm">
|
|
122
|
+
<div className="font-medium text-theme-text-primary">{c.name || 'container'}</div>
|
|
123
|
+
<div className="text-xs text-theme-text-secondary truncate" title={c.image}>{c.image}</div>
|
|
124
|
+
{c.ports && c.ports.length > 0 && (
|
|
125
|
+
<div className="text-xs text-theme-text-tertiary mt-1">
|
|
126
|
+
Ports: {c.ports.map((p: any) => `${p.containerPort}/${p.protocol || 'TCP'}`).join(', ')}
|
|
127
|
+
</div>
|
|
128
|
+
)}
|
|
129
|
+
</div>
|
|
130
|
+
))}
|
|
131
|
+
</div>
|
|
132
|
+
</Section>
|
|
133
|
+
)}
|
|
134
|
+
|
|
135
|
+
<ConditionsSection conditions={data.status?.conditions || []} />
|
|
136
|
+
</>
|
|
137
|
+
)
|
|
138
|
+
}
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import { Clock, Server, Container, Link2 } from 'lucide-react'
|
|
2
|
+
import { clsx } from 'clsx'
|
|
3
|
+
import { Section, PropertyList, Property, ConditionsSection, KnativeNotReadyBanner, ResourceLink } from '../../ui/drawer-components'
|
|
4
|
+
import { getKnativeConditionStatus } from '../resource-utils-knative'
|
|
5
|
+
|
|
6
|
+
interface RendererProps {
|
|
7
|
+
data: any
|
|
8
|
+
onNavigate?: (ref: { kind: string; namespace: string; name: string }) => void
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function SinkProperty({ sink, ns, onNavigate }: { sink: any; ns: string; onNavigate?: RendererProps['onNavigate'] }) {
|
|
12
|
+
if (!sink) return <Property label="Sink" value="-" />
|
|
13
|
+
|
|
14
|
+
if (sink.ref) {
|
|
15
|
+
return (
|
|
16
|
+
<Property label="Sink" value={
|
|
17
|
+
<ResourceLink
|
|
18
|
+
name={sink.ref.name}
|
|
19
|
+
kind={(sink.ref.kind?.toLowerCase() || 'services') + (sink.ref.kind?.toLowerCase().endsWith('s') ? '' : 's')}
|
|
20
|
+
namespace={sink.ref.namespace || ns}
|
|
21
|
+
onNavigate={onNavigate}
|
|
22
|
+
/>
|
|
23
|
+
} />
|
|
24
|
+
)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (sink.uri) {
|
|
28
|
+
return <Property label="Sink URI" value={
|
|
29
|
+
<span className="text-theme-text-primary break-all">{sink.uri}</span>
|
|
30
|
+
} />
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return <Property label="Sink" value="-" />
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// ============================================================================
|
|
37
|
+
// PingSource
|
|
38
|
+
// ============================================================================
|
|
39
|
+
|
|
40
|
+
export function PingSourceRenderer({ data, onNavigate }: RendererProps) {
|
|
41
|
+
const status = getKnativeConditionStatus(data)
|
|
42
|
+
const ns = data.metadata?.namespace || ''
|
|
43
|
+
const spec = data.spec || {}
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<>
|
|
47
|
+
<KnativeNotReadyBanner status={status} data={data} resourceType="PingSource" />
|
|
48
|
+
|
|
49
|
+
<Section title="Overview" icon={Clock} defaultExpanded>
|
|
50
|
+
<PropertyList>
|
|
51
|
+
<Property label="Status" value={
|
|
52
|
+
<span className={clsx('px-2 py-0.5 rounded text-xs font-medium', status.color)}>
|
|
53
|
+
{status.text}
|
|
54
|
+
</span>
|
|
55
|
+
} />
|
|
56
|
+
<Property label="Schedule" value={spec.schedule} />
|
|
57
|
+
<Property label="Timezone" value={spec.timezone} />
|
|
58
|
+
<Property label="Content Type" value={spec.contentType} />
|
|
59
|
+
<Property label="Data" value={spec.data ? (
|
|
60
|
+
<span className="font-mono text-xs break-all">{spec.data.length > 200 ? spec.data.slice(0, 200) + '...' : spec.data}</span>
|
|
61
|
+
) : undefined} />
|
|
62
|
+
<SinkProperty sink={spec.sink} ns={ns} onNavigate={onNavigate} />
|
|
63
|
+
</PropertyList>
|
|
64
|
+
</Section>
|
|
65
|
+
|
|
66
|
+
<ConditionsSection conditions={data.status?.conditions || []} />
|
|
67
|
+
</>
|
|
68
|
+
)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// ============================================================================
|
|
72
|
+
// ApiServerSource
|
|
73
|
+
// ============================================================================
|
|
74
|
+
|
|
75
|
+
export function ApiServerSourceRenderer({ data, onNavigate }: RendererProps) {
|
|
76
|
+
const status = getKnativeConditionStatus(data)
|
|
77
|
+
const ns = data.metadata?.namespace || ''
|
|
78
|
+
const spec = data.spec || {}
|
|
79
|
+
const resources = spec.resources || []
|
|
80
|
+
|
|
81
|
+
return (
|
|
82
|
+
<>
|
|
83
|
+
<KnativeNotReadyBanner status={status} data={data} resourceType="ApiServerSource" />
|
|
84
|
+
|
|
85
|
+
<Section title="Overview" icon={Server} defaultExpanded>
|
|
86
|
+
<PropertyList>
|
|
87
|
+
<Property label="Status" value={
|
|
88
|
+
<span className={clsx('px-2 py-0.5 rounded text-xs font-medium', status.color)}>
|
|
89
|
+
{status.text}
|
|
90
|
+
</span>
|
|
91
|
+
} />
|
|
92
|
+
<Property label="Mode" value={spec.mode || spec.eventMode} />
|
|
93
|
+
<Property label="Service Account" value={spec.serviceAccountName} />
|
|
94
|
+
<SinkProperty sink={spec.sink} ns={ns} onNavigate={onNavigate} />
|
|
95
|
+
</PropertyList>
|
|
96
|
+
</Section>
|
|
97
|
+
|
|
98
|
+
{resources.length > 0 && (
|
|
99
|
+
<Section title={`Watched Resources (${resources.length})`} defaultExpanded>
|
|
100
|
+
<div className="space-y-1.5">
|
|
101
|
+
{resources.map((r: any, i: number) => (
|
|
102
|
+
<div key={i} className="bg-theme-elevated/30 rounded p-2 text-sm">
|
|
103
|
+
<span className="text-theme-text-primary">{r.apiVersion}/{r.kind}</span>
|
|
104
|
+
{r.selector && (
|
|
105
|
+
<div className="text-xs text-theme-text-tertiary mt-0.5">
|
|
106
|
+
selector: {typeof r.selector === 'string' ? r.selector : JSON.stringify(r.selector.matchLabels || r.selector)}
|
|
107
|
+
</div>
|
|
108
|
+
)}
|
|
109
|
+
</div>
|
|
110
|
+
))}
|
|
111
|
+
</div>
|
|
112
|
+
</Section>
|
|
113
|
+
)}
|
|
114
|
+
|
|
115
|
+
<ConditionsSection conditions={data.status?.conditions || []} />
|
|
116
|
+
</>
|
|
117
|
+
)
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// ============================================================================
|
|
121
|
+
// ContainerSource
|
|
122
|
+
// ============================================================================
|
|
123
|
+
|
|
124
|
+
export function ContainerSourceRenderer({ data, onNavigate }: RendererProps) {
|
|
125
|
+
const status = getKnativeConditionStatus(data)
|
|
126
|
+
const ns = data.metadata?.namespace || ''
|
|
127
|
+
const spec = data.spec || {}
|
|
128
|
+
const template = spec.template?.spec || {}
|
|
129
|
+
const containers = template.containers || []
|
|
130
|
+
|
|
131
|
+
return (
|
|
132
|
+
<>
|
|
133
|
+
<KnativeNotReadyBanner status={status} data={data} resourceType="ContainerSource" />
|
|
134
|
+
|
|
135
|
+
<Section title="Overview" icon={Container} defaultExpanded>
|
|
136
|
+
<PropertyList>
|
|
137
|
+
<Property label="Status" value={
|
|
138
|
+
<span className={clsx('px-2 py-0.5 rounded text-xs font-medium', status.color)}>
|
|
139
|
+
{status.text}
|
|
140
|
+
</span>
|
|
141
|
+
} />
|
|
142
|
+
<SinkProperty sink={spec.sink} ns={ns} onNavigate={onNavigate} />
|
|
143
|
+
</PropertyList>
|
|
144
|
+
</Section>
|
|
145
|
+
|
|
146
|
+
{containers.length > 0 && (
|
|
147
|
+
<Section title={`Containers (${containers.length})`} defaultExpanded>
|
|
148
|
+
<div className="space-y-2">
|
|
149
|
+
{containers.map((c: any, i: number) => (
|
|
150
|
+
<div key={i} className="bg-theme-elevated/30 rounded p-2 text-sm">
|
|
151
|
+
<div className="font-medium text-theme-text-primary">{c.name || 'container'}</div>
|
|
152
|
+
<div className="text-xs text-theme-text-secondary truncate" title={c.image}>{c.image}</div>
|
|
153
|
+
{c.args && c.args.length > 0 && (
|
|
154
|
+
<div className="text-xs text-theme-text-tertiary mt-1 font-mono truncate">
|
|
155
|
+
$ {c.args.join(' ')}
|
|
156
|
+
</div>
|
|
157
|
+
)}
|
|
158
|
+
</div>
|
|
159
|
+
))}
|
|
160
|
+
</div>
|
|
161
|
+
</Section>
|
|
162
|
+
)}
|
|
163
|
+
|
|
164
|
+
<ConditionsSection conditions={data.status?.conditions || []} />
|
|
165
|
+
</>
|
|
166
|
+
)
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// ============================================================================
|
|
170
|
+
// SinkBinding
|
|
171
|
+
// ============================================================================
|
|
172
|
+
|
|
173
|
+
export function SinkBindingRenderer({ data, onNavigate }: RendererProps) {
|
|
174
|
+
const status = getKnativeConditionStatus(data)
|
|
175
|
+
const ns = data.metadata?.namespace || ''
|
|
176
|
+
const spec = data.spec || {}
|
|
177
|
+
const subjectRef = spec.subject
|
|
178
|
+
|
|
179
|
+
return (
|
|
180
|
+
<>
|
|
181
|
+
<KnativeNotReadyBanner status={status} data={data} resourceType="SinkBinding" />
|
|
182
|
+
|
|
183
|
+
<Section title="Overview" icon={Link2} defaultExpanded>
|
|
184
|
+
<PropertyList>
|
|
185
|
+
<Property label="Status" value={
|
|
186
|
+
<span className={clsx('px-2 py-0.5 rounded text-xs font-medium', status.color)}>
|
|
187
|
+
{status.text}
|
|
188
|
+
</span>
|
|
189
|
+
} />
|
|
190
|
+
{subjectRef && (
|
|
191
|
+
<>
|
|
192
|
+
<Property label="Subject Kind" value={subjectRef.kind} />
|
|
193
|
+
<Property label="Subject API" value={subjectRef.apiVersion} />
|
|
194
|
+
{subjectRef.name && (
|
|
195
|
+
<Property label="Subject" value={
|
|
196
|
+
<ResourceLink
|
|
197
|
+
name={subjectRef.name}
|
|
198
|
+
kind={(subjectRef.kind?.toLowerCase() || 'deployments') + 's'}
|
|
199
|
+
namespace={subjectRef.namespace || ns}
|
|
200
|
+
onNavigate={onNavigate}
|
|
201
|
+
/>
|
|
202
|
+
} />
|
|
203
|
+
)}
|
|
204
|
+
{subjectRef.selector && (
|
|
205
|
+
<Property label="Selector" value={
|
|
206
|
+
<span className="text-xs font-mono">
|
|
207
|
+
{JSON.stringify(subjectRef.selector.matchLabels || subjectRef.selector)}
|
|
208
|
+
</span>
|
|
209
|
+
} />
|
|
210
|
+
)}
|
|
211
|
+
</>
|
|
212
|
+
)}
|
|
213
|
+
<SinkProperty sink={spec.sink} ns={ns} onNavigate={onNavigate} />
|
|
214
|
+
</PropertyList>
|
|
215
|
+
</Section>
|
|
216
|
+
|
|
217
|
+
<ConditionsSection conditions={data.status?.conditions || []} />
|
|
218
|
+
</>
|
|
219
|
+
)
|
|
220
|
+
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { Layers, FolderTree } from 'lucide-react'
|
|
2
|
+
import { Section, PropertyList, Property, ConditionsSection, ProblemAlerts } from '../../ui/drawer-components'
|
|
3
|
+
import { formatAge } from '../resource-utils'
|
|
4
|
+
import { GitOpsStatusBadge, ManagedResourcesList, SyncCountdown } from '../../gitops'
|
|
5
|
+
import { fluxConditionsToGitOpsStatus, parseFluxInventory, type FluxCondition } from '../../../types/gitops'
|
|
6
|
+
|
|
7
|
+
interface KustomizationRendererProps {
|
|
8
|
+
data: any
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function KustomizationRenderer({ data }: KustomizationRendererProps) {
|
|
12
|
+
const status = data.status || {}
|
|
13
|
+
const spec = data.spec || {}
|
|
14
|
+
const conditions = (status.conditions || []) as FluxCondition[]
|
|
15
|
+
const inventoryEntries = status.inventory?.entries || []
|
|
16
|
+
|
|
17
|
+
// Convert to unified GitOps status
|
|
18
|
+
const gitOpsStatus = fluxConditionsToGitOpsStatus(conditions, spec.suspend === true)
|
|
19
|
+
|
|
20
|
+
// Parse inventory to managed resources
|
|
21
|
+
const managedResources = parseFluxInventory(inventoryEntries)
|
|
22
|
+
|
|
23
|
+
// Problem detection for alerts
|
|
24
|
+
const problems: Array<{ color: 'red' | 'yellow'; message: string }> = []
|
|
25
|
+
|
|
26
|
+
if (gitOpsStatus.suspended) {
|
|
27
|
+
problems.push({ color: 'yellow', message: 'Kustomization is suspended' })
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (gitOpsStatus.health === 'Degraded' && gitOpsStatus.message) {
|
|
31
|
+
problems.push({ color: 'red', message: gitOpsStatus.message })
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const healthyCondition = conditions.find(c => c.type === 'Healthy')
|
|
35
|
+
if (healthyCondition?.status === 'False' && healthyCondition.message) {
|
|
36
|
+
problems.push({
|
|
37
|
+
color: 'yellow',
|
|
38
|
+
message: healthyCondition.message || 'Deployed resources are not healthy',
|
|
39
|
+
})
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Source reference
|
|
43
|
+
const sourceRef = spec.sourceRef || {}
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<>
|
|
47
|
+
<ProblemAlerts problems={problems} />
|
|
48
|
+
|
|
49
|
+
{/* Status section */}
|
|
50
|
+
<Section title="Status">
|
|
51
|
+
<div className="space-y-3">
|
|
52
|
+
<GitOpsStatusBadge status={gitOpsStatus} />
|
|
53
|
+
{spec.interval && (
|
|
54
|
+
<SyncCountdown
|
|
55
|
+
interval={spec.interval}
|
|
56
|
+
lastSyncTime={status.lastHandledReconcileAt}
|
|
57
|
+
suspended={gitOpsStatus.suspended}
|
|
58
|
+
/>
|
|
59
|
+
)}
|
|
60
|
+
</div>
|
|
61
|
+
</Section>
|
|
62
|
+
|
|
63
|
+
{/* Source Reference section */}
|
|
64
|
+
<Section title="Source" icon={FolderTree}>
|
|
65
|
+
<PropertyList>
|
|
66
|
+
<Property label="Kind" value={sourceRef.kind} />
|
|
67
|
+
<Property label="Name" value={sourceRef.name} />
|
|
68
|
+
{sourceRef.namespace && (
|
|
69
|
+
<Property label="Namespace" value={sourceRef.namespace} />
|
|
70
|
+
)}
|
|
71
|
+
<Property label="Path" value={spec.path || './'} />
|
|
72
|
+
</PropertyList>
|
|
73
|
+
</Section>
|
|
74
|
+
|
|
75
|
+
{/* Configuration section */}
|
|
76
|
+
<Section title="Configuration" icon={Layers}>
|
|
77
|
+
<PropertyList>
|
|
78
|
+
<Property
|
|
79
|
+
label="Prune"
|
|
80
|
+
value={spec.prune ? 'Enabled' : 'Disabled'}
|
|
81
|
+
/>
|
|
82
|
+
<Property label="Target Namespace" value={spec.targetNamespace} />
|
|
83
|
+
<Property label="Service Account" value={spec.serviceAccountName} />
|
|
84
|
+
<Property label="Timeout" value={spec.timeout} />
|
|
85
|
+
{spec.retryInterval && (
|
|
86
|
+
<Property label="Retry Interval" value={spec.retryInterval} />
|
|
87
|
+
)}
|
|
88
|
+
{spec.force !== undefined && (
|
|
89
|
+
<Property label="Force" value={spec.force ? 'Yes' : 'No'} />
|
|
90
|
+
)}
|
|
91
|
+
{spec.wait !== undefined && (
|
|
92
|
+
<Property label="Wait" value={spec.wait ? 'Yes' : 'No'} />
|
|
93
|
+
)}
|
|
94
|
+
</PropertyList>
|
|
95
|
+
</Section>
|
|
96
|
+
|
|
97
|
+
{/* Health checks */}
|
|
98
|
+
{spec.healthChecks && spec.healthChecks.length > 0 && (
|
|
99
|
+
<Section title={`Health Checks (${spec.healthChecks.length})`} defaultExpanded={false}>
|
|
100
|
+
<div className="space-y-1">
|
|
101
|
+
{spec.healthChecks.map((check: any, idx: number) => (
|
|
102
|
+
<div
|
|
103
|
+
key={idx}
|
|
104
|
+
className="text-sm px-2 py-1 bg-theme-elevated/30 rounded"
|
|
105
|
+
>
|
|
106
|
+
<span className="text-theme-text-tertiary">{check.kind}/</span>
|
|
107
|
+
<span className="text-theme-text-primary">{check.name}</span>
|
|
108
|
+
{check.namespace && (
|
|
109
|
+
<span className="text-theme-text-tertiary ml-1">
|
|
110
|
+
({check.namespace})
|
|
111
|
+
</span>
|
|
112
|
+
)}
|
|
113
|
+
</div>
|
|
114
|
+
))}
|
|
115
|
+
</div>
|
|
116
|
+
</Section>
|
|
117
|
+
)}
|
|
118
|
+
|
|
119
|
+
{/* Managed Resources (Inventory) */}
|
|
120
|
+
{managedResources.length > 0 && (
|
|
121
|
+
<ManagedResourcesList
|
|
122
|
+
resources={managedResources}
|
|
123
|
+
title={`Inventory (${managedResources.length} resources)`}
|
|
124
|
+
/>
|
|
125
|
+
)}
|
|
126
|
+
|
|
127
|
+
{/* Revision info */}
|
|
128
|
+
{(status.lastAppliedRevision || status.lastAttemptedRevision) && (
|
|
129
|
+
<Section title="Revision" defaultExpanded={false}>
|
|
130
|
+
<PropertyList>
|
|
131
|
+
{status.lastAppliedRevision && (
|
|
132
|
+
<Property label="Applied" value={status.lastAppliedRevision} />
|
|
133
|
+
)}
|
|
134
|
+
{status.lastAttemptedRevision && status.lastAttemptedRevision !== status.lastAppliedRevision && (
|
|
135
|
+
<Property label="Attempted" value={status.lastAttemptedRevision} />
|
|
136
|
+
)}
|
|
137
|
+
{status.lastHandledReconcileAt && (
|
|
138
|
+
<Property
|
|
139
|
+
label="Last Reconciled"
|
|
140
|
+
value={formatAge(status.lastHandledReconcileAt)}
|
|
141
|
+
/>
|
|
142
|
+
)}
|
|
143
|
+
</PropertyList>
|
|
144
|
+
</Section>
|
|
145
|
+
)}
|
|
146
|
+
|
|
147
|
+
{/* Conditions section */}
|
|
148
|
+
<ConditionsSection conditions={conditions} />
|
|
149
|
+
</>
|
|
150
|
+
)
|
|
151
|
+
}
|