@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,142 @@
|
|
|
1
|
+
import { ListOrdered, GitFork } 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 RefDisplay({ ref: destRef, ns, onNavigate }: { ref: any; ns: string; onNavigate?: RendererProps['onNavigate'] }) {
|
|
12
|
+
if (!destRef) return <span className="text-theme-text-tertiary">-</span>
|
|
13
|
+
|
|
14
|
+
if (destRef.ref) {
|
|
15
|
+
return (
|
|
16
|
+
<ResourceLink
|
|
17
|
+
name={destRef.ref.name}
|
|
18
|
+
kind={(destRef.ref.kind?.toLowerCase() || 'services') + (destRef.ref.kind?.toLowerCase().endsWith('s') ? '' : 's')}
|
|
19
|
+
namespace={destRef.ref.namespace || ns}
|
|
20
|
+
onNavigate={onNavigate}
|
|
21
|
+
/>
|
|
22
|
+
)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (destRef.uri) {
|
|
26
|
+
return <span className="text-theme-text-primary break-all text-xs">{destRef.uri}</span>
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return <span className="text-theme-text-tertiary">-</span>
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// ============================================================================
|
|
33
|
+
// Sequence
|
|
34
|
+
// ============================================================================
|
|
35
|
+
|
|
36
|
+
export function SequenceRenderer({ data, onNavigate }: RendererProps) {
|
|
37
|
+
const status = getKnativeConditionStatus(data)
|
|
38
|
+
const ns = data.metadata?.namespace || ''
|
|
39
|
+
const spec = data.spec || {}
|
|
40
|
+
const steps = spec.steps || []
|
|
41
|
+
const reply = spec.reply
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<>
|
|
45
|
+
<KnativeNotReadyBanner status={status} data={data} resourceType="Sequence" />
|
|
46
|
+
|
|
47
|
+
<Section title="Overview" icon={ListOrdered} defaultExpanded>
|
|
48
|
+
<PropertyList>
|
|
49
|
+
<Property label="Status" value={
|
|
50
|
+
<span className={clsx('px-2 py-0.5 rounded text-xs font-medium', status.color)}>
|
|
51
|
+
{status.text}
|
|
52
|
+
</span>
|
|
53
|
+
} />
|
|
54
|
+
<Property label="Steps" value={String(steps.length)} />
|
|
55
|
+
{reply && (
|
|
56
|
+
<Property label="Reply" value={
|
|
57
|
+
<RefDisplay ref={reply} ns={ns} onNavigate={onNavigate} />
|
|
58
|
+
} />
|
|
59
|
+
)}
|
|
60
|
+
</PropertyList>
|
|
61
|
+
</Section>
|
|
62
|
+
|
|
63
|
+
{steps.length > 0 && (
|
|
64
|
+
<Section title={`Steps (${steps.length})`} defaultExpanded>
|
|
65
|
+
<div className="space-y-2">
|
|
66
|
+
{steps.map((step: any, i: number) => (
|
|
67
|
+
<div key={i} className="bg-theme-elevated/30 rounded p-2 flex items-center gap-2">
|
|
68
|
+
<span className="text-xs font-medium text-theme-text-tertiary w-6 shrink-0">#{i + 1}</span>
|
|
69
|
+
<RefDisplay ref={step} ns={ns} onNavigate={onNavigate} />
|
|
70
|
+
</div>
|
|
71
|
+
))}
|
|
72
|
+
</div>
|
|
73
|
+
</Section>
|
|
74
|
+
)}
|
|
75
|
+
|
|
76
|
+
<ConditionsSection conditions={data.status?.conditions || []} />
|
|
77
|
+
</>
|
|
78
|
+
)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// ============================================================================
|
|
82
|
+
// Parallel
|
|
83
|
+
// ============================================================================
|
|
84
|
+
|
|
85
|
+
export function ParallelRenderer({ data, onNavigate }: RendererProps) {
|
|
86
|
+
const status = getKnativeConditionStatus(data)
|
|
87
|
+
const ns = data.metadata?.namespace || ''
|
|
88
|
+
const spec = data.spec || {}
|
|
89
|
+
const branches = spec.branches || []
|
|
90
|
+
const reply = spec.reply
|
|
91
|
+
|
|
92
|
+
return (
|
|
93
|
+
<>
|
|
94
|
+
<KnativeNotReadyBanner status={status} data={data} resourceType="Parallel" />
|
|
95
|
+
|
|
96
|
+
<Section title="Overview" icon={GitFork} defaultExpanded>
|
|
97
|
+
<PropertyList>
|
|
98
|
+
<Property label="Status" value={
|
|
99
|
+
<span className={clsx('px-2 py-0.5 rounded text-xs font-medium', status.color)}>
|
|
100
|
+
{status.text}
|
|
101
|
+
</span>
|
|
102
|
+
} />
|
|
103
|
+
<Property label="Branches" value={String(branches.length)} />
|
|
104
|
+
{reply && (
|
|
105
|
+
<Property label="Reply" value={
|
|
106
|
+
<RefDisplay ref={reply} ns={ns} onNavigate={onNavigate} />
|
|
107
|
+
} />
|
|
108
|
+
)}
|
|
109
|
+
</PropertyList>
|
|
110
|
+
</Section>
|
|
111
|
+
|
|
112
|
+
{branches.length > 0 && (
|
|
113
|
+
<Section title={`Branches (${branches.length})`} defaultExpanded>
|
|
114
|
+
<div className="space-y-3">
|
|
115
|
+
{branches.map((branch: any, i: number) => (
|
|
116
|
+
<div key={i} className="bg-theme-elevated/30 rounded p-3">
|
|
117
|
+
<div className="text-sm font-medium text-theme-text-primary mb-2">Branch {i + 1}</div>
|
|
118
|
+
<PropertyList>
|
|
119
|
+
{branch.filter && (
|
|
120
|
+
<Property label="Filter" value={
|
|
121
|
+
<RefDisplay ref={branch.filter} ns={ns} onNavigate={onNavigate} />
|
|
122
|
+
} />
|
|
123
|
+
)}
|
|
124
|
+
<Property label="Subscriber" value={
|
|
125
|
+
<RefDisplay ref={branch.subscriber} ns={ns} onNavigate={onNavigate} />
|
|
126
|
+
} />
|
|
127
|
+
{branch.reply && (
|
|
128
|
+
<Property label="Reply" value={
|
|
129
|
+
<RefDisplay ref={branch.reply} ns={ns} onNavigate={onNavigate} />
|
|
130
|
+
} />
|
|
131
|
+
)}
|
|
132
|
+
</PropertyList>
|
|
133
|
+
</div>
|
|
134
|
+
))}
|
|
135
|
+
</div>
|
|
136
|
+
</Section>
|
|
137
|
+
)}
|
|
138
|
+
|
|
139
|
+
<ConditionsSection conditions={data.status?.conditions || []} />
|
|
140
|
+
</>
|
|
141
|
+
)
|
|
142
|
+
}
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import { Network, ShieldCheck, Server, Globe } 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
|
+
// ============================================================================
|
|
12
|
+
// KnativeIngress (Ingress from networking.internal.knative.dev)
|
|
13
|
+
// ============================================================================
|
|
14
|
+
|
|
15
|
+
export function KnativeIngressRenderer({ data }: RendererProps) {
|
|
16
|
+
const status = getKnativeConditionStatus(data)
|
|
17
|
+
const spec = data.spec || {}
|
|
18
|
+
const rules = spec.rules || []
|
|
19
|
+
const ingressClass = data.metadata?.annotations?.['networking.knative.dev/ingress.class']
|
|
20
|
+
const httpOption = spec.httpOption
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<>
|
|
24
|
+
<KnativeNotReadyBanner status={status} data={data} resourceType="Ingress" />
|
|
25
|
+
|
|
26
|
+
<Section title="Overview" icon={Network} defaultExpanded>
|
|
27
|
+
<PropertyList>
|
|
28
|
+
<Property label="Status" value={
|
|
29
|
+
<span className={clsx('px-2 py-0.5 rounded text-xs font-medium', status.color)}>
|
|
30
|
+
{status.text}
|
|
31
|
+
</span>
|
|
32
|
+
} />
|
|
33
|
+
<Property label="Ingress Class" value={ingressClass} />
|
|
34
|
+
<Property label="HTTP" value={httpOption} />
|
|
35
|
+
</PropertyList>
|
|
36
|
+
</Section>
|
|
37
|
+
|
|
38
|
+
{rules.length > 0 && (
|
|
39
|
+
<Section title={`Rules (${rules.length})`} defaultExpanded>
|
|
40
|
+
<div className="space-y-3">
|
|
41
|
+
{rules.map((rule: any, i: number) => (
|
|
42
|
+
<div key={i} className="bg-theme-elevated/30 rounded p-3">
|
|
43
|
+
<div className="flex flex-wrap gap-1 mb-2">
|
|
44
|
+
{(rule.hosts || []).map((host: string, hi: number) => (
|
|
45
|
+
<span key={hi} className="px-1.5 py-0.5 bg-blue-500/10 text-blue-400 rounded text-xs">
|
|
46
|
+
{host}
|
|
47
|
+
</span>
|
|
48
|
+
))}
|
|
49
|
+
{rule.visibility && (
|
|
50
|
+
<span className="px-1.5 py-0.5 bg-theme-hover rounded text-[10px] text-theme-text-secondary">
|
|
51
|
+
{rule.visibility}
|
|
52
|
+
</span>
|
|
53
|
+
)}
|
|
54
|
+
</div>
|
|
55
|
+
{rule.http?.paths && rule.http.paths.length > 0 && (
|
|
56
|
+
<div className="space-y-1.5">
|
|
57
|
+
{rule.http.paths.map((path: any, pi: number) => (
|
|
58
|
+
<div key={pi} className="text-xs">
|
|
59
|
+
<span className="text-theme-text-tertiary">
|
|
60
|
+
{path.path || '/'}
|
|
61
|
+
</span>
|
|
62
|
+
{path.splits && path.splits.length > 0 && (
|
|
63
|
+
<div className="ml-3 mt-1 space-y-0.5">
|
|
64
|
+
{path.splits.map((split: any, si: number) => (
|
|
65
|
+
<div key={si} className="text-theme-text-secondary">
|
|
66
|
+
{split.serviceName}:{split.servicePort}
|
|
67
|
+
{split.percent !== undefined && (
|
|
68
|
+
<span className="text-theme-text-tertiary ml-1">({split.percent}%)</span>
|
|
69
|
+
)}
|
|
70
|
+
</div>
|
|
71
|
+
))}
|
|
72
|
+
</div>
|
|
73
|
+
)}
|
|
74
|
+
</div>
|
|
75
|
+
))}
|
|
76
|
+
</div>
|
|
77
|
+
)}
|
|
78
|
+
</div>
|
|
79
|
+
))}
|
|
80
|
+
</div>
|
|
81
|
+
</Section>
|
|
82
|
+
)}
|
|
83
|
+
|
|
84
|
+
<ConditionsSection conditions={data.status?.conditions || []} />
|
|
85
|
+
</>
|
|
86
|
+
)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// ============================================================================
|
|
90
|
+
// KnativeCertificate (Certificate from networking.internal.knative.dev)
|
|
91
|
+
// ============================================================================
|
|
92
|
+
|
|
93
|
+
export function KnativeCertificateRenderer({ data }: RendererProps) {
|
|
94
|
+
const status = getKnativeConditionStatus(data)
|
|
95
|
+
const spec = data.spec || {}
|
|
96
|
+
const dnsNames = spec.dnsNames || []
|
|
97
|
+
const secretName = spec.secretName || data.status?.http01Challenges?.[0]?.secretName
|
|
98
|
+
|
|
99
|
+
return (
|
|
100
|
+
<>
|
|
101
|
+
<KnativeNotReadyBanner status={status} data={data} resourceType="Certificate" />
|
|
102
|
+
|
|
103
|
+
<Section title="Overview" icon={ShieldCheck} defaultExpanded>
|
|
104
|
+
<PropertyList>
|
|
105
|
+
<Property label="Status" value={
|
|
106
|
+
<span className={clsx('px-2 py-0.5 rounded text-xs font-medium', status.color)}>
|
|
107
|
+
{status.text}
|
|
108
|
+
</span>
|
|
109
|
+
} />
|
|
110
|
+
<Property label="Secret Name" value={secretName} />
|
|
111
|
+
<Property label="Domain" value={spec.domain} />
|
|
112
|
+
</PropertyList>
|
|
113
|
+
</Section>
|
|
114
|
+
|
|
115
|
+
{dnsNames.length > 0 && (
|
|
116
|
+
<Section title={`DNS Names (${dnsNames.length})`} defaultExpanded>
|
|
117
|
+
<div className="flex flex-wrap gap-1">
|
|
118
|
+
{dnsNames.map((name: string, i: number) => (
|
|
119
|
+
<span key={i} className="px-1.5 py-0.5 bg-theme-elevated rounded text-xs text-theme-text-secondary">
|
|
120
|
+
{name}
|
|
121
|
+
</span>
|
|
122
|
+
))}
|
|
123
|
+
</div>
|
|
124
|
+
</Section>
|
|
125
|
+
)}
|
|
126
|
+
|
|
127
|
+
<ConditionsSection conditions={data.status?.conditions || []} />
|
|
128
|
+
</>
|
|
129
|
+
)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// ============================================================================
|
|
133
|
+
// ServerlessService (from networking.internal.knative.dev)
|
|
134
|
+
// ============================================================================
|
|
135
|
+
|
|
136
|
+
export function ServerlessServiceRenderer({ data, onNavigate }: RendererProps) {
|
|
137
|
+
const status = getKnativeConditionStatus(data)
|
|
138
|
+
const ns = data.metadata?.namespace || ''
|
|
139
|
+
const spec = data.spec || {}
|
|
140
|
+
const mode = spec.mode
|
|
141
|
+
const numActivators = spec.numActivators
|
|
142
|
+
const protocolType = spec.protocolType
|
|
143
|
+
const objectRef = spec.objectRef
|
|
144
|
+
const privateServiceName = data.status?.privateServiceName
|
|
145
|
+
const serviceName = data.status?.serviceName
|
|
146
|
+
|
|
147
|
+
return (
|
|
148
|
+
<>
|
|
149
|
+
<KnativeNotReadyBanner status={status} data={data} resourceType="ServerlessService" />
|
|
150
|
+
|
|
151
|
+
<Section title="Overview" icon={Server} defaultExpanded>
|
|
152
|
+
<PropertyList>
|
|
153
|
+
<Property label="Status" value={
|
|
154
|
+
<span className={clsx('px-2 py-0.5 rounded text-xs font-medium', status.color)}>
|
|
155
|
+
{status.text}
|
|
156
|
+
</span>
|
|
157
|
+
} />
|
|
158
|
+
<Property label="Mode" value={mode ? (
|
|
159
|
+
<span className={clsx(
|
|
160
|
+
'px-2 py-0.5 rounded text-xs font-medium',
|
|
161
|
+
mode === 'Proxy' ? 'bg-yellow-500/20 text-yellow-400' : 'bg-green-500/20 text-green-400'
|
|
162
|
+
)}>
|
|
163
|
+
{mode}
|
|
164
|
+
</span>
|
|
165
|
+
) : undefined} />
|
|
166
|
+
<Property label="Activators" value={numActivators != null ? String(numActivators) : undefined} />
|
|
167
|
+
<Property label="Protocol" value={protocolType} />
|
|
168
|
+
{objectRef && (
|
|
169
|
+
<Property label="Target" value={
|
|
170
|
+
<ResourceLink
|
|
171
|
+
name={objectRef.name}
|
|
172
|
+
kind={(objectRef.kind?.toLowerCase() || 'deployments') + 's'}
|
|
173
|
+
namespace={ns}
|
|
174
|
+
onNavigate={onNavigate}
|
|
175
|
+
/>
|
|
176
|
+
} />
|
|
177
|
+
)}
|
|
178
|
+
{serviceName && <Property label="Public Service" value={serviceName} />}
|
|
179
|
+
{privateServiceName && <Property label="Private Service" value={privateServiceName} />}
|
|
180
|
+
</PropertyList>
|
|
181
|
+
</Section>
|
|
182
|
+
|
|
183
|
+
<ConditionsSection conditions={data.status?.conditions || []} />
|
|
184
|
+
</>
|
|
185
|
+
)
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// ============================================================================
|
|
189
|
+
// DomainMapping (serving.knative.dev/v1beta1)
|
|
190
|
+
// ============================================================================
|
|
191
|
+
|
|
192
|
+
export function DomainMappingRenderer({ data, onNavigate }: RendererProps) {
|
|
193
|
+
const status = getKnativeConditionStatus(data)
|
|
194
|
+
const ns = data.metadata?.namespace || ''
|
|
195
|
+
const url = data.status?.url
|
|
196
|
+
const ref = data.spec?.ref
|
|
197
|
+
const tlsSecret = data.spec?.tls?.secretName
|
|
198
|
+
|
|
199
|
+
return (
|
|
200
|
+
<>
|
|
201
|
+
<KnativeNotReadyBanner status={status} data={data} resourceType="DomainMapping" />
|
|
202
|
+
|
|
203
|
+
<Section title="Overview" icon={Globe} defaultExpanded>
|
|
204
|
+
<PropertyList>
|
|
205
|
+
<Property label="Status" value={
|
|
206
|
+
<span className={clsx('px-2 py-0.5 rounded text-xs font-medium', status.color)}>
|
|
207
|
+
{status.text}
|
|
208
|
+
</span>
|
|
209
|
+
} />
|
|
210
|
+
<Property label="URL" value={url ? (
|
|
211
|
+
<a href={url} target="_blank" rel="noopener noreferrer" className="text-blue-400 hover:text-blue-300 break-all">
|
|
212
|
+
{url}
|
|
213
|
+
</a>
|
|
214
|
+
) : undefined} />
|
|
215
|
+
{ref && (
|
|
216
|
+
<Property label="Target" value={
|
|
217
|
+
<ResourceLink
|
|
218
|
+
name={ref.name}
|
|
219
|
+
kind={(ref.kind?.toLowerCase() || 'services') + (ref.kind?.toLowerCase().endsWith('s') ? '' : 's')}
|
|
220
|
+
namespace={ns}
|
|
221
|
+
onNavigate={onNavigate}
|
|
222
|
+
/>
|
|
223
|
+
} />
|
|
224
|
+
)}
|
|
225
|
+
{tlsSecret && <Property label="TLS Secret" value={tlsSecret} />}
|
|
226
|
+
</PropertyList>
|
|
227
|
+
</Section>
|
|
228
|
+
|
|
229
|
+
<ConditionsSection conditions={data.status?.conditions || []} />
|
|
230
|
+
</>
|
|
231
|
+
)
|
|
232
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { Container, Settings } from 'lucide-react'
|
|
2
|
+
import { clsx } from 'clsx'
|
|
3
|
+
import { Section, PropertyList, Property, ConditionsSection, KnativeNotReadyBanner } from '../../ui/drawer-components'
|
|
4
|
+
import { getRevisionStatus } from '../resource-utils-knative'
|
|
5
|
+
|
|
6
|
+
interface KnativeRevisionRendererProps {
|
|
7
|
+
data: any
|
|
8
|
+
onNavigate?: (ref: { kind: string; namespace: string; name: string }) => void
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function KnativeRevisionRenderer({ data }: KnativeRevisionRendererProps) {
|
|
12
|
+
const status = getRevisionStatus(data)
|
|
13
|
+
const spec = data.spec || {}
|
|
14
|
+
const containers = spec.containers || []
|
|
15
|
+
const containerConcurrency = spec.containerConcurrency
|
|
16
|
+
const timeoutSeconds = spec.timeoutSeconds
|
|
17
|
+
const serviceAccountName = spec.serviceAccountName
|
|
18
|
+
|
|
19
|
+
const firstContainer = containers[0] || {}
|
|
20
|
+
const image = firstContainer.image
|
|
21
|
+
|
|
22
|
+
// Runtime status
|
|
23
|
+
const actualReplicas = data.status?.actualReplicas
|
|
24
|
+
const desiredReplicas = data.status?.desiredReplicas
|
|
25
|
+
const routingState = data.metadata?.labels?.['serving.knative.dev/routingState']
|
|
26
|
+
const imageDigest = data.status?.containerStatuses?.[0]?.imageDigest
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<>
|
|
30
|
+
<KnativeNotReadyBanner status={status} data={data} resourceType="Revision" />
|
|
31
|
+
|
|
32
|
+
<Section title="Overview" icon={Settings} defaultExpanded>
|
|
33
|
+
<PropertyList>
|
|
34
|
+
<Property label="Status" value={
|
|
35
|
+
<span className={clsx('px-2 py-0.5 rounded text-xs font-medium', status.color)}>
|
|
36
|
+
{status.text}
|
|
37
|
+
</span>
|
|
38
|
+
} />
|
|
39
|
+
<Property label="Image" value={image} />
|
|
40
|
+
{imageDigest && <Property label="Image Digest" value={
|
|
41
|
+
<span className="text-xs font-mono text-theme-text-secondary break-all">{imageDigest}</span>
|
|
42
|
+
} />}
|
|
43
|
+
{routingState && <Property label="Routing" value={
|
|
44
|
+
<span className={clsx(
|
|
45
|
+
'px-2 py-0.5 rounded text-xs font-medium',
|
|
46
|
+
routingState === 'active' ? 'bg-green-500/20 text-green-400' : 'bg-theme-hover text-theme-text-secondary'
|
|
47
|
+
)}>
|
|
48
|
+
{routingState}
|
|
49
|
+
</span>
|
|
50
|
+
} />}
|
|
51
|
+
{(actualReplicas != null || desiredReplicas != null) && (
|
|
52
|
+
<Property label="Replicas" value={`${actualReplicas ?? 0} / ${desiredReplicas ?? 0}`} />
|
|
53
|
+
)}
|
|
54
|
+
<Property label="Concurrency" value={containerConcurrency != null ? (containerConcurrency === 0 ? 'Unlimited' : String(containerConcurrency)) : undefined} />
|
|
55
|
+
<Property label="Timeout" value={timeoutSeconds != null ? `${timeoutSeconds}s` : undefined} />
|
|
56
|
+
<Property label="Service Account" value={serviceAccountName} />
|
|
57
|
+
</PropertyList>
|
|
58
|
+
</Section>
|
|
59
|
+
|
|
60
|
+
{containers.length > 0 && (
|
|
61
|
+
<Section title={`Containers (${containers.length})`} icon={Container} defaultExpanded>
|
|
62
|
+
<div className="space-y-2">
|
|
63
|
+
{containers.map((c: any, i: number) => (
|
|
64
|
+
<div key={i} className="bg-theme-elevated/30 rounded p-2 text-sm">
|
|
65
|
+
<div className="font-medium text-theme-text-primary">{c.name || 'container'}</div>
|
|
66
|
+
<div className="text-xs text-theme-text-secondary truncate" title={c.image}>{c.image}</div>
|
|
67
|
+
{c.ports && c.ports.length > 0 && (
|
|
68
|
+
<div className="text-xs text-theme-text-tertiary mt-1">
|
|
69
|
+
Ports: {c.ports.map((p: any) => `${p.containerPort}/${p.protocol || 'TCP'}`).join(', ')}
|
|
70
|
+
</div>
|
|
71
|
+
)}
|
|
72
|
+
{c.resources && (c.resources.requests || c.resources.limits) && (
|
|
73
|
+
<div className="text-xs text-theme-text-tertiary mt-1">
|
|
74
|
+
{c.resources.requests && (
|
|
75
|
+
<span>Requests: {Object.entries(c.resources.requests).map(([k, v]) => `${k}=${v}`).join(', ')}</span>
|
|
76
|
+
)}
|
|
77
|
+
{c.resources.requests && c.resources.limits && ' | '}
|
|
78
|
+
{c.resources.limits && (
|
|
79
|
+
<span>Limits: {Object.entries(c.resources.limits).map(([k, v]) => `${k}=${v}`).join(', ')}</span>
|
|
80
|
+
)}
|
|
81
|
+
</div>
|
|
82
|
+
)}
|
|
83
|
+
{c.env && c.env.length > 0 && (
|
|
84
|
+
<div className="text-xs text-theme-text-tertiary mt-1">
|
|
85
|
+
Env: {c.env.length} variable{c.env.length !== 1 ? 's' : ''}
|
|
86
|
+
</div>
|
|
87
|
+
)}
|
|
88
|
+
</div>
|
|
89
|
+
))}
|
|
90
|
+
</div>
|
|
91
|
+
</Section>
|
|
92
|
+
)}
|
|
93
|
+
|
|
94
|
+
<ConditionsSection conditions={data.status?.conditions || []} />
|
|
95
|
+
</>
|
|
96
|
+
)
|
|
97
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { Route } 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 KnativeRouteRendererProps {
|
|
7
|
+
data: any
|
|
8
|
+
onNavigate?: (ref: { kind: string; namespace: string; name: string }) => void
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function KnativeRouteRenderer({ data, onNavigate }: KnativeRouteRendererProps) {
|
|
12
|
+
const status = getKnativeConditionStatus(data)
|
|
13
|
+
const traffic = data.status?.traffic || data.spec?.traffic || []
|
|
14
|
+
const ns = data.metadata?.namespace || ''
|
|
15
|
+
const url = data.status?.url || data.status?.address?.url
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<>
|
|
19
|
+
<KnativeNotReadyBanner status={status} data={data} resourceType="Route" />
|
|
20
|
+
|
|
21
|
+
<Section title="Overview" icon={Route} defaultExpanded>
|
|
22
|
+
<PropertyList>
|
|
23
|
+
<Property label="Status" value={
|
|
24
|
+
<span className={clsx('px-2 py-0.5 rounded text-xs font-medium', status.color)}>
|
|
25
|
+
{status.text}
|
|
26
|
+
</span>
|
|
27
|
+
} />
|
|
28
|
+
<Property label="URL" value={url ? (
|
|
29
|
+
<a href={url} target="_blank" rel="noopener noreferrer" className="text-blue-400 hover:text-blue-300 hover:underline break-all">
|
|
30
|
+
{url}
|
|
31
|
+
</a>
|
|
32
|
+
) : undefined} />
|
|
33
|
+
</PropertyList>
|
|
34
|
+
</Section>
|
|
35
|
+
|
|
36
|
+
{traffic.length > 0 && (
|
|
37
|
+
<Section title={`Traffic Targets (${traffic.length})`} defaultExpanded>
|
|
38
|
+
<div className="space-y-2">
|
|
39
|
+
{traffic.map((t: any, i: number) => (
|
|
40
|
+
<div key={i} className="flex items-center gap-2 text-sm">
|
|
41
|
+
<div className="flex items-center gap-1 w-16 shrink-0">
|
|
42
|
+
<div className="flex-1 h-1.5 bg-theme-hover rounded-full overflow-hidden">
|
|
43
|
+
<div
|
|
44
|
+
className="h-full bg-blue-500 rounded-full"
|
|
45
|
+
style={{ width: `${t.percent || 0}%` }}
|
|
46
|
+
/>
|
|
47
|
+
</div>
|
|
48
|
+
<span className="text-theme-text-secondary font-medium text-xs">{t.percent || 0}%</span>
|
|
49
|
+
</div>
|
|
50
|
+
{t.revisionName ? (
|
|
51
|
+
<ResourceLink
|
|
52
|
+
name={t.revisionName}
|
|
53
|
+
kind="revisions"
|
|
54
|
+
namespace={ns}
|
|
55
|
+
onNavigate={onNavigate}
|
|
56
|
+
/>
|
|
57
|
+
) : (
|
|
58
|
+
<span className="text-theme-text-secondary">{t.configurationName || (t.latestRevision ? '@latest' : '-')}</span>
|
|
59
|
+
)}
|
|
60
|
+
{t.tag && (
|
|
61
|
+
<span className="px-1.5 py-0.5 bg-theme-hover rounded text-[10px] text-theme-text-secondary">
|
|
62
|
+
tag: {t.tag}
|
|
63
|
+
</span>
|
|
64
|
+
)}
|
|
65
|
+
</div>
|
|
66
|
+
))}
|
|
67
|
+
</div>
|
|
68
|
+
</Section>
|
|
69
|
+
)}
|
|
70
|
+
|
|
71
|
+
<ConditionsSection conditions={data.status?.conditions || []} />
|
|
72
|
+
</>
|
|
73
|
+
)
|
|
74
|
+
}
|