@oneuptime/common 14.0.8 → 14.0.9
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/Models/DatabaseModels/Index.ts +2 -0
- package/Models/DatabaseModels/KubernetesAiAgent.ts +364 -0
- package/Models/DatabaseModels/KubernetesCluster.ts +3 -3
- package/Models/DatabaseModels/Project.ts +55 -5
- package/Models/DatabaseModels/ProxmoxResource.ts +49 -1
- package/Models/DatabaseModels/RunnerJob.ts +75 -0
- package/Models/DatabaseModels/TeamComplianceSetting.ts +143 -2
- package/Models/DatabaseModels/WorkspaceProjectAuthToken.ts +17 -0
- package/Server/API/AIChatAPI.ts +6 -3
- package/Server/API/AIInvestigationAPI.ts +17 -10
- package/Server/API/AutoRemediationAPI.ts +207 -25
- package/Server/API/KubernetesClusterAiAccessAPI.ts +623 -21
- package/Server/API/MicrosoftTeamsAPI.ts +93 -14
- package/Server/API/ProxmoxResourceAPI.ts +244 -14
- package/Server/Infrastructure/GlobalCache.ts +32 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1796000000000-AddTeamComplianceRuleScope.ts +99 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1796100000000-AddKubernetesAiAgentAndAiDefaults.ts +137 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1796200000000-AddProxmoxResourceNativePushColumns.ts +42 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
- package/Server/Middleware/TelemetryIngest.ts +41 -18
- package/Server/Services/AIService.ts +70 -1
- package/Server/Services/AlertService.ts +352 -11
- package/Server/Services/AlertSeverityService.ts +65 -15
- package/Server/Services/AutoRemediationRuleService.ts +1 -1
- package/Server/Services/IncidentService.ts +280 -104
- package/Server/Services/IncidentSeverityService.ts +66 -15
- package/Server/Services/KubernetesAiAgentJobService.ts +185 -0
- package/Server/Services/KubernetesAiAgentService.ts +1634 -0
- package/Server/Services/KubernetesClusterAiAccessService.ts +1118 -451
- package/Server/Services/KubernetesClusterService.ts +129 -21
- package/Server/Services/ProjectService.ts +32 -0
- package/Server/Services/ProxmoxResourceService.ts +322 -5
- package/Server/Services/RunnerJobService.ts +241 -104
- package/Server/Services/RunnerService.ts +1 -1
- package/Server/Services/ScheduledMaintenanceService.ts +737 -1
- package/Server/Services/ScheduledMaintenanceStateTimelineService.ts +414 -56
- package/Server/Services/TeamComplianceSettingService.ts +1125 -9
- package/Server/Utils/AI/ClusterAccess/ClusterAccessContext.ts +67 -9
- package/Server/Utils/AI/ClusterAccess/KubectlInvestigationToolkit.ts +39 -10
- package/Server/Utils/AI/ClusterAccess/KubectlJobRunner.ts +14 -3
- package/Server/Utils/AI/Remediation/RemediationCommandTools.ts +37 -15
- package/Server/Utils/AI/Remediation/RemediationExecutionRunner.ts +67 -24
- package/Server/Utils/AI/SRE/AIInvestigationEngine.ts +48 -5
- package/Server/Utils/AI/SRE/IncidentPostmortemRunner.ts +40 -8
- package/Server/Utils/AI/SRE/InvestigationEligibility.ts +13 -2
- package/Server/Utils/AI/SRE/InvestigationGrader.ts +1 -1
- package/Server/Utils/AutoRemediation/CommandPlanExecutor.ts +6 -1
- package/Server/Utils/Telemetry/InventoryEntityRegistry.ts +133 -7
- package/Server/Utils/Telemetry/ProxmoxCephSnapshotScan.ts +58 -4
- package/Server/Utils/Telemetry/ProxmoxNativeNodeLiveness.ts +447 -0
- package/Server/Utils/Telemetry/ProxmoxNativePush.ts +903 -0
- package/Server/Utils/Telemetry/TelemetryEntity.ts +87 -27
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +684 -47
- package/Tests/App/AdminDashboard/RowActionPlacementOverrides.test.tsx +278 -0
- package/Tests/App/Dashboard/AIChatChartWidgetZoom.test.tsx +738 -0
- package/Tests/App/Dashboard/AIFeaturesSettingsPointers.test.tsx +147 -0
- package/Tests/App/Dashboard/AIInsightsKubernetesClusterPage.test.tsx +1523 -0
- package/Tests/App/Dashboard/AdminUserNotificationMethodsPage.test.tsx +463 -3
- package/Tests/App/Dashboard/AffectedResourcesPickerDropdownPlacement.test.tsx +958 -0
- package/Tests/App/Dashboard/AffectedResourcesPickerFocusLeave.test.tsx +595 -0
- package/Tests/App/Dashboard/AskAiAvailability.test.ts +20 -3
- package/Tests/App/Dashboard/AskAiDisabled.test.tsx +8 -3
- package/Tests/App/Dashboard/CephRateChartReload.test.tsx +1456 -0
- package/Tests/App/Dashboard/CephTimeRangeZoom.test.tsx +1229 -0
- package/Tests/App/Dashboard/ChartCardTimeRangeZoom.test.tsx +151 -0
- package/Tests/App/Dashboard/ChartCardZoomAffordances.test.tsx +257 -0
- package/Tests/App/Dashboard/ChartRefetchFrame.test.tsx +141 -0
- package/Tests/App/Dashboard/ChartZoomHarness.tsx +249 -0
- package/Tests/App/Dashboard/ChartZoomStandIn.tsx +131 -0
- package/Tests/App/Dashboard/CloudServerlessSlowLoads.test.tsx +628 -0
- package/Tests/App/Dashboard/CloudServerlessTimeRangeZoom.test.tsx +607 -0
- package/Tests/App/Dashboard/ClusterAccessNotice.test.tsx +91 -19
- package/Tests/App/Dashboard/CompanionMetricsTabZoom.test.tsx +632 -0
- package/Tests/App/Dashboard/ContainerChartZoomStandIn.tsx +195 -0
- package/Tests/App/Dashboard/ContainerHostOverviewSlowLoads.test.tsx +542 -0
- package/Tests/App/Dashboard/ContainerHostOverviewTimeRangeZoom.test.tsx +848 -0
- package/Tests/App/Dashboard/ContainerMetricsTimeRangeZoom.test.tsx +561 -0
- package/Tests/App/Dashboard/DashboardBoardWideZoomShell.test.tsx +1147 -0
- package/Tests/App/Dashboard/DashboardEditPermissions.test.tsx +3 -2
- package/Tests/App/Dashboard/DashboardHistogramWidgetDragCursor.test.tsx +399 -0
- package/Tests/App/Dashboard/DashboardHistogramWidgetZoom.test.tsx +985 -0
- package/Tests/App/Dashboard/DashboardHistogramWidgetZoomHint.test.tsx +803 -0
- package/Tests/App/Dashboard/DashboardLazyPages.test.tsx +1 -0
- package/Tests/App/Dashboard/DashboardSettingsPreviewZoom.test.tsx +679 -0
- package/Tests/App/Dashboard/DashboardSloAndDataSourceChartZoom.test.tsx +881 -0
- package/Tests/App/Dashboard/DashboardTraceStatusWidgets.test.tsx +878 -0
- package/Tests/App/Dashboard/DatabaseMetricChartModalTimeRangeZoom.test.tsx +442 -0
- package/Tests/App/Dashboard/DatabaseOverviewTimeRangeZoom.test.tsx +831 -0
- package/Tests/App/Dashboard/DatabaseServerComponents.test.tsx +43 -0
- package/Tests/App/Dashboard/DockerSwarmInsightsTimeRangeZoom.test.tsx +524 -0
- package/Tests/App/Dashboard/DockerSwarmRateChartRefresh.test.tsx +259 -0
- package/Tests/App/Dashboard/EdgeDetailPanelHistory.test.tsx +763 -0
- package/Tests/App/Dashboard/EdgeDetailPanelTimeRangeZoom.test.tsx +547 -0
- package/Tests/App/Dashboard/EdgeHistoryBucketsCases.tsx +565 -0
- package/Tests/App/Dashboard/EdgeHistoryBucketsKathmandu.test.tsx +73 -0
- package/Tests/App/Dashboard/EdgeHistoryBucketsKolkata.test.tsx +74 -0
- package/Tests/App/Dashboard/EdgeHistoryBucketsNewYork.test.tsx +72 -0
- package/Tests/App/Dashboard/EdgeHistoryBucketsUtc.test.tsx +72 -0
- package/Tests/App/Dashboard/EmbeddedMetricCardRefresh.test.tsx +310 -0
- package/Tests/App/Dashboard/EmbeddedMetricCardTimeRangeZoom.test.tsx +536 -0
- package/Tests/App/Dashboard/EscalationRuleReadiness.test.tsx +3 -1
- package/Tests/App/Dashboard/EscalationRuleRowActions.test.tsx +660 -0
- package/Tests/App/Dashboard/EventNotes.test.tsx +2 -2
- package/Tests/App/Dashboard/EventOverviewPages.test.tsx +587 -13
- package/Tests/App/Dashboard/EventOverviewSnapshotExplorerZoom.test.tsx +1139 -0
- package/Tests/App/Dashboard/EventOverviewSnapshotZoomAcrossTabs.test.tsx +1057 -0
- package/Tests/App/Dashboard/EventOverviewTelemetrySnapshotZoom.test.tsx +757 -0
- package/Tests/App/Dashboard/ExceptionOccurrenceTrendZoom.test.tsx +675 -0
- package/Tests/App/Dashboard/ExceptionOccurrencesZoomSurvivesViewSwitch.test.tsx +405 -0
- package/Tests/App/Dashboard/ExceptionSignalPages.test.tsx +67 -3
- package/Tests/App/Dashboard/ExceptionTablesSpanStatus.test.tsx +515 -0
- package/Tests/App/Dashboard/ExplorerOwnZoomRegression.test.tsx +739 -0
- package/Tests/App/Dashboard/FlowBandwidthAxisCases.tsx +461 -0
- package/Tests/App/Dashboard/FlowBandwidthAxisKathmandu.test.tsx +25 -0
- package/Tests/App/Dashboard/FlowBandwidthAxisKolkata.test.tsx +25 -0
- package/Tests/App/Dashboard/FlowBandwidthAxisNewYork.test.tsx +25 -0
- package/Tests/App/Dashboard/FlowBandwidthAxisUtc.test.tsx +24 -0
- package/Tests/App/Dashboard/FlowTopTalkersZoomRefetch.test.tsx +722 -0
- package/Tests/App/Dashboard/FlowViewportGuard.test.tsx +2526 -0
- package/Tests/App/Dashboard/HostPagesSlowLoads.test.tsx +872 -0
- package/Tests/App/Dashboard/HostPagesTimeRangeZoom.test.tsx +1208 -0
- package/Tests/App/Dashboard/IncidentRootCauseTimeRangeZoom.test.tsx +358 -0
- package/Tests/App/Dashboard/InfrastructureGraph.test.tsx +100 -9
- package/Tests/App/Dashboard/InfrastructureMetricsTabTimeRangeZoom.test.tsx +485 -0
- package/Tests/App/Dashboard/InvestigationDrawerCompanionZoom.test.tsx +655 -0
- package/Tests/App/Dashboard/InvestigationDrawerZoom.test.tsx +830 -0
- package/Tests/App/Dashboard/InvestigationNotStarted.test.tsx +338 -2
- package/Tests/App/Dashboard/InvoicesPayInvoice.test.tsx +454 -16
- package/Tests/App/Dashboard/KubernetesClusterAiAccessSettings.test.ts +799 -819
- package/Tests/App/Dashboard/KubernetesClusterAiAgentOverviewCard.test.tsx +367 -0
- package/Tests/App/Dashboard/KubernetesClusterAiAgentStatus.test.ts +1202 -0
- package/Tests/App/Dashboard/KubernetesClusterAiDocumentationMarkdown.test.ts +106 -0
- package/Tests/App/Dashboard/KubernetesClusterAiNavigation.test.tsx +354 -0
- package/Tests/App/Dashboard/KubernetesClusterAiPage.test.tsx +1884 -2054
- package/Tests/App/Dashboard/KubernetesClusterAiPageServerParity.test.ts +478 -179
- package/Tests/App/Dashboard/KubernetesClusterMetricTooltips.test.ts +50 -0
- package/Tests/App/Dashboard/KubernetesClusterOverviewTooltips.test.tsx +2 -1
- package/Tests/App/Dashboard/KubernetesClusterOverviewZoom.test.tsx +1217 -0
- package/Tests/App/Dashboard/KubernetesClusterPagesZoom.test.tsx +731 -0
- package/Tests/App/Dashboard/KubernetesCostsLoadRecovery.test.tsx +869 -0
- package/Tests/App/Dashboard/KubernetesCostsZoom.test.tsx +1214 -0
- package/Tests/App/Dashboard/KubernetesCostsZoomExactHours.test.tsx +692 -0
- package/Tests/App/Dashboard/KubernetesNetworkThroughputReload.test.tsx +902 -0
- package/Tests/App/Dashboard/KubernetesNetworkZoomBucketEdges.test.tsx +571 -0
- package/Tests/App/Dashboard/KubernetesOverviewZoomBucketEdges.test.tsx +697 -0
- package/Tests/App/Dashboard/KubernetesResourceMetricsTabZoom.test.tsx +633 -0
- package/Tests/App/Dashboard/LogsExplorerTimeRangeZoom.test.tsx +470 -0
- package/Tests/App/Dashboard/LogsInsightsTimeRangeZoom.test.tsx +948 -0
- package/Tests/App/Dashboard/LogsViewerPinnedWindowZoom.test.tsx +486 -0
- package/Tests/App/Dashboard/MetricChartsBucketInspectorDoubleClick.test.tsx +1001 -0
- package/Tests/App/Dashboard/MetricExplorerInvestigationAutoRefresh.test.tsx +514 -0
- package/Tests/App/Dashboard/MetricExplorerSavedViewZoomRoundTrip.test.tsx +581 -0
- package/Tests/App/Dashboard/MetricExplorerTimeRangeZoom.test.tsx +1162 -0
- package/Tests/App/Dashboard/MetricMonitorPreviewZoomLabel.test.ts +72 -0
- package/Tests/App/Dashboard/MetricRowSparklineTimeRangeZoom.test.tsx +204 -0
- package/Tests/App/Dashboard/MetricViewFirstResultLands.test.tsx +408 -0
- package/Tests/App/Dashboard/MetricViewOwnZoomResetPlacement.test.tsx +952 -0
- package/Tests/App/Dashboard/MetricViewTimeRange.test.ts +139 -0
- package/Tests/App/Dashboard/MetricViewTimeRangeZoom.test.tsx +556 -0
- package/Tests/App/Dashboard/MonitorMetricsChartWrappersZoom.test.tsx +552 -0
- package/Tests/App/Dashboard/MonitorMetricsTabsTimeRangeZoom.test.tsx +740 -0
- package/Tests/App/Dashboard/MonitorOverviewChartsTimeRangeZoom.test.tsx +735 -0
- package/Tests/App/Dashboard/MonitorStepPreviewsTimeRangeZoom.test.tsx +835 -0
- package/Tests/App/Dashboard/NetworkDeviceTimeRangeZoom.test.tsx +1115 -0
- package/Tests/App/Dashboard/OnCallPreventionGuards.test.tsx +186 -17
- package/Tests/App/Dashboard/OnCallRulesDeleteGuard.test.tsx +155 -46
- package/Tests/App/Dashboard/PasskeySettings.test.tsx +87 -2
- package/Tests/App/Dashboard/ProjectAISettingsPages.test.tsx +884 -0
- package/Tests/App/Dashboard/ProxmoxNodeRemove.test.tsx +621 -0
- package/Tests/App/Dashboard/ProxmoxOverviewSlowLoads.test.tsx +584 -0
- package/Tests/App/Dashboard/ProxmoxPagesTimeRangeZoom.test.tsx +823 -0
- package/Tests/App/Dashboard/ProxmoxRateChartReload.test.tsx +1253 -0
- package/Tests/App/Dashboard/PublicDashboardBoardWideZoom.test.tsx +605 -0
- package/Tests/App/Dashboard/RealRowsLineChart.tsx +250 -0
- package/Tests/App/Dashboard/RechartsHostsPlotCursor.test.tsx +513 -0
- package/Tests/App/Dashboard/RowActionPlacementOverrides.test.tsx +865 -0
- package/Tests/App/Dashboard/RumOverviewTimeRangeZoom.test.tsx +877 -0
- package/Tests/App/Dashboard/RunnerKubernetesAgentForm.test.tsx +20 -4
- package/Tests/App/Dashboard/RunnerSupersededByAiAgentNote.test.tsx +296 -0
- package/Tests/App/Dashboard/SecurityEventConnectionsTable.test.tsx +146 -36
- package/Tests/App/Dashboard/ServiceDatabaseSlowLoads.test.tsx +1166 -0
- package/Tests/App/Dashboard/ServiceMapGraph.test.tsx +1243 -104
- package/Tests/App/Dashboard/ServiceOverviewTimeRangeZoom.test.tsx +792 -0
- package/Tests/App/Dashboard/SloBudgetBurnDownZoom.test.tsx +771 -0
- package/Tests/App/Dashboard/SloBudgetBurnDownZoomAffordances.test.tsx +380 -0
- package/Tests/App/Dashboard/SloEventMetricsBarChartZoom.test.tsx +369 -0
- package/Tests/App/Dashboard/SloHistoryChartsTimeRangeZoom.test.tsx +694 -0
- package/Tests/App/Dashboard/SloHistoryChartsZoomAffordances.test.tsx +497 -0
- package/Tests/App/Dashboard/SloMetricsTimeRangeZoom.test.tsx +541 -0
- package/Tests/App/Dashboard/SlowLoadHarness.ts +123 -0
- package/Tests/App/Dashboard/SnapshotExplorerPrimaryZoom.test.tsx +1194 -0
- package/Tests/App/Dashboard/SnapshotViewerPinnedWindow.test.tsx +620 -0
- package/Tests/App/Dashboard/TelemetrySnapshotPanelTimeRangeZoom.test.tsx +765 -0
- package/Tests/App/Dashboard/TelemetrySnapshotZoom.test.tsx +516 -0
- package/Tests/App/Dashboard/TelemetrySnapshotZoomAcrossTabs.test.tsx +827 -0
- package/Tests/App/Dashboard/TimeRangeZoomPageHarness.tsx +463 -0
- package/Tests/App/Dashboard/TraceChartEditorStatusSplit.test.tsx +543 -0
- package/Tests/App/Dashboard/TraceStatusPresentation.test.tsx +967 -0
- package/Tests/App/Dashboard/TraceTimelineMinimapZoom.test.tsx +315 -0
- package/Tests/App/Dashboard/TracesAnalyticsStatusSplit.test.tsx +778 -0
- package/Tests/App/Dashboard/TracesAnalyticsViewZoom.test.tsx +349 -0
- package/Tests/App/Dashboard/TracesExplorerTimeRangeZoom.test.tsx +551 -0
- package/Tests/App/Dashboard/TracesStatusChartAndFacet.test.tsx +687 -0
- package/Tests/App/Dashboard/TracesViewerStaleResponses.test.tsx +458 -0
- package/Tests/App/Dashboard/UptimeStripsExcludedFromZoom.test.tsx +406 -0
- package/Tests/App/Dashboard/VMwareOverviewSlowLoads.test.tsx +535 -0
- package/Tests/App/Dashboard/VMwarePagesTimeRangeZoom.test.tsx +606 -0
- package/Tests/App/Dashboard/ValueWidgetSparklineStaleHover.test.tsx +1292 -0
- package/Tests/App/Dashboard/ValueWidgetSparklineZoom.test.tsx +765 -0
- package/Tests/App/StatusPage/StatusPageResourceExplorer.test.tsx +98 -0
- package/Tests/Models/DatabaseModels/KubernetesAiAgentModel.test.ts +295 -0
- package/Tests/Models/DatabaseModels/TeamComplianceSettingModel.test.ts +347 -0
- package/Tests/Server/API/AIChatRouteAuthorization.test.ts +58 -0
- package/Tests/Server/API/AIGenerationProjectAIToggle.test.ts +1 -1
- package/Tests/Server/API/AIInvestigationAPI.test.ts +123 -45
- package/Tests/Server/API/AutoRemediationApproveClusterRound.test.ts +1329 -0
- package/Tests/Server/API/AutoRemediationApproveKubectlRecheck.test.ts +25 -2
- package/Tests/Server/API/KubernetesClusterAiAccessAPI.test.ts +2 -0
- package/Tests/Server/API/KubernetesClusterAiAccessAPIAgent.test.ts +903 -0
- package/Tests/Server/API/MicrosoftTeamsChatsRefreshRoute.test.ts +667 -0
- package/Tests/Server/API/MicrosoftTeamsManifest.test.ts +294 -6
- package/Tests/Server/API/ProxmoxResourceAPIRemoveNode.test.ts +1932 -0
- package/Tests/Server/Infrastructure/GlobalCache.test.ts +195 -0
- package/Tests/Server/Infrastructure/Postgres/AddKubernetesAiAgentAndAiDefaultsMigration.test.ts +623 -0
- package/Tests/Server/Infrastructure/Postgres/AddKubernetesClusterAiAccessMigration.test.ts +87 -10
- package/Tests/Server/Infrastructure/Postgres/AddTeamComplianceRuleScopeMigration.test.ts +622 -0
- package/Tests/Server/Middleware/TelemetryIngestBrowserKey.test.ts +61 -4
- package/Tests/Server/Middleware/TelemetryIngestKubernetesAgentRunnerPinnedKey.test.ts +98 -2
- package/Tests/Server/Middleware/TelemetryIngestKubernetesAgentRunnerRateLimit.test.ts +105 -2
- package/Tests/Server/Services/AIServiceBalanceBlocker.test.ts +282 -0
- package/Tests/Server/Services/AlertMonitorClearWritesNull.test.ts +409 -0
- package/Tests/Server/Services/AlertMonitorEditFeed.test.ts +474 -0
- package/Tests/Server/Services/AlertMonitorEditGuard.test.ts +610 -0
- package/Tests/Server/Services/AutoRemediationClusterRuleEngine.test.ts +2 -0
- package/Tests/Server/Services/AutoRemediationRuleCommandRunners.test.ts +2 -1
- package/Tests/Server/Services/IncidentAffectedMonitorsEdit.test.ts +1360 -0
- package/Tests/Server/Services/IncidentAlertSloLinkSurvivesEdit.test.ts +3 -1
- package/Tests/Server/Services/IncidentSeverityDeletePausesComplianceRules.test.ts +488 -0
- package/Tests/Server/Services/KubernetesAiAgentJobService.test.ts +329 -0
- package/Tests/Server/Services/KubernetesAiAgentServiceHelpers.test.ts +618 -0
- package/Tests/Server/Services/KubernetesAiAgentServiceLifecycle.test.ts +1444 -0
- package/Tests/Server/Services/KubernetesAiAgentServiceRegister.test.ts +1666 -0
- package/Tests/Server/Services/KubernetesClusterAiAccessDeletedRunnerRemedy.test.ts +140 -111
- package/Tests/Server/Services/KubernetesClusterAiAccessGapNextSteps.test.ts +267 -105
- package/Tests/Server/Services/KubernetesClusterAiAccessLegacySuperseded.test.ts +440 -0
- package/Tests/Server/Services/KubernetesClusterAiAccessService.test.ts +567 -411
- package/Tests/Server/Services/KubernetesClusterAiAccessTarget.test.ts +1168 -0
- package/Tests/Server/Services/KubernetesClusterAiSettingsPermission.test.ts +410 -12
- package/Tests/Server/Services/KubernetesClusterServiceAiAccessFeed.test.ts +55 -0
- package/Tests/Server/Services/ProjectServiceNewProjectAiDefaults.test.ts +288 -0
- package/Tests/Server/Services/ProxmoxResourcePostgres.test.ts +5633 -0
- package/Tests/Server/Services/ProxmoxResourceService.test.ts +6458 -5
- package/Tests/Server/Services/RunnerJobEnqueueKubectl.test.ts +48 -15
- package/Tests/Server/Services/RunnerJobEnqueueKubectlAiAgent.test.ts +620 -0
- package/Tests/Server/Services/RunnerJobKubectlWriteScope.test.ts +170 -3
- package/Tests/Server/Services/RunnerJobTimeoutReason.test.ts +72 -0
- package/Tests/Server/Services/RunnerServiceAgentName.test.ts +6 -4
- package/Tests/Server/Services/ScheduledMaintenanceAttachmentEdit.test.ts +2113 -0
- package/Tests/Server/Services/ScheduledMaintenanceMonitorRelease.test.ts +972 -0
- package/Tests/Server/Services/TeamComplianceSettingPostgres.test.ts +2237 -0
- package/Tests/Server/Services/TeamComplianceSettingService.test.ts +3988 -138
- package/Tests/Server/Utils/AI/ClusterAccessContext.test.ts +107 -1
- package/Tests/Server/Utils/AI/IncidentPostmortemRunner.test.ts +351 -0
- package/Tests/Server/Utils/AI/InvestigationClusterAccessWiring.test.ts +2 -0
- package/Tests/Server/Utils/AI/InvestigationEligibility.test.ts +310 -0
- package/Tests/Server/Utils/AI/KubectlInvestigationToolkit.test.ts +70 -0
- package/Tests/Server/Utils/AI/KubectlJobRunnerFinishedJob.test.ts +58 -0
- package/Tests/Server/Utils/AI/RemediationCommandToolsKubectl.test.ts +2 -0
- package/Tests/Server/Utils/AI/RemediationCommandToolsKubectlOutcome.test.ts +2 -0
- package/Tests/Server/Utils/AI/RemediationCommandToolsLiveCluster.test.ts +2 -0
- package/Tests/Server/Utils/AI/RemediationCommandToolsRunnerScope.test.ts +125 -1
- package/Tests/Server/Utils/AI/RemediationExecutionRunner.test.ts +252 -3
- package/Tests/Server/Utils/AI/RemediationExecutionRunnerClusterMode.test.ts +2 -0
- package/Tests/Server/Utils/AI/RemediationExecutionRunnerProjectGates.test.ts +240 -0
- package/Tests/Server/Utils/AI/RemediationKubectlCopyParity.test.ts +2 -0
- package/Tests/Server/Utils/AutoRemediation/CommandPlanExecutor.test.ts +2 -0
- package/Tests/Server/Utils/AutoRemediation/CommandPlanExecutorUnknownRun.test.ts +2 -0
- package/Tests/Server/Utils/AutoRemediation/CommandPlanVerification.test.ts +2 -0
- package/Tests/Server/Utils/Telemetry/HostAssetAttributesFromOtlp.test.ts +68 -0
- package/Tests/Server/Utils/Telemetry/InventoryMirrorPostgres.test.ts +370 -0
- package/Tests/Server/Utils/Telemetry/NetworkDeviceInventoryAttributes.test.ts +522 -0
- package/Tests/Server/Utils/Telemetry/ProxmoxCephSnapshotScan.test.ts +155 -0
- package/Tests/Server/Utils/Telemetry/ProxmoxNativeNodeLiveness.test.ts +8631 -0
- package/Tests/Server/Utils/Telemetry/ProxmoxNativePush.test.ts +2852 -0
- package/Tests/Server/Utils/Telemetry/TelemetryEntity.test.ts +367 -1
- package/Tests/Server/Utils/Telemetry/TelemetryIngestionKeyGuard.test.ts +45 -3
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsChats.test.ts +25 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsGroupChatNames.test.ts +3119 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsGroupChatNamesPostgres.test.ts +1721 -0
- package/Tests/Types/Kubernetes/KubernetesAgentChartAiAccess.test.ts +581 -113
- package/Tests/Types/Kubernetes/KubernetesAiAgentAccessContract.test.ts +510 -0
- package/Tests/Types/Team/ComplianceRule.test.ts +1029 -0
- package/Tests/Types/Team/TeamComplianceStatus.test.ts +176 -0
- package/Tests/UI/Components/ActionButton/RowActions.test.tsx +641 -0
- package/Tests/UI/Components/ActionButton/RowActionsAccessibility.test.tsx +414 -0
- package/Tests/UI/Components/ActionButton/SplitActionButtons.test.ts +565 -0
- package/Tests/UI/Components/Charts/BarChartDragToSelect.test.tsx +386 -0
- package/Tests/UI/Components/Charts/ChartDoubleClickResetWithoutDblclick.test.tsx +1025 -0
- package/Tests/UI/Components/Charts/ChartGroupPageZoomHint.test.tsx +196 -0
- package/Tests/UI/Components/Charts/ChartPlaceholdersTakeDoubleClick.test.tsx +1861 -0
- package/Tests/UI/Components/Charts/ChartPlotClicksWhileResetArmed.test.tsx +382 -0
- package/Tests/UI/Components/Charts/ChartRangeSelection.test.tsx +704 -0
- package/Tests/UI/Components/Charts/ChartRangeSelectionDoubleClickReset.test.tsx +1481 -0
- package/Tests/UI/Components/Charts/ChartRangeSelectionRealRecharts.test.tsx +918 -0
- package/Tests/UI/Components/Charts/ChartRowBucketStart.test.ts +350 -0
- package/Tests/UI/Components/Charts/DoubleClickReset.test.tsx +996 -0
- package/Tests/UI/Components/Charts/HistogramDoubleClickResetRealRecharts.test.tsx +965 -0
- package/Tests/UI/Components/Charts/HistogramDriftThenRefetch.test.tsx +277 -0
- package/Tests/UI/Components/Charts/HistogramRangeSelectionDataChange.test.tsx +1757 -0
- package/Tests/UI/Components/Charts/HistogramRangeSelectionRealRecharts.test.tsx +560 -0
- package/Tests/UI/Components/Charts/TimeRangeZoom/ChartPageTimeRangeZoom.test.tsx +513 -0
- package/Tests/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomContext.test.tsx +845 -0
- package/Tests/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomHint.test.tsx +119 -0
- package/Tests/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomHintTailwind.test.tsx +274 -0
- package/Tests/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomUtil.test.ts +433 -0
- package/Tests/UI/Components/Charts/TimeRangeZoom/UseTimeRangeZoom.test.tsx +863 -0
- package/Tests/UI/Components/Charts/TimeRangeZoom/ZoomDocsPromises.test.tsx +1147 -0
- package/Tests/UI/Components/DisabledButtonTooltip.test.tsx +14 -3
- package/Tests/UI/Components/EntityDropdownEscape.test.tsx +454 -0
- package/Tests/UI/Components/EntityDropdownFocusLeave.test.tsx +420 -0
- package/Tests/UI/Components/Forms/FormFieldDropdownDisabled.test.tsx +233 -0
- package/Tests/UI/Components/Input.test.tsx +80 -1
- package/Tests/UI/Components/LogsAnalyticsViewZoom.test.tsx +947 -0
- package/Tests/UI/Components/LogsHistogramDragTooltip.test.tsx +17 -5
- package/Tests/UI/Components/LogsViewerAnalyticsZoom.test.tsx +501 -0
- package/Tests/UI/Components/LogsViewerHistogramZoom.test.tsx +1 -1
- package/Tests/UI/Components/ModelTable/BaseModelTableBulkDelete.test.tsx +6 -4
- package/Tests/UI/Components/ModelTable/BaseModelTablePermissionGating.test.tsx +60 -8
- package/Tests/UI/Components/ModelTable/BaseModelTableRowActions.test.tsx +476 -0
- package/Tests/UI/Components/ModelTable/ModelTableWrapContent.test.tsx +7 -5
- package/Tests/UI/Components/MoreMenuPortal.test.tsx +623 -0
- package/Tests/UI/Components/StatusPage/ResourceGridActions.test.tsx +538 -0
- package/Tests/UI/Components/StatusPage/ResourceGridSelection.test.tsx +14 -4
- package/Tests/UI/Components/TableCellWrapping.test.tsx +3 -3
- package/Tests/UI/Components/TableRowActions.test.tsx +472 -0
- package/Tests/UI/Components/TelemetryHistogramDragTooltip.test.tsx +1 -1
- package/Tests/UI/Components/TelemetryViewer/TelemetryViewerHistogramClickZoom.test.tsx +1 -1
- package/Tests/UI/Components/TelemetryViewer/TelemetryViewerZoomScope.test.tsx +470 -0
- package/Tests/UI/Components/TelemetryViewer/UseViewerTimeRangeZoom.test.tsx +571 -0
- package/Tests/UI/Components/TelemetryViewer/ViewerDoubleClickResetUnderDataChange.test.tsx +928 -0
- package/Tests/UI/Components/TelemetryViewer/ViewerFollowsEnclosingZoom.test.tsx +1569 -0
- package/Tests/UI/Components/Toggle.test.tsx +66 -0
- package/Tests/UI/MicrosoftTeams/MicrosoftTeamsChatsCardRefreshNames.test.tsx +1023 -0
- package/Tests/UI/Rum/ChunkLoader.test.ts +201 -0
- package/Tests/UI/Rum/FidelityNotices.test.ts +54 -0
- package/Tests/UI/Rum/ReplayCorrelationPanel.test.tsx +72 -0
- package/Tests/UI/Rum/ReplayFrameCapture.test.ts +1009 -9
- package/Tests/UI/Rum/ReplayRecordedAssets.test.ts +1069 -0
- package/Tests/UI/Rum/ReplayStage.test.tsx +913 -2
- package/Tests/UI/Rum/SessionReplayTable.test.tsx +443 -8
- package/Tests/UI/Rum/SessionReplayUsersTable.test.tsx +439 -9
- package/Tests/UI/Rum/UserFlowTablesRowActions.test.tsx +501 -0
- package/Tests/Utils/AiRemediation/KubectlPolicyChartRbacParity.test.ts +47 -19
- package/Tests/Utils/AiRemediation/KubectlWriteScopeCallerParity.test.ts +2 -0
- package/Tests/Utils/AiRemediation/KubernetesAiAgentPolicyCopyParity.test.ts +396 -0
- package/Tests/Utils/Dashboard/DashboardTimeRangeZoom.test.ts +104 -1
- package/Types/AI/AIRunType.ts +9 -4
- package/Types/AI/InvestigationNotStartedReason.ts +6 -0
- package/Types/AutoRemediation/AiRemediationCommandPlan.ts +14 -16
- package/Types/AutoRemediation/AiRemediationCommandPolicyVerdict.ts +28 -0
- package/Types/Dashboard/DashboardComponents/DashboardTraceChartComponent.ts +4 -2
- package/Types/Kubernetes/KubernetesClusterAiAccess.ts +263 -32
- package/Types/Kubernetes/KubernetesClusterAiAccessPermissions.ts +20 -16
- package/Types/Kubernetes/KubernetesClusterAiInsights.ts +81 -0
- package/Types/Monitor/ProxmoxAlertTemplates.ts +4 -4
- package/Types/Team/ComplianceNotificationChannel.ts +22 -0
- package/Types/Team/ComplianceRule.ts +434 -0
- package/Types/Team/ComplianceRuleType.ts +21 -0
- package/Types/Team/TeamComplianceStatus.ts +81 -0
- package/Types/Telemetry/TelemetryIngestSurface.ts +28 -0
- package/UI/Components/ActionButton/ActionButtonSchema.ts +21 -0
- package/UI/Components/ActionButton/RowActions.tsx +238 -0
- package/UI/Components/ActionButton/SplitActionButtons.ts +173 -0
- package/UI/Components/Charts/Area/AreaChart.tsx +32 -2
- package/UI/Components/Charts/Bar/BarChart.tsx +40 -3
- package/UI/Components/Charts/ChartGroup/ChartGroup.tsx +37 -11
- package/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.tsx +80 -243
- package/UI/Components/Charts/ChartLibrary/BarChart/BarChart.tsx +122 -31
- package/UI/Components/Charts/ChartLibrary/LineChart/LineChart.tsx +95 -244
- package/UI/Components/Charts/ChartLibrary/Utils/DoubleClick.ts +214 -0
- package/UI/Components/Charts/ChartLibrary/Utils/UseChartBucketsChange.ts +32 -0
- package/UI/Components/Charts/ChartLibrary/Utils/UseChartRangeSelection.ts +599 -0
- package/UI/Components/Charts/Line/LineChart.tsx +32 -2
- package/UI/Components/Charts/TimeRangeZoom/ResetTimeRangeZoomButton.tsx +70 -0
- package/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomContext.tsx +226 -0
- package/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomHint.tsx +73 -0
- package/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomUtil.ts +163 -0
- package/UI/Components/Charts/TimeRangeZoom/UseTimeRangeZoom.ts +215 -0
- package/UI/Components/Charts/Utils/DataPoint.ts +20 -8
- package/UI/Components/Charts/Utils/XAxis.ts +75 -0
- package/UI/Components/Charts/Utils/useHistogramRangeSelection.ts +493 -59
- package/UI/Components/EntityDropdown/EntityDropdown.tsx +107 -11
- package/UI/Components/Forms/Fields/FormField.tsx +10 -0
- package/UI/Components/Input/Input.tsx +90 -57
- package/UI/Components/List/ListRow.tsx +8 -74
- package/UI/Components/LogsViewer/LogsViewer.tsx +40 -11
- package/UI/Components/LogsViewer/components/LogTimeRangePicker.tsx +22 -6
- package/UI/Components/LogsViewer/components/LogsAnalyticsView.tsx +209 -6
- package/UI/Components/LogsViewer/components/LogsHistogram.tsx +127 -84
- package/UI/Components/LogsViewer/components/LogsViewerToolbar.tsx +3 -0
- package/UI/Components/ModelTable/BaseModelTable.tsx +12 -1
- package/UI/Components/MoreMenu/MoreMenu.tsx +365 -30
- package/UI/Components/MoreMenu/MoreMenuItem.tsx +70 -17
- package/UI/Components/OrderedStatesList/Item.tsx +7 -72
- package/UI/Components/StatusPage/ResourceGrid.tsx +126 -77
- package/UI/Components/Table/TableBody.tsx +8 -2
- package/UI/Components/Table/TableRow.tsx +20 -140
- package/UI/Components/TelemetryViewer/TelemetryViewer.tsx +41 -10
- package/UI/Components/TelemetryViewer/components/TelemetryHistogram.tsx +47 -9
- package/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.tsx +25 -6
- package/UI/Components/TelemetryViewer/types.ts +2 -0
- package/UI/Components/TelemetryViewer/useViewerTimeRangeZoom.ts +448 -0
- package/UI/Components/Toggle/Toggle.tsx +26 -0
- package/UI/Components/Tooltip/Tooltip.tsx +8 -1
- package/UI/Styles/Theme.css +14 -2
- package/Utils/AiRemediation/CommandPolicy.ts +1 -1
- package/Utils/AiRemediation/KubectlPolicy.ts +1 -1
- package/Utils/Dashboard/DashboardTimeRangeZoom.ts +46 -2
- package/build/dist/Models/DatabaseModels/Index.js +2 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/KubernetesAiAgent.js +385 -0
- package/build/dist/Models/DatabaseModels/KubernetesAiAgent.js.map +1 -0
- package/build/dist/Models/DatabaseModels/KubernetesCluster.js +3 -3
- package/build/dist/Models/DatabaseModels/KubernetesCluster.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Project.js +56 -5
- package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ProxmoxResource.js +51 -1
- package/build/dist/Models/DatabaseModels/ProxmoxResource.js.map +1 -1
- package/build/dist/Models/DatabaseModels/RunnerJob.js +74 -0
- package/build/dist/Models/DatabaseModels/RunnerJob.js.map +1 -1
- package/build/dist/Models/DatabaseModels/TeamComplianceSetting.js +134 -3
- package/build/dist/Models/DatabaseModels/TeamComplianceSetting.js.map +1 -1
- package/build/dist/Models/DatabaseModels/WorkspaceProjectAuthToken.js.map +1 -1
- package/build/dist/Server/API/AIChatAPI.js +6 -1
- package/build/dist/Server/API/AIChatAPI.js.map +1 -1
- package/build/dist/Server/API/AIInvestigationAPI.js +17 -10
- package/build/dist/Server/API/AIInvestigationAPI.js.map +1 -1
- package/build/dist/Server/API/AutoRemediationAPI.js +144 -24
- package/build/dist/Server/API/AutoRemediationAPI.js.map +1 -1
- package/build/dist/Server/API/KubernetesClusterAiAccessAPI.js +436 -22
- package/build/dist/Server/API/KubernetesClusterAiAccessAPI.js.map +1 -1
- package/build/dist/Server/API/MicrosoftTeamsAPI.js +69 -13
- package/build/dist/Server/API/MicrosoftTeamsAPI.js.map +1 -1
- package/build/dist/Server/API/ProxmoxResourceAPI.js +187 -14
- package/build/dist/Server/API/ProxmoxResourceAPI.js.map +1 -1
- package/build/dist/Server/Infrastructure/GlobalCache.js +27 -0
- package/build/dist/Server/Infrastructure/GlobalCache.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796000000000-AddTeamComplianceRuleScope.js +50 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796000000000-AddTeamComplianceRuleScope.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796100000000-AddKubernetesAiAgentAndAiDefaults.js +84 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796100000000-AddKubernetesAiAgentAndAiDefaults.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796200000000-AddProxmoxResourceNativePushColumns.js +31 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796200000000-AddProxmoxResourceNativePushColumns.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Middleware/TelemetryIngest.js +34 -19
- package/build/dist/Server/Middleware/TelemetryIngest.js.map +1 -1
- package/build/dist/Server/Services/AIService.js +59 -1
- package/build/dist/Server/Services/AIService.js.map +1 -1
- package/build/dist/Server/Services/AlertService.js +248 -13
- package/build/dist/Server/Services/AlertService.js.map +1 -1
- package/build/dist/Server/Services/AlertSeverityService.js +51 -15
- package/build/dist/Server/Services/AlertSeverityService.js.map +1 -1
- package/build/dist/Server/Services/AutoRemediationRuleService.js +1 -1
- package/build/dist/Server/Services/AutoRemediationRuleService.js.map +1 -1
- package/build/dist/Server/Services/IncidentService.js +199 -72
- package/build/dist/Server/Services/IncidentService.js.map +1 -1
- package/build/dist/Server/Services/IncidentSeverityService.js +51 -15
- package/build/dist/Server/Services/IncidentSeverityService.js.map +1 -1
- package/build/dist/Server/Services/KubernetesAiAgentJobService.js +158 -0
- package/build/dist/Server/Services/KubernetesAiAgentJobService.js.map +1 -0
- package/build/dist/Server/Services/KubernetesAiAgentService.js +1145 -0
- package/build/dist/Server/Services/KubernetesAiAgentService.js.map +1 -0
- package/build/dist/Server/Services/KubernetesClusterAiAccessService.js +842 -371
- package/build/dist/Server/Services/KubernetesClusterAiAccessService.js.map +1 -1
- package/build/dist/Server/Services/KubernetesClusterService.js +86 -17
- package/build/dist/Server/Services/KubernetesClusterService.js.map +1 -1
- package/build/dist/Server/Services/ProjectService.js +22 -0
- package/build/dist/Server/Services/ProjectService.js.map +1 -1
- package/build/dist/Server/Services/ProxmoxResourceService.js +258 -3
- package/build/dist/Server/Services/ProxmoxResourceService.js.map +1 -1
- package/build/dist/Server/Services/RunnerJobService.js +178 -92
- package/build/dist/Server/Services/RunnerJobService.js.map +1 -1
- package/build/dist/Server/Services/RunnerService.js +1 -1
- package/build/dist/Server/Services/RunnerService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceService.js +535 -3
- package/build/dist/Server/Services/ScheduledMaintenanceService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceStateTimelineService.js +316 -46
- package/build/dist/Server/Services/ScheduledMaintenanceStateTimelineService.js.map +1 -1
- package/build/dist/Server/Services/TeamComplianceSettingService.js +833 -7
- package/build/dist/Server/Services/TeamComplianceSettingService.js.map +1 -1
- package/build/dist/Server/Utils/AI/ClusterAccess/ClusterAccessContext.js +52 -9
- package/build/dist/Server/Utils/AI/ClusterAccess/ClusterAccessContext.js.map +1 -1
- package/build/dist/Server/Utils/AI/ClusterAccess/KubectlInvestigationToolkit.js +13 -9
- package/build/dist/Server/Utils/AI/ClusterAccess/KubectlInvestigationToolkit.js.map +1 -1
- package/build/dist/Server/Utils/AI/ClusterAccess/KubectlJobRunner.js +7 -3
- package/build/dist/Server/Utils/AI/ClusterAccess/KubectlJobRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/Remediation/RemediationCommandTools.js +29 -15
- package/build/dist/Server/Utils/AI/Remediation/RemediationCommandTools.js.map +1 -1
- package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js +56 -20
- package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js +39 -5
- package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/IncidentPostmortemRunner.js +30 -3
- package/build/dist/Server/Utils/AI/SRE/IncidentPostmortemRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/InvestigationEligibility.js +13 -2
- package/build/dist/Server/Utils/AI/SRE/InvestigationEligibility.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/InvestigationGrader.js +1 -1
- package/build/dist/Server/Utils/AutoRemediation/CommandPlanExecutor.js +4 -2
- package/build/dist/Server/Utils/AutoRemediation/CommandPlanExecutor.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/InventoryEntityRegistry.js +111 -6
- package/build/dist/Server/Utils/Telemetry/InventoryEntityRegistry.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/ProxmoxCephSnapshotScan.js +40 -4
- package/build/dist/Server/Utils/Telemetry/ProxmoxCephSnapshotScan.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/ProxmoxNativeNodeLiveness.js +296 -0
- package/build/dist/Server/Utils/Telemetry/ProxmoxNativeNodeLiveness.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/ProxmoxNativePush.js +699 -0
- package/build/dist/Server/Utils/Telemetry/ProxmoxNativePush.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js +77 -19
- package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +505 -42
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
- package/build/dist/Types/AI/AIRunType.js +9 -4
- package/build/dist/Types/AI/AIRunType.js.map +1 -1
- package/build/dist/Types/AutoRemediation/AiRemediationCommandPlan.js +10 -16
- package/build/dist/Types/AutoRemediation/AiRemediationCommandPlan.js.map +1 -1
- package/build/dist/Types/AutoRemediation/AiRemediationCommandPolicyVerdict.js +28 -0
- package/build/dist/Types/AutoRemediation/AiRemediationCommandPolicyVerdict.js.map +1 -0
- package/build/dist/Types/Kubernetes/KubernetesClusterAiAccess.js +72 -16
- package/build/dist/Types/Kubernetes/KubernetesClusterAiAccess.js.map +1 -1
- package/build/dist/Types/Kubernetes/KubernetesClusterAiAccessPermissions.js +20 -16
- package/build/dist/Types/Kubernetes/KubernetesClusterAiAccessPermissions.js.map +1 -1
- package/build/dist/Types/Kubernetes/KubernetesClusterAiInsights.js +17 -0
- package/build/dist/Types/Kubernetes/KubernetesClusterAiInsights.js.map +1 -0
- package/build/dist/Types/Monitor/ProxmoxAlertTemplates.js +4 -4
- package/build/dist/Types/Monitor/ProxmoxAlertTemplates.js.map +1 -1
- package/build/dist/Types/Team/ComplianceNotificationChannel.js +23 -0
- package/build/dist/Types/Team/ComplianceNotificationChannel.js.map +1 -0
- package/build/dist/Types/Team/ComplianceRule.js +304 -0
- package/build/dist/Types/Team/ComplianceRule.js.map +1 -0
- package/build/dist/Types/Team/ComplianceRuleType.js +21 -0
- package/build/dist/Types/Team/ComplianceRuleType.js.map +1 -1
- package/build/dist/Types/Team/TeamComplianceStatus.js +2 -0
- package/build/dist/Types/Team/TeamComplianceStatus.js.map +1 -0
- package/build/dist/Types/Telemetry/TelemetryIngestSurface.js +25 -0
- package/build/dist/Types/Telemetry/TelemetryIngestSurface.js.map +1 -1
- package/build/dist/UI/Components/ActionButton/ActionButtonSchema.js +20 -1
- package/build/dist/UI/Components/ActionButton/ActionButtonSchema.js.map +1 -1
- package/build/dist/UI/Components/ActionButton/RowActions.js +113 -0
- package/build/dist/UI/Components/ActionButton/RowActions.js.map +1 -0
- package/build/dist/UI/Components/ActionButton/SplitActionButtons.js +71 -0
- package/build/dist/UI/Components/ActionButton/SplitActionButtons.js.map +1 -0
- package/build/dist/UI/Components/Charts/Area/AreaChart.js +16 -1
- package/build/dist/UI/Components/Charts/Area/AreaChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/Bar/BarChart.js +16 -1
- package/build/dist/UI/Components/Charts/Bar/BarChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js +27 -5
- package/build/dist/UI/Components/Charts/ChartGroup/ChartGroup.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.js +61 -194
- package/build/dist/UI/Components/Charts/ChartLibrary/AreaChart/AreaChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartLibrary/BarChart/BarChart.js +84 -26
- package/build/dist/UI/Components/Charts/ChartLibrary/BarChart/BarChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartLibrary/LineChart/LineChart.js +75 -196
- package/build/dist/UI/Components/Charts/ChartLibrary/LineChart/LineChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartLibrary/Utils/DoubleClick.js +133 -0
- package/build/dist/UI/Components/Charts/ChartLibrary/Utils/DoubleClick.js.map +1 -1
- package/build/dist/UI/Components/Charts/ChartLibrary/Utils/UseChartBucketsChange.js +26 -0
- package/build/dist/UI/Components/Charts/ChartLibrary/Utils/UseChartBucketsChange.js.map +1 -0
- package/build/dist/UI/Components/Charts/ChartLibrary/Utils/UseChartRangeSelection.js +371 -0
- package/build/dist/UI/Components/Charts/ChartLibrary/Utils/UseChartRangeSelection.js.map +1 -0
- package/build/dist/UI/Components/Charts/Line/LineChart.js +16 -1
- package/build/dist/UI/Components/Charts/Line/LineChart.js.map +1 -1
- package/build/dist/UI/Components/Charts/TimeRangeZoom/ResetTimeRangeZoomButton.js +35 -0
- package/build/dist/UI/Components/Charts/TimeRangeZoom/ResetTimeRangeZoomButton.js.map +1 -0
- package/build/dist/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomContext.js +107 -0
- package/build/dist/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomContext.js.map +1 -0
- package/build/dist/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomHint.js +41 -0
- package/build/dist/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomHint.js.map +1 -0
- package/build/dist/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomUtil.js +117 -0
- package/build/dist/UI/Components/Charts/TimeRangeZoom/TimeRangeZoomUtil.js.map +1 -0
- package/build/dist/UI/Components/Charts/TimeRangeZoom/UseTimeRangeZoom.js +121 -0
- package/build/dist/UI/Components/Charts/TimeRangeZoom/UseTimeRangeZoom.js.map +1 -0
- package/build/dist/UI/Components/Charts/Utils/DataPoint.js +15 -7
- package/build/dist/UI/Components/Charts/Utils/DataPoint.js.map +1 -1
- package/build/dist/UI/Components/Charts/Utils/XAxis.js +70 -0
- package/build/dist/UI/Components/Charts/Utils/XAxis.js.map +1 -1
- package/build/dist/UI/Components/Charts/Utils/useHistogramRangeSelection.js +305 -38
- package/build/dist/UI/Components/Charts/Utils/useHistogramRangeSelection.js.map +1 -1
- package/build/dist/UI/Components/EntityDropdown/EntityDropdown.js +89 -14
- package/build/dist/UI/Components/EntityDropdown/EntityDropdown.js.map +1 -1
- package/build/dist/UI/Components/Forms/Fields/FormField.js +11 -2
- package/build/dist/UI/Components/Forms/Fields/FormField.js.map +1 -1
- package/build/dist/UI/Components/Input/Input.js +69 -54
- package/build/dist/UI/Components/Input/Input.js.map +1 -1
- package/build/dist/UI/Components/List/ListRow.js +4 -39
- package/build/dist/UI/Components/List/ListRow.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/LogsViewer.js +31 -8
- package/build/dist/UI/Components/LogsViewer/LogsViewer.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogTimeRangePicker.js +10 -1
- package/build/dist/UI/Components/LogsViewer/components/LogTimeRangePicker.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js +139 -21
- package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsHistogram.js +30 -8
- package/build/dist/UI/Components/LogsViewer/components/LogsHistogram.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsViewerToolbar.js +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsViewerToolbar.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js +10 -0
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
- package/build/dist/UI/Components/MoreMenu/MoreMenu.js +253 -14
- package/build/dist/UI/Components/MoreMenu/MoreMenu.js.map +1 -1
- package/build/dist/UI/Components/MoreMenu/MoreMenuItem.js +43 -13
- package/build/dist/UI/Components/MoreMenu/MoreMenuItem.js.map +1 -1
- package/build/dist/UI/Components/OrderedStatesList/Item.js +2 -38
- package/build/dist/UI/Components/OrderedStatesList/Item.js.map +1 -1
- package/build/dist/UI/Components/StatusPage/ResourceGrid.js +53 -15
- package/build/dist/UI/Components/StatusPage/ResourceGrid.js.map +1 -1
- package/build/dist/UI/Components/Table/TableBody.js +6 -2
- package/build/dist/UI/Components/Table/TableBody.js.map +1 -1
- package/build/dist/UI/Components/Table/TableRow.js +12 -75
- package/build/dist/UI/Components/Table/TableRow.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js +32 -7
- package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogram.js +27 -9
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogram.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.js +11 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/useViewerTimeRangeZoom.js +272 -0
- package/build/dist/UI/Components/TelemetryViewer/useViewerTimeRangeZoom.js.map +1 -0
- package/build/dist/UI/Components/Toggle/Toggle.js +14 -1
- package/build/dist/UI/Components/Toggle/Toggle.js.map +1 -1
- package/build/dist/UI/Components/Tooltip/Tooltip.js +1 -1
- package/build/dist/UI/Components/Tooltip/Tooltip.js.map +1 -1
- package/build/dist/Utils/AiRemediation/CommandPolicy.js +1 -1
- package/build/dist/Utils/AiRemediation/CommandPolicy.js.map +1 -1
- package/build/dist/Utils/AiRemediation/KubectlPolicy.js +1 -1
- package/build/dist/Utils/AiRemediation/KubectlPolicy.js.map +1 -1
- package/build/dist/Utils/Dashboard/DashboardTimeRangeZoom.js +27 -1
- package/build/dist/Utils/Dashboard/DashboardTimeRangeZoom.js.map +1 -1
- package/package.json +1 -1
|
@@ -30,10 +30,7 @@ import { holdsAnyPermission } from "../Utils/Runbook/RunbookExecutePermission";
|
|
|
30
30
|
import DatabaseCommonInteractionProps from "../../Types/BaseDatabase/DatabaseCommonInteractionProps";
|
|
31
31
|
import BadDataException from "../../Types/Exception/BadDataException";
|
|
32
32
|
import NotAuthorizedException from "../../Types/Exception/NotAuthorizedException";
|
|
33
|
-
import {
|
|
34
|
-
KubernetesAiRemediationMode,
|
|
35
|
-
isUnattendedRemediationMode,
|
|
36
|
-
} from "../../Types/Kubernetes/KubernetesClusterAiAccess";
|
|
33
|
+
import { KubernetesAiRemediationMode } from "../../Types/Kubernetes/KubernetesClusterAiAccess";
|
|
37
34
|
import {
|
|
38
35
|
KUBERNETES_AI_ACCESS_ADMIN_PERMISSIONS,
|
|
39
36
|
KUBERNETES_AI_ACCESS_CREDENTIAL_PERMISSIONS,
|
|
@@ -41,6 +38,7 @@ import {
|
|
|
41
38
|
import { PermissionHelper } from "../../Types/Permission";
|
|
42
39
|
import RunbookCredentialType from "../../Types/Runbook/RunbookCredentialType";
|
|
43
40
|
import KubernetesClusterFeedService from "./KubernetesClusterFeedService";
|
|
41
|
+
import KubernetesAiAgentService from "./KubernetesAiAgentService";
|
|
44
42
|
import { KubernetesClusterFeedEventType } from "../../Models/DatabaseModels/KubernetesClusterFeed";
|
|
45
43
|
import ResourceFeedUtil from "../Utils/ResourceFeed/ResourceFeedUtil";
|
|
46
44
|
import { Blue500, Gray500, Green500, Yellow500 } from "../../Types/BrandColors";
|
|
@@ -151,11 +149,11 @@ export const AI_ACCESS_CREDENTIAL_REFUSAL: string =
|
|
|
151
149
|
"Credential not found, or it is not a Kubernetes credential in this project. The AI access credential must be a Kubernetes credential (API server URL and ServiceAccount token) that belongs to this project.";
|
|
152
150
|
|
|
153
151
|
export function getAiAccessAdminRefusal(): string {
|
|
154
|
-
return `You need one of these permissions to let OneUptime AI do more on a Kubernetes cluster (
|
|
152
|
+
return `You need one of these permissions to let OneUptime AI do more on a Kubernetes cluster (turn AI fixes on or give them more autonomy, add kubectl allowlist patterns, bind a Runner or credential, or clear one while the cluster has a Kubernetes AI agent): ${PermissionHelper.getPermissionTitles(
|
|
155
153
|
KUBERNETES_AI_ACCESS_ADMIN_PERMISSIONS,
|
|
156
154
|
).join(
|
|
157
155
|
", ",
|
|
158
|
-
)}. Anyone who may edit the cluster can still turn AI
|
|
156
|
+
)}. Anyone who may edit the cluster can still turn AI fixes off or down to Ask for approval, and remove allowlist patterns.`;
|
|
159
157
|
}
|
|
160
158
|
|
|
161
159
|
export function getAiAccessCredentialRefusal(): string {
|
|
@@ -183,11 +181,22 @@ export interface AiAccessSettingsSnapshot {
|
|
|
183
181
|
aiKubectlCommandAllowlist: Array<string>;
|
|
184
182
|
aiAccessRunnerId: string | null;
|
|
185
183
|
aiAccessCredentialId: string | null;
|
|
184
|
+
/*
|
|
185
|
+
* Whether the cluster has a Kubernetes AI agent row. Read only for a
|
|
186
|
+
* write that clears the Runner or credential binding (absent otherwise):
|
|
187
|
+
* with an agent, clearing an advanced Runner hands the cluster to the
|
|
188
|
+
* agent, whose RBAC may reach more, so it is a loosening.
|
|
189
|
+
*/
|
|
190
|
+
hasKubernetesAiAgent?: boolean | undefined;
|
|
186
191
|
}
|
|
187
192
|
|
|
188
|
-
|
|
193
|
+
/*
|
|
194
|
+
* What a cluster that was never AI-configured has: the column defaults
|
|
195
|
+
* (investigation on — it only ever runs read-only kubectl — and remediation
|
|
196
|
+
* Disabled).
|
|
197
|
+
*/
|
|
189
198
|
const NEVER_CONFIGURED_AI_ACCESS: AiAccessSettingsSnapshot = {
|
|
190
|
-
isAiInvestigationEnabled:
|
|
199
|
+
isAiInvestigationEnabled: true,
|
|
191
200
|
aiRemediationMode: KubernetesAiRemediationMode.Disabled,
|
|
192
201
|
aiKubectlCommandAllowlist: [],
|
|
193
202
|
aiAccessRunnerId: null,
|
|
@@ -229,7 +238,7 @@ function getClusterDeleteCarryForward(
|
|
|
229
238
|
}
|
|
230
239
|
|
|
231
240
|
// What loosening an operator's write would do to one cluster.
|
|
232
|
-
interface AiAccessLoosening {
|
|
241
|
+
export interface AiAccessLoosening {
|
|
233
242
|
loosens: boolean;
|
|
234
243
|
bindsCredential: boolean;
|
|
235
244
|
}
|
|
@@ -319,7 +328,9 @@ export class Service extends DatabaseService<Model> {
|
|
|
319
328
|
|
|
320
329
|
if (!updateBy.props.isRoot && this.isAiAccessSettingWritten(data)) {
|
|
321
330
|
const previousAiAccessSettings: Record<string, AiAccessSettingsSnapshot> =
|
|
322
|
-
await this.getAiAccessSettingsForUpdateQuery(updateBy
|
|
331
|
+
await this.getAiAccessSettingsForUpdateQuery(updateBy, {
|
|
332
|
+
withKubernetesAiAgent: this.clearsAiAccessBinding(data),
|
|
333
|
+
});
|
|
323
334
|
|
|
324
335
|
if (!updateBy.props.isMasterAdmin) {
|
|
325
336
|
this.assertMayChangeAiAccess({
|
|
@@ -657,22 +668,29 @@ export class Service extends DatabaseService<Model> {
|
|
|
657
668
|
|
|
658
669
|
/*
|
|
659
670
|
* Does this write let AI do more on a cluster whose settings are
|
|
660
|
-
* `current`? Only a real change counts: the AI page posts every
|
|
661
|
-
* its form, so an editor who only flips the investigation switch
|
|
662
|
-
* an unchanged mode, allowlist and binding, and must not be
|
|
663
|
-
* settings someone else chose.
|
|
671
|
+
* `current`? Only a real change counts: the AI agent page posts every
|
|
672
|
+
* field of its form, so an editor who only flips the investigation switch
|
|
673
|
+
* re-posts an unchanged mode, allowlist and binding, and must not be
|
|
674
|
+
* refused for settings someone else chose.
|
|
664
675
|
*
|
|
665
|
-
* - mode:
|
|
666
|
-
*
|
|
676
|
+
* - mode: ANY move up — turning fixes on from Off (even to Ask for
|
|
677
|
+
* approval: with the chart's write RBAC in place that is the step that
|
|
678
|
+
* lets AI change the cluster at all, and no project opt-in stands behind
|
|
679
|
+
* it any more for a cluster reached through its agent), or up to
|
|
680
|
+
* Automatic or Bypass approval. Moving down (Bypass approval ->
|
|
681
|
+
* Automatic, anything -> Off) tightens;
|
|
667
682
|
* - allowlist: adding a pattern the cluster did not already have
|
|
668
683
|
* (removing patterns, or clearing the list, tightens);
|
|
669
|
-
* - Runner or credential: binding one other than the current one
|
|
670
|
-
*
|
|
684
|
+
* - Runner or credential: binding one other than the current one; and
|
|
685
|
+
* clearing one while the cluster has a Kubernetes AI agent, which hands
|
|
686
|
+
* the cluster to the agent (resolveKubernetesAiAccessTarget) and its
|
|
687
|
+
* RBAC. Without an agent, clearing leaves AI nothing to reach the
|
|
688
|
+
* cluster through, and tightens.
|
|
671
689
|
*
|
|
672
690
|
* `data` has been through validateAiRemediationSettings, so the mode is a
|
|
673
691
|
* known value and the allowlist a trimmed array or null.
|
|
674
692
|
*/
|
|
675
|
-
|
|
693
|
+
public getAiAccessLoosening(
|
|
676
694
|
data: JSONObject,
|
|
677
695
|
current: AiAccessSettingsSnapshot,
|
|
678
696
|
): AiAccessLoosening {
|
|
@@ -685,7 +703,6 @@ export class Service extends DatabaseService<Model> {
|
|
|
685
703
|
|
|
686
704
|
if (
|
|
687
705
|
mode !== undefined &&
|
|
688
|
-
isUnattendedRemediationMode(mode) &&
|
|
689
706
|
REMEDIATION_MODES_BY_AUTONOMY.indexOf(mode) >
|
|
690
707
|
REMEDIATION_MODES_BY_AUTONOMY.indexOf(current.aiRemediationMode)
|
|
691
708
|
) {
|
|
@@ -729,9 +746,42 @@ export class Service extends DatabaseService<Model> {
|
|
|
729
746
|
bindsCredential = true;
|
|
730
747
|
}
|
|
731
748
|
|
|
749
|
+
if (current.hasKubernetesAiAgent === true) {
|
|
750
|
+
const clearsRunner: boolean =
|
|
751
|
+
isAnyKeyWritten(data, AI_ACCESS_RUNNER_KEYS) &&
|
|
752
|
+
!runnerId &&
|
|
753
|
+
current.aiAccessRunnerId !== null;
|
|
754
|
+
const clearsCredential: boolean =
|
|
755
|
+
isAnyKeyWritten(data, AI_ACCESS_CREDENTIAL_KEYS) &&
|
|
756
|
+
!credentialId &&
|
|
757
|
+
current.aiAccessCredentialId !== null;
|
|
758
|
+
|
|
759
|
+
if (clearsRunner || clearsCredential) {
|
|
760
|
+
loosens = true;
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
|
|
732
764
|
return { loosens, bindsCredential };
|
|
733
765
|
}
|
|
734
766
|
|
|
767
|
+
// The write clears the Runner or the credential binding (null).
|
|
768
|
+
private clearsAiAccessBinding(data: JSONObject): boolean {
|
|
769
|
+
return (
|
|
770
|
+
(isAnyKeyWritten(data, AI_ACCESS_RUNNER_KEYS) &&
|
|
771
|
+
!RelationIdUtil.readConsistent(
|
|
772
|
+
data,
|
|
773
|
+
AI_ACCESS_RUNNER_KEYS,
|
|
774
|
+
"AI access Runner",
|
|
775
|
+
)) ||
|
|
776
|
+
(isAnyKeyWritten(data, AI_ACCESS_CREDENTIAL_KEYS) &&
|
|
777
|
+
!RelationIdUtil.readConsistent(
|
|
778
|
+
data,
|
|
779
|
+
AI_ACCESS_CREDENTIAL_KEYS,
|
|
780
|
+
"AI access credential",
|
|
781
|
+
))
|
|
782
|
+
);
|
|
783
|
+
}
|
|
784
|
+
|
|
735
785
|
/*
|
|
736
786
|
* The AI access settings of every cluster an operator's update reaches,
|
|
737
787
|
* read before the write. onBeforeUpdate runs before the framework scopes
|
|
@@ -742,6 +792,10 @@ export class Service extends DatabaseService<Model> {
|
|
|
742
792
|
@CaptureSpan()
|
|
743
793
|
private async getAiAccessSettingsForUpdateQuery(
|
|
744
794
|
updateBy: UpdateBy<Model>,
|
|
795
|
+
options: {
|
|
796
|
+
// Also read whether each cluster has a Kubernetes AI agent row.
|
|
797
|
+
withKubernetesAiAgent: boolean;
|
|
798
|
+
} = { withKubernetesAiAgent: false },
|
|
745
799
|
): Promise<Record<string, AiAccessSettingsSnapshot>> {
|
|
746
800
|
const clusters: Array<Model> = await this.findBy({
|
|
747
801
|
query: {
|
|
@@ -790,9 +844,63 @@ export class Service extends DatabaseService<Model> {
|
|
|
790
844
|
};
|
|
791
845
|
}
|
|
792
846
|
|
|
847
|
+
if (options.withKubernetesAiAgent) {
|
|
848
|
+
await this.readKubernetesAiAgentPresence(settings);
|
|
849
|
+
}
|
|
850
|
+
|
|
793
851
|
return settings;
|
|
794
852
|
}
|
|
795
853
|
|
|
854
|
+
/*
|
|
855
|
+
* Fill in hasKubernetesAiAgent on each snapshot, one query per project the
|
|
856
|
+
* write reaches. Fails closed: when the agent rows cannot be read, every
|
|
857
|
+
* cluster is treated as having one, so clearing a binding then needs the
|
|
858
|
+
* admin permissions rather than slipping through unchecked.
|
|
859
|
+
*/
|
|
860
|
+
private async readKubernetesAiAgentPresence(
|
|
861
|
+
settings: Record<string, AiAccessSettingsSnapshot>,
|
|
862
|
+
): Promise<void> {
|
|
863
|
+
const clusterIdsByProject: Map<string, Array<ObjectID>> = new Map<
|
|
864
|
+
string,
|
|
865
|
+
Array<ObjectID>
|
|
866
|
+
>();
|
|
867
|
+
|
|
868
|
+
for (const [clusterId, snapshot] of Object.entries(settings)) {
|
|
869
|
+
const projectId: string = snapshot.projectId?.toString() || "";
|
|
870
|
+
const clusterIds: Array<ObjectID> =
|
|
871
|
+
clusterIdsByProject.get(projectId) || [];
|
|
872
|
+
clusterIds.push(new ObjectID(clusterId));
|
|
873
|
+
clusterIdsByProject.set(projectId, clusterIds);
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
for (const [projectId, clusterIds] of clusterIdsByProject.entries()) {
|
|
877
|
+
let agentClusterIds: Set<string> | null = null;
|
|
878
|
+
|
|
879
|
+
if (projectId) {
|
|
880
|
+
try {
|
|
881
|
+
agentClusterIds = new Set<string>(
|
|
882
|
+
(
|
|
883
|
+
await KubernetesAiAgentService.findForClusters({
|
|
884
|
+
projectId: new ObjectID(projectId),
|
|
885
|
+
kubernetesClusterIds: clusterIds,
|
|
886
|
+
})
|
|
887
|
+
).keys(),
|
|
888
|
+
);
|
|
889
|
+
} catch (error) {
|
|
890
|
+
logger.error(
|
|
891
|
+
`KubernetesClusterService: could not read the Kubernetes AI agents of project ${projectId}; treating every cluster as having one: ${error}`,
|
|
892
|
+
);
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
for (const clusterId of clusterIds) {
|
|
897
|
+
settings[clusterId.toString()]!.hasKubernetesAiAgent = agentClusterIds
|
|
898
|
+
? agentClusterIds.has(clusterId.toString())
|
|
899
|
+
: true;
|
|
900
|
+
}
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
|
|
796
904
|
/*
|
|
797
905
|
* aiAccessRunnerId / aiAccessCredentialId are editable through ordinary
|
|
798
906
|
* CRUD by every member who may edit a cluster, and nothing in the
|
|
@@ -977,7 +1085,7 @@ export class Service extends DatabaseService<Model> {
|
|
|
977
1085
|
|
|
978
1086
|
if (isAgentRunner && !isThisClustersAgent && isRunnerChanged) {
|
|
979
1087
|
throw new BadDataException(
|
|
980
|
-
`Runner "${runner.name}" is the in-cluster Runner the Kubernetes agent chart installed on another cluster. Its ServiceAccount reaches only the cluster its pod runs in, and it is never given a credential, so it cannot run kubectl for this cluster.
|
|
1088
|
+
`Runner "${runner.name}" is the in-cluster Runner the Kubernetes agent chart installed on another cluster. Its ServiceAccount reaches only the cluster its pod runs in, and it is never given a credential, so it cannot run kubectl for this cluster. Leave the Runner empty to use this cluster's Kubernetes AI agent, or bind a Runner you created under Project Settings → Runners together with a Kubernetes credential for this cluster.`,
|
|
981
1089
|
);
|
|
982
1090
|
}
|
|
983
1091
|
|
|
@@ -554,9 +554,41 @@ export class ProjectService extends DatabaseService<Model> {
|
|
|
554
554
|
data.data.alertEpisodeNumberPrefix = "AE-";
|
|
555
555
|
}
|
|
556
556
|
|
|
557
|
+
this.applyNewProjectAiDefaults(data.data);
|
|
558
|
+
|
|
557
559
|
return Promise.resolve({ createBy: data, carryForward: null });
|
|
558
560
|
}
|
|
559
561
|
|
|
562
|
+
/*
|
|
563
|
+
* A new project starts with AI investigating its incidents and alerts:
|
|
564
|
+
* both automatic-investigation opt-ins are turned on unless the create
|
|
565
|
+
* request set them itself (a request that says false keeps false). The
|
|
566
|
+
* columns' database default stays false, so projects that existed before
|
|
567
|
+
* this are never switched on by an upgrade, and a create that bypasses
|
|
568
|
+
* this hook entirely gets the old behaviour rather than a surprise.
|
|
569
|
+
*
|
|
570
|
+
* Postmortem drafting is deliberately NOT turned on here: it is its own
|
|
571
|
+
* opt-in (enableAutomaticPostmortemDraft), off by default.
|
|
572
|
+
*/
|
|
573
|
+
public applyNewProjectAiDefaults(data: {
|
|
574
|
+
enableAutomaticIncidentInvestigation?: boolean | null | undefined;
|
|
575
|
+
enableAutomaticAlertInvestigation?: boolean | null | undefined;
|
|
576
|
+
}): void {
|
|
577
|
+
if (
|
|
578
|
+
data.enableAutomaticIncidentInvestigation === undefined ||
|
|
579
|
+
data.enableAutomaticIncidentInvestigation === null
|
|
580
|
+
) {
|
|
581
|
+
data.enableAutomaticIncidentInvestigation = true;
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
if (
|
|
585
|
+
data.enableAutomaticAlertInvestigation === undefined ||
|
|
586
|
+
data.enableAutomaticAlertInvestigation === null
|
|
587
|
+
) {
|
|
588
|
+
data.enableAutomaticAlertInvestigation = true;
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
|
|
560
592
|
/*
|
|
561
593
|
* Session replay is gated on the project's org-wide allow flag, and the
|
|
562
594
|
* ingest gate caches the resolved policy per pod. Turning the flag off has
|
|
@@ -7,6 +7,18 @@ import OneUptimeDate from "../../Types/Date";
|
|
|
7
7
|
import QueryHelper from "../Types/Database/QueryHelper";
|
|
8
8
|
import { truncateShortText } from "../Utils/Database/TruncateColumnValue";
|
|
9
9
|
import logger from "../Utils/Logger";
|
|
10
|
+
import {
|
|
11
|
+
ProxmoxRosterNode,
|
|
12
|
+
isProxmoxSilentNodeDetectionEnabled,
|
|
13
|
+
} from "../Utils/Telemetry/ProxmoxNativeNodeLiveness";
|
|
14
|
+
|
|
15
|
+
const NODE_ID_PREFIX: string = "node/";
|
|
16
|
+
|
|
17
|
+
export type ProxmoxRemoveNodeResult =
|
|
18
|
+
| "removed"
|
|
19
|
+
| "not-found"
|
|
20
|
+
| "not-native"
|
|
21
|
+
| "still-reporting";
|
|
10
22
|
|
|
11
23
|
/*
|
|
12
24
|
* ------------------------------------------------------------------
|
|
@@ -88,6 +100,7 @@ const UPSERT_COLUMNS: Array<string> = [
|
|
|
88
100
|
"isBackedUp",
|
|
89
101
|
"uptimeSeconds",
|
|
90
102
|
"lastSeenAt",
|
|
103
|
+
"isNativePush",
|
|
91
104
|
"version",
|
|
92
105
|
];
|
|
93
106
|
|
|
@@ -127,12 +140,17 @@ export class Service extends DatabaseService<Model> {
|
|
|
127
140
|
* a complete scrape, but a batch that happens to lack an info series
|
|
128
141
|
* (e.g. only pve_up made it through a pipeline filter) must not blank
|
|
129
142
|
* name/vmid/haState that an earlier batch already filled.
|
|
143
|
+
*
|
|
144
|
+
* isNativePush records where the batch came from — the Proxmox VE
|
|
145
|
+
* native push (true) or the agent (false) — and follows the latest
|
|
146
|
+
* observation, so a cluster moved from one to the other follows too.
|
|
130
147
|
*/
|
|
131
148
|
@CaptureSpan()
|
|
132
149
|
public async bulkUpsert(data: {
|
|
133
150
|
projectId: ObjectID;
|
|
134
151
|
proxmoxClusterId: ObjectID;
|
|
135
152
|
resources: Array<ParsedProxmoxResource>;
|
|
153
|
+
isNativePush?: boolean | undefined;
|
|
136
154
|
}): Promise<void> {
|
|
137
155
|
if (data.resources.length === 0) {
|
|
138
156
|
return;
|
|
@@ -183,6 +201,7 @@ export class Service extends DatabaseService<Model> {
|
|
|
183
201
|
r.isBackedUp,
|
|
184
202
|
r.uptimeSeconds !== null ? Math.trunc(r.uptimeSeconds) : null,
|
|
185
203
|
r.lastSeenAt,
|
|
204
|
+
Boolean(data.isNativePush),
|
|
186
205
|
0, // version (BaseModel @VersionColumn)
|
|
187
206
|
);
|
|
188
207
|
}
|
|
@@ -192,7 +211,7 @@ export class Service extends DatabaseService<Model> {
|
|
|
192
211
|
"projectId", "proxmoxClusterId", "kind", "externalId",
|
|
193
212
|
"name", "vmid", "guestType", "parentNodeName",
|
|
194
213
|
"isUp", "haState", "onboot", "isBackedUp", "uptimeSeconds",
|
|
195
|
-
"lastSeenAt", "version"
|
|
214
|
+
"lastSeenAt", "isNativePush", "version"
|
|
196
215
|
)
|
|
197
216
|
VALUES ${valueFragments.join(", ")}
|
|
198
217
|
ON CONFLICT ("projectId", "proxmoxClusterId", "kind", "externalId")
|
|
@@ -207,6 +226,8 @@ export class Service extends DatabaseService<Model> {
|
|
|
207
226
|
"isBackedUp" = COALESCE(EXCLUDED."isBackedUp", "ProxmoxResource"."isBackedUp"),
|
|
208
227
|
"uptimeSeconds" = COALESCE(EXCLUDED."uptimeSeconds", "ProxmoxResource"."uptimeSeconds"),
|
|
209
228
|
"lastSeenAt" = EXCLUDED."lastSeenAt",
|
|
229
|
+
"isNativePush" = EXCLUDED."isNativePush",
|
|
230
|
+
"notReportingMarkedAt" = NULL,
|
|
210
231
|
"updatedAt" = now()
|
|
211
232
|
WHERE EXCLUDED."lastSeenAt" >= "ProxmoxResource"."lastSeenAt"
|
|
212
233
|
`;
|
|
@@ -313,17 +334,48 @@ export class Service extends DatabaseService<Model> {
|
|
|
313
334
|
* than olderThan. Returns the number of deleted rows. Only called by
|
|
314
335
|
* the cleanup worker for clusters that are still connected — a
|
|
315
336
|
* disconnected cluster keeps its last-known inventory.
|
|
337
|
+
*
|
|
338
|
+
* Exception: a Node that reports itself over the Proxmox VE native push
|
|
339
|
+
* (isNativePush) is kept until it has been silent for longer than the
|
|
340
|
+
* retention window, or is removed (removeOfflineNode). Those pushes
|
|
341
|
+
* never say which nodes the cluster has — the Node rows ARE the
|
|
342
|
+
* cluster's membership, the roster the nodes still alive report the
|
|
343
|
+
* silent ones from (getNodeRoster uses the same cutoff). Pruning a
|
|
344
|
+
* silent native node at the normal cutoff would drop it from the
|
|
345
|
+
* roster: it would never be reported down, its Node Offline alert
|
|
346
|
+
* would resolve, and Quorum at Risk would stop counting it. That
|
|
347
|
+
* holds whether or not it has been marked Offline yet — a node that
|
|
348
|
+
* died just before or during a OneUptime outage is only marked once
|
|
349
|
+
* the nodes have pushed again for two minutes after it. With silent-node
|
|
350
|
+
* detection switched off (PVE_NATIVE_NODE_SILENCE_DETECTION=false)
|
|
351
|
+
* nothing would ever mark such a node, so the keep is off too and every
|
|
352
|
+
* row ages out as before.
|
|
316
353
|
*/
|
|
317
354
|
@CaptureSpan()
|
|
318
355
|
public async deleteStaleForCluster(data: {
|
|
319
356
|
proxmoxClusterId: ObjectID;
|
|
320
357
|
olderThan: Date;
|
|
358
|
+
now?: Date | undefined;
|
|
321
359
|
}): Promise<number> {
|
|
322
360
|
const result: Array<{ affected?: number }> | { affected?: number } =
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
361
|
+
isProxmoxSilentNodeDetectionEnabled()
|
|
362
|
+
? await this.getRepository().manager.query(
|
|
363
|
+
`DELETE FROM "ProxmoxResource"
|
|
364
|
+
WHERE "proxmoxClusterId" = $1
|
|
365
|
+
AND "lastSeenAt" < $2
|
|
366
|
+
AND NOT ("kind" = 'Node'
|
|
367
|
+
AND "isNativePush" IS TRUE
|
|
368
|
+
AND "lastSeenAt" >= $3)`,
|
|
369
|
+
[
|
|
370
|
+
data.proxmoxClusterId.toString(),
|
|
371
|
+
data.olderThan,
|
|
372
|
+
this.getSilentNodeRetentionCutoff(data.now),
|
|
373
|
+
],
|
|
374
|
+
)
|
|
375
|
+
: await this.getRepository().manager.query(
|
|
376
|
+
`DELETE FROM "ProxmoxResource" WHERE "proxmoxClusterId" = $1 AND "lastSeenAt" < $2`,
|
|
377
|
+
[data.proxmoxClusterId.toString(), data.olderThan],
|
|
378
|
+
);
|
|
327
379
|
|
|
328
380
|
// Postgres driver returns [rows, affected] for DELETE — normalize.
|
|
329
381
|
let affected: number = 0;
|
|
@@ -343,6 +395,271 @@ export class Service extends DatabaseService<Model> {
|
|
|
343
395
|
return affected;
|
|
344
396
|
}
|
|
345
397
|
|
|
398
|
+
/**
|
|
399
|
+
* The cluster's nodes, for deciding which ones have stopped reporting
|
|
400
|
+
* (ProxmoxNativeNodeLiveness). A node silent for longer than the
|
|
401
|
+
* retention window drops out, so a node removed from the cluster stops
|
|
402
|
+
* being reported after at most that long even if nobody removes it.
|
|
403
|
+
*/
|
|
404
|
+
@CaptureSpan()
|
|
405
|
+
public async getNodeRoster(data: {
|
|
406
|
+
projectId: ObjectID;
|
|
407
|
+
proxmoxClusterId: ObjectID;
|
|
408
|
+
now?: Date | undefined;
|
|
409
|
+
}): Promise<Array<ProxmoxRosterNode>> {
|
|
410
|
+
const seenSince: Date = this.getSilentNodeRetentionCutoff(data.now);
|
|
411
|
+
const rows: Array<{
|
|
412
|
+
externalId: string;
|
|
413
|
+
lastSeenAt: Date | string;
|
|
414
|
+
isUp: boolean | null;
|
|
415
|
+
notReportingMarkedAt: Date | string | null;
|
|
416
|
+
}> = await this.getRepository().manager.query(
|
|
417
|
+
`SELECT "externalId", "lastSeenAt", "isUp", "notReportingMarkedAt" FROM "ProxmoxResource"
|
|
418
|
+
WHERE "projectId" = $1 AND "proxmoxClusterId" = $2
|
|
419
|
+
AND "kind" = 'Node' AND "deletedAt" IS NULL
|
|
420
|
+
AND "lastSeenAt" >= $3`,
|
|
421
|
+
[data.projectId.toString(), data.proxmoxClusterId.toString(), seenSince],
|
|
422
|
+
);
|
|
423
|
+
|
|
424
|
+
const roster: Array<ProxmoxRosterNode> = [];
|
|
425
|
+
for (const row of rows) {
|
|
426
|
+
if (!row.externalId || !row.externalId.startsWith(NODE_ID_PREFIX)) {
|
|
427
|
+
continue;
|
|
428
|
+
}
|
|
429
|
+
const nodeName: string = row.externalId.substring(NODE_ID_PREFIX.length);
|
|
430
|
+
const lastSeenAt: Date = new Date(row.lastSeenAt);
|
|
431
|
+
if (!nodeName || isNaN(lastSeenAt.getTime())) {
|
|
432
|
+
continue;
|
|
433
|
+
}
|
|
434
|
+
const markedAt: Date | null =
|
|
435
|
+
row.notReportingMarkedAt instanceof Date ||
|
|
436
|
+
typeof row.notReportingMarkedAt === "string"
|
|
437
|
+
? new Date(row.notReportingMarkedAt)
|
|
438
|
+
: null;
|
|
439
|
+
roster.push({
|
|
440
|
+
nodeName,
|
|
441
|
+
lastSeenAt,
|
|
442
|
+
isUp: typeof row.isUp === "boolean" ? row.isUp : null,
|
|
443
|
+
notReportingMarkedAt:
|
|
444
|
+
markedAt && !isNaN(markedAt.getTime()) ? markedAt : null,
|
|
445
|
+
});
|
|
446
|
+
}
|
|
447
|
+
return roster;
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* Mark nodes that their live siblings report as not reporting
|
|
452
|
+
* (Proxmox VE native push) as Offline: isUp = false, uptimeSeconds
|
|
453
|
+
* cleared. Never touches lastSeenAt or metricsUpdatedAt, which stay the
|
|
454
|
+
* node's own last push. The node's next push flips it back through
|
|
455
|
+
* bulkUpsert (a newer lastSeenAt, isUp = true). A row the node itself
|
|
456
|
+
* refreshed after `silentBefore` is left alone, so a late report can
|
|
457
|
+
* never mark a live node down. Returns the number of rows written.
|
|
458
|
+
*
|
|
459
|
+
* A node the native pushes report is a member of a native-push cluster,
|
|
460
|
+
* so the mark also sets isNativePush: a node that was already down when
|
|
461
|
+
* the cluster moved from the agent to the native push (or before this
|
|
462
|
+
* column existed) is then kept like any other native node instead of
|
|
463
|
+
* being pruned while it is still being reported.
|
|
464
|
+
*
|
|
465
|
+
* The mark itself is notReportingMarkedAt, refreshed at most once a
|
|
466
|
+
* minute while the node stays reported: the "marked recently" the
|
|
467
|
+
* reports of an Offline node rely on to carry on through a gap
|
|
468
|
+
* (ProxmoxNativeNodeLiveness). It is written as `markedAt`, on the
|
|
469
|
+
* caller's (the ingest worker's) clock — the clock it is later judged
|
|
470
|
+
* against — never the database's now(), and only here; the node's own
|
|
471
|
+
* next push clears it (bulkUpsert).
|
|
472
|
+
*/
|
|
473
|
+
@CaptureSpan()
|
|
474
|
+
public async markNodesNotReporting(data: {
|
|
475
|
+
projectId: ObjectID;
|
|
476
|
+
proxmoxClusterId: ObjectID;
|
|
477
|
+
nodeNames: Array<string>;
|
|
478
|
+
// The report's own time minus the silence window, on the PVE clock.
|
|
479
|
+
silentBefore: Date;
|
|
480
|
+
// Now, on the ingest worker's clock.
|
|
481
|
+
markedAt?: Date | undefined;
|
|
482
|
+
}): Promise<number> {
|
|
483
|
+
if (data.nodeNames.length === 0) {
|
|
484
|
+
return 0;
|
|
485
|
+
}
|
|
486
|
+
const markedAt: Date = data.markedAt || OneUptimeDate.getCurrentDate();
|
|
487
|
+
const externalIds: Array<string> = data.nodeNames.map(
|
|
488
|
+
(nodeName: string) => {
|
|
489
|
+
return truncateShortText(`${NODE_ID_PREFIX}${nodeName}`) as string;
|
|
490
|
+
},
|
|
491
|
+
);
|
|
492
|
+
|
|
493
|
+
const result: unknown = await this.getRepository().manager.query(
|
|
494
|
+
`UPDATE "ProxmoxResource"
|
|
495
|
+
SET "isUp" = false,
|
|
496
|
+
"uptimeSeconds" = NULL,
|
|
497
|
+
"isNativePush" = true,
|
|
498
|
+
"notReportingMarkedAt" = $5,
|
|
499
|
+
"updatedAt" = now()
|
|
500
|
+
WHERE "projectId" = $1 AND "proxmoxClusterId" = $2
|
|
501
|
+
AND "kind" = 'Node' AND "externalId" = ANY($3)
|
|
502
|
+
AND "deletedAt" IS NULL
|
|
503
|
+
AND "lastSeenAt" < $4
|
|
504
|
+
AND ("isUp" IS DISTINCT FROM false
|
|
505
|
+
OR "isNativePush" IS DISTINCT FROM true
|
|
506
|
+
OR "notReportingMarkedAt" IS NULL
|
|
507
|
+
OR "notReportingMarkedAt" < $6)`,
|
|
508
|
+
[
|
|
509
|
+
data.projectId.toString(),
|
|
510
|
+
data.proxmoxClusterId.toString(),
|
|
511
|
+
externalIds,
|
|
512
|
+
data.silentBefore,
|
|
513
|
+
markedAt,
|
|
514
|
+
OneUptimeDate.addRemoveSeconds(markedAt, -60),
|
|
515
|
+
],
|
|
516
|
+
);
|
|
517
|
+
|
|
518
|
+
// Postgres driver returns [rows, affected] for UPDATE — normalize.
|
|
519
|
+
if (Array.isArray(result) && typeof result[1] === "number") {
|
|
520
|
+
return result[1];
|
|
521
|
+
}
|
|
522
|
+
return 0;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
/**
|
|
526
|
+
* Take a cluster's Node rows into the native-push keep. Called when the
|
|
527
|
+
* cluster's native push is flushed (fenced by the caller): a node that
|
|
528
|
+
* was already down under the Proxmox Agent — or before isNativePush
|
|
529
|
+
* existed — never pushes itself, so without this its old row would be
|
|
530
|
+
* pruned in the two minutes before the live nodes first report it, and
|
|
531
|
+
* it would drop off the roster while still down. Only rows last seen no
|
|
532
|
+
* later than `seenUpTo` (the batch's newest observation) are taken: a
|
|
533
|
+
* native batch processed late, after the cluster moved back to the
|
|
534
|
+
* agent, must not take the agent's newer rows. It is not a report: the
|
|
535
|
+
* rows' notReportingMarkedAt is left alone. Returns the number of rows
|
|
536
|
+
* flagged.
|
|
537
|
+
*/
|
|
538
|
+
@CaptureSpan()
|
|
539
|
+
public async adoptNodesAsNativePush(data: {
|
|
540
|
+
projectId: ObjectID;
|
|
541
|
+
proxmoxClusterId: ObjectID;
|
|
542
|
+
seenUpTo: Date;
|
|
543
|
+
}): Promise<number> {
|
|
544
|
+
const result: unknown = await this.getRepository().manager.query(
|
|
545
|
+
`UPDATE "ProxmoxResource"
|
|
546
|
+
SET "isNativePush" = true
|
|
547
|
+
WHERE "projectId" = $1 AND "proxmoxClusterId" = $2
|
|
548
|
+
AND "kind" = 'Node' AND "deletedAt" IS NULL
|
|
549
|
+
AND "isNativePush" IS DISTINCT FROM true
|
|
550
|
+
AND "lastSeenAt" <= $3`,
|
|
551
|
+
[
|
|
552
|
+
data.projectId.toString(),
|
|
553
|
+
data.proxmoxClusterId.toString(),
|
|
554
|
+
data.seenUpTo,
|
|
555
|
+
],
|
|
556
|
+
);
|
|
557
|
+
|
|
558
|
+
// Postgres driver returns [rows, affected] for UPDATE — normalize.
|
|
559
|
+
if (Array.isArray(result) && typeof result[1] === "number") {
|
|
560
|
+
return result[1];
|
|
561
|
+
}
|
|
562
|
+
return 0;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
/**
|
|
566
|
+
* Remove a node that has stopped reporting — for a node taken out of
|
|
567
|
+
* the cluster for good, which OneUptime cannot tell apart from a dead
|
|
568
|
+
* one on the Proxmox VE native push. Its siblings stop reporting it
|
|
569
|
+
* within a minute and its Node Offline alert resolves. Only such a node
|
|
570
|
+
* is removed:
|
|
571
|
+
* - "not-found": no such node in this cluster;
|
|
572
|
+
* - "not-native": an agent node — the agent lets a node go on its own
|
|
573
|
+
* once the cluster no longer lists it, and would re-create a node
|
|
574
|
+
* it still lists on the next scrape;
|
|
575
|
+
* - "still-reporting": the node is up; it would reappear on its next
|
|
576
|
+
* push.
|
|
577
|
+
*/
|
|
578
|
+
@CaptureSpan()
|
|
579
|
+
public async removeOfflineNode(data: {
|
|
580
|
+
projectId: ObjectID;
|
|
581
|
+
proxmoxClusterId: ObjectID;
|
|
582
|
+
externalId: string;
|
|
583
|
+
}): Promise<ProxmoxRemoveNodeResult> {
|
|
584
|
+
if (!data.externalId.startsWith(NODE_ID_PREFIX)) {
|
|
585
|
+
return "not-found";
|
|
586
|
+
}
|
|
587
|
+
// Clamped the way bulkUpsert stored it.
|
|
588
|
+
const params: Array<string> = [
|
|
589
|
+
data.projectId.toString(),
|
|
590
|
+
data.proxmoxClusterId.toString(),
|
|
591
|
+
truncateShortText(data.externalId) as string,
|
|
592
|
+
];
|
|
593
|
+
|
|
594
|
+
const result: unknown = await this.getRepository().manager.query(
|
|
595
|
+
`DELETE FROM "ProxmoxResource"
|
|
596
|
+
WHERE "projectId" = $1 AND "proxmoxClusterId" = $2
|
|
597
|
+
AND "kind" = 'Node' AND "externalId" = $3
|
|
598
|
+
AND "deletedAt" IS NULL
|
|
599
|
+
AND "isUp" IS FALSE AND "isNativePush" IS TRUE`,
|
|
600
|
+
params,
|
|
601
|
+
);
|
|
602
|
+
|
|
603
|
+
// Postgres driver returns [rows, affected] for DELETE — normalize.
|
|
604
|
+
if (
|
|
605
|
+
Array.isArray(result) &&
|
|
606
|
+
typeof result[1] === "number" &&
|
|
607
|
+
result[1] > 0
|
|
608
|
+
) {
|
|
609
|
+
return "removed";
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
// Not deleted: say why, so the caller can answer precisely.
|
|
613
|
+
const rows: Array<{ isUp: boolean | null; isNativePush: boolean | null }> =
|
|
614
|
+
await this.getRepository().manager.query(
|
|
615
|
+
`SELECT "isUp", "isNativePush" FROM "ProxmoxResource"
|
|
616
|
+
WHERE "projectId" = $1 AND "proxmoxClusterId" = $2
|
|
617
|
+
AND "kind" = 'Node' AND "externalId" = $3
|
|
618
|
+
AND "deletedAt" IS NULL`,
|
|
619
|
+
params,
|
|
620
|
+
);
|
|
621
|
+
const row:
|
|
622
|
+
| { isUp: boolean | null; isNativePush: boolean | null }
|
|
623
|
+
| undefined = rows[0];
|
|
624
|
+
if (!row) {
|
|
625
|
+
return "not-found";
|
|
626
|
+
}
|
|
627
|
+
if (row.isNativePush !== true) {
|
|
628
|
+
return "not-native";
|
|
629
|
+
}
|
|
630
|
+
return "still-reporting";
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
/**
|
|
634
|
+
* The oldest last report a native-push node may have and still be kept
|
|
635
|
+
* and reported: now minus getSilentNodeRetentionHours().
|
|
636
|
+
*/
|
|
637
|
+
public getSilentNodeRetentionCutoff(now?: Date | undefined): Date {
|
|
638
|
+
return OneUptimeDate.addRemoveHours(
|
|
639
|
+
now || OneUptimeDate.getCurrentDate(),
|
|
640
|
+
-this.getSilentNodeRetentionHours(),
|
|
641
|
+
);
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
/**
|
|
645
|
+
* How long a node that stopped reporting is still reported (and kept
|
|
646
|
+
* as Offline) before it is treated as gone. 7 days by default — long
|
|
647
|
+
* enough to outlast a weekend, short enough that a node removed from
|
|
648
|
+
* the cluster without using "Remove Node" eventually lets go. Tune via
|
|
649
|
+
* PVE_SILENT_NODE_RETENTION_HOURS (min 1).
|
|
650
|
+
*/
|
|
651
|
+
public getSilentNodeRetentionHours(): number {
|
|
652
|
+
const raw: string | undefined =
|
|
653
|
+
process.env["PVE_SILENT_NODE_RETENTION_HOURS"];
|
|
654
|
+
if (raw) {
|
|
655
|
+
const parsed: number = parseInt(raw, 10);
|
|
656
|
+
if (!isNaN(parsed) && parsed >= 1) {
|
|
657
|
+
return parsed;
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
return 7 * 24;
|
|
661
|
+
}
|
|
662
|
+
|
|
346
663
|
/**
|
|
347
664
|
* Compute the sidebar/overview summary in Postgres: counts per kind
|
|
348
665
|
* plus the online/running breakdowns, in a single round-trip.
|