@skyhook-io/radar-app 0.1.1
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/README.md +67 -0
- package/package.json +80 -0
- package/src/App.tsx +1538 -0
- package/src/RadarApp.tsx +145 -0
- package/src/api/apiResources.ts +28 -0
- package/src/api/client.ts +2583 -0
- package/src/api/config.ts +116 -0
- package/src/api/traffic.ts +139 -0
- package/src/components/ConnectionErrorView.tsx +272 -0
- package/src/components/ContextSwitcher.tsx +481 -0
- package/src/components/DebugOverlay.tsx +94 -0
- package/src/components/UserMenu.tsx +87 -0
- package/src/components/audit/AuditSettingsDialog.tsx +162 -0
- package/src/components/audit/AuditView.tsx +123 -0
- package/src/components/cost/CostTrendChart.tsx +388 -0
- package/src/components/cost/CostView.tsx +545 -0
- package/src/components/dock/BottomDock.tsx +96 -0
- package/src/components/dock/DockContext.tsx +11 -0
- package/src/components/dock/LocalTerminalTab.tsx +22 -0
- package/src/components/dock/LogsTab.tsx +26 -0
- package/src/components/dock/NodeTerminalTab.tsx +50 -0
- package/src/components/dock/TerminalTab.tsx +42 -0
- package/src/components/dock/TrafficFlowListTab.tsx +18 -0
- package/src/components/dock/WorkloadLogsTab.tsx +23 -0
- package/src/components/dock/index.ts +2 -0
- package/src/components/gitops/GitOpsActions.tsx +1 -0
- package/src/components/gitops/GitOpsStatusBadge.tsx +1 -0
- package/src/components/gitops/ManagedResourcesList.tsx +1 -0
- package/src/components/gitops/SyncCountdown.tsx +1 -0
- package/src/components/gitops/index.ts +4 -0
- package/src/components/helm/ChartBrowser.tsx +580 -0
- package/src/components/helm/HelmReleaseDrawer.tsx +774 -0
- package/src/components/helm/HelmView.tsx +475 -0
- package/src/components/helm/InstallWizard.tsx +1060 -0
- package/src/components/helm/ManifestDiffViewer.tsx +91 -0
- package/src/components/helm/ManifestViewer.tsx +61 -0
- package/src/components/helm/OwnedResources.tsx +465 -0
- package/src/components/helm/RevisionHistory.tsx +167 -0
- package/src/components/helm/ValuesDiffPreview.tsx +190 -0
- package/src/components/helm/ValuesViewer.tsx +365 -0
- package/src/components/helm/helm-utils.ts +37 -0
- package/src/components/home/ActivitySummary.tsx +262 -0
- package/src/components/home/CertificateHealthCard.tsx +105 -0
- package/src/components/home/ClusterHealthCard.tsx +483 -0
- package/src/components/home/CostCard.tsx +112 -0
- package/src/components/home/HealthRing.tsx +1 -0
- package/src/components/home/HelmSummary.tsx +129 -0
- package/src/components/home/HomeView.tsx +224 -0
- package/src/components/home/MCPSetupDialog.tsx +417 -0
- package/src/components/home/NetworkPolicyCoverageCard.tsx +109 -0
- package/src/components/home/TopologyPreview.tsx +219 -0
- package/src/components/home/TrafficSummary.tsx +154 -0
- package/src/components/logs/JsonLogLine.tsx +1 -0
- package/src/components/logs/LogCore.tsx +2 -0
- package/src/components/logs/LogsViewer.tsx +44 -0
- package/src/components/logs/WorkloadLogsViewer.tsx +40 -0
- package/src/components/logs/useLogBuffer.ts +2 -0
- package/src/components/logs/useLogSearch.ts +1 -0
- package/src/components/portforward/PortForwardButton.tsx +375 -0
- package/src/components/portforward/PortForwardManager.tsx +871 -0
- package/src/components/resource/PrometheusCharts.tsx +687 -0
- package/src/components/resource-drawer/ResourceDrawer.tsx +214 -0
- package/src/components/resources/ImageFilesystemModal.tsx +745 -0
- package/src/components/resources/PodFilesystemModal.tsx +407 -0
- package/src/components/resources/ResourceDetailDrawer.tsx +43 -0
- package/src/components/resources/ResourcesView.tsx +190 -0
- package/src/components/resources/drawer-components.tsx +1 -0
- package/src/components/resources/file-browser-utils.ts +35 -0
- package/src/components/resources/renderers/AlertRenderer.tsx +1 -0
- package/src/components/resources/renderers/ArgoApplicationRenderer.tsx +17 -0
- package/src/components/resources/renderers/CNPGBackupRenderer.tsx +1 -0
- package/src/components/resources/renderers/CNPGClusterRenderer.tsx +1 -0
- package/src/components/resources/renderers/CNPGPoolerRenderer.tsx +1 -0
- package/src/components/resources/renderers/CNPGScheduledBackupRenderer.tsx +1 -0
- package/src/components/resources/renderers/CertificateRenderer.tsx +1 -0
- package/src/components/resources/renderers/CertificateRequestRenderer.tsx +1 -0
- package/src/components/resources/renderers/ChallengeRenderer.tsx +1 -0
- package/src/components/resources/renderers/ClusterComplianceReportRenderer.tsx +1 -0
- package/src/components/resources/renderers/ClusterExternalSecretRenderer.tsx +1 -0
- package/src/components/resources/renderers/ClusterIssuerRenderer.tsx +1 -0
- package/src/components/resources/renderers/ConfigAuditReportRenderer.tsx +1 -0
- package/src/components/resources/renderers/ConfigMapRenderer.tsx +1 -0
- package/src/components/resources/renderers/CronJobRenderer.tsx +1 -0
- package/src/components/resources/renderers/EventRenderer.tsx +1 -0
- package/src/components/resources/renderers/ExposedSecretReportRenderer.tsx +1 -0
- package/src/components/resources/renderers/ExternalSecretRenderer.tsx +1 -0
- package/src/components/resources/renderers/FluxHelmReleaseRenderer.tsx +1 -0
- package/src/components/resources/renderers/GRPCRouteRenderer.tsx +1 -0
- package/src/components/resources/renderers/GatewayClassRenderer.tsx +1 -0
- package/src/components/resources/renderers/GatewayRenderer.tsx +1 -0
- package/src/components/resources/renderers/GenericRenderer.tsx +1 -0
- package/src/components/resources/renderers/GitRepositoryRenderer.tsx +1 -0
- package/src/components/resources/renderers/HPARenderer.tsx +1 -0
- package/src/components/resources/renderers/HTTPRouteRenderer.tsx +1 -0
- package/src/components/resources/renderers/HelmRepositoryRenderer.tsx +1 -0
- package/src/components/resources/renderers/IngressClassRenderer.tsx +1 -0
- package/src/components/resources/renderers/IngressRenderer.tsx +1 -0
- package/src/components/resources/renderers/IstioAuthorizationPolicyRenderer.tsx +1 -0
- package/src/components/resources/renderers/IstioDestinationRuleRenderer.tsx +1 -0
- package/src/components/resources/renderers/IstioGatewayRenderer.tsx +1 -0
- package/src/components/resources/renderers/IstioPeerAuthenticationRenderer.tsx +1 -0
- package/src/components/resources/renderers/IstioServiceEntryRenderer.tsx +1 -0
- package/src/components/resources/renderers/IstioVirtualServiceRenderer.tsx +1 -0
- package/src/components/resources/renderers/JobRenderer.tsx +1 -0
- package/src/components/resources/renderers/KarpenterEC2NodeClassRenderer.tsx +1 -0
- package/src/components/resources/renderers/KarpenterNodeClaimRenderer.tsx +1 -0
- package/src/components/resources/renderers/KarpenterNodePoolRenderer.tsx +1 -0
- package/src/components/resources/renderers/KedaScaledJobRenderer.tsx +1 -0
- package/src/components/resources/renderers/KedaScaledObjectRenderer.tsx +1 -0
- package/src/components/resources/renderers/KedaTriggerAuthRenderer.tsx +1 -0
- package/src/components/resources/renderers/KnativeConfigurationRenderer.tsx +1 -0
- package/src/components/resources/renderers/KnativeEventingRenderer.tsx +1 -0
- package/src/components/resources/renderers/KnativeFlowRenderer.tsx +1 -0
- package/src/components/resources/renderers/KnativeNetworkingRenderer.tsx +1 -0
- package/src/components/resources/renderers/KnativeRevisionRenderer.tsx +1 -0
- package/src/components/resources/renderers/KnativeRouteRenderer.tsx +1 -0
- package/src/components/resources/renderers/KnativeServiceRenderer.tsx +1 -0
- package/src/components/resources/renderers/KnativeSourceRenderer.tsx +1 -0
- package/src/components/resources/renderers/KustomizationRenderer.tsx +1 -0
- package/src/components/resources/renderers/KyvernoPolicyReportRenderer.tsx +1 -0
- package/src/components/resources/renderers/LeaseRenderer.tsx +1 -0
- package/src/components/resources/renderers/NetworkPolicyRenderer.tsx +1 -0
- package/src/components/resources/renderers/NodeRenderer.tsx +44 -0
- package/src/components/resources/renderers/OCIRepositoryRenderer.tsx +1 -0
- package/src/components/resources/renderers/OrderRenderer.tsx +1 -0
- package/src/components/resources/renderers/PVCRenderer.tsx +1 -0
- package/src/components/resources/renderers/PersistentVolumeRenderer.tsx +1 -0
- package/src/components/resources/renderers/PodDisruptionBudgetRenderer.tsx +1 -0
- package/src/components/resources/renderers/PodMonitorRenderer.tsx +1 -0
- package/src/components/resources/renderers/PodRenderer.tsx +94 -0
- package/src/components/resources/renderers/PriorityClassRenderer.tsx +1 -0
- package/src/components/resources/renderers/PrometheusRuleRenderer.tsx +1 -0
- package/src/components/resources/renderers/ReplicaSetRenderer.tsx +1 -0
- package/src/components/resources/renderers/RoleBindingRenderer.tsx +1 -0
- package/src/components/resources/renderers/RoleRenderer.tsx +1 -0
- package/src/components/resources/renderers/RolloutRenderer.tsx +1 -0
- package/src/components/resources/renderers/RuntimeClassRenderer.tsx +1 -0
- package/src/components/resources/renderers/SbomReportRenderer.tsx +1 -0
- package/src/components/resources/renderers/SealedSecretRenderer.tsx +1 -0
- package/src/components/resources/renderers/SecretRenderer.tsx +1 -0
- package/src/components/resources/renderers/SecretStoreRenderer.tsx +1 -0
- package/src/components/resources/renderers/ServiceAccountRenderer.tsx +1 -0
- package/src/components/resources/renderers/ServiceMonitorRenderer.tsx +1 -0
- package/src/components/resources/renderers/ServiceRenderer.tsx +26 -0
- package/src/components/resources/renderers/SimpleRouteRenderer.tsx +1 -0
- package/src/components/resources/renderers/StorageClassRenderer.tsx +1 -0
- package/src/components/resources/renderers/TraefikIngressRouteRenderer.tsx +1 -0
- package/src/components/resources/renderers/VPARenderer.tsx +1 -0
- package/src/components/resources/renderers/VeleroBSLRenderer.tsx +1 -0
- package/src/components/resources/renderers/VeleroBackupRenderer.tsx +1 -0
- package/src/components/resources/renderers/VeleroRestoreRenderer.tsx +1 -0
- package/src/components/resources/renderers/VeleroScheduleRenderer.tsx +1 -0
- package/src/components/resources/renderers/VeleroVSLRenderer.tsx +1 -0
- package/src/components/resources/renderers/VulnerabilityReportRenderer.tsx +1 -0
- package/src/components/resources/renderers/WebhookConfigRenderer.tsx +1 -0
- package/src/components/resources/renderers/WorkflowRenderer.tsx +1 -0
- package/src/components/resources/renderers/WorkflowTemplateRenderer.tsx +1 -0
- package/src/components/resources/renderers/WorkloadRenderer.tsx +52 -0
- package/src/components/resources/renderers/argo-cells.tsx +1 -0
- package/src/components/resources/renderers/certmanager-cells.tsx +1 -0
- package/src/components/resources/renderers/cnpg-cells.tsx +1 -0
- package/src/components/resources/renderers/eso-cells.tsx +1 -0
- package/src/components/resources/renderers/flux-cells.tsx +1 -0
- package/src/components/resources/renderers/index.ts +91 -0
- package/src/components/resources/renderers/istio-cells.tsx +1 -0
- package/src/components/resources/renderers/karpenter-cells.tsx +1 -0
- package/src/components/resources/renderers/keda-cells.tsx +1 -0
- package/src/components/resources/renderers/knative-cells.tsx +1 -0
- package/src/components/resources/renderers/kyverno-cells.tsx +1 -0
- package/src/components/resources/renderers/prometheus-cells.tsx +1 -0
- package/src/components/resources/renderers/traefik-cells.tsx +1 -0
- package/src/components/resources/renderers/trivy-cells.tsx +1 -0
- package/src/components/resources/renderers/trivy-shared.tsx +1 -0
- package/src/components/resources/renderers/velero-cells.tsx +1 -0
- package/src/components/resources/resource-utils-argo.ts +2 -0
- package/src/components/resources/resource-utils-certmanager.ts +2 -0
- package/src/components/resources/resource-utils-cnpg.ts +2 -0
- package/src/components/resources/resource-utils-eso.ts +2 -0
- package/src/components/resources/resource-utils-flux.ts +2 -0
- package/src/components/resources/resource-utils-istio.ts +2 -0
- package/src/components/resources/resource-utils-karpenter.ts +2 -0
- package/src/components/resources/resource-utils-keda.ts +2 -0
- package/src/components/resources/resource-utils-knative.ts +2 -0
- package/src/components/resources/resource-utils-kyverno.ts +2 -0
- package/src/components/resources/resource-utils-prometheus.ts +2 -0
- package/src/components/resources/resource-utils-traefik.ts +1 -0
- package/src/components/resources/resource-utils-trivy.ts +2 -0
- package/src/components/resources/resource-utils-velero.ts +2 -0
- package/src/components/resources/resource-utils.ts +5 -0
- package/src/components/settings/SettingsDialog.tsx +537 -0
- package/src/components/shared/CreateResourceDialog.tsx +17 -0
- package/src/components/shared/EditableYamlView.tsx +24 -0
- package/src/components/shared/LargeClusterNamespacePicker.tsx +70 -0
- package/src/components/shared/ResourceRendererDispatch.tsx +31 -0
- package/src/components/timeline/DiffViewer.tsx +1 -0
- package/src/components/timeline/TimelineList.tsx +69 -0
- package/src/components/timeline/TimelineSwimlanes.tsx +1308 -0
- package/src/components/timeline/TimelineView.tsx +157 -0
- package/src/components/timeline/shared.tsx +1 -0
- package/src/components/traffic/TrafficFilterSidebar.tsx +571 -0
- package/src/components/traffic/TrafficFlowList.tsx +415 -0
- package/src/components/traffic/TrafficFlowListContext.tsx +68 -0
- package/src/components/traffic/TrafficGraph.tsx +1546 -0
- package/src/components/traffic/TrafficView.tsx +1213 -0
- package/src/components/traffic/TrafficWizard.tsx +386 -0
- package/src/components/traffic/index.ts +3 -0
- package/src/components/ui/CodeViewer.tsx +8 -0
- package/src/components/ui/CommandPalette.tsx +460 -0
- package/src/components/ui/ConfirmDialog.tsx +1 -0
- package/src/components/ui/DiagnosticsOverlay.tsx +619 -0
- package/src/components/ui/ErrorBoundary.tsx +46 -0
- package/src/components/ui/ForceDeleteConfirmDialog.tsx +1 -0
- package/src/components/ui/Markdown.tsx +108 -0
- package/src/components/ui/MetricsChart.tsx +1 -0
- package/src/components/ui/NamespaceSelector.tsx +436 -0
- package/src/components/ui/ResourceBar.tsx +1 -0
- package/src/components/ui/ShortcutHelpOverlay.tsx +301 -0
- package/src/components/ui/Toast.tsx +1 -0
- package/src/components/ui/Tooltip.tsx +1 -0
- package/src/components/ui/UpdateNotification.tsx +299 -0
- package/src/components/ui/YamlEditor.tsx +1 -0
- package/src/components/workload/WorkloadView.tsx +532 -0
- package/src/context/ConnectionContext.tsx +173 -0
- package/src/context/ContextSwitchContext.tsx +56 -0
- package/src/context/NavCustomization.tsx +62 -0
- package/src/context/ThemeContext.tsx +97 -0
- package/src/contexts/CapabilitiesContext.tsx +130 -0
- package/src/hooks/useAnimatedUnmount.ts +1 -0
- package/src/hooks/useDesktopDownload.ts +41 -0
- package/src/hooks/useEventSource.ts +262 -0
- package/src/hooks/useFavorites.ts +69 -0
- package/src/hooks/useKeyboardShortcuts.tsx +7 -0
- package/src/hooks/useRefreshAnimation.ts +1 -0
- package/src/index.css +243 -0
- package/src/index.ts +17 -0
- package/src/main.tsx +158 -0
- package/src/types/gitops.ts +2 -0
- package/src/types.ts +3 -0
- package/src/utils/animation.ts +2 -0
- package/src/utils/badge-colors.ts +2 -0
- package/src/utils/context-name.ts +2 -0
- package/src/utils/desktop-download.ts +66 -0
- package/src/utils/desktop-open-folder.ts +21 -0
- package/src/utils/format.ts +2 -0
- package/src/utils/log-format.ts +12 -0
- package/src/utils/navigation.ts +23 -0
- package/src/utils/resource-hierarchy.ts +2 -0
- package/src/utils/resource-icons.ts +2 -0
- package/src/utils/skeleton-yaml.ts +2 -0
- package/src/utils/traffic-colors.ts +54 -0
- package/src/vite-env.d.ts +1 -0
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
import { useMemo } from 'react'
|
|
2
|
+
import type { Topology } from '../../types'
|
|
3
|
+
import type { DashboardTopologySummary } from '../../api/client'
|
|
4
|
+
import { Network, ArrowRight } from 'lucide-react'
|
|
5
|
+
import { clsx } from 'clsx'
|
|
6
|
+
|
|
7
|
+
interface TopologyPreviewProps {
|
|
8
|
+
topology: Topology | null
|
|
9
|
+
summary: DashboardTopologySummary
|
|
10
|
+
onNavigate: () => void
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Static schematic SVG that hints at the topology graph layout.
|
|
15
|
+
* Two groups with interconnected nodes using real topology color palette.
|
|
16
|
+
*/
|
|
17
|
+
function TopologySchematic() {
|
|
18
|
+
// Colors matching the real topology graph
|
|
19
|
+
const ingress = '#a78bfa' // violet-400
|
|
20
|
+
const service = '#60a5fa' // blue-400
|
|
21
|
+
const deploy = '#34d399' // emerald-400
|
|
22
|
+
const pod = '#84cc16' // lime-500
|
|
23
|
+
const config = '#fbbf24' // amber-400
|
|
24
|
+
const groupBorder = 'rgba(59, 130, 246, 0.25)'
|
|
25
|
+
const groupBg = 'rgba(59, 130, 246, 0.04)'
|
|
26
|
+
|
|
27
|
+
// Edge color — use a concrete color so markers render reliably
|
|
28
|
+
const ec = '#64748b' // slate-500
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<svg viewBox="0 0 160 120" className="w-full h-full" aria-hidden="true">
|
|
32
|
+
<defs>
|
|
33
|
+
<marker id="arr" viewBox="0 0 8 6" refX="7" refY="3"
|
|
34
|
+
markerWidth="6" markerHeight="5" orient="auto">
|
|
35
|
+
<path d="M 0 0 L 8 3 L 0 6 z" fill={ec} opacity="0.6" />
|
|
36
|
+
</marker>
|
|
37
|
+
<marker id="arr-f" viewBox="0 0 8 6" refX="7" refY="3"
|
|
38
|
+
markerWidth="6" markerHeight="5" orient="auto">
|
|
39
|
+
<path d="M 0 0 L 8 3 L 0 6 z" fill={ec} opacity="0.35" />
|
|
40
|
+
</marker>
|
|
41
|
+
</defs>
|
|
42
|
+
|
|
43
|
+
{/* Group 1 — top: Ingress → Service → Deploys → Pods */}
|
|
44
|
+
<rect x="4" y="4" width="100" height="52" rx="6"
|
|
45
|
+
fill={groupBg} stroke={groupBorder} strokeWidth="1" strokeDasharray="3 2" />
|
|
46
|
+
|
|
47
|
+
{/* Nodes */}
|
|
48
|
+
<rect x="10" y="24" width="16" height="10" rx="3" fill={ingress} opacity="0.85" />
|
|
49
|
+
<rect x="38" y="24" width="16" height="10" rx="3" fill={service} opacity="0.85" />
|
|
50
|
+
<rect x="66" y="14" width="16" height="10" rx="3" fill={deploy} opacity="0.85" />
|
|
51
|
+
<rect x="66" y="34" width="16" height="10" rx="3" fill={deploy} opacity="0.85" />
|
|
52
|
+
<circle cx="96" cy="19" r="4.5" fill={pod} opacity="0.65" />
|
|
53
|
+
<circle cx="96" cy="39" r="4.5" fill={pod} opacity="0.65" />
|
|
54
|
+
|
|
55
|
+
{/* Edges — group 1 */}
|
|
56
|
+
<line x1="26" y1="29" x2="37" y2="29" stroke={ec} strokeWidth="1" opacity="0.55" markerEnd="url(#arr)" />
|
|
57
|
+
<line x1="54" y1="29" x2="65" y2="20" stroke={ec} strokeWidth="1" opacity="0.55" markerEnd="url(#arr)" />
|
|
58
|
+
<line x1="54" y1="29" x2="65" y2="38" stroke={ec} strokeWidth="1" opacity="0.55" markerEnd="url(#arr)" />
|
|
59
|
+
<line x1="82" y1="19" x2="90" y2="19" stroke={ec} strokeWidth="1" opacity="0.55" markerEnd="url(#arr)" />
|
|
60
|
+
<line x1="82" y1="39" x2="90" y2="39" stroke={ec} strokeWidth="1" opacity="0.55" markerEnd="url(#arr)" />
|
|
61
|
+
|
|
62
|
+
{/* Group 2 — bottom: Service → Deploys → Pods + ConfigMap */}
|
|
63
|
+
<rect x="30" y="64" width="126" height="52" rx="6"
|
|
64
|
+
fill={groupBg} stroke={groupBorder} strokeWidth="1" strokeDasharray="3 2" />
|
|
65
|
+
|
|
66
|
+
{/* Nodes */}
|
|
67
|
+
<rect x="36" y="82" width="16" height="10" rx="3" fill={service} opacity="0.85" />
|
|
68
|
+
<rect x="66" y="72" width="16" height="10" rx="3" fill={deploy} opacity="0.85" />
|
|
69
|
+
<rect x="66" y="92" width="16" height="10" rx="3" fill={deploy} opacity="0.85" />
|
|
70
|
+
<circle cx="96" cy="73" r="4.5" fill={pod} opacity="0.65" />
|
|
71
|
+
<circle cx="96" cy="87" r="4.5" fill={pod} opacity="0.65" />
|
|
72
|
+
<circle cx="96" cy="101" r="4.5" fill={pod} opacity="0.65" />
|
|
73
|
+
|
|
74
|
+
{/* Config node */}
|
|
75
|
+
<rect x="120" y="82" width="16" height="10" rx="3" fill={config} opacity="0.55" />
|
|
76
|
+
|
|
77
|
+
{/* Edges — group 2 */}
|
|
78
|
+
<line x1="52" y1="87" x2="65" y2="78" stroke={ec} strokeWidth="1" opacity="0.55" markerEnd="url(#arr)" />
|
|
79
|
+
<line x1="52" y1="87" x2="65" y2="96" stroke={ec} strokeWidth="1" opacity="0.55" markerEnd="url(#arr)" />
|
|
80
|
+
<line x1="82" y1="77" x2="90" y2="74" stroke={ec} strokeWidth="1" opacity="0.55" markerEnd="url(#arr)" />
|
|
81
|
+
<line x1="82" y1="77" x2="90" y2="87" stroke={ec} strokeWidth="1" opacity="0.55" markerEnd="url(#arr)" />
|
|
82
|
+
<line x1="82" y1="97" x2="90" y2="101" stroke={ec} strokeWidth="1" opacity="0.55" markerEnd="url(#arr)" />
|
|
83
|
+
|
|
84
|
+
{/* Config dashed edge */}
|
|
85
|
+
<line x1="82" y1="77" x2="119" y2="87" stroke={ec} strokeWidth="0.7" opacity="0.3" strokeDasharray="2 2" markerEnd="url(#arr-f)" />
|
|
86
|
+
|
|
87
|
+
{/* Cross-group curved edge */}
|
|
88
|
+
<path d="M 18 34 Q 18 64, 36 82" fill="none" stroke={ec} strokeWidth="0.8" opacity="0.3" markerEnd="url(#arr-f)" />
|
|
89
|
+
</svg>
|
|
90
|
+
)
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Derive stats from real topology data
|
|
94
|
+
function useTopologyStats(topology: Topology | null) {
|
|
95
|
+
return useMemo(() => {
|
|
96
|
+
if (!topology || topology.nodes.length === 0) return null
|
|
97
|
+
|
|
98
|
+
const kindCounts: Record<string, number> = {}
|
|
99
|
+
const healthCounts = { healthy: 0, degraded: 0, unhealthy: 0, unknown: 0 }
|
|
100
|
+
|
|
101
|
+
for (const node of topology.nodes) {
|
|
102
|
+
kindCounts[node.kind] = (kindCounts[node.kind] || 0) + 1
|
|
103
|
+
if (node.status in healthCounts) {
|
|
104
|
+
healthCounts[node.status as keyof typeof healthCounts]++
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Top kinds sorted by display priority
|
|
109
|
+
const kindPriority: Record<string, number> = {
|
|
110
|
+
Deployment: 1, Rollout: 1, StatefulSet: 2, DaemonSet: 2,
|
|
111
|
+
Service: 3, Ingress: 4, Gateway: 4,
|
|
112
|
+
HTTPRoute: 4, GRPCRoute: 4, TCPRoute: 4, TLSRoute: 4,
|
|
113
|
+
Pod: 5, PodGroup: 5,
|
|
114
|
+
Job: 6, CronJob: 6, ConfigMap: 7, Secret: 7,
|
|
115
|
+
}
|
|
116
|
+
const topKinds = Object.entries(kindCounts)
|
|
117
|
+
.filter(([kind]) => kind !== 'Internet')
|
|
118
|
+
.sort(([a], [b]) => (kindPriority[a] || 99) - (kindPriority[b] || 99))
|
|
119
|
+
.slice(0, 8)
|
|
120
|
+
|
|
121
|
+
return { topKinds, healthCounts }
|
|
122
|
+
}, [topology])
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const kindDotColors: Record<string, string> = {
|
|
126
|
+
Deployment: 'bg-emerald-400', Rollout: 'bg-emerald-400',
|
|
127
|
+
StatefulSet: 'bg-cyan-400', DaemonSet: 'bg-teal-400',
|
|
128
|
+
Service: 'bg-blue-400', Ingress: 'bg-violet-400', Gateway: 'bg-violet-400',
|
|
129
|
+
HTTPRoute: 'bg-purple-400', GRPCRoute: 'bg-purple-400', TCPRoute: 'bg-purple-400', TLSRoute: 'bg-purple-400',
|
|
130
|
+
Pod: 'bg-lime-500', PodGroup: 'bg-lime-500',
|
|
131
|
+
Job: 'bg-purple-400', CronJob: 'bg-purple-400',
|
|
132
|
+
ConfigMap: 'bg-amber-400', Secret: 'bg-red-400',
|
|
133
|
+
ReplicaSet: 'bg-green-400', HPA: 'bg-pink-500', PVC: 'bg-cyan-400',
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export function TopologyPreview({ topology, summary, onNavigate }: TopologyPreviewProps) {
|
|
137
|
+
const stats = useTopologyStats(topology)
|
|
138
|
+
|
|
139
|
+
return (
|
|
140
|
+
<button
|
|
141
|
+
onClick={onNavigate}
|
|
142
|
+
className="group h-[260px] rounded-xl bg-theme-surface shadow-theme-sm hover:-translate-y-1 hover:shadow-theme-md transition-all duration-200 text-left overflow-hidden"
|
|
143
|
+
>
|
|
144
|
+
<div className="flex flex-col h-full w-full">
|
|
145
|
+
<div className="flex items-center justify-between px-5 py-3 border-b border-theme-border/50">
|
|
146
|
+
<div className="flex items-center gap-2">
|
|
147
|
+
<Network className="w-4 h-4 text-theme-text-tertiary" />
|
|
148
|
+
<span className="text-xs font-semibold uppercase tracking-wider text-theme-text-secondary">Topology</span>
|
|
149
|
+
</div>
|
|
150
|
+
<span className="text-[11px] text-theme-text-tertiary">
|
|
151
|
+
{summary.nodeCount} resources · {summary.edgeCount} conn
|
|
152
|
+
</span>
|
|
153
|
+
</div>
|
|
154
|
+
|
|
155
|
+
{/* Stats (left) + Schematic (right) */}
|
|
156
|
+
<div className="flex-1 flex items-stretch min-h-0 px-3 py-1.5 gap-2">
|
|
157
|
+
{/* Left: compact stats */}
|
|
158
|
+
<div className="flex flex-col justify-center gap-0.5 min-w-0 w-[105px] shrink-0">
|
|
159
|
+
{stats ? (
|
|
160
|
+
<>
|
|
161
|
+
{stats.topKinds.map(([kind, count]) => (
|
|
162
|
+
<div key={kind} className="flex items-center gap-1.5 text-[10px] leading-tight">
|
|
163
|
+
<span className={clsx(
|
|
164
|
+
'w-1.5 h-1.5 rounded-full shrink-0',
|
|
165
|
+
kindDotColors[kind] || 'bg-theme-text-tertiary',
|
|
166
|
+
)} />
|
|
167
|
+
<span className="text-theme-text-primary font-medium w-5 text-right tabular-nums">{count}</span>
|
|
168
|
+
<span className="text-theme-text-tertiary truncate">{kind}</span>
|
|
169
|
+
</div>
|
|
170
|
+
))}
|
|
171
|
+
|
|
172
|
+
{(stats.healthCounts.degraded > 0 || stats.healthCounts.unhealthy > 0) && (
|
|
173
|
+
<div className="flex items-center gap-1.5 text-[10px] text-theme-text-tertiary mt-0.5 pt-1 border-t border-theme-border/50">
|
|
174
|
+
{stats.healthCounts.unhealthy > 0 && (
|
|
175
|
+
<span className="flex items-center gap-0.5">
|
|
176
|
+
<span className="w-1.5 h-1.5 rounded-full bg-red-500" />
|
|
177
|
+
{stats.healthCounts.unhealthy}
|
|
178
|
+
</span>
|
|
179
|
+
)}
|
|
180
|
+
{stats.healthCounts.degraded > 0 && (
|
|
181
|
+
<span className="flex items-center gap-0.5">
|
|
182
|
+
<span className="w-1.5 h-1.5 rounded-full bg-yellow-500" />
|
|
183
|
+
{stats.healthCounts.degraded}
|
|
184
|
+
</span>
|
|
185
|
+
)}
|
|
186
|
+
</div>
|
|
187
|
+
)}
|
|
188
|
+
</>
|
|
189
|
+
) : (
|
|
190
|
+
// Show summary-based placeholder while full topology loads via SSE
|
|
191
|
+
<div className="flex flex-col gap-0.5">
|
|
192
|
+
<div className="flex items-center gap-1.5 text-[10px] leading-tight">
|
|
193
|
+
<span className="w-1.5 h-1.5 rounded-full bg-blue-400 shrink-0" />
|
|
194
|
+
<span className="text-theme-text-primary font-medium w-5 text-right tabular-nums">{summary.nodeCount}</span>
|
|
195
|
+
<span className="text-theme-text-tertiary">resources</span>
|
|
196
|
+
</div>
|
|
197
|
+
<div className="flex items-center gap-1.5 text-[10px] leading-tight">
|
|
198
|
+
<span className="w-1.5 h-1.5 rounded-full bg-theme-text-tertiary shrink-0" />
|
|
199
|
+
<span className="text-theme-text-primary font-medium w-5 text-right tabular-nums">{summary.edgeCount}</span>
|
|
200
|
+
<span className="text-theme-text-tertiary">connections</span>
|
|
201
|
+
</div>
|
|
202
|
+
</div>
|
|
203
|
+
)}
|
|
204
|
+
</div>
|
|
205
|
+
|
|
206
|
+
{/* Right: schematic illustration */}
|
|
207
|
+
<div className="flex-1 flex items-center min-w-0">
|
|
208
|
+
<TopologySchematic />
|
|
209
|
+
</div>
|
|
210
|
+
</div>
|
|
211
|
+
|
|
212
|
+
<div className="px-4 py-1.5 border-t border-theme-border/50 flex items-center justify-end gap-1.5 text-[10px] font-semibold uppercase tracking-wider text-theme-text-secondary group-hover:text-theme-text-primary transition-colors">
|
|
213
|
+
Open Topology
|
|
214
|
+
<ArrowRight className="w-3.5 h-3.5 transition-transform group-hover:translate-x-0.5" />
|
|
215
|
+
</div>
|
|
216
|
+
</div>
|
|
217
|
+
</button>
|
|
218
|
+
)
|
|
219
|
+
}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import type { DashboardTrafficSummary } from '../../api/client'
|
|
2
|
+
import { Activity, ArrowRight, ArrowRightLeft } from 'lucide-react'
|
|
3
|
+
|
|
4
|
+
interface TrafficSummaryProps {
|
|
5
|
+
data: DashboardTrafficSummary | null
|
|
6
|
+
onNavigate: () => void
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Static schematic SVG mimicking the real traffic view layout:
|
|
11
|
+
* vertical spine on the left, Internet node, chunky arrows branching
|
|
12
|
+
* right to colored service nodes, some with further connections.
|
|
13
|
+
*/
|
|
14
|
+
function TrafficSchematic() {
|
|
15
|
+
// Service node colors matching the real traffic view
|
|
16
|
+
const green = '#22c55e' // skyhook-connector style
|
|
17
|
+
const blue = '#3b82f6' // dev services
|
|
18
|
+
const brown = '#a3734c' // staging services
|
|
19
|
+
const teal = '#14b8a6' // keda style
|
|
20
|
+
const red = '#ef4444' // unhealthy / alert
|
|
21
|
+
const purple = '#a855f7' // envoy / system
|
|
22
|
+
const inet = '#93c5fd' // light blue — Internet node bg
|
|
23
|
+
const inetBorder = '#60a5fa'
|
|
24
|
+
|
|
25
|
+
// Edge color
|
|
26
|
+
const ec = '#6b7280' // gray-500
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<svg viewBox="0 0 160 120" className="w-full h-auto max-h-full" aria-hidden="true">
|
|
30
|
+
<defs>
|
|
31
|
+
<marker id="trf-a" viewBox="0 0 10 8" refX="9" refY="4"
|
|
32
|
+
markerWidth="7" markerHeight="6" orient="auto">
|
|
33
|
+
<path d="M 0 0 L 10 4 L 0 8 z" fill={ec} opacity="0.55" />
|
|
34
|
+
</marker>
|
|
35
|
+
<marker id="trf-a2" viewBox="0 0 10 8" refX="9" refY="4"
|
|
36
|
+
markerWidth="7" markerHeight="6" orient="auto">
|
|
37
|
+
<path d="M 0 0 L 10 4 L 0 8 z" fill={ec} opacity="0.35" />
|
|
38
|
+
</marker>
|
|
39
|
+
</defs>
|
|
40
|
+
|
|
41
|
+
{/* Vertical spine */}
|
|
42
|
+
<line x1="38" y1="6" x2="38" y2="114" stroke={ec} strokeWidth="2.5" opacity="0.3" strokeLinecap="round" />
|
|
43
|
+
|
|
44
|
+
{/* Internet node — rounded rect with light fill */}
|
|
45
|
+
<rect x="3" y="43" width="24" height="16" rx="5" fill={inet} opacity="0.35" stroke={inetBorder} strokeWidth="0.8" />
|
|
46
|
+
<circle cx="12" cy="51" r="2.5" fill={inetBorder} opacity="0.6" />
|
|
47
|
+
|
|
48
|
+
{/* Arrow: Internet → spine */}
|
|
49
|
+
<line x1="27" y1="51" x2="36" y2="51" stroke={ec} strokeWidth="2.5" opacity="0.45" markerEnd="url(#trf-a)" />
|
|
50
|
+
|
|
51
|
+
{/* === Branch 1: green service (top) === */}
|
|
52
|
+
<line x1="39" y1="14" x2="56" y2="14" stroke={ec} strokeWidth="2" opacity="0.4" markerEnd="url(#trf-a)" />
|
|
53
|
+
<rect x="58" y="8" width="28" height="12" rx="3" fill={green} opacity="0.85" />
|
|
54
|
+
{/* status dot */}
|
|
55
|
+
<circle cx="62" cy="14" r="1.5" fill="#fbbf24" opacity="0.9" />
|
|
56
|
+
|
|
57
|
+
{/* === Branch 2: blue service → right node === */}
|
|
58
|
+
<line x1="39" y1="33" x2="56" y2="33" stroke={ec} strokeWidth="1.8" opacity="0.4" markerEnd="url(#trf-a)" />
|
|
59
|
+
<rect x="58" y="27" width="28" height="12" rx="3" fill={blue} opacity="0.85" />
|
|
60
|
+
<circle cx="62" cy="33" r="1.5" fill={green} opacity="0.9" />
|
|
61
|
+
{/* → right node (external) */}
|
|
62
|
+
<line x1="86" y1="33" x2="108" y2="24" stroke={ec} strokeWidth="1.2" opacity="0.35" markerEnd="url(#trf-a2)" />
|
|
63
|
+
<rect x="110" y="18" width="28" height="12" rx="3" fill={red} opacity="0.7" />
|
|
64
|
+
|
|
65
|
+
{/* === Branch 3: brown service === */}
|
|
66
|
+
<line x1="39" y1="51" x2="56" y2="51" stroke={ec} strokeWidth="2.2" opacity="0.45" markerEnd="url(#trf-a)" />
|
|
67
|
+
<rect x="58" y="45" width="28" height="12" rx="3" fill={brown} opacity="0.85" />
|
|
68
|
+
<circle cx="62" cy="51" r="1.5" fill={green} opacity="0.9" />
|
|
69
|
+
|
|
70
|
+
{/* === Branch 4: teal service → right node === */}
|
|
71
|
+
<line x1="39" y1="69" x2="56" y2="69" stroke={ec} strokeWidth="1.5" opacity="0.38" markerEnd="url(#trf-a)" />
|
|
72
|
+
<rect x="58" y="63" width="28" height="12" rx="3" fill={teal} opacity="0.85" />
|
|
73
|
+
<circle cx="62" cy="69" r="1.5" fill={green} opacity="0.9" />
|
|
74
|
+
{/* → right node */}
|
|
75
|
+
<line x1="86" y1="69" x2="108" y2="76" stroke={ec} strokeWidth="1.2" opacity="0.35" markerEnd="url(#trf-a2)" />
|
|
76
|
+
<rect x="110" y="70" width="28" height="12" rx="3" fill={blue} opacity="0.7" />
|
|
77
|
+
|
|
78
|
+
{/* === Branch 5: purple service (bottom) === */}
|
|
79
|
+
<line x1="39" y1="87" x2="56" y2="87" stroke={ec} strokeWidth="1.3" opacity="0.35" markerEnd="url(#trf-a)" />
|
|
80
|
+
<rect x="58" y="81" width="28" height="12" rx="3" fill={purple} opacity="0.85" />
|
|
81
|
+
<circle cx="62" cy="87" r="1.5" fill={green} opacity="0.9" />
|
|
82
|
+
|
|
83
|
+
{/* === Branch 6: small red service === */}
|
|
84
|
+
<line x1="39" y1="103" x2="56" y2="103" stroke={ec} strokeWidth="1" opacity="0.3" markerEnd="url(#trf-a)" />
|
|
85
|
+
<rect x="58" y="97" width="28" height="12" rx="3" fill={red} opacity="0.65" />
|
|
86
|
+
<circle cx="62" cy="103" r="1.5" fill={red} opacity="0.9" />
|
|
87
|
+
</svg>
|
|
88
|
+
)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function TrafficSummary({ data, onNavigate }: TrafficSummaryProps) {
|
|
92
|
+
const hasFlows = data && data.flowCount > 0
|
|
93
|
+
|
|
94
|
+
return (
|
|
95
|
+
<button
|
|
96
|
+
onClick={onNavigate}
|
|
97
|
+
className="group h-[260px] rounded-xl bg-theme-surface shadow-theme-sm hover:-translate-y-1 hover:shadow-theme-md transition-all duration-200 text-left overflow-hidden"
|
|
98
|
+
>
|
|
99
|
+
<div className="flex flex-col h-full w-full">
|
|
100
|
+
<div className="flex items-center justify-between px-5 py-3 border-b border-theme-border/50">
|
|
101
|
+
<div className="flex items-center gap-2">
|
|
102
|
+
<Activity className="w-4 h-4 text-theme-text-tertiary" />
|
|
103
|
+
<span className="text-xs font-semibold uppercase tracking-wider text-theme-text-secondary">Traffic</span>
|
|
104
|
+
</div>
|
|
105
|
+
{hasFlows && (
|
|
106
|
+
<span className="text-[11px] text-theme-text-tertiary">
|
|
107
|
+
{data.source} · {data.flowCount} flows
|
|
108
|
+
</span>
|
|
109
|
+
)}
|
|
110
|
+
</div>
|
|
111
|
+
|
|
112
|
+
<div className="flex-1 min-h-0 overflow-hidden">
|
|
113
|
+
{hasFlows ? (
|
|
114
|
+
/* Real data: show top flows */
|
|
115
|
+
<div className="px-4 py-2 space-y-1.5">
|
|
116
|
+
{data.topFlows.map((flow, i) => (
|
|
117
|
+
<div key={i} className="flex items-center gap-2 text-xs">
|
|
118
|
+
<span className="text-theme-text-primary truncate">{flow.src}</span>
|
|
119
|
+
<ArrowRightLeft className="w-3 h-3 text-theme-text-tertiary shrink-0" />
|
|
120
|
+
<span className="text-theme-text-primary truncate">{flow.dst}</span>
|
|
121
|
+
<span className="text-xs text-theme-text-tertiary shrink-0 ml-auto">
|
|
122
|
+
{flow.connections} conn
|
|
123
|
+
</span>
|
|
124
|
+
</div>
|
|
125
|
+
))}
|
|
126
|
+
</div>
|
|
127
|
+
) : (
|
|
128
|
+
/* No data yet: schematic + description */
|
|
129
|
+
<div className="flex items-stretch gap-2 px-3 py-1.5 h-full">
|
|
130
|
+
<div className="flex flex-col justify-center gap-1.5 w-[105px] shrink-0">
|
|
131
|
+
<p className="text-[11px] leading-snug text-theme-text-secondary">
|
|
132
|
+
Visualize live service-to-service network flows and external dependencies
|
|
133
|
+
</p>
|
|
134
|
+
{data && (
|
|
135
|
+
<span className="text-[10px] text-theme-text-tertiary">
|
|
136
|
+
Source: {data.source}
|
|
137
|
+
</span>
|
|
138
|
+
)}
|
|
139
|
+
</div>
|
|
140
|
+
<div className="flex-1 min-w-0 overflow-hidden">
|
|
141
|
+
<TrafficSchematic />
|
|
142
|
+
</div>
|
|
143
|
+
</div>
|
|
144
|
+
)}
|
|
145
|
+
</div>
|
|
146
|
+
|
|
147
|
+
<div className="px-4 py-1.5 border-t border-theme-border/50 flex items-center justify-end gap-1.5 text-[10px] font-semibold uppercase tracking-wider text-theme-text-secondary group-hover:text-theme-text-primary transition-colors">
|
|
148
|
+
Open Traffic
|
|
149
|
+
<ArrowRight className="w-3.5 h-3.5 transition-transform group-hover:translate-x-0.5" />
|
|
150
|
+
</div>
|
|
151
|
+
</div>
|
|
152
|
+
</button>
|
|
153
|
+
)
|
|
154
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { StructuredLogLine as JsonLogLine } from '@skyhook-io/k8s-ui'
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { useCallback } from 'react'
|
|
2
|
+
import { fetchJSON, createLogStream } from '../../api/client'
|
|
3
|
+
import { LogsViewer as SharedLogsViewer } from '@skyhook-io/k8s-ui'
|
|
4
|
+
import type { LogsFetchParams } from '@skyhook-io/k8s-ui'
|
|
5
|
+
import { useDesktopDownload } from '../../hooks/useDesktopDownload'
|
|
6
|
+
|
|
7
|
+
interface LogsViewerProps {
|
|
8
|
+
namespace: string
|
|
9
|
+
podName: string
|
|
10
|
+
containers: string[]
|
|
11
|
+
initialContainer?: string
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function LogsViewer({ namespace, podName, containers, initialContainer }: LogsViewerProps) {
|
|
15
|
+
const desktopDownload = useDesktopDownload()
|
|
16
|
+
|
|
17
|
+
const fetchLogs = useCallback(async (params: LogsFetchParams) => {
|
|
18
|
+
const query = new URLSearchParams()
|
|
19
|
+
query.set('container', params.container)
|
|
20
|
+
if (params.tailLines) query.set('tailLines', String(params.tailLines))
|
|
21
|
+
if (params.sinceSeconds) query.set('sinceSeconds', String(params.sinceSeconds))
|
|
22
|
+
if (params.previous) query.set('previous', 'true')
|
|
23
|
+
const data = await fetchJSON<{ logs: { [container: string]: string } }>(
|
|
24
|
+
`/pods/${namespace}/${podName}/logs?${query}`
|
|
25
|
+
)
|
|
26
|
+
return data.logs
|
|
27
|
+
}, [namespace, podName])
|
|
28
|
+
|
|
29
|
+
const makeStream = useCallback((params: Omit<LogsFetchParams, 'previous'>) => {
|
|
30
|
+
return createLogStream(namespace, podName, params)
|
|
31
|
+
}, [namespace, podName])
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<SharedLogsViewer
|
|
35
|
+
namespace={namespace}
|
|
36
|
+
podName={podName}
|
|
37
|
+
containers={containers}
|
|
38
|
+
initialContainer={initialContainer}
|
|
39
|
+
fetchLogs={fetchLogs}
|
|
40
|
+
createStream={makeStream}
|
|
41
|
+
overrideDownload={desktopDownload}
|
|
42
|
+
/>
|
|
43
|
+
)
|
|
44
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { useCallback } from 'react'
|
|
2
|
+
import { fetchJSON, createWorkloadLogStream } from '../../api/client'
|
|
3
|
+
import { WorkloadLogsViewer as SharedWorkloadLogsViewer } from '@skyhook-io/k8s-ui'
|
|
4
|
+
import type { WorkloadLogsFetchParams, WorkloadLogsResult } from '@skyhook-io/k8s-ui'
|
|
5
|
+
import { useDesktopDownload } from '../../hooks/useDesktopDownload'
|
|
6
|
+
|
|
7
|
+
interface WorkloadLogsViewerProps {
|
|
8
|
+
kind: string
|
|
9
|
+
namespace: string
|
|
10
|
+
name: string
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function WorkloadLogsViewer({ kind, namespace, name }: WorkloadLogsViewerProps) {
|
|
14
|
+
const desktopDownload = useDesktopDownload()
|
|
15
|
+
|
|
16
|
+
const fetchAll = useCallback(async (params: WorkloadLogsFetchParams): Promise<WorkloadLogsResult> => {
|
|
17
|
+
const query = new URLSearchParams()
|
|
18
|
+
if (params.container) query.set('container', params.container)
|
|
19
|
+
if (params.tailLines) query.set('tailLines', String(params.tailLines))
|
|
20
|
+
if (params.sinceSeconds) query.set('sinceSeconds', String(params.sinceSeconds))
|
|
21
|
+
const qs = query.toString()
|
|
22
|
+
const data = await fetchJSON<WorkloadLogsResult>(
|
|
23
|
+
`/workloads/${kind}/${namespace}/${name}/logs${qs ? `?${qs}` : ''}`
|
|
24
|
+
)
|
|
25
|
+
return data
|
|
26
|
+
}, [kind, namespace, name])
|
|
27
|
+
|
|
28
|
+
const makeStream = useCallback((params: WorkloadLogsFetchParams) => {
|
|
29
|
+
return createWorkloadLogStream(kind, namespace, name, params)
|
|
30
|
+
}, [kind, namespace, name])
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<SharedWorkloadLogsViewer
|
|
34
|
+
name={name}
|
|
35
|
+
fetchAll={fetchAll}
|
|
36
|
+
createStream={makeStream}
|
|
37
|
+
overrideDownload={desktopDownload}
|
|
38
|
+
/>
|
|
39
|
+
)
|
|
40
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useLogSearch } from '@skyhook-io/k8s-ui'
|