@skyhook-io/radar-app 1.17.0 → 1.17.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 +1 -1
- package/package.json +3 -3
- package/src/App.tsx +125 -87
- package/src/api/actions.errorCode.test.ts +40 -0
- package/src/api/actions.test.ts +48 -0
- package/src/api/actions.ts +79 -0
- package/src/api/apiResources.navigation.test.tsx +232 -0
- package/src/api/apiResources.ts +46 -3
- package/src/api/client.helmSource.test.ts +39 -0
- package/src/api/client.namespaceSwitch.hook.test.tsx +54 -0
- package/src/api/client.namespaceSwitch.test.ts +107 -0
- package/src/api/client.ts +266 -39
- package/src/api/cnpg-ha.live.test.ts +140 -0
- package/src/api/cnpg-ha.test.ts +78 -0
- package/src/api/cnpg-ha.ts +19 -0
- package/src/api/cnpg-history.ts +123 -0
- package/src/api/cnpg-inspect.ts +102 -0
- package/src/api/cnpg-protection.ts +112 -0
- package/src/api/cnpg-recovery.test.tsx +60 -0
- package/src/api/cnpg-recovery.ts +262 -0
- package/src/api/cnpg-sessions.ts +175 -0
- package/src/api/cnpg-storage.ts +138 -0
- package/src/api/cnpg.legacy-reads.test.ts +43 -0
- package/src/api/cnpg.pooler-runtime.test.ts +15 -0
- package/src/api/cnpg.ts +428 -10
- package/src/api/radarFeatures.render.test.tsx +47 -3
- package/src/api/radarFeatures.ts +4 -1
- package/src/api/reviewedActionMutation.test.tsx +164 -0
- package/src/api/reviewedActionMutation.ts +66 -0
- package/src/api/timelineSource.test.ts +9 -0
- package/src/api/timelineSource.ts +8 -0
- package/src/components/audit/AuditView.tsx +9 -0
- package/src/components/capacity/CapacityActivity.tsx +3 -31
- package/src/components/capacity/CapacityDemand.tsx +4 -36
- package/src/components/capacity/CapacityOverview.tsx +217 -56
- package/src/components/capacity/CapacityPoolDetail.tsx +6 -55
- package/src/components/capacity/CapacityView.test.tsx +323 -0
- package/src/components/capacity/ClusterSchedulingCard.tsx +2 -10
- package/src/components/capacity/certaintyGlyph.test.tsx +2 -9
- package/src/components/capacity/routes.ts +42 -0
- package/src/components/capacity/shared.tsx +11 -129
- package/src/components/capacity/workspaceRoute.ts +18 -0
- package/src/components/cnpg/CNPGActionHost.compatibility.test.tsx +30 -0
- package/src/components/cnpg/CNPGArchivingRepair.tsx +191 -0
- package/src/components/cnpg/CNPGBlockingSessions.test.tsx +50 -0
- package/src/components/cnpg/CNPGBlockingSessions.tsx +333 -0
- package/src/components/cnpg/CNPGClusterActivity.test.tsx +11 -0
- package/src/components/cnpg/CNPGClusterActivity.tsx +18 -9
- package/src/components/cnpg/CNPGClusterLogs.compatibility.test.tsx +130 -0
- package/src/components/cnpg/CNPGClusterLogs.empty.test.tsx +29 -0
- package/src/components/cnpg/CNPGClusterLogs.test.ts +9 -0
- package/src/components/cnpg/CNPGClusterLogs.tsx +81 -24
- package/src/components/cnpg/CNPGClusterTabs.test.tsx +152 -0
- package/src/components/cnpg/CNPGClusterTabs.tsx +187 -0
- package/src/components/cnpg/CNPGClustersKindView.tsx +46 -0
- package/src/components/cnpg/CNPGConfiguration.test.tsx +223 -0
- package/src/components/cnpg/CNPGConfiguration.tsx +190 -0
- package/src/components/cnpg/CNPGCreateClusterDialog.test.tsx +113 -0
- package/src/components/cnpg/CNPGCreateClusterDialog.tsx +74 -0
- package/src/components/cnpg/CNPGDeclarations.test.ts +107 -0
- package/src/components/cnpg/CNPGDeclarations.tsx +236 -78
- package/src/components/cnpg/CNPGDetailPage.test.tsx +62 -0
- package/src/components/cnpg/CNPGDetailPage.tsx +159 -98
- package/src/components/cnpg/CNPGDrawerTrail.tsx +2 -2
- package/src/components/cnpg/CNPGInvestigationAction.test.tsx +30 -0
- package/src/components/cnpg/CNPGOperator.test.tsx +34 -0
- package/src/components/cnpg/CNPGOperator.tsx +78 -30
- package/src/components/cnpg/CNPGOperatorBanner.tsx +39 -0
- package/src/components/cnpg/CNPGOperatorConditions.test.tsx +45 -0
- package/src/components/cnpg/CNPGOperatorConditions.tsx +16 -0
- package/src/components/cnpg/CNPGOperatorConfig.test.tsx +27 -0
- package/src/components/cnpg/CNPGOperatorDiagnosis.tsx +247 -0
- package/src/components/cnpg/CNPGOverview.test.tsx +171 -0
- package/src/components/cnpg/CNPGOverview.tsx +238 -63
- package/src/components/cnpg/CNPGParametersInEffect.test.tsx +51 -0
- package/src/components/cnpg/CNPGParametersInEffect.tsx +120 -0
- package/src/components/cnpg/CNPGPerformance.prerequisite.test.tsx +48 -0
- package/src/components/cnpg/CNPGPerformance.test.tsx +73 -0
- package/src/components/cnpg/CNPGPerformance.tsx +477 -0
- package/src/components/cnpg/CNPGPooling.test.tsx +89 -0
- package/src/components/cnpg/CNPGPooling.tsx +97 -40
- package/src/components/cnpg/CNPGProtection.test.tsx +145 -0
- package/src/components/cnpg/CNPGProtection.tsx +228 -122
- package/src/components/cnpg/CNPGReplicationTab.test.tsx +87 -0
- package/src/components/cnpg/CNPGReplicationTab.tsx +212 -0
- package/src/components/cnpg/CNPGReplicationView.tsx +264 -0
- package/src/components/cnpg/CNPGStorage.test.tsx +140 -0
- package/src/components/cnpg/CNPGStorage.tsx +619 -0
- package/src/components/cnpg/CNPGSummaryHost.overview.test.tsx +44 -0
- package/src/components/cnpg/CNPGSummaryHost.test.tsx +23 -0
- package/src/components/cnpg/CNPGSummaryHost.tsx +228 -54
- package/src/components/cnpg/CNPGTrends.denied.test.tsx +33 -0
- package/src/components/cnpg/CNPGTrends.missing.test.tsx +69 -0
- package/src/components/cnpg/CNPGTrends.test.ts +38 -0
- package/src/components/cnpg/CNPGTrends.tsx +702 -0
- package/src/components/cnpg/CNPGView.tsx +34 -21
- package/src/components/cnpg/CNPGWorkspace.compatibility.test.tsx +90 -0
- package/src/components/cnpg/actions/CNPGClusterActions.dialog.test.tsx +79 -0
- package/src/components/cnpg/actions/CNPGClusterActions.test.tsx +142 -0
- package/src/components/cnpg/actions/CNPGClusterActions.tsx +853 -0
- package/src/components/cnpg/actions/CNPGConnectButton.read.test.tsx +40 -0
- package/src/components/cnpg/actions/CNPGConnectButton.test.ts +25 -0
- package/src/components/cnpg/actions/CNPGConnectButton.tsx +131 -0
- package/src/components/cnpg/actions/CNPGDestroyInstanceDialog.tsx +185 -0
- package/src/components/cnpg/actions/CNPGInstanceActions.test.tsx +38 -0
- package/src/components/cnpg/actions/CNPGInstanceActions.tsx +74 -0
- package/src/components/cnpg/actions/CNPGMaintenanceBanner.tsx +53 -0
- package/src/components/cnpg/actions/CNPGPoolerActions.test.tsx +35 -0
- package/src/components/cnpg/actions/CNPGPoolerActions.tsx +79 -0
- package/src/components/cnpg/actions/CNPGReportDialog.test.tsx +12 -0
- package/src/components/cnpg/actions/CNPGReportDialog.tsx +91 -0
- package/src/components/cnpg/actions/CNPGScheduleActions.run.test.tsx +58 -0
- package/src/components/cnpg/actions/CNPGScheduleActions.test.tsx +54 -0
- package/src/components/cnpg/actions/CNPGScheduleActions.tsx +208 -0
- package/src/components/cnpg/actions/actionModel.test.ts +111 -0
- package/src/components/cnpg/actions/actionModel.ts +127 -0
- package/src/components/cnpg/actions/renderCNPGHeaderActions.tsx +60 -0
- package/src/components/cnpg/actions/useCNPGWriteGuard.tsx +58 -0
- package/src/components/cnpg/actions/useOpenCNPGPsql.ts +22 -0
- package/src/components/cnpg/archivingRepair.test.ts +104 -0
- package/src/components/cnpg/archivingRepair.ts +145 -0
- package/src/components/cnpg/baseBackup.test.ts +36 -0
- package/src/components/cnpg/baseBackup.ts +36 -0
- package/src/components/cnpg/blocking.test.ts +59 -0
- package/src/components/cnpg/blocking.ts +131 -0
- package/src/components/cnpg/coverageText.test.ts +27 -0
- package/src/components/cnpg/creation/CNPGTargetFields.tsx +110 -0
- package/src/components/cnpg/creation/targetModel.test.ts +137 -0
- package/src/components/cnpg/creation/targetModel.ts +149 -0
- package/src/components/cnpg/fleetStatus.test.ts +46 -0
- package/src/components/cnpg/fleetStatus.ts +43 -0
- package/src/components/cnpg/formFields.ts +2 -0
- package/src/components/cnpg/grantText.test.tsx +11 -0
- package/src/components/cnpg/host.test.tsx +24 -0
- package/src/components/cnpg/host.tsx +101 -0
- package/src/components/cnpg/inspectModel.test.ts +120 -0
- package/src/components/cnpg/inspectModel.ts +140 -0
- package/src/components/cnpg/logicalSlots.test.ts +30 -0
- package/src/components/cnpg/logicalSlots.ts +29 -0
- package/src/components/cnpg/lsn.test.ts +40 -0
- package/src/components/cnpg/lsn.ts +43 -0
- package/src/components/cnpg/operations/CNPGFleetOperation.tsx +30 -0
- package/src/components/cnpg/operations/CNPGOperationTracker.test.tsx +247 -0
- package/src/components/cnpg/operations/CNPGOperationTracker.tsx +255 -0
- package/src/components/cnpg/operations/model.test.ts +510 -0
- package/src/components/cnpg/operations/model.ts +499 -0
- package/src/components/cnpg/operations/presentation.test.ts +80 -0
- package/src/components/cnpg/operations/presentation.ts +84 -0
- package/src/components/cnpg/operations/store.ts +98 -0
- package/src/components/cnpg/operatorStatus.test.ts +134 -0
- package/src/components/cnpg/operatorStatus.ts +194 -0
- package/src/components/cnpg/paths.test.ts +54 -0
- package/src/components/cnpg/paths.ts +47 -4
- package/src/components/cnpg/protection/CNPGAttachArchiveDialog.tsx +185 -0
- package/src/components/cnpg/protection/CNPGCreateScheduleDialog.tsx +196 -0
- package/src/components/cnpg/protection/CNPGProtectionSetup.test.tsx +121 -0
- package/src/components/cnpg/protection/CNPGProtectionSetup.tsx +452 -0
- package/src/components/cnpg/protection/CNPGScheduleInput.tsx +115 -0
- package/src/components/cnpg/protection/CNPGScheduleRepairButton.tsx +120 -0
- package/src/components/cnpg/protection/scheduleModel.test.ts +19 -0
- package/src/components/cnpg/protection/scheduleModel.ts +16 -0
- package/src/components/cnpg/recovery/CNPGRecoveryPoint.tsx +220 -0
- package/src/components/cnpg/recovery/CNPGRestoreButton.test.tsx +29 -0
- package/src/components/cnpg/recovery/CNPGRestoreButton.tsx +26 -0
- package/src/components/cnpg/recovery/CNPGRestoreChecks.test.tsx +23 -0
- package/src/components/cnpg/recovery/CNPGRestoreChecks.tsx +153 -0
- package/src/components/cnpg/recovery/CNPGRestoreDialog.back.test.tsx +149 -0
- package/src/components/cnpg/recovery/CNPGRestoreDialog.test.tsx +46 -0
- package/src/components/cnpg/recovery/CNPGRestoreDialog.tsx +333 -0
- package/src/components/cnpg/recovery/CNPGRestoreProgress.tsx +182 -0
- package/src/components/cnpg/recovery/CNPGRestoreValidation.tsx +216 -0
- package/src/components/cnpg/recovery/restoreModel.test.ts +709 -0
- package/src/components/cnpg/recovery/restoreModel.ts +685 -0
- package/src/components/cnpg/recovery/restoreOperation.ts +56 -0
- package/src/components/cnpg/refresh.test.ts +38 -0
- package/src/components/cnpg/refresh.ts +17 -0
- package/src/components/cnpg/refreshNotice.test.tsx +29 -0
- package/src/components/cnpg/routes.test.ts +34 -3
- package/src/components/cnpg/routes.ts +60 -48
- package/src/components/cnpg/runtimeAssessment.ts +198 -0
- package/src/components/cnpg/runtimeModel.test.ts +175 -0
- package/src/components/cnpg/runtimeModel.ts +196 -0
- package/src/components/cnpg/runtimeParts.test.tsx +17 -0
- package/src/components/cnpg/runtimeParts.tsx +79 -0
- package/src/components/cnpg/shared.test.tsx +59 -0
- package/src/components/cnpg/shared.tsx +100 -182
- package/src/components/cnpg/storageModel.test.ts +107 -0
- package/src/components/cnpg/storageModel.ts +101 -0
- package/src/components/cnpg/trendSamples.test.ts +148 -0
- package/src/components/cnpg/trendSamples.ts +222 -0
- package/src/components/cnpg/useCNPGClusterAssessment.ts +30 -0
- package/src/components/cnpg/useCNPGKubectlContext.test.tsx +45 -0
- package/src/components/cnpg/useCNPGKubectlContext.ts +13 -0
- package/src/components/cnpg/useCNPGNavigate.test.tsx +58 -0
- package/src/components/cnpg/useCNPGNavigate.ts +21 -0
- package/src/components/cnpg/useCNPGPoolerLive.ts +46 -0
- package/src/components/cnpg/useCNPGScreenParams.ts +24 -0
- package/src/components/cnpg/useCNPGSidebarWorkspace.ts +66 -16
- package/src/components/cnpg/workspaceRoute.ts +23 -0
- package/src/components/cost/ApplicationCostTab.test.ts +7 -0
- package/src/components/cost/ApplicationCostTab.tsx +7 -7
- package/src/components/cost/CostView.test.ts +2 -1
- package/src/components/cost/CostView.tsx +0 -2
- package/src/components/cost/WorkloadCostTab.tsx +2 -4
- package/src/components/cost/errors.ts +3 -1
- package/src/components/cost/source.test.ts +10 -0
- package/src/components/cost/source.ts +5 -1
- package/src/components/diagnose/investigationEvidence/adapters/issues.ts +8 -0
- package/src/components/diagnose/investigationEvidence/projection.test.ts +16 -0
- package/src/components/dock/BottomDock.tsx +2 -0
- package/src/components/dock/TerminalTab.test.tsx +17 -0
- package/src/components/dock/TerminalTab.tsx +7 -3
- package/src/components/gitops/ArgoResourceDiffLoader.tsx +4 -2
- package/src/components/gitops/GitOpsView.tsx +16 -23
- package/src/components/helm/HelmCompareRoute.test.tsx +59 -0
- package/src/components/helm/HelmCompareRoute.tsx +57 -26
- package/src/components/helm/HelmReleaseDrawer.test.ts +55 -3
- package/src/components/helm/HelmReleaseDrawer.tsx +50 -12
- package/src/components/helm/TrackChartSourceDialog.render.test.tsx +120 -0
- package/src/components/helm/TrackChartSourceDialog.test.ts +50 -0
- package/src/components/helm/TrackChartSourceDialog.tsx +153 -176
- package/src/components/helm/ValuesViewer.test.tsx +301 -0
- package/src/components/helm/ValuesViewer.tsx +169 -78
- package/src/components/home/ActivitySummary.tsx +2 -1
- package/src/components/home/HomeView.tsx +20 -9
- package/src/components/home/ProblemsPanel.test.tsx +81 -0
- package/src/components/home/TopologyPreview.tsx +2 -2
- package/src/components/issues/IssuesPane.render.test.tsx +122 -0
- package/src/components/issues/IssuesPane.test.ts +65 -1
- package/src/components/issues/IssuesPane.tsx +188 -25
- package/src/components/issues/uncheckedSources.ts +21 -0
- package/src/components/resource/PVCUsageBar.render.test.tsx +32 -0
- package/src/components/resource/PVCUsageBar.test.tsx +24 -0
- package/src/components/resource/PVCUsageBar.tsx +15 -6
- package/src/components/resource/WorkloadMetricsHelpDialog.test.tsx +3 -1
- package/src/components/resource/WorkloadMetricsHelpDialog.tsx +1 -1
- package/src/components/resources/CompositeRenderer.tsx +4 -4
- package/src/components/resources/ResourceDetailDrawer.tsx +2 -2
- package/src/components/resources/ResourcesView.tsx +26 -12
- package/src/components/settings/LocalIntegrationStatus.test.tsx +52 -0
- package/src/components/settings/LocalIntegrationStatus.tsx +3 -4
- package/src/components/settings/SettingsDialog.tsx +28 -15
- package/src/components/timeline/TimelineList.tsx +22 -24
- package/src/components/timeline/TimelineLoadError.test.tsx +62 -0
- package/src/components/timeline/TimelineLoadError.tsx +96 -0
- package/src/components/timeline/TimelineView.tsx +18 -45
- package/src/components/timeline/ViewModeToggle.tsx +20 -0
- package/src/components/timeline/useStickyError.test.tsx +47 -0
- package/src/components/timeline/useStickyError.ts +15 -0
- package/src/components/ui/DiagnosticsOverlay.tsx +34 -2
- package/src/components/ui/Markdown.test.tsx +65 -0
- package/src/components/ui/Markdown.tsx +144 -127
- package/src/components/whats-new/releaseNotes.ts +63 -1
- package/src/components/workload/WorkloadView.test.ts +10 -1
- package/src/components/workload/WorkloadView.tsx +27 -239
- package/src/components/workspace/layout.test.tsx +29 -0
- package/src/components/workspace/layout.tsx +259 -0
- package/src/components/workspace/table.ts +7 -0
- package/src/contexts/CapabilitiesContext.tsx +1 -1
- package/src/integrations/resourceHost.test.tsx +55 -0
- package/src/integrations/resourceHost.ts +99 -0
- package/src/integrations/resourceHosts.test.tsx +141 -0
- package/src/integrations/resourceHosts.tsx +119 -0
- package/src/integrations/workspaceRoute.ts +20 -0
- package/src/integrations/workspaceRoutes.test.ts +40 -0
- package/src/integrations/workspaceRoutes.ts +22 -0
- package/src/integrations/workspaceScreens.tsx +14 -0
- package/src/utils/drawer-trail.ts +35 -0
- package/src/utils/kindFilterStore.test.ts +147 -0
- package/src/utils/kindFilterStore.ts +91 -0
- package/src/utils/navigation.test.ts +13 -1
- package/src/utils/navigation.ts +39 -2
- package/src/utils/page-links.ts +21 -0
- package/src/utils/tabStorage.ts +40 -0
- package/src/utils/viewMemory.test.ts +78 -0
- package/src/utils/viewMemory.ts +54 -0
|
@@ -3,10 +3,13 @@ import { Layers3, X } from "lucide-react";
|
|
|
3
3
|
import {
|
|
4
4
|
Collapse,
|
|
5
5
|
CollapseChevron,
|
|
6
|
+
formatDuration,
|
|
6
7
|
StatusDot,
|
|
8
|
+
Tooltip,
|
|
7
9
|
WithTooltip,
|
|
8
10
|
mapHealthToTone,
|
|
9
11
|
type CapacityAutoscalerBackoff,
|
|
12
|
+
type CapacityAutoscalerScaleDown,
|
|
10
13
|
type CapacityAutoscalerChildObservation,
|
|
11
14
|
type CapacityBoundedResultMeta,
|
|
12
15
|
type CapacityCertainty,
|
|
@@ -25,48 +28,10 @@ import { ClusterSchedulingCard } from "./ClusterSchedulingCard";
|
|
|
25
28
|
import { Badge } from "@skyhook-io/k8s-ui/components/ui/Badge";
|
|
26
29
|
import type { useCapacityOverview } from "../../api/client";
|
|
27
30
|
import type { SelectedResource } from "../../types";
|
|
28
|
-
import {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
coverageHasObservations,
|
|
33
|
-
coverageIsDenied,
|
|
34
|
-
coverageIsLowerBound,
|
|
35
|
-
CertaintyGlyph,
|
|
36
|
-
formatQuantity,
|
|
37
|
-
coverageMessage,
|
|
38
|
-
DeniedBadge,
|
|
39
|
-
EmptyState,
|
|
40
|
-
errorMessage,
|
|
41
|
-
formatTimestamp,
|
|
42
|
-
humanizeCode,
|
|
43
|
-
identityToSelectedResource,
|
|
44
|
-
InlineEmpty,
|
|
45
|
-
integrationBlock,
|
|
46
|
-
InventoryQuantityCell,
|
|
47
|
-
KpiTile,
|
|
48
|
-
LinkButton,
|
|
49
|
-
managerStatusTone,
|
|
50
|
-
Notice,
|
|
51
|
-
pickWorstPressure,
|
|
52
|
-
PoolReadyBadge,
|
|
53
|
-
poolReadinessDetail,
|
|
54
|
-
RefreshError,
|
|
55
|
-
relativeTime,
|
|
56
|
-
ROW_HOVER,
|
|
57
|
-
ScopeBadges,
|
|
58
|
-
ScrollableContent,
|
|
59
|
-
SectionCard,
|
|
60
|
-
shortResourceLabel,
|
|
61
|
-
sortedResourceEntries,
|
|
62
|
-
TABLE_HEAD,
|
|
63
|
-
TABLE_WRAP,
|
|
64
|
-
TBODY,
|
|
65
|
-
TD,
|
|
66
|
-
TH,
|
|
67
|
-
worstManagerStatus,
|
|
68
|
-
type CapacityConnectionState,
|
|
69
|
-
} from "./shared";
|
|
31
|
+
import { actionSeverity, CapacityFreshness, capacityManagerLabel, coverageHasObservations, coverageIsDenied, coverageIsLowerBound, formatQuantity, coverageMessage, DeniedBadge, errorMessage, formatTimestamp, humanizeCode, identityToSelectedResource, InlineEmpty, integrationBlock, InventoryQuantityCell, KpiTile, LinkButton, managerStatusTone, pickWorstPressure, PoolReadyBadge, poolReadinessDetail, RefreshError, relativeTime, ScopeBadges, ScrollableContent, SectionCard, shortResourceLabel, sortedResourceEntries, worstManagerStatus, type CapacityConnectionState } from "./shared";
|
|
32
|
+
import { CertaintyGlyph } from "@skyhook-io/k8s-ui";
|
|
33
|
+
import { Notice, ScreenEmptyState } from "../workspace/layout";
|
|
34
|
+
import { ROW_HOVER, TABLE_HEAD, TABLE_WRAP, TBODY, TD, TH } from "../workspace/table";
|
|
70
35
|
|
|
71
36
|
const EXPLAIN_CARDS: { term: string; body: string }[] = [
|
|
72
37
|
{
|
|
@@ -337,7 +302,7 @@ export function CapacityOverview({
|
|
|
337
302
|
// NodePool coverage by definition — that is not an error to block on.
|
|
338
303
|
if (karpenterActive && !coverageHasObservations(data.coverage.nodePools)) {
|
|
339
304
|
return (
|
|
340
|
-
<
|
|
305
|
+
<ScreenEmptyState
|
|
341
306
|
icon={Layers3}
|
|
342
307
|
title="NodePool inventory unavailable"
|
|
343
308
|
detail={coverageMessage(data.coverage.nodePools, "NodePool inventory")}
|
|
@@ -345,6 +310,10 @@ export function CapacityOverview({
|
|
|
345
310
|
);
|
|
346
311
|
}
|
|
347
312
|
|
|
313
|
+
const showScaleDown =
|
|
314
|
+
data.groups.some((group) =>
|
|
315
|
+
group.children.some((child) => child.scaleDown),
|
|
316
|
+
) || data.orphanAutoscalerGroups.some((child) => child.scaleDown);
|
|
348
317
|
const summary = data.summary;
|
|
349
318
|
const coverage = data.coverage;
|
|
350
319
|
const podsDeniedFlag = coverageIsDenied(coverage.pods);
|
|
@@ -569,6 +538,7 @@ export function CapacityOverview({
|
|
|
569
538
|
)}
|
|
570
539
|
|
|
571
540
|
<NodeGroupsSection
|
|
541
|
+
showScaleDown={showScaleDown}
|
|
572
542
|
sectionRef={inventoryRef}
|
|
573
543
|
groups={data.groups}
|
|
574
544
|
pools={data.pools}
|
|
@@ -580,6 +550,7 @@ export function CapacityOverview({
|
|
|
580
550
|
/>
|
|
581
551
|
|
|
582
552
|
<OrphanAutoscalerSection
|
|
553
|
+
showScaleDown={showScaleDown}
|
|
583
554
|
orphans={data.orphanAutoscalerGroups}
|
|
584
555
|
meta={data.orphanAutoscalerGroupsMeta}
|
|
585
556
|
/>
|
|
@@ -762,6 +733,7 @@ function ManagerLine({
|
|
|
762
733
|
// ============================================================================
|
|
763
734
|
|
|
764
735
|
function NodeGroupsSection({
|
|
736
|
+
showScaleDown,
|
|
765
737
|
sectionRef,
|
|
766
738
|
groups,
|
|
767
739
|
pools,
|
|
@@ -771,6 +743,7 @@ function NodeGroupsSection({
|
|
|
771
743
|
onOpenPool,
|
|
772
744
|
onOpenResource,
|
|
773
745
|
}: {
|
|
746
|
+
showScaleDown: boolean;
|
|
774
747
|
sectionRef: RefObject<HTMLDivElement | null>;
|
|
775
748
|
groups: CapacityGroupSummary[];
|
|
776
749
|
pools: CapacityPoolSummary[];
|
|
@@ -843,6 +816,7 @@ function NodeGroupsSection({
|
|
|
843
816
|
<GroupRow
|
|
844
817
|
key={group.id}
|
|
845
818
|
group={group}
|
|
819
|
+
showScaleDown={showScaleDown}
|
|
846
820
|
pool={
|
|
847
821
|
group.manager === "karpenter"
|
|
848
822
|
? poolByName.get(group.name)
|
|
@@ -980,12 +954,14 @@ function worstChildHealth(
|
|
|
980
954
|
|
|
981
955
|
function GroupRow({
|
|
982
956
|
group,
|
|
957
|
+
showScaleDown,
|
|
983
958
|
pool,
|
|
984
959
|
detectionFailure,
|
|
985
960
|
onOpenPool,
|
|
986
961
|
onOpenResource,
|
|
987
962
|
}: {
|
|
988
963
|
group: CapacityGroupSummary;
|
|
964
|
+
showScaleDown: boolean;
|
|
989
965
|
pool?: CapacityPoolSummary;
|
|
990
966
|
/** Why manager detection could not run, when it could not. Non-null forbids
|
|
991
967
|
* the "none detected" conclusion for a group with no attributed manager. */
|
|
@@ -1000,8 +976,24 @@ function GroupRow({
|
|
|
1000
976
|
? pickWorstPressure(pool.ledger.limitPressure)
|
|
1001
977
|
: undefined;
|
|
1002
978
|
const childHealth = worstChildHealth(group.children);
|
|
1003
|
-
|
|
1004
|
-
|
|
979
|
+
const noScaleDownCandidates =
|
|
980
|
+
hasChildren &&
|
|
981
|
+
!group.childrenMeta.truncated &&
|
|
982
|
+
!group.scaling.some((fact) => fact.code === "at_min_size") &&
|
|
983
|
+
group.children.every(
|
|
984
|
+
(child) =>
|
|
985
|
+
child.minSize !== undefined &&
|
|
986
|
+
child.target !== undefined &&
|
|
987
|
+
child.target >= child.minSize &&
|
|
988
|
+
child.scaleDown?.status === "NoCandidates" &&
|
|
989
|
+
child.scaleDown.candidates === 0,
|
|
990
|
+
) &&
|
|
991
|
+
group.children.some(
|
|
992
|
+
(child) =>
|
|
993
|
+
child.target !== undefined &&
|
|
994
|
+
child.minSize !== undefined &&
|
|
995
|
+
child.target > child.minSize,
|
|
996
|
+
);
|
|
1005
997
|
|
|
1006
998
|
return (
|
|
1007
999
|
<>
|
|
@@ -1020,7 +1012,7 @@ function GroupRow({
|
|
|
1020
1012
|
: undefined
|
|
1021
1013
|
}
|
|
1022
1014
|
>
|
|
1023
|
-
<td className={TD}>
|
|
1015
|
+
<td className={`${TD} whitespace-nowrap`}>
|
|
1024
1016
|
<div className="flex items-center gap-1.5">
|
|
1025
1017
|
{hasChildren ? (
|
|
1026
1018
|
<button
|
|
@@ -1092,7 +1084,7 @@ function GroupRow({
|
|
|
1092
1084
|
)}
|
|
1093
1085
|
</div>
|
|
1094
1086
|
</td>
|
|
1095
|
-
<td className={TD}>
|
|
1087
|
+
<td className={`${TD} whitespace-nowrap`}>
|
|
1096
1088
|
{group.manager ? (
|
|
1097
1089
|
<span className="flex flex-wrap items-center gap-1.5">
|
|
1098
1090
|
<Badge tone="structural" size="sm">
|
|
@@ -1119,27 +1111,88 @@ function GroupRow({
|
|
|
1119
1111
|
>
|
|
1120
1112
|
{`${group.readyNodeCount}/${group.nodeCount}`}
|
|
1121
1113
|
</td>
|
|
1122
|
-
<td className={TD}>
|
|
1114
|
+
<td className={`${TD} whitespace-nowrap`}>
|
|
1123
1115
|
<InventoryQuantityCell
|
|
1124
1116
|
observation={group.allocatable}
|
|
1125
1117
|
empty="Not observed"
|
|
1126
1118
|
/>
|
|
1127
1119
|
</td>
|
|
1128
|
-
<td className={TD}>
|
|
1120
|
+
<td className={`${TD} whitespace-nowrap`}>
|
|
1129
1121
|
<InventoryQuantityCell
|
|
1130
1122
|
observation={group.scheduledRequests}
|
|
1131
1123
|
empty="Not observed"
|
|
1132
1124
|
/>
|
|
1133
1125
|
</td>
|
|
1134
1126
|
<td className={`${TD} text-xs text-theme-text-secondary`}>
|
|
1135
|
-
{
|
|
1127
|
+
{/* The only wrapping column, so long prose adds lines instead of
|
|
1128
|
+
squeezing names and badges. Inline tooltip triggers let a fact
|
|
1129
|
+
wrap with the text around it rather than as one box. */}
|
|
1130
|
+
<div className="min-w-[10rem]">
|
|
1131
|
+
{group.scaling.map((fact, index) => (
|
|
1132
|
+
<span key={fact.code}>
|
|
1133
|
+
{index > 0 && " · "}
|
|
1134
|
+
{fact.code === "at_min_size" ? (
|
|
1135
|
+
<Tooltip
|
|
1136
|
+
content={MIN_SIZE_EXPLANATION}
|
|
1137
|
+
wrapperClassName="!inline"
|
|
1138
|
+
>
|
|
1139
|
+
<span
|
|
1140
|
+
tabIndex={0}
|
|
1141
|
+
role="note"
|
|
1142
|
+
aria-label={`${fact.summary}. ${MIN_SIZE_EXPLANATION}`}
|
|
1143
|
+
className="cursor-help rounded focus-visible:outline focus-visible:outline-2 focus-visible:outline-skyhook-500"
|
|
1144
|
+
>
|
|
1145
|
+
{fact.summary}
|
|
1146
|
+
</span>
|
|
1147
|
+
</Tooltip>
|
|
1148
|
+
) : fact.code === "scale_down_candidates" ? (
|
|
1149
|
+
<Tooltip
|
|
1150
|
+
content={SCALE_DOWN_EXPLANATION}
|
|
1151
|
+
wrapperClassName="!inline"
|
|
1152
|
+
>
|
|
1153
|
+
<span
|
|
1154
|
+
tabIndex={0}
|
|
1155
|
+
role="note"
|
|
1156
|
+
aria-label={`${fact.summary}. ${SCALE_DOWN_EXPLANATION}`}
|
|
1157
|
+
className="cursor-help rounded focus-visible:outline focus-visible:outline-2 focus-visible:outline-skyhook-500"
|
|
1158
|
+
>
|
|
1159
|
+
{fact.summary}
|
|
1160
|
+
</span>
|
|
1161
|
+
</Tooltip>
|
|
1162
|
+
) : (
|
|
1163
|
+
fact.summary
|
|
1164
|
+
)}
|
|
1165
|
+
</span>
|
|
1166
|
+
))}
|
|
1167
|
+
{noScaleDownCandidates && (
|
|
1168
|
+
<>
|
|
1169
|
+
{group.scaling.length > 0 && " · "}
|
|
1170
|
+
<Tooltip
|
|
1171
|
+
content={NO_CANDIDATES_EXPLANATION}
|
|
1172
|
+
wrapperClassName="!inline"
|
|
1173
|
+
>
|
|
1174
|
+
<span
|
|
1175
|
+
tabIndex={0}
|
|
1176
|
+
role="note"
|
|
1177
|
+
aria-label={`No node can be removed right now. ${NO_CANDIDATES_EXPLANATION}`}
|
|
1178
|
+
className="cursor-help rounded focus-visible:outline focus-visible:outline-2 focus-visible:outline-skyhook-500"
|
|
1179
|
+
>
|
|
1180
|
+
No node can be removed right now
|
|
1181
|
+
</span>
|
|
1182
|
+
</Tooltip>
|
|
1183
|
+
</>
|
|
1184
|
+
)}
|
|
1185
|
+
{group.scaling.length === 0 && !noScaleDownCandidates && (
|
|
1186
|
+
<span className="text-theme-text-tertiary">—</span>
|
|
1187
|
+
)}
|
|
1188
|
+
</div>
|
|
1136
1189
|
</td>
|
|
1137
1190
|
</tr>
|
|
1138
1191
|
{hasChildren && (
|
|
1139
1192
|
<tr>
|
|
1140
1193
|
<td colSpan={7} className="p-0">
|
|
1141
1194
|
<Collapse open={expanded}>
|
|
1142
|
-
<ChildSubTable group={group} />
|
|
1195
|
+
<ChildSubTable group={group} showScaleDown={showScaleDown} />
|
|
1143
1196
|
</Collapse>
|
|
1144
1197
|
</td>
|
|
1145
1198
|
</tr>
|
|
@@ -1148,10 +1201,30 @@ function GroupRow({
|
|
|
1148
1201
|
);
|
|
1149
1202
|
}
|
|
1150
1203
|
|
|
1204
|
+
const MIN_SIZE_EXPLANATION =
|
|
1205
|
+
"Every observed autoscaler group has its target at its published minimum. Lowering the pool's minimum is required for it to shrink below this size. Unattributed groups are separate; current registered nodes may still exceed the target.";
|
|
1206
|
+
|
|
1207
|
+
const SCALE_DOWN_EXPLANATION =
|
|
1208
|
+
"Scale-down candidates are observations, not guaranteed removals. PodDisruptionBudgets, local storage, kube-system pods, or safe-to-evict annotations can block removal. Radar can't tell which nodes the autoscaler picked, but a node's drain plan shows what would block removing it.";
|
|
1209
|
+
const NO_CANDIDATES_EXPLANATION =
|
|
1210
|
+
"The autoscaler found no node it can remove. Usually every node is above its utilization threshold, or pods on emptier nodes can't move (PodDisruptionBudgets, local storage, kube-system pods, safe-to-evict annotations). A node's drain plan shows what would block it.";
|
|
1211
|
+
const SCALE_DOWN_STATUS_LABELS = new Map([
|
|
1212
|
+
["NoCandidates", "No scale-down candidates"],
|
|
1213
|
+
["CandidatesPresent", "Scale-down candidates present"],
|
|
1214
|
+
["InProgress", "Scale-down in progress"],
|
|
1215
|
+
["NoActivity", "No scale-down activity"],
|
|
1216
|
+
]);
|
|
1217
|
+
|
|
1151
1218
|
const CHILD_TH = "px-3 py-1.5 text-left font-medium whitespace-nowrap";
|
|
1152
1219
|
const CHILD_TD = "px-3 py-1.5 align-top text-xs text-theme-text-primary";
|
|
1153
1220
|
|
|
1154
|
-
function ChildSubTable({
|
|
1221
|
+
function ChildSubTable({
|
|
1222
|
+
group,
|
|
1223
|
+
showScaleDown,
|
|
1224
|
+
}: {
|
|
1225
|
+
group: CapacityGroupSummary;
|
|
1226
|
+
showScaleDown: boolean;
|
|
1227
|
+
}) {
|
|
1155
1228
|
return (
|
|
1156
1229
|
<div className="border-t border-theme-border-subtle bg-theme-base/40 px-4 py-3">
|
|
1157
1230
|
<div className="mb-1.5 text-[11px] font-medium uppercase tracking-wide text-theme-text-tertiary">
|
|
@@ -1167,13 +1240,14 @@ function ChildSubTable({ group }: { group: CapacityGroupSummary }) {
|
|
|
1167
1240
|
<th className={CHILD_TH}>Ready / total</th>
|
|
1168
1241
|
<th className={CHILD_TH}>Health</th>
|
|
1169
1242
|
<th className={CHILD_TH}>Backoff</th>
|
|
1170
|
-
<th className={CHILD_TH}>
|
|
1243
|
+
{showScaleDown && <th className={CHILD_TH}>Scale-down</th>}
|
|
1244
|
+
<th className={CHILD_TH}>Health observed</th>
|
|
1171
1245
|
</tr>
|
|
1172
1246
|
</thead>
|
|
1173
1247
|
<tbody className={TBODY}>
|
|
1174
1248
|
{group.children.map((child) => (
|
|
1175
1249
|
<tr key={child.id} className={ROW_HOVER}>
|
|
1176
|
-
<td className={`${CHILD_TD} font-mono`}>
|
|
1250
|
+
<td className={`${CHILD_TD} whitespace-nowrap font-mono`}>
|
|
1177
1251
|
<WithTooltip tip={child.name}>
|
|
1178
1252
|
<span>{child.id}</span>
|
|
1179
1253
|
</WithTooltip>
|
|
@@ -1197,6 +1271,11 @@ function ChildSubTable({ group }: { group: CapacityGroupSummary }) {
|
|
|
1197
1271
|
<td className={CHILD_TD}>
|
|
1198
1272
|
<ChildBackoff backoff={child.backoff} />
|
|
1199
1273
|
</td>
|
|
1274
|
+
{showScaleDown && (
|
|
1275
|
+
<td className={CHILD_TD}>
|
|
1276
|
+
<ChildScaleDown scaleDown={child.scaleDown} />
|
|
1277
|
+
</td>
|
|
1278
|
+
)}
|
|
1200
1279
|
<td className={CHILD_TD}>
|
|
1201
1280
|
<ChildObserved asOf={child.asOf} />
|
|
1202
1281
|
</td>
|
|
@@ -1219,9 +1298,11 @@ function ChildSubTable({ group }: { group: CapacityGroupSummary }) {
|
|
|
1219
1298
|
// ============================================================================
|
|
1220
1299
|
|
|
1221
1300
|
function OrphanAutoscalerSection({
|
|
1301
|
+
showScaleDown,
|
|
1222
1302
|
orphans,
|
|
1223
1303
|
meta,
|
|
1224
1304
|
}: {
|
|
1305
|
+
showScaleDown: boolean;
|
|
1225
1306
|
orphans: CapacityAutoscalerChildObservation[];
|
|
1226
1307
|
meta: CapacityBoundedResultMeta;
|
|
1227
1308
|
}) {
|
|
@@ -1240,13 +1321,14 @@ function OrphanAutoscalerSection({
|
|
|
1240
1321
|
<th className={TH}>Min–max</th>
|
|
1241
1322
|
<th className={TH}>Target</th>
|
|
1242
1323
|
<th className={TH}>Health</th>
|
|
1243
|
-
<th className={TH}>
|
|
1324
|
+
{showScaleDown && <th className={TH}>Scale-down</th>}
|
|
1325
|
+
<th className={TH}>Health observed</th>
|
|
1244
1326
|
</tr>
|
|
1245
1327
|
</thead>
|
|
1246
1328
|
<tbody className={TBODY}>
|
|
1247
1329
|
{orphans.map((child) => (
|
|
1248
1330
|
<tr key={child.id} className={ROW_HOVER}>
|
|
1249
|
-
<td className={`${TD} font-mono text-xs`}>
|
|
1331
|
+
<td className={`${TD} whitespace-nowrap font-mono text-xs`}>
|
|
1250
1332
|
<WithTooltip tip={child.name}>
|
|
1251
1333
|
<span>{child.id}</span>
|
|
1252
1334
|
</WithTooltip>
|
|
@@ -1262,6 +1344,11 @@ function OrphanAutoscalerSection({
|
|
|
1262
1344
|
<td className={TD}>
|
|
1263
1345
|
<ChildHealth health={child.health} />
|
|
1264
1346
|
</td>
|
|
1347
|
+
{showScaleDown && (
|
|
1348
|
+
<td className={TD}>
|
|
1349
|
+
<ChildScaleDown scaleDown={child.scaleDown} />
|
|
1350
|
+
</td>
|
|
1351
|
+
)}
|
|
1265
1352
|
<td className={TD}>
|
|
1266
1353
|
<ChildObserved asOf={child.asOf} />
|
|
1267
1354
|
</td>
|
|
@@ -1337,6 +1424,80 @@ function ChildBackoff({ backoff }: { backoff?: CapacityAutoscalerBackoff }) {
|
|
|
1337
1424
|
);
|
|
1338
1425
|
}
|
|
1339
1426
|
|
|
1427
|
+
function ChildScaleDown({
|
|
1428
|
+
scaleDown,
|
|
1429
|
+
}: {
|
|
1430
|
+
scaleDown?: CapacityAutoscalerScaleDown;
|
|
1431
|
+
}) {
|
|
1432
|
+
if (!scaleDown) {
|
|
1433
|
+
return <span className="text-theme-text-tertiary">Not published</span>;
|
|
1434
|
+
}
|
|
1435
|
+
const candidatesLabel =
|
|
1436
|
+
scaleDown.candidates === undefined
|
|
1437
|
+
? "Candidates: not published"
|
|
1438
|
+
: `${scaleDown.candidates} scale-down ${scaleDown.candidates === 1 ? "candidate" : "candidates"}`;
|
|
1439
|
+
const statusLabel = scaleDown.status
|
|
1440
|
+
? (SCALE_DOWN_STATUS_LABELS.get(scaleDown.status) ?? scaleDown.status)
|
|
1441
|
+
: "Status not published";
|
|
1442
|
+
const countIsStatus =
|
|
1443
|
+
scaleDown.status === "CandidatesPresent" &&
|
|
1444
|
+
scaleDown.candidates !== undefined;
|
|
1445
|
+
const noCandidates =
|
|
1446
|
+
scaleDown.status === "NoCandidates" && scaleDown.candidates === 0;
|
|
1447
|
+
const explanation =
|
|
1448
|
+
scaleDown.status === "NoCandidates"
|
|
1449
|
+
? NO_CANDIDATES_EXPLANATION
|
|
1450
|
+
: SCALE_DOWN_EXPLANATION;
|
|
1451
|
+
const transition = scaleDown.lastTransitionTime
|
|
1452
|
+
? Date.parse(scaleDown.lastTransitionTime)
|
|
1453
|
+
: NaN;
|
|
1454
|
+
return (
|
|
1455
|
+
<div className="space-y-1 text-theme-text-secondary">
|
|
1456
|
+
<div className="flex items-center gap-1">
|
|
1457
|
+
<WithTooltip tip={`${statusLabel}. ${explanation}`}>
|
|
1458
|
+
<span
|
|
1459
|
+
tabIndex={0}
|
|
1460
|
+
role="note"
|
|
1461
|
+
aria-label={`${countIsStatus ? candidatesLabel : statusLabel}. ${explanation}`}
|
|
1462
|
+
className="cursor-help rounded focus-visible:outline focus-visible:outline-2 focus-visible:outline-skyhook-500"
|
|
1463
|
+
>
|
|
1464
|
+
{countIsStatus ? candidatesLabel : statusLabel}
|
|
1465
|
+
</span>
|
|
1466
|
+
</WithTooltip>
|
|
1467
|
+
{(countIsStatus || noCandidates) && (
|
|
1468
|
+
<CertaintyGlyph
|
|
1469
|
+
certainty="exact"
|
|
1470
|
+
title={`Candidate count published by the autoscaler: ${scaleDown.candidates}.`}
|
|
1471
|
+
/>
|
|
1472
|
+
)}
|
|
1473
|
+
</div>
|
|
1474
|
+
{!countIsStatus && !noCandidates && (
|
|
1475
|
+
<div className="flex items-center gap-1 text-theme-text-tertiary">
|
|
1476
|
+
{candidatesLabel}
|
|
1477
|
+
<CertaintyGlyph
|
|
1478
|
+
certainty={scaleDown.candidates === undefined ? "unknown" : "exact"}
|
|
1479
|
+
title={
|
|
1480
|
+
scaleDown.candidates === undefined
|
|
1481
|
+
? "Candidate count not published by the autoscaler."
|
|
1482
|
+
: "Candidate count published by the autoscaler."
|
|
1483
|
+
}
|
|
1484
|
+
/>
|
|
1485
|
+
</div>
|
|
1486
|
+
)}
|
|
1487
|
+
<div className="text-theme-text-tertiary">
|
|
1488
|
+
Probe: <ChildObserved asOf={scaleDown.asOf} />
|
|
1489
|
+
</div>
|
|
1490
|
+
{scaleDown.lastTransitionTime && (
|
|
1491
|
+
<div className="text-theme-text-tertiary">
|
|
1492
|
+
Status since {formatTimestamp(scaleDown.lastTransitionTime)}
|
|
1493
|
+
{Number.isFinite(transition) &&
|
|
1494
|
+
` (for ${formatDuration(Math.max(0, Date.now() - transition))})`}
|
|
1495
|
+
</div>
|
|
1496
|
+
)}
|
|
1497
|
+
</div>
|
|
1498
|
+
);
|
|
1499
|
+
}
|
|
1500
|
+
|
|
1340
1501
|
/** Relative freshness; an absent `asOf` is "not probed" — never a zero time
|
|
1341
1502
|
* and never "now" (the payload published null, meaning we never checked). */
|
|
1342
1503
|
function ChildObserved({ asOf }: { asOf?: string }) {
|
|
@@ -19,59 +19,10 @@ import {
|
|
|
19
19
|
} from "../../api/client";
|
|
20
20
|
import type { SelectedResource } from "../../types";
|
|
21
21
|
import { refToSelectedResource } from "../../utils/navigation";
|
|
22
|
-
import {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
CapacityIssueEvidence,
|
|
27
|
-
CertaintyGlyph,
|
|
28
|
-
ClaimStageBadge,
|
|
29
|
-
conditionSummary,
|
|
30
|
-
ConditionBadge,
|
|
31
|
-
coverageHasObservations,
|
|
32
|
-
coverageIsDenied,
|
|
33
|
-
coverageIsLowerBound,
|
|
34
|
-
coverageMessage,
|
|
35
|
-
DeniedBadge,
|
|
36
|
-
EmptyState,
|
|
37
|
-
errorMessage,
|
|
38
|
-
formatQuantity,
|
|
39
|
-
formatTaint,
|
|
40
|
-
humanizeCode,
|
|
41
|
-
identityKey,
|
|
42
|
-
identityToSelectedResource,
|
|
43
|
-
InlineEmpty,
|
|
44
|
-
integrationBlock,
|
|
45
|
-
KeyValueRows,
|
|
46
|
-
LinkButton,
|
|
47
|
-
memberCoverageSource,
|
|
48
|
-
MiniCount,
|
|
49
|
-
NodeReadyBadge,
|
|
50
|
-
Notice,
|
|
51
|
-
observationTitle,
|
|
52
|
-
PoolReadyBadge,
|
|
53
|
-
POOL_SECTIONS,
|
|
54
|
-
PressureDetail,
|
|
55
|
-
quantityResourceRank,
|
|
56
|
-
QuantityInline,
|
|
57
|
-
RefreshError,
|
|
58
|
-
resourceLabel,
|
|
59
|
-
ResourceLink,
|
|
60
|
-
ROW_HOVER,
|
|
61
|
-
ScopeBadges,
|
|
62
|
-
ScrollableContent,
|
|
63
|
-
SectionCard,
|
|
64
|
-
TABLE_HEAD,
|
|
65
|
-
TABLE_WRAP,
|
|
66
|
-
TBODY,
|
|
67
|
-
TD,
|
|
68
|
-
TH,
|
|
69
|
-
TokenGroup,
|
|
70
|
-
useCapacityCursorRecovery,
|
|
71
|
-
useCapacityPagination,
|
|
72
|
-
type CapacityConnectionState,
|
|
73
|
-
type PoolSection,
|
|
74
|
-
} from "./shared";
|
|
22
|
+
import { ActualUsageDetail, ActualUsageInline, CapacityFreshness, CapacityIssueEvidence, ClaimStageBadge, conditionSummary, ConditionBadge, coverageHasObservations, coverageIsDenied, coverageIsLowerBound, coverageMessage, DeniedBadge, errorMessage, formatQuantity, formatTaint, humanizeCode, identityKey, identityToSelectedResource, InlineEmpty, integrationBlock, KeyValueRows, LinkButton, memberCoverageSource, MiniCount, NodeReadyBadge, observationTitle, PoolReadyBadge, POOL_SECTIONS, PressureDetail, quantityResourceRank, QuantityInline, RefreshError, resourceLabel, ResourceLink, ScopeBadges, ScrollableContent, SectionCard, TokenGroup, useCapacityCursorRecovery, useCapacityPagination, type CapacityConnectionState, type PoolSection } from "./shared";
|
|
23
|
+
import { CertaintyGlyph } from "@skyhook-io/k8s-ui";
|
|
24
|
+
import { Notice, ScreenEmptyState } from "../workspace/layout";
|
|
25
|
+
import { ROW_HOVER, TABLE_HEAD, TABLE_WRAP, TBODY, TD, TH } from "../workspace/table";
|
|
75
26
|
|
|
76
27
|
export function CapacityPoolDetail({
|
|
77
28
|
name,
|
|
@@ -123,7 +74,7 @@ export function CapacityPoolDetail({
|
|
|
123
74
|
const response = query.data;
|
|
124
75
|
if (response && !coverageHasObservations(response.coverage.nodePools)) {
|
|
125
76
|
return (
|
|
126
|
-
<
|
|
77
|
+
<ScreenEmptyState
|
|
127
78
|
icon={Layers3}
|
|
128
79
|
title="NodePool inventory unavailable"
|
|
129
80
|
detail={coverageMessage(
|
|
@@ -136,7 +87,7 @@ export function CapacityPoolDetail({
|
|
|
136
87
|
const pool = response?.pool;
|
|
137
88
|
if (!response || !pool) {
|
|
138
89
|
return (
|
|
139
|
-
<
|
|
90
|
+
<ScreenEmptyState
|
|
140
91
|
icon={CircleHelp}
|
|
141
92
|
title="NodePool unavailable"
|
|
142
93
|
detail="The Capacity API did not return an observation for this NodePool."
|