@oneuptime/common 14.0.7 → 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/Incident.ts +267 -1
- package/Models/DatabaseModels/IncidentCustomField.ts +202 -0
- package/Models/DatabaseModels/IncidentEpisode.ts +30 -0
- package/Models/DatabaseModels/IncidentTemplate.ts +126 -1
- 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/StatusPage.ts +55 -0
- package/Models/DatabaseModels/StatusPageSubscriber.ts +128 -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/IncidentAPI.ts +162 -0
- package/Server/API/KubernetesClusterAiAccessAPI.ts +623 -21
- package/Server/API/MicrosoftTeamsAPI.ts +93 -14
- package/Server/API/ProxmoxResourceAPI.ts +244 -14
- package/Server/API/StatusPageAPI.ts +487 -171
- package/Server/API/StatusPageSubscriberAPI.ts +63 -15
- package/Server/Infrastructure/GlobalCache.ts +32 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1795300000000-SkipHiddenIncidentCreatedNotifications.ts +49 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1795400000000-AddIncidentStatusPageScope.ts +108 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1795500000000-AddIncidentTemplateStatusPageScopeFlag.ts +33 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1795600000000-AddStatusPageSubscriberUnsubscribeToken.ts +51 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1795700000000-AddStatusPageSubscriberIsAddedByTeam.ts +33 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1795800000000-AddIncidentCustomFieldCreateAndNotificationSettings.ts +168 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1795900000000-AddSubscriberNotificationClaimedAt.ts +44 -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 +20 -0
- package/Server/Infrastructure/Semaphore.ts +10 -0
- package/Server/Middleware/IdentityRateLimit.ts +108 -3
- package/Server/Middleware/SubscriberNotificationPreviewRateLimit.ts +237 -0
- package/Server/Middleware/SubscriberNotificationTestSendRateLimit.ts +304 -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/DatabaseService.ts +93 -10
- package/Server/Services/IncidentCustomFieldService.ts +276 -1
- package/Server/Services/IncidentEpisodePublicNoteService.ts +28 -0
- package/Server/Services/IncidentEpisodeService.ts +15 -0
- package/Server/Services/IncidentEpisodeStateTimelineService.ts +27 -1
- package/Server/Services/IncidentPublicNoteService.ts +30 -1
- package/Server/Services/IncidentService.ts +1788 -142
- package/Server/Services/IncidentSeverityService.ts +66 -15
- package/Server/Services/IncidentStateTimelineService.ts +13 -0
- package/Server/Services/IncidentTemplateService.ts +109 -0
- 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/ScheduledMaintenancePublicNoteService.ts +30 -1
- package/Server/Services/ScheduledMaintenanceService.ts +805 -19
- package/Server/Services/ScheduledMaintenanceStateTimelineService.ts +414 -56
- package/Server/Services/SmsService.ts +10 -0
- package/Server/Services/StatusPageService.ts +65 -8
- package/Server/Services/StatusPageSubscriberNotificationTemplateService.ts +299 -37
- package/Server/Services/StatusPageSubscriberNotificationTemplateStatusPageService.ts +129 -0
- package/Server/Services/StatusPageSubscriberService.ts +1161 -64
- package/Server/Services/TeamComplianceSettingService.ts +1125 -9
- package/Server/Types/Markdown.ts +153 -6
- package/Server/Types/Workflow/Components/Email.ts +61 -2
- 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/CustomField/CustomFieldRename.ts +378 -0
- package/Server/Utils/DataSource/EgressGuard.ts +66 -21
- package/Server/Utils/Mail/PinnedSmtpSocket.ts +130 -0
- package/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.ts +10 -0
- package/Server/Utils/SSRFProtection.ts +76 -16
- package/Server/Utils/StatusPage/IncidentStatusPageScope.ts +948 -0
- package/Server/Utils/StatusPage/IncidentSubscriberAudienceBuilder.ts +656 -0
- package/Server/Utils/StatusPage/IncidentTemplateVariableBuilder.ts +805 -0
- package/Server/Utils/StatusPage/StatusPageExclusion.ts +18 -0
- package/Server/Utils/StatusPage/StatusPageReadAccess.ts +125 -0
- package/Server/Utils/StatusPage/StatusPageSubscriberUnsubscribeNotice.ts +151 -0
- package/Server/Utils/StatusPage/StatusPageSubscriberUnsubscribeToken.ts +70 -0
- package/Server/Utils/StatusPage/SubscriberIncidentEmailBuilder.ts +421 -0
- package/Server/Utils/StatusPage/SubscriberNotificationClaim.ts +107 -0
- package/Server/Utils/StatusPage/SubscriberNotificationDeliveryRecord.ts +1049 -0
- package/Server/Utils/StatusPage/SubscriberNotificationFanOut.ts +180 -0
- package/Server/Utils/StatusPage/SubscriberNotificationPreviewBuilder.ts +839 -0
- package/Server/Utils/StatusPage/SubscriberNotificationResendAccess.ts +393 -0
- package/Server/Utils/StatusPage/SubscriberNotificationRunLimit.ts +246 -0
- package/Server/Utils/StatusPage/SubscriberNotificationTiming.ts +133 -0
- package/Server/Utils/StatusPage/SubscriberTemplateIncidentRecordAccess.ts +215 -0
- package/Server/Utils/StatusPageResource.ts +51 -20
- 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/VM/VMAPI.ts +1 -0
- package/Server/Utils/VM/VMRunner.ts +10 -0
- package/Server/Utils/Workflow/OAuth2TokenClient.ts +10 -0
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +684 -47
- package/Server/Views/Partials/SensitiveUrlToken.ejs +8 -5
- package/Tests/App/Accounts/RegisterVerifyEmail.test.tsx +748 -0
- package/Tests/App/Accounts/ResendVerificationEmail.test.tsx +1222 -0
- package/Tests/App/Accounts/VerificationEmailResendUtils.test.ts +797 -0
- package/Tests/App/Accounts/VerifyEmailPending.test.tsx +538 -0
- package/Tests/App/Accounts/VerifyEmailResend.test.tsx +779 -0
- 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/CustomFieldsSettingsIncidentOptions.test.tsx +357 -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 +778 -2
- package/Tests/App/Dashboard/EventNotesPages.test.tsx +119 -0
- package/Tests/App/Dashboard/EventNotesUtil.test.ts +116 -17
- package/Tests/App/Dashboard/EventOverviewPages.test.tsx +828 -17
- 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/IncidentChangeStateNotifyDefault.test.tsx +91 -1
- package/Tests/App/Dashboard/IncidentCreateDetailsStep.test.tsx +643 -0
- package/Tests/App/Dashboard/IncidentCreateFromAlerts.test.tsx +8 -1
- package/Tests/App/Dashboard/IncidentCreateStatusPageScope.test.tsx +601 -0
- package/Tests/App/Dashboard/IncidentCustomFieldTemplateVariables.test.tsx +386 -0
- package/Tests/App/Dashboard/IncidentNoteTemplatePlaceholders.test.tsx +124 -0
- package/Tests/App/Dashboard/IncidentNoteTemplateVariablesLoader.test.ts +305 -0
- package/Tests/App/Dashboard/IncidentOverviewNotifyDefault.test.tsx +112 -0
- package/Tests/App/Dashboard/IncidentRootCauseTimeRangeZoom.test.tsx +358 -0
- package/Tests/App/Dashboard/IncidentSettingsRenotifyOnPublish.test.tsx +674 -0
- package/Tests/App/Dashboard/IncidentSettingsStatusPageScope.test.tsx +1051 -0
- package/Tests/App/Dashboard/IncidentTemplateCustomFields.test.tsx +384 -0
- package/Tests/App/Dashboard/IncidentTemplateStatusPageScopeCard.test.tsx +215 -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/PublicNotePagesNotifyDefault.test.tsx +113 -1
- 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/SubscriberAudienceSummary.test.tsx +512 -0
- package/Tests/App/Dashboard/SubscriberNotificationPreviewModal.test.tsx +837 -0
- package/Tests/App/Dashboard/SubscriberNotificationStatusLabel.test.tsx +88 -0
- package/Tests/App/Dashboard/SubscriberNotificationStatusResend.test.tsx +473 -0
- package/Tests/App/Dashboard/SubscriberTemplateLivePreview.test.tsx +196 -0
- package/Tests/App/Dashboard/TeamAddedSubscribersUnsubscribedNotice.test.tsx +248 -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/SensitiveUrlTokenBootstrap.test.ts +64 -3
- package/Tests/App/StatusPage/StatusPageResourceExplorer.test.tsx +98 -0
- package/Tests/App/StatusPage/StatusPageUnsubscribePage.test.tsx +412 -0
- package/Tests/Models/DatabaseModels/KubernetesAiAgentModel.test.ts +295 -0
- package/Tests/Models/DatabaseModels/TeamComplianceSettingModel.test.ts +347 -0
- package/Tests/Models/IncidentCustomFieldApiSchemaContract.test.ts +217 -0
- package/Tests/Models/IncidentCustomFieldCreateSettingsColumns.test.ts +252 -0
- package/Tests/Models/StatusPageSubscriberUnsubscribeColumns.test.ts +218 -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/ExpiredSessionRouteGuards.test.ts +7 -0
- package/Tests/Server/API/IncidentSubscriberAudienceAPI.test.ts +1408 -0
- 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/API/StatusPageIncidentScope.test.ts +1868 -0
- package/Tests/Server/API/StatusPageIncidentScopePostgres.test.ts +790 -0
- package/Tests/Server/API/StatusPageManageSubscriptionRecipient.test.ts +10 -1
- package/Tests/Server/API/StatusPageManageSubscriptionTemplateVariables.test.ts +206 -18
- package/Tests/Server/API/StatusPagePostmortemVisibility.test.ts +14 -2
- package/Tests/Server/API/StatusPageSubscriberCreateResponse.test.ts +217 -0
- package/Tests/Server/API/StatusPageSubscriberOwnership.test.ts +103 -2
- package/Tests/Server/API/StatusPageUnsubscribeAPI.test.ts +396 -0
- package/Tests/Server/Infrastructure/GlobalCache.test.ts +195 -0
- package/Tests/Server/Infrastructure/Postgres/AddIncidentStatusPageScopeMigration.test.ts +395 -0
- package/Tests/Server/Infrastructure/Postgres/AddIncidentTemplateStatusPageScopeFlagMigration.test.ts +150 -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/AddSubscriberNotificationClaimedAtMigration.test.ts +156 -0
- package/Tests/Server/Infrastructure/Postgres/AddTeamComplianceRuleScopeMigration.test.ts +622 -0
- package/Tests/Server/Infrastructure/Postgres/SkipHiddenIncidentCreatedNotificationsMigration.test.ts +410 -0
- package/Tests/Server/Middleware/IdentityRateLimit.test.ts +551 -1
- package/Tests/Server/Middleware/SubscriberNotificationPreviewRateLimit.test.ts +238 -0
- package/Tests/Server/Middleware/SubscriberNotificationTestSendRateLimit.test.ts +245 -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/AddStatusPageSubscriberUnsubscribeTokenMigration.test.ts +152 -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/CrossProjectRelationWriteGuard.test.ts +221 -36
- package/Tests/Server/Services/DatabaseServiceCompareAndSetColumns.test.ts +191 -0
- package/Tests/Server/Services/IncidentAffectedMonitorsEdit.test.ts +1360 -0
- package/Tests/Server/Services/IncidentAlertSloLinkSurvivesEdit.test.ts +3 -1
- package/Tests/Server/Services/IncidentCreatedRenotifyOnPublish.test.ts +681 -0
- package/Tests/Server/Services/IncidentCreatedResend.test.ts +775 -0
- package/Tests/Server/Services/IncidentCustomFieldRenamePostgres.test.ts +713 -0
- package/Tests/Server/Services/IncidentCustomFieldService.test.ts +751 -0
- package/Tests/Server/Services/IncidentCustomFieldValueValidation.test.ts +556 -0
- package/Tests/Server/Services/IncidentSeverityDeletePausesComplianceRules.test.ts +488 -0
- package/Tests/Server/Services/IncidentStatusPageScope.test.ts +2971 -0
- package/Tests/Server/Services/IncidentStatusPageScopeFeed.test.ts +131 -0
- package/Tests/Server/Services/IncidentStatusPageScopePostgres.test.ts +625 -0
- package/Tests/Server/Services/IncidentTemplateCustomFieldsCopy.test.ts +311 -0
- package/Tests/Server/Services/IncidentTemplateStatusPageScope.test.ts +363 -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/PublicNoteEditFeedEventType.test.ts +213 -0
- package/Tests/Server/Services/PublicNoteResendAccess.test.ts +994 -0
- 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/ScheduledMaintenanceSubscriberTemplateFormats.test.ts +289 -9
- package/Tests/Server/Services/SmsServiceFailIfNotSent.test.ts +67 -0
- package/Tests/Server/Services/StatusPageReportIncidentCounts.test.ts +610 -0
- package/Tests/Server/Services/StatusPageSubscriberAudienceCounts.test.ts +201 -0
- package/Tests/Server/Services/StatusPageSubscriberAudienceCountsPostgres.test.ts +271 -0
- package/Tests/Server/Services/StatusPageSubscriberConfirmationTemplateEscaping.test.ts +200 -0
- package/Tests/Server/Services/StatusPageSubscriberNotificationLogRedaction.test.ts +54 -0
- package/Tests/Server/Services/StatusPageSubscriberNotificationTemplateCompile.test.ts +37 -0
- package/Tests/Server/Services/StatusPageSubscriberNotificationTemplateIncidentRecordAccess.test.ts +772 -0
- package/Tests/Server/Services/StatusPageSubscriberNotificationTemplateLookup.test.ts +506 -0
- package/Tests/Server/Services/StatusPageSubscriberNotificationTemplateLookupPostgres.test.ts +261 -0
- package/Tests/Server/Services/StatusPageSubscriberReport.test.ts +21 -5
- package/Tests/Server/Services/StatusPageSubscriberUnsubscribe.test.ts +1618 -0
- package/Tests/Server/Services/StatusPageSubscriberUnsubscribeLinkSenders.test.ts +373 -0
- package/Tests/Server/Services/StatusPageSubscriberUnsubscribePostgres.test.ts +388 -0
- package/Tests/Server/Services/SubscriberNotificationInFlightRequeue.test.ts +500 -0
- package/Tests/Server/Services/TeamComplianceSettingPostgres.test.ts +2237 -0
- package/Tests/Server/Services/TeamComplianceSettingService.test.ts +3988 -138
- package/Tests/Server/Types/MarkdownEmailLinks.test.ts +320 -0
- package/Tests/Server/Types/Workflow/Components/Email.test.ts +491 -1
- package/Tests/Server/Types/Workflow/Components/EmailSmtpPinning.test.ts +398 -0
- 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/CustomField/CustomFieldRename.test.ts +586 -0
- package/Tests/Server/Utils/DataSource/EgressGuard.test.ts +246 -10
- package/Tests/Server/Utils/DataSource/EgressGuardDeploymentConfig.test.ts +226 -0
- package/Tests/Server/Utils/DataSource/EgressGuardPinning.test.ts +131 -0
- package/Tests/Server/Utils/DataSource/HttpFetch.test.ts +4 -0
- package/Tests/Server/Utils/EgressPolicyEnvironment.ts +45 -0
- package/Tests/Server/Utils/Mail/PinnedSmtpSocket.test.ts +409 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaObservationBuilderUnits.test.ts +23 -0
- package/Tests/Server/Utils/SSRFProtection.test.ts +4 -0
- package/Tests/Server/Utils/SSRFProtectionCloudServiceAddresses.test.ts +4 -0
- package/Tests/Server/Utils/SSRFProtectionPrivateNetwork.test.ts +4 -0
- package/Tests/Server/Utils/SSRFProtectionResolutionDetail.test.ts +314 -0
- package/Tests/Server/Utils/StatusPage/IncidentStatusPageScope.test.ts +1699 -0
- package/Tests/Server/Utils/StatusPage/IncidentStatusPageScopeQueriesPostgres.test.ts +508 -0
- package/Tests/Server/Utils/StatusPage/IncidentSubscriberAudienceCallerPermission.test.ts +246 -0
- package/Tests/Server/Utils/StatusPage/IncidentTemplateVariableBuilder.test.ts +1348 -0
- package/Tests/Server/Utils/StatusPage/StatusPageReadAccess.test.ts +221 -0
- package/Tests/Server/Utils/StatusPage/StatusPageSubscriberUnsubscribeNotice.test.ts +132 -0
- package/Tests/Server/Utils/StatusPage/StatusPageSubscriberUnsubscribeToken.test.ts +155 -0
- package/Tests/Server/Utils/StatusPage/SubscriberIncidentEmailBuilder.test.ts +708 -0
- package/Tests/Server/Utils/StatusPage/SubscriberNotificationClaim.test.ts +255 -0
- package/Tests/Server/Utils/StatusPage/SubscriberNotificationClaimPostgres.test.ts +528 -0
- package/Tests/Server/Utils/StatusPage/SubscriberNotificationDeliveryRecord.test.ts +1238 -0
- package/Tests/Server/Utils/StatusPage/SubscriberNotificationFanOut.test.ts +472 -0
- package/Tests/Server/Utils/StatusPage/SubscriberNotificationPreviewBuilder.test.ts +1168 -0
- package/Tests/Server/Utils/StatusPage/SubscriberNotificationRunLimit.test.ts +275 -0
- package/Tests/Server/Utils/StatusPage/SubscriberNotificationTiming.test.ts +131 -0
- package/Tests/Server/Utils/StatusPageResource.test.ts +98 -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/VM/VMRunnerPrivateNetworkWiring.test.ts +17 -0
- package/Tests/Server/Utils/VM/VMRunnerSsrf.test.ts +75 -0
- 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/CustomField/CustomFieldSavedViews.test.ts +247 -0
- package/Tests/Types/CustomField/CustomFieldTemplateValues.test.ts +186 -0
- package/Tests/Types/CustomField/CustomFieldTypeCorrespondence.test.ts +48 -0
- package/Tests/Types/CustomField/CustomFieldValueFormat.test.ts +215 -0
- package/Tests/Types/CustomField/CustomFieldValueValidator.test.ts +343 -0
- package/Tests/Types/CustomField/CustomFieldVariableKey.test.ts +364 -0
- package/Tests/Types/Kubernetes/KubernetesAgentChartAiAccess.test.ts +581 -113
- package/Tests/Types/Kubernetes/KubernetesAiAgentAccessContract.test.ts +510 -0
- package/Tests/Types/SafeHtml.test.ts +102 -0
- package/Tests/Types/StatusPage/IncidentCreatedRenotify.test.ts +419 -0
- package/Tests/Types/StatusPage/IncidentCreatedResend.test.ts +118 -0
- package/Tests/Types/StatusPage/IncidentScopeAddedPagesNotification.test.ts +558 -0
- package/Tests/Types/StatusPage/IncidentSubscriberAudience.test.ts +284 -0
- package/Tests/Types/StatusPage/StatusPageSubscriberUnsubscribe.test.ts +341 -0
- package/Tests/Types/StatusPage/SubscriberNotificationPreview.test.ts +196 -0
- package/Tests/Types/StatusPage/SubscriberNotificationResend.test.ts +201 -0
- package/Tests/Types/StatusPage/SubscriberNotificationTemplateCompiler.test.ts +277 -0
- package/Tests/Types/StatusPage/SubscriberNotificationTemplatePreview.test.ts +179 -0
- package/Tests/Types/StatusPage/SubscriberNotificationTemplateVariables.test.ts +324 -0
- package/Tests/Types/StatusPage/SubscriberUpdateNotification.test.ts +60 -13
- 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/CustomFields/CustomFieldFormFields.test.ts +432 -0
- package/Tests/UI/Components/CustomFields/CustomFieldModelFormFields.test.tsx +685 -0
- package/Tests/UI/Components/CustomFields/CustomFieldsDetailOrder.test.tsx +469 -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/Forms/ModelFormCustomFieldInputs.test.tsx +325 -0
- package/Tests/UI/Components/Forms/ModelFormDropdownOptionsRefused.test.tsx +358 -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/CustomFieldColumns.test.tsx +22 -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/Monitor/NetworkPathView.test.tsx +289 -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/Tests/Utils/Incident/IncidentNoteTemplateVariables.test.ts +623 -0
- package/Tests/Utils/Markdown/MarkdownEscape.test.ts +89 -0
- package/Tests/Utils/ProbeNetworkFailureUtil.test.ts +992 -0
- package/Tests/Utils/RequestFailedDetails.test.ts +575 -0
- 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/CustomField/CustomFieldOrder.ts +55 -0
- package/Types/CustomField/CustomFieldSavedViews.ts +225 -0
- package/Types/CustomField/CustomFieldTemplateMerge.ts +71 -0
- package/Types/CustomField/CustomFieldType.ts +14 -0
- package/Types/CustomField/CustomFieldValueFormat.ts +161 -0
- package/Types/CustomField/CustomFieldValueValidator.ts +488 -0
- package/Types/CustomField/CustomFieldVariableKey.ts +211 -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/SafeHtml.ts +93 -0
- package/Types/StatusPage/IncidentCreatedRenotify.ts +224 -0
- package/Types/StatusPage/IncidentCreatedResend.ts +108 -0
- package/Types/StatusPage/IncidentScopeAddedPagesNotification.ts +343 -0
- package/Types/StatusPage/IncidentSubscriberAudience.ts +332 -0
- package/Types/StatusPage/StatusPageSubscriberUnsubscribe.ts +405 -0
- package/Types/StatusPage/SubscriberNotificationInterruption.ts +32 -0
- package/Types/StatusPage/SubscriberNotificationPreview.ts +322 -0
- package/Types/StatusPage/SubscriberNotificationResend.ts +132 -0
- package/Types/StatusPage/SubscriberNotificationTemplateCompiler.ts +180 -0
- package/Types/StatusPage/SubscriberNotificationTemplatePreview.ts +301 -0
- package/Types/StatusPage/SubscriberNotificationTemplateVariables.ts +217 -4
- package/Types/StatusPage/SubscriberUpdateNotification.ts +32 -11
- 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/CustomFields/CustomFieldFormFields.ts +317 -0
- package/UI/Components/CustomFields/CustomFieldModelFormFields.tsx +395 -0
- package/UI/Components/CustomFields/CustomFieldsDetail.tsx +95 -55
- package/UI/Components/EntityDropdown/EntityDropdown.tsx +107 -11
- package/UI/Components/Forms/Fields/FormField.tsx +10 -0
- package/UI/Components/Forms/ModelForm.tsx +70 -8
- package/UI/Components/Forms/Validation.ts +1 -1
- 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/ModelFormModal/ModelFormModal.tsx +2 -4
- package/UI/Components/ModelTable/AnalyticsModelTable.tsx +2 -6
- package/UI/Components/ModelTable/BaseModelTable.tsx +21 -9
- package/UI/Components/ModelTable/CustomFieldColumns.tsx +14 -1
- package/UI/Components/ModelTable/ModelTable.tsx +6 -7
- 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/UI/Utils/SensitiveUrlToken.ts +10 -5
- package/Utils/API.ts +247 -2
- package/Utils/AiRemediation/CommandPolicy.ts +1 -1
- package/Utils/AiRemediation/KubectlPolicy.ts +1 -1
- package/Utils/Dashboard/DashboardTimeRangeZoom.ts +46 -2
- package/Utils/Incident/IncidentNoteTemplateVariables.ts +304 -0
- package/Utils/Markdown/MarkdownEscape.ts +65 -0
- package/Utils/ProbeNetworkFailureUtil.ts +673 -0
- package/build/dist/Models/DatabaseModels/Incident.js +267 -1
- package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentCustomField.js +207 -1
- package/build/dist/Models/DatabaseModels/IncidentCustomField.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentEpisode.js +31 -0
- package/build/dist/Models/DatabaseModels/IncidentEpisode.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentTemplate.js +124 -1
- package/build/dist/Models/DatabaseModels/IncidentTemplate.js.map +1 -1
- 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/StatusPage.js +56 -0
- package/build/dist/Models/DatabaseModels/StatusPage.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageSubscriber.js +131 -0
- package/build/dist/Models/DatabaseModels/StatusPageSubscriber.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/IncidentAPI.js +100 -1
- package/build/dist/Server/API/IncidentAPI.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/API/StatusPageAPI.js +417 -176
- package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
- package/build/dist/Server/API/StatusPageSubscriberAPI.js +52 -13
- package/build/dist/Server/API/StatusPageSubscriberAPI.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/1795300000000-SkipHiddenIncidentCreatedNotifications.js +41 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795300000000-SkipHiddenIncidentCreatedNotifications.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795400000000-AddIncidentStatusPageScope.js +57 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795400000000-AddIncidentStatusPageScope.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795500000000-AddIncidentTemplateStatusPageScopeFlag.js +23 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795500000000-AddIncidentTemplateStatusPageScopeFlag.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795600000000-AddStatusPageSubscriberUnsubscribeToken.js +40 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795600000000-AddStatusPageSubscriberUnsubscribeToken.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795700000000-AddStatusPageSubscriberIsAddedByTeam.js +26 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795700000000-AddStatusPageSubscriberIsAddedByTeam.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795800000000-AddIncidentCustomFieldCreateAndNotificationSettings.js +89 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795800000000-AddIncidentCustomFieldCreateAndNotificationSettings.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795900000000-AddSubscriberNotificationClaimedAt.js +29 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795900000000-AddSubscriberNotificationClaimedAt.js.map +1 -0
- 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 +20 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Infrastructure/Semaphore.js +3 -0
- package/build/dist/Server/Infrastructure/Semaphore.js.map +1 -1
- package/build/dist/Server/Middleware/IdentityRateLimit.js +89 -3
- package/build/dist/Server/Middleware/IdentityRateLimit.js.map +1 -1
- package/build/dist/Server/Middleware/SubscriberNotificationPreviewRateLimit.js +149 -0
- package/build/dist/Server/Middleware/SubscriberNotificationPreviewRateLimit.js.map +1 -0
- package/build/dist/Server/Middleware/SubscriberNotificationTestSendRateLimit.js +190 -0
- package/build/dist/Server/Middleware/SubscriberNotificationTestSendRateLimit.js.map +1 -0
- 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/DatabaseService.js +56 -7
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/IncidentCustomFieldService.js +204 -8
- package/build/dist/Server/Services/IncidentCustomFieldService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodePublicNoteService.js +24 -0
- package/build/dist/Server/Services/IncidentEpisodePublicNoteService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodeService.js +14 -0
- package/build/dist/Server/Services/IncidentEpisodeService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodeStateTimelineService.js +26 -0
- package/build/dist/Server/Services/IncidentEpisodeStateTimelineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentPublicNoteService.js +26 -1
- package/build/dist/Server/Services/IncidentPublicNoteService.js.map +1 -1
- package/build/dist/Server/Services/IncidentService.js +1251 -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/IncidentStateTimelineService.js +12 -0
- package/build/dist/Server/Services/IncidentStateTimelineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentTemplateService.js +83 -0
- package/build/dist/Server/Services/IncidentTemplateService.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/ScheduledMaintenancePublicNoteService.js +26 -1
- package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceService.js +582 -20
- 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/SmsService.js +2 -22
- package/build/dist/Server/Services/SmsService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageService.js +47 -9
- package/build/dist/Server/Services/StatusPageService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageSubscriberNotificationTemplateService.js +237 -32
- package/build/dist/Server/Services/StatusPageSubscriberNotificationTemplateService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageSubscriberNotificationTemplateStatusPageService.js +109 -0
- package/build/dist/Server/Services/StatusPageSubscriberNotificationTemplateStatusPageService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageSubscriberService.js +925 -99
- package/build/dist/Server/Services/StatusPageSubscriberService.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/Types/Markdown.js +110 -6
- package/build/dist/Server/Types/Markdown.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/Email.js +55 -6
- package/build/dist/Server/Types/Workflow/Components/Email.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/CustomField/CustomFieldRename.js +211 -0
- package/build/dist/Server/Utils/CustomField/CustomFieldRename.js.map +1 -0
- package/build/dist/Server/Utils/DataSource/EgressGuard.js +41 -12
- package/build/dist/Server/Utils/DataSource/EgressGuard.js.map +1 -1
- package/build/dist/Server/Utils/Mail/PinnedSmtpSocket.js +101 -0
- package/build/dist/Server/Utils/Mail/PinnedSmtpSocket.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js +9 -0
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js.map +1 -1
- package/build/dist/Server/Utils/SSRFProtection.js +48 -6
- package/build/dist/Server/Utils/SSRFProtection.js.map +1 -1
- package/build/dist/Server/Utils/StatusPage/IncidentStatusPageScope.js +631 -0
- package/build/dist/Server/Utils/StatusPage/IncidentStatusPageScope.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/IncidentSubscriberAudienceBuilder.js +403 -0
- package/build/dist/Server/Utils/StatusPage/IncidentSubscriberAudienceBuilder.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/IncidentTemplateVariableBuilder.js +451 -0
- package/build/dist/Server/Utils/StatusPage/IncidentTemplateVariableBuilder.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/StatusPageExclusion.js +13 -0
- package/build/dist/Server/Utils/StatusPage/StatusPageExclusion.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/StatusPageReadAccess.js +91 -0
- package/build/dist/Server/Utils/StatusPage/StatusPageReadAccess.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/StatusPageSubscriberUnsubscribeNotice.js +101 -0
- package/build/dist/Server/Utils/StatusPage/StatusPageSubscriberUnsubscribeNotice.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/StatusPageSubscriberUnsubscribeToken.js +47 -0
- package/build/dist/Server/Utils/StatusPage/StatusPageSubscriberUnsubscribeToken.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberIncidentEmailBuilder.js +273 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberIncidentEmailBuilder.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationClaim.js +73 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationClaim.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationDeliveryRecord.js +722 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationDeliveryRecord.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationFanOut.js +102 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationFanOut.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationPreviewBuilder.js +527 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationPreviewBuilder.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationResendAccess.js +278 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationResendAccess.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationRunLimit.js +137 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationRunLimit.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationTiming.js +103 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationTiming.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberTemplateIncidentRecordAccess.js +114 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberTemplateIncidentRecordAccess.js.map +1 -0
- package/build/dist/Server/Utils/StatusPageResource.js +39 -7
- package/build/dist/Server/Utils/StatusPageResource.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/VM/VMAPI.js.map +1 -1
- package/build/dist/Server/Utils/VM/VMRunner.js +1 -0
- package/build/dist/Server/Utils/VM/VMRunner.js.map +1 -1
- package/build/dist/Server/Utils/Workflow/OAuth2TokenClient.js +3 -0
- package/build/dist/Server/Utils/Workflow/OAuth2TokenClient.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/CustomField/CustomFieldOrder.js +36 -0
- package/build/dist/Types/CustomField/CustomFieldOrder.js.map +1 -0
- package/build/dist/Types/CustomField/CustomFieldSavedViews.js +135 -0
- package/build/dist/Types/CustomField/CustomFieldSavedViews.js.map +1 -0
- package/build/dist/Types/CustomField/CustomFieldTemplateMerge.js +27 -0
- package/build/dist/Types/CustomField/CustomFieldTemplateMerge.js.map +1 -0
- package/build/dist/Types/CustomField/CustomFieldType.js +12 -0
- package/build/dist/Types/CustomField/CustomFieldType.js.map +1 -1
- package/build/dist/Types/CustomField/CustomFieldValueFormat.js +126 -0
- package/build/dist/Types/CustomField/CustomFieldValueFormat.js.map +1 -0
- package/build/dist/Types/CustomField/CustomFieldValueValidator.js +280 -0
- package/build/dist/Types/CustomField/CustomFieldValueValidator.js.map +1 -0
- package/build/dist/Types/CustomField/CustomFieldVariableKey.js +150 -0
- package/build/dist/Types/CustomField/CustomFieldVariableKey.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/SafeHtml.js +84 -0
- package/build/dist/Types/SafeHtml.js.map +1 -0
- package/build/dist/Types/StatusPage/IncidentCreatedRenotify.js +117 -0
- package/build/dist/Types/StatusPage/IncidentCreatedRenotify.js.map +1 -0
- package/build/dist/Types/StatusPage/IncidentCreatedResend.js +86 -0
- package/build/dist/Types/StatusPage/IncidentCreatedResend.js.map +1 -0
- package/build/dist/Types/StatusPage/IncidentScopeAddedPagesNotification.js +246 -0
- package/build/dist/Types/StatusPage/IncidentScopeAddedPagesNotification.js.map +1 -0
- package/build/dist/Types/StatusPage/IncidentSubscriberAudience.js +183 -0
- package/build/dist/Types/StatusPage/IncidentSubscriberAudience.js.map +1 -0
- package/build/dist/Types/StatusPage/StatusPageSubscriberUnsubscribe.js +277 -0
- package/build/dist/Types/StatusPage/StatusPageSubscriberUnsubscribe.js.map +1 -0
- package/build/dist/Types/StatusPage/SubscriberNotificationInterruption.js +27 -0
- package/build/dist/Types/StatusPage/SubscriberNotificationInterruption.js.map +1 -0
- package/build/dist/Types/StatusPage/SubscriberNotificationPreview.js +190 -0
- package/build/dist/Types/StatusPage/SubscriberNotificationPreview.js.map +1 -0
- package/build/dist/Types/StatusPage/SubscriberNotificationResend.js +102 -0
- package/build/dist/Types/StatusPage/SubscriberNotificationResend.js.map +1 -0
- package/build/dist/Types/StatusPage/SubscriberNotificationTemplateCompiler.js +97 -0
- package/build/dist/Types/StatusPage/SubscriberNotificationTemplateCompiler.js.map +1 -0
- package/build/dist/Types/StatusPage/SubscriberNotificationTemplatePreview.js +175 -0
- package/build/dist/Types/StatusPage/SubscriberNotificationTemplatePreview.js.map +1 -0
- package/build/dist/Types/StatusPage/SubscriberNotificationTemplateVariables.js +144 -4
- package/build/dist/Types/StatusPage/SubscriberNotificationTemplateVariables.js.map +1 -1
- package/build/dist/Types/StatusPage/SubscriberUpdateNotification.js +29 -9
- package/build/dist/Types/StatusPage/SubscriberUpdateNotification.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/CustomFields/CustomFieldFormFields.js +169 -0
- package/build/dist/UI/Components/CustomFields/CustomFieldFormFields.js.map +1 -0
- package/build/dist/UI/Components/CustomFields/CustomFieldModelFormFields.js +212 -0
- package/build/dist/UI/Components/CustomFields/CustomFieldModelFormFields.js.map +1 -0
- package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js +64 -49
- package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.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/Forms/ModelForm.js +39 -5
- package/build/dist/UI/Components/Forms/ModelForm.js.map +1 -1
- package/build/dist/UI/Components/Forms/Validation.js +1 -1
- package/build/dist/UI/Components/Forms/Validation.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/ModelFormModal/ModelFormModal.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/AnalyticsModelTable.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js +12 -2
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/CustomFieldColumns.js +13 -1
- package/build/dist/UI/Components/ModelTable/CustomFieldColumns.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/ModelTable.js +1 -1
- package/build/dist/UI/Components/ModelTable/ModelTable.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/UI/Utils/SensitiveUrlToken.js +10 -5
- package/build/dist/UI/Utils/SensitiveUrlToken.js.map +1 -1
- package/build/dist/Utils/API.js +177 -1
- package/build/dist/Utils/API.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/build/dist/Utils/Incident/IncidentNoteTemplateVariables.js +155 -0
- package/build/dist/Utils/Incident/IncidentNoteTemplateVariables.js.map +1 -0
- package/build/dist/Utils/Markdown/MarkdownEscape.js +48 -0
- package/build/dist/Utils/Markdown/MarkdownEscape.js.map +1 -1
- package/build/dist/Utils/ProbeNetworkFailureUtil.js +460 -0
- package/build/dist/Utils/ProbeNetworkFailureUtil.js.map +1 -0
- package/package.json +1 -1
|
@@ -18,12 +18,14 @@ import Version from "../../Types/Version";
|
|
|
18
18
|
import { getDeletedAgentRunnerRebindNote } from "../../Types/Kubernetes/KubernetesClusterAiAccessPermissions";
|
|
19
19
|
import RunbookCredentialType from "../../Types/Runbook/RunbookCredentialType";
|
|
20
20
|
import { RUNNER_ALIVE_WINDOW_IN_MINUTES, RunnerLiveStatus, getRunnerLiveStatus, } from "../../Types/Runner/RunnerLiveStatus";
|
|
21
|
-
import { KUBERNETES_AGENT_RUNNER_NAME_PREFIX, KubernetesAiRemediationMode, isInClusterPostureForCluster, isSameKubernetesClusterIdentifier, normalizeKubernetesClusterIdentifier, parseKubernetesRunnerPosture, } from "../../Types/Kubernetes/KubernetesClusterAiAccess";
|
|
21
|
+
import { KUBECTL_ALLOW_WRITES_ENV, KUBECTL_WRITE_NAMESPACES_ENV, KUBERNETES_AGENT_RUNNER_NAME_PREFIX, KUBERNETES_AI_AGENT_COMPONENT, KUBERNETES_AI_AGENT_DISPLAY_NAME, KubernetesAiRemediationMode, isInClusterPostureForCluster, isSameKubernetesClusterIdentifier, normalizeKubernetesClusterIdentifier, parseKubernetesAgentPosture, parseKubernetesRunnerPosture, } from "../../Types/Kubernetes/KubernetesClusterAiAccess";
|
|
22
22
|
import { KubernetesClusterFeedEventType } from "../../Models/DatabaseModels/KubernetesClusterFeed";
|
|
23
23
|
import { Blue500, Green500, Yellow500 } from "../../Types/BrandColors";
|
|
24
24
|
import QueryHelper from "../Types/Database/QueryHelper";
|
|
25
|
+
import AIService from "./AIService";
|
|
25
26
|
import AlertService from "./AlertService";
|
|
26
27
|
import IncidentService from "./IncidentService";
|
|
28
|
+
import KubernetesAiAgentService from "./KubernetesAiAgentService";
|
|
27
29
|
import KubernetesClusterFeedService from "./KubernetesClusterFeedService";
|
|
28
30
|
import KubernetesClusterService from "./KubernetesClusterService";
|
|
29
31
|
import LlmProviderService from "./LlmProviderService";
|
|
@@ -73,15 +75,139 @@ export const CLUSTER_AI_ACCESS_SELECT = {
|
|
|
73
75
|
};
|
|
74
76
|
const MAX_CLUSTERS_PER_SUBJECT = 10;
|
|
75
77
|
/*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
* bound what the write role reaches: the namespaces it is bound in and the
|
|
81
|
-
* node switch. Shown verbatim on incident pages too, so it names the page
|
|
82
|
-
* rather than saying "this page".
|
|
78
|
+
* Where every next step sends an operator: the cluster's AI agent page
|
|
79
|
+
* (AI → Agent in the cluster's side menu). Shown verbatim on incident pages
|
|
80
|
+
* and in the investigation panel too, so it always names the page rather
|
|
81
|
+
* than saying "this page".
|
|
83
82
|
*/
|
|
84
|
-
export const
|
|
83
|
+
export const CLUSTER_AI_AGENT_PAGE = "the cluster's AI agent page (AI → Agent)";
|
|
84
|
+
/*
|
|
85
|
+
* The one command that installs the Kubernetes AI agent (or turns it back
|
|
86
|
+
* on), exactly as the dashboard, the docs and the chart's notes print it.
|
|
87
|
+
* --reuse-values keeps everything else the release already has.
|
|
88
|
+
*/
|
|
89
|
+
export const AI_AGENT_INSTALL_COMMAND = [
|
|
90
|
+
"helm repo update",
|
|
91
|
+
"helm upgrade kubernetes-agent oneuptime/kubernetes-agent \\",
|
|
92
|
+
" --namespace oneuptime-agent --reuse-values \\",
|
|
93
|
+
" --set aiAgent.enabled=true",
|
|
94
|
+
].join("\n");
|
|
95
|
+
/*
|
|
96
|
+
* How to read the agent pod's logs. The namespace is the one the agent
|
|
97
|
+
* reported (posture.podNamespace) when it is known, a placeholder otherwise.
|
|
98
|
+
*/
|
|
99
|
+
export function getAiAgentLogsCommand(namespace) {
|
|
100
|
+
return `kubectl logs -n ${(namespace === null || namespace === void 0 ? void 0 : namespace.trim()) || "<namespace>"} -l component=${KUBERNETES_AI_AGENT_COMPONENT} --tail=100`;
|
|
101
|
+
}
|
|
102
|
+
/*
|
|
103
|
+
* The next step for a cluster no access target can reach: install the
|
|
104
|
+
* agent, with the command verbatim, or check its pod if that was done.
|
|
105
|
+
*/
|
|
106
|
+
export const AI_AGENT_NOT_CONNECTED_NEXT_STEP = `Install the Kubernetes AI agent (use your own release name and namespace if they differ):\n\n${AI_AGENT_INSTALL_COMMAND}\n\nAlready installed? Check its logs: ${getAiAgentLogsCommand()}`;
|
|
107
|
+
/*
|
|
108
|
+
* What to do about a read-only executor while remediation is on. For the
|
|
109
|
+
* agent it names the value that grants writes and the two that bound them
|
|
110
|
+
* (the namespaces the write role is bound in and the node switch); the
|
|
111
|
+
* complete command is on the AI agent page (a bare --set line would miss
|
|
112
|
+
* the chart index refresh and --reuse-values).
|
|
113
|
+
*/
|
|
114
|
+
export const REMEDIATION_WRITE_ACCESS_NEXT_STEP = `Upgrade the Kubernetes agent chart with --set aiAgent.remediation.enabled=true; the complete command is on ${CLUSTER_AI_AGENT_PAGE}. List the namespaces AI may fix in aiAgent.remediation.namespaces (without it the write role is cluster-wide), and add aiAgent.remediation.nodeOperations=false to keep fixes off nodes.`;
|
|
115
|
+
// The same for the previous in-cluster Runner: the AI agent replaces it.
|
|
116
|
+
export const LEGACY_RUNNER_REMEDIATION_WRITE_ACCESS_NEXT_STEP = `Upgrade the Kubernetes agent chart: the Kubernetes AI agent replaces this Runner and your settings carry over. Add --set aiAgent.remediation.enabled=true to the upgrade to let it apply fixes; the complete command is on ${CLUSTER_AI_AGENT_PAGE}.`;
|
|
117
|
+
// The same for a Runner no chart configures: its own environment.
|
|
118
|
+
export const CREDENTIAL_RUNNER_REMEDIATION_WRITE_ACCESS_NEXT_STEP = `Set ${KUBECTL_ALLOW_WRITES_ENV}=true on the Runner's host and restart it (${KUBECTL_WRITE_NAMESPACES_ENV} limits the namespaces it may change).`;
|
|
119
|
+
export function getRemediationWriteAccessNextStep(kind) {
|
|
120
|
+
switch (kind) {
|
|
121
|
+
case "ai_agent":
|
|
122
|
+
return REMEDIATION_WRITE_ACCESS_NEXT_STEP;
|
|
123
|
+
case "legacy_runner":
|
|
124
|
+
return LEGACY_RUNNER_REMEDIATION_WRITE_ACCESS_NEXT_STEP;
|
|
125
|
+
default:
|
|
126
|
+
return CREDENTIAL_RUNNER_REMEDIATION_WRITE_ACCESS_NEXT_STEP;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
// The id jobs and plans name the target by (runnerId), or null for none.
|
|
130
|
+
export function getKubernetesAiAccessTargetId(target) {
|
|
131
|
+
var _a, _b;
|
|
132
|
+
switch (target.type) {
|
|
133
|
+
case "ai_agent":
|
|
134
|
+
return ((_a = target.agent.id) === null || _a === void 0 ? void 0 : _a.toString()) || null;
|
|
135
|
+
case "advanced_runner":
|
|
136
|
+
case "legacy_runner":
|
|
137
|
+
return ((_b = target.runner.id) === null || _b === void 0 ? void 0 : _b.toString()) || null;
|
|
138
|
+
default:
|
|
139
|
+
return null;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
/*
|
|
143
|
+
* THE rule for which access target AI uses for a cluster. Liveness based,
|
|
144
|
+
* so a helm upgrade to the AI agent switches over the moment the agent is
|
|
145
|
+
* online, and a rollback that stops the agent falls back on its own to the
|
|
146
|
+
* previous in-cluster Runner the cluster is still bound to — no dashboard
|
|
147
|
+
* step either way:
|
|
148
|
+
*
|
|
149
|
+
* 1. a bound Runner that is not a kubernetes-agent row: the advanced Runner
|
|
150
|
+
* an operator chose (with its Kubernetes credential). An explicit
|
|
151
|
+
* operator choice wins over everything the chart installs.
|
|
152
|
+
* 2. the cluster's AI agent, when online.
|
|
153
|
+
* 3. the bound Runner, when it is THIS cluster's previous in-cluster Runner
|
|
154
|
+
* and online (the agent is not, or was never installed).
|
|
155
|
+
* 4. the cluster's AI agent, offline (its offline gap says what to check).
|
|
156
|
+
* 5. the bound previous in-cluster Runner, offline.
|
|
157
|
+
* 6. nothing.
|
|
158
|
+
*
|
|
159
|
+
* A bound Runner that is another cluster's kubernetes-agent row is none of
|
|
160
|
+
* these: its ServiceAccount can never reach this cluster. Pure: liveness is
|
|
161
|
+
* decided by the caller (isRunnerOnline, KubernetesAiAgentService.isOnline).
|
|
162
|
+
*/
|
|
163
|
+
export function resolveKubernetesAiAccessTarget(data) {
|
|
164
|
+
/*
|
|
165
|
+
* Only the row the binding names: a row with another id (a stale read)
|
|
166
|
+
* is not the bound Runner.
|
|
167
|
+
*/
|
|
168
|
+
const boundRunner = data.aiAccessRunnerId &&
|
|
169
|
+
data.boundRunner &&
|
|
170
|
+
(!data.boundRunner.id ||
|
|
171
|
+
data.boundRunner.id.toString() === data.aiAccessRunnerId.toString())
|
|
172
|
+
? data.boundRunner
|
|
173
|
+
: null;
|
|
174
|
+
if (boundRunner &&
|
|
175
|
+
!RunnerServiceClass.isKubernetesAgentRunnerRow(boundRunner)) {
|
|
176
|
+
return {
|
|
177
|
+
type: "advanced_runner",
|
|
178
|
+
runner: boundRunner,
|
|
179
|
+
isOnline: data.isBoundRunnerOnline,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
const legacyRunner = boundRunner &&
|
|
183
|
+
RunnerServiceClass.isKubernetesAgentRunnerOfCluster(boundRunner, data.clusterIdentifier)
|
|
184
|
+
? boundRunner
|
|
185
|
+
: null;
|
|
186
|
+
if (data.agent && data.isAgentOnline) {
|
|
187
|
+
return { type: "ai_agent", agent: data.agent, isOnline: true };
|
|
188
|
+
}
|
|
189
|
+
if (legacyRunner && data.isBoundRunnerOnline) {
|
|
190
|
+
return { type: "legacy_runner", runner: legacyRunner, isOnline: true };
|
|
191
|
+
}
|
|
192
|
+
if (data.agent) {
|
|
193
|
+
return { type: "ai_agent", agent: data.agent, isOnline: false };
|
|
194
|
+
}
|
|
195
|
+
if (legacyRunner) {
|
|
196
|
+
return { type: "legacy_runner", runner: legacyRunner, isOnline: false };
|
|
197
|
+
}
|
|
198
|
+
return { type: "none" };
|
|
199
|
+
}
|
|
200
|
+
// What target resolution and the status read off a bound Runner row.
|
|
201
|
+
const BOUND_RUNNER_SELECT = {
|
|
202
|
+
_id: true,
|
|
203
|
+
name: true,
|
|
204
|
+
lastAlive: true,
|
|
205
|
+
connectionStatus: true,
|
|
206
|
+
canRunAiCommands: true,
|
|
207
|
+
canRunRunbooks: true,
|
|
208
|
+
canRunCodeFixTasks: true,
|
|
209
|
+
hostInfo: true,
|
|
210
|
+
};
|
|
85
211
|
/*
|
|
86
212
|
* Why deleting an in-cluster Runner is a two-step remedy (the helper lives
|
|
87
213
|
* with the permissions it names, so RunnerService can use it too).
|
|
@@ -108,6 +234,17 @@ export class KubernetesAgentRegistrationRefusedException extends ForbiddenExcept
|
|
|
108
234
|
this.retryAfterSeconds = data.retryAfterSeconds;
|
|
109
235
|
}
|
|
110
236
|
}
|
|
237
|
+
/*
|
|
238
|
+
* How long a previous in-cluster Runner refused because the cluster's
|
|
239
|
+
* Kubernetes AI agent is online waits before it asks again. The refusal
|
|
240
|
+
* lasts only while the agent is online, so the Runner keeps asking — slowly
|
|
241
|
+
* — and is admitted within a minute of the agent stopping (a helm rollback).
|
|
242
|
+
*/
|
|
243
|
+
export const SUPERSEDED_BY_AI_AGENT_RETRY_AFTER_SECONDS = 60;
|
|
244
|
+
// Why the previous in-cluster Runner was refused: the AI agent replaces it.
|
|
245
|
+
export function getSupersededByAiAgentMessage(clusterIdentifier) {
|
|
246
|
+
return `The Kubernetes AI agent of cluster "${clusterIdentifier}" is online and replaces this in-cluster Runner, so the Runner was not registered. Nothing needs to be done: upgrading the Kubernetes agent chart removes the Runner, and it is admitted again only if the AI agent stops (for example after a helm rollback).`;
|
|
247
|
+
}
|
|
111
248
|
/*
|
|
112
249
|
* When a registration refused because the previous instance is online may
|
|
113
250
|
* try again: once that instance's last heartbeat is older than the alive
|
|
@@ -121,6 +258,8 @@ export function getPreviousInstanceRetryAfterSeconds(data) {
|
|
|
121
258
|
const now = (data.now || OneUptimeDate.getCurrentDate()).getTime();
|
|
122
259
|
return Math.max(1, Math.ceil((admittedAt - now) / 1000));
|
|
123
260
|
}
|
|
261
|
+
// What to do about an empty AI balance (ai_balance_insufficient).
|
|
262
|
+
export const AI_BALANCE_INSUFFICIENT_NEXT_STEP = "Add AI credits under Project Settings → AI Credits (or enable auto-recharge).";
|
|
124
263
|
class KubernetesClusterAiAccessServiceClass {
|
|
125
264
|
/*
|
|
126
265
|
* ------------------------------------------------------------------
|
|
@@ -134,24 +273,51 @@ class KubernetesClusterAiAccessServiceClass {
|
|
|
134
273
|
enableAi: true,
|
|
135
274
|
enableAutoRemediation: true,
|
|
136
275
|
enableAiCommandExecution: true,
|
|
276
|
+
enableAutomaticIncidentInvestigation: true,
|
|
277
|
+
enableAutomaticAlertInvestigation: true,
|
|
137
278
|
},
|
|
138
279
|
props: { isRoot: true },
|
|
139
280
|
});
|
|
140
|
-
|
|
281
|
+
// undefined: the lookup failed, so neither it nor the balance is known.
|
|
282
|
+
let llmProvider = undefined;
|
|
141
283
|
try {
|
|
142
|
-
|
|
143
|
-
|
|
284
|
+
llmProvider =
|
|
285
|
+
await LlmProviderService.getLLMProviderForProject(projectId);
|
|
144
286
|
}
|
|
145
287
|
catch (error) {
|
|
146
288
|
logger.error(`KubernetesClusterAiAccess: could not resolve the LLM provider for project ${projectId.toString()}: ${error}`);
|
|
147
289
|
}
|
|
290
|
+
/*
|
|
291
|
+
* An empty balance is a precondition like the provider: when it cannot
|
|
292
|
+
* be checked, the status says nothing about it rather than claiming a
|
|
293
|
+
* blocker that may not exist (the AI call itself still refuses). The
|
|
294
|
+
* provider resolved above is handed over, so it is looked up once.
|
|
295
|
+
*/
|
|
296
|
+
let aiBalanceBlocker = null;
|
|
297
|
+
if (llmProvider !== undefined) {
|
|
298
|
+
try {
|
|
299
|
+
aiBalanceBlocker = await AIService.getAiBalanceBlocker({
|
|
300
|
+
projectId,
|
|
301
|
+
llmProvider,
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
catch (error) {
|
|
305
|
+
logger.error(`KubernetesClusterAiAccess: could not check the AI balance of project ${projectId.toString()}: ${error}`);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
148
308
|
return {
|
|
149
309
|
// Kill switches: a missing column counts as enabled (=== false idiom).
|
|
150
310
|
isAiEnabled: (project === null || project === void 0 ? void 0 : project.enableAi) !== false,
|
|
151
311
|
isAutoRemediationEnabled: (project === null || project === void 0 ? void 0 : project.enableAutoRemediation) !== false,
|
|
152
312
|
// Explicit opt-in (=== true idiom), same as the Bash/SSH lane.
|
|
153
313
|
isAiCommandExecutionEnabled: (project === null || project === void 0 ? void 0 : project.enableAiCommandExecution) === true,
|
|
154
|
-
|
|
314
|
+
// A failed lookup reads as none, like no provider at all.
|
|
315
|
+
hasLlmProvider: Boolean(llmProvider),
|
|
316
|
+
aiBalanceBlocker,
|
|
317
|
+
automaticInvestigation: {
|
|
318
|
+
incidents: (project === null || project === void 0 ? void 0 : project.enableAutomaticIncidentInvestigation) === true,
|
|
319
|
+
alerts: (project === null || project === void 0 ? void 0 : project.enableAutomaticAlertInvestigation) === true,
|
|
320
|
+
},
|
|
155
321
|
};
|
|
156
322
|
}
|
|
157
323
|
async getStatusForCluster(data) {
|
|
@@ -172,226 +338,178 @@ class KubernetesClusterAiAccessServiceClass {
|
|
|
172
338
|
});
|
|
173
339
|
}
|
|
174
340
|
/*
|
|
175
|
-
*
|
|
176
|
-
*
|
|
177
|
-
*
|
|
178
|
-
* because "we could not check" must not read as "ready".
|
|
341
|
+
* ------------------------------------------------------------------
|
|
342
|
+
* The access target
|
|
343
|
+
* ------------------------------------------------------------------
|
|
179
344
|
*/
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
345
|
+
/*
|
|
346
|
+
* Is this Runner online right now? One rule for readiness, target
|
|
347
|
+
* resolution and registration: it heartbeated within the alive window
|
|
348
|
+
* (RunnerLiveStatus) AND it has not signed off since. A Runner signs off
|
|
349
|
+
* on a clean shutdown (/runner-ingest/disconnect), which is what a helm
|
|
350
|
+
* upgrade or uninstall does to the chart's in-cluster Runner pod — it
|
|
351
|
+
* must read offline at once, not stay "Connected" until its last
|
|
352
|
+
* heartbeat ages out while investigations queue kubectl it will never
|
|
353
|
+
* claim.
|
|
354
|
+
*/
|
|
355
|
+
isRunnerOnline(runner) {
|
|
356
|
+
return this.getRunnerPresence(runner).isOnline;
|
|
357
|
+
}
|
|
358
|
+
/*
|
|
359
|
+
* resolveKubernetesAiAccessTarget with each row's liveness read the one
|
|
360
|
+
* way this module reads it.
|
|
361
|
+
*/
|
|
362
|
+
resolveAccessTarget(cluster, data) {
|
|
363
|
+
return resolveKubernetesAiAccessTarget({
|
|
364
|
+
clusterIdentifier: cluster.clusterIdentifier,
|
|
365
|
+
aiAccessRunnerId: cluster.aiAccessRunnerId,
|
|
366
|
+
boundRunner: data.boundRunner,
|
|
367
|
+
isBoundRunnerOnline: data.boundRunner
|
|
368
|
+
? this.isRunnerOnline(data.boundRunner)
|
|
369
|
+
: false,
|
|
370
|
+
agent: data.agentRow,
|
|
371
|
+
isAgentOnline: data.agentRow
|
|
372
|
+
? KubernetesAiAgentService.isOnline(data.agentRow)
|
|
373
|
+
: false,
|
|
374
|
+
});
|
|
375
|
+
}
|
|
376
|
+
/*
|
|
377
|
+
* Read what the resolution needs — the bound Runner row and the cluster's
|
|
378
|
+
* agent row (unless the caller already has it) — and resolve. Lookup
|
|
379
|
+
* failures propagate: the enqueue chokepoint must fail closed on a target
|
|
380
|
+
* it could not check.
|
|
381
|
+
*/
|
|
382
|
+
async loadAccessTarget(data) {
|
|
383
|
+
const { cluster } = data;
|
|
384
|
+
if (!cluster.id || !cluster.projectId) {
|
|
385
|
+
throw new BadDataException("The cluster's id and project are needed to resolve its AI access target.");
|
|
192
386
|
}
|
|
193
|
-
|
|
194
|
-
|
|
387
|
+
const agent = data.agentRow !== undefined
|
|
388
|
+
? data.agentRow
|
|
389
|
+
: await KubernetesAiAgentService.findForCluster({
|
|
390
|
+
projectId: cluster.projectId,
|
|
391
|
+
kubernetesClusterId: cluster.id,
|
|
392
|
+
});
|
|
393
|
+
const boundRunner = cluster.aiAccessRunnerId
|
|
394
|
+
? await RunnerService.findOneBy({
|
|
195
395
|
query: {
|
|
196
396
|
_id: cluster.aiAccessRunnerId.toString(),
|
|
197
397
|
projectId: cluster.projectId,
|
|
198
398
|
},
|
|
199
|
-
select:
|
|
200
|
-
_id: true,
|
|
201
|
-
name: true,
|
|
202
|
-
lastAlive: true,
|
|
203
|
-
connectionStatus: true,
|
|
204
|
-
canRunAiCommands: true,
|
|
205
|
-
// What would stop an offline agent row from re-registering.
|
|
206
|
-
canRunRunbooks: true,
|
|
207
|
-
canRunCodeFixTasks: true,
|
|
208
|
-
hostInfo: true,
|
|
209
|
-
},
|
|
399
|
+
select: BOUND_RUNNER_SELECT,
|
|
210
400
|
props: { isRoot: true },
|
|
211
|
-
})
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
}
|
|
268
|
-
/*
|
|
269
|
-
* In-cluster access means "kubectl with the pod's own
|
|
270
|
-
* ServiceAccount", which reaches whatever cluster the pod lives
|
|
271
|
-
* in. So it is usable only when the Runner's posture names THIS
|
|
272
|
-
* cluster — a Runner that is in-cluster somewhere else (the
|
|
273
|
-
* dashboard lets an operator pick any Runner) would run every
|
|
274
|
-
* command for this cluster against the wrong one.
|
|
275
|
-
*/
|
|
276
|
-
const isInClusterForThisCluster = isInClusterPostureForCluster(posture, cluster.clusterIdentifier);
|
|
277
|
-
if (isInClusterForThisCluster) {
|
|
278
|
-
accessMethod = "in_cluster";
|
|
279
|
-
}
|
|
280
|
-
else if (cluster.aiAccessCredentialId && isAgentRunnerRow) {
|
|
281
|
-
/*
|
|
282
|
-
* A kubernetes-agent Runner is never handed credential material:
|
|
283
|
-
* its row is minted and re-keyed with the project's telemetry
|
|
284
|
-
* ingestion key, so a credential it carried would be one leaked
|
|
285
|
-
* ingestion key away from anyone. The claim path refuses to
|
|
286
|
-
* resolve one for it (by the same name-or-posture rule);
|
|
287
|
-
* readiness says so instead of promising access that would fail
|
|
288
|
-
* on every command.
|
|
289
|
-
*/
|
|
290
|
-
gaps.push({
|
|
291
|
-
code: "credential_on_agent_runner",
|
|
292
|
-
title: "An in-cluster Runner cannot carry a credential",
|
|
293
|
-
description: `Runner "${runner.name}" is ${((_a = posture === null || posture === void 0 ? void 0 : posture.clusterIdentifier) === null || _a === void 0 ? void 0 : _a.trim())
|
|
294
|
-
? `the in-cluster Runner of cluster "${posture.clusterIdentifier.trim()}"`
|
|
295
|
-
: "a Kubernetes agent's in-cluster Runner"}. It runs kubectl with its own ServiceAccount only and is never given a credential, so the Kubernetes credential selected for this cluster cannot be used through it.`,
|
|
296
|
-
nextStep: "Create a Runner under Project Settings → Runners, assign the Kubernetes credential to it and select both on the cluster's AI page — or install the in-cluster Runner on THIS cluster with --set aiAccess.enabled=true, which needs no credential.",
|
|
297
|
-
blocks: "both",
|
|
298
|
-
});
|
|
299
|
-
}
|
|
300
|
-
else if (cluster.aiAccessCredentialId) {
|
|
301
|
-
const credential = await RunbookCredentialService.findOneBy({
|
|
302
|
-
query: {
|
|
303
|
-
_id: cluster.aiAccessCredentialId.toString(),
|
|
304
|
-
projectId: cluster.projectId,
|
|
305
|
-
},
|
|
306
|
-
select: {
|
|
307
|
-
_id: true,
|
|
308
|
-
name: true,
|
|
309
|
-
credentialType: true,
|
|
310
|
-
runners: { _id: true },
|
|
311
|
-
},
|
|
312
|
-
props: { isRoot: true },
|
|
313
|
-
});
|
|
314
|
-
const isAssignedToRunner = Boolean((_b = credential === null || credential === void 0 ? void 0 : credential.runners) === null || _b === void 0 ? void 0 : _b.some((assigned) => {
|
|
315
|
-
var _a, _b;
|
|
316
|
-
return ((_a = assigned.id) === null || _a === void 0 ? void 0 : _a.toString()) === ((_b = runner.id) === null || _b === void 0 ? void 0 : _b.toString());
|
|
317
|
-
}));
|
|
318
|
-
if (!credential ||
|
|
319
|
-
credential.credentialType !== RunbookCredentialType.Kubernetes ||
|
|
320
|
-
!isAssignedToRunner) {
|
|
321
|
-
gaps.push({
|
|
322
|
-
code: "credential_missing",
|
|
323
|
-
title: "The Kubernetes credential is not usable by the Runner",
|
|
324
|
-
description: !credential
|
|
325
|
-
? "The credential bound to this cluster no longer exists."
|
|
326
|
-
: credential.credentialType !== RunbookCredentialType.Kubernetes
|
|
327
|
-
? `"${credential.name}" is not a Kubernetes credential.`
|
|
328
|
-
: `"${credential.name}" is not assigned to Runner "${runner.name}".`,
|
|
329
|
-
nextStep: "Create a Kubernetes credential (API server URL + ServiceAccount token) under Project Settings → Runner Credentials, assign it to the Runner, and select it on the cluster's AI page.",
|
|
330
|
-
blocks: "both",
|
|
331
|
-
});
|
|
332
|
-
}
|
|
333
|
-
else {
|
|
334
|
-
accessMethod = "credential";
|
|
335
|
-
credentialId = credential.id.toString();
|
|
336
|
-
credentialName = credential.name;
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
else if (posture === null || posture === void 0 ? void 0 : posture.inCluster) {
|
|
340
|
-
/*
|
|
341
|
-
* In-cluster, but for another cluster (or for no named cluster
|
|
342
|
-
* at all). Say so explicitly: the operator picked this Runner
|
|
343
|
-
* believing "in-cluster" meant "in this cluster".
|
|
344
|
-
*/
|
|
345
|
-
const reportedCluster = ((_c = posture.clusterIdentifier) === null || _c === void 0 ? void 0 : _c.trim()) || undefined;
|
|
346
|
-
gaps.push({
|
|
347
|
-
code: "runner_cluster_mismatch",
|
|
348
|
-
title: reportedCluster
|
|
349
|
-
? "The bound Runner is the in-cluster Runner of a different cluster"
|
|
350
|
-
: "The bound Runner did not report which cluster it runs in",
|
|
351
|
-
description: reportedCluster
|
|
352
|
-
? `Runner "${runner.name}" runs inside cluster "${reportedCluster}", not "${cluster.clusterIdentifier || cluster.name || "this cluster"}". Its ServiceAccount would run every kubectl command against "${reportedCluster}", so OneUptime AI will not use it for this cluster.`
|
|
353
|
-
: `Runner "${runner.name}" reports that it runs inside a Kubernetes cluster but not which one, so OneUptime AI cannot tell whether that is this cluster.`,
|
|
354
|
-
nextStep: "Install the in-cluster Runner on THIS cluster with --set aiAccess.enabled=true and select it on the cluster's AI page as its Runner (a registering Runner never replaces the Runner a cluster is bound to), or bind a Runner that holds a Kubernetes credential for this cluster and select that credential on the cluster's AI page.",
|
|
355
|
-
blocks: "both",
|
|
356
|
-
});
|
|
357
|
-
}
|
|
358
|
-
else {
|
|
359
|
-
gaps.push({
|
|
360
|
-
code: "credential_missing",
|
|
361
|
-
title: "The Runner has no credential for this cluster",
|
|
362
|
-
description: `Runner "${runner.name}" runs outside the cluster, so it needs a Kubernetes credential to reach the API server.`,
|
|
363
|
-
nextStep: "Select a Kubernetes credential assigned to this Runner on the cluster's AI page — or install the in-cluster Runner with --set aiAccess.enabled=true, which needs no credential.",
|
|
364
|
-
blocks: "both",
|
|
365
|
-
});
|
|
366
|
-
}
|
|
367
|
-
if (remediationMode !== KubernetesAiRemediationMode.Disabled &&
|
|
368
|
-
(posture === null || posture === void 0 ? void 0 : posture.inCluster) &&
|
|
369
|
-
posture.allowWrites !== true) {
|
|
370
|
-
gaps.push({
|
|
371
|
-
code: "remediation_write_access_missing",
|
|
372
|
-
title: "The in-cluster Runner is read-only",
|
|
373
|
-
description: "The Kubernetes agent was installed without write access, so kubectl changes would be refused by the cluster.",
|
|
374
|
-
nextStep: REMEDIATION_WRITE_ACCESS_NEXT_STEP,
|
|
375
|
-
blocks: "remediation",
|
|
376
|
-
});
|
|
377
|
-
}
|
|
378
|
-
}
|
|
401
|
+
})
|
|
402
|
+
: null;
|
|
403
|
+
return {
|
|
404
|
+
target: this.resolveAccessTarget(cluster, {
|
|
405
|
+
boundRunner,
|
|
406
|
+
agentRow: agent,
|
|
407
|
+
}),
|
|
408
|
+
boundRunner,
|
|
409
|
+
agent,
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
/*
|
|
413
|
+
* This cluster's previous in-cluster Runner — the kubernetes-agent Runner
|
|
414
|
+
* row an older chart registered — or null. Found by its (bounded) name,
|
|
415
|
+
* matched case-insensitively like registration matches it; a row whose
|
|
416
|
+
* posture names a DIFFERENT cluster is not this cluster's (a shortened
|
|
417
|
+
* name's hash collision). Failing that, the cluster's bound Runner when it
|
|
418
|
+
* is this cluster's agent by posture.
|
|
419
|
+
*
|
|
420
|
+
* A failed lookup propagates rather than reading as none: the AI agent's
|
|
421
|
+
* registration asks this to keep a live Runner's cluster, and "could not
|
|
422
|
+
* tell" must refuse (the agent retries) — never admit an agent that then
|
|
423
|
+
* outranks a Runner that is still working. A caller that may treat "could
|
|
424
|
+
* not tell" as "nothing to do" catches it itself.
|
|
425
|
+
*/
|
|
426
|
+
async getLegacyAgentRunnerForCluster(data) {
|
|
427
|
+
const clusterIdentifier = (data.clusterIdentifier || "").trim();
|
|
428
|
+
if (!clusterIdentifier) {
|
|
429
|
+
return null;
|
|
430
|
+
}
|
|
431
|
+
const byName = await RunnerService.findOneBy({
|
|
432
|
+
query: {
|
|
433
|
+
projectId: data.projectId,
|
|
434
|
+
name: QueryHelper.findWithSameText(getKubernetesAgentRunnerNameForCluster(clusterIdentifier)),
|
|
435
|
+
},
|
|
436
|
+
select: BOUND_RUNNER_SELECT,
|
|
437
|
+
props: { isRoot: true },
|
|
438
|
+
});
|
|
439
|
+
if (byName) {
|
|
440
|
+
return this.postureNamesAnotherCluster({
|
|
441
|
+
runner: byName,
|
|
442
|
+
clusterIdentifier,
|
|
443
|
+
})
|
|
444
|
+
? null
|
|
445
|
+
: byName;
|
|
446
|
+
}
|
|
447
|
+
const cluster = await KubernetesClusterService.findOneBy({
|
|
448
|
+
query: {
|
|
449
|
+
_id: data.kubernetesClusterId.toString(),
|
|
450
|
+
projectId: data.projectId,
|
|
451
|
+
},
|
|
452
|
+
select: { _id: true, aiAccessRunnerId: true },
|
|
453
|
+
props: { isRoot: true },
|
|
454
|
+
});
|
|
455
|
+
if (!(cluster === null || cluster === void 0 ? void 0 : cluster.aiAccessRunnerId)) {
|
|
456
|
+
return null;
|
|
379
457
|
}
|
|
458
|
+
const bound = await RunnerService.findOneBy({
|
|
459
|
+
query: {
|
|
460
|
+
_id: cluster.aiAccessRunnerId.toString(),
|
|
461
|
+
projectId: data.projectId,
|
|
462
|
+
},
|
|
463
|
+
select: BOUND_RUNNER_SELECT,
|
|
464
|
+
props: { isRoot: true },
|
|
465
|
+
});
|
|
466
|
+
return bound &&
|
|
467
|
+
RunnerServiceClass.isKubernetesAgentRunnerOfCluster(bound, clusterIdentifier)
|
|
468
|
+
? bound
|
|
469
|
+
: null;
|
|
470
|
+
}
|
|
471
|
+
/*
|
|
472
|
+
* The readiness computation proper. Resolves the cluster's access target
|
|
473
|
+
* (resolveKubernetesAiAccessTarget), reads the bound Runner, the agent row
|
|
474
|
+
* and the credential as root (the cluster row is already tenant-scoped by
|
|
475
|
+
* the caller) and folds project gates in. Always sets aiAgent (the
|
|
476
|
+
* cluster's agent whether or not it is the target) and
|
|
477
|
+
* automaticInvestigation.
|
|
478
|
+
*/
|
|
479
|
+
async getStatusForClusterModel(data) {
|
|
480
|
+
var _a, _b;
|
|
481
|
+
const { cluster, gates } = data;
|
|
482
|
+
const gaps = [];
|
|
483
|
+
const remediationMode = this.normalizeRemediationMode(cluster.aiRemediationMode);
|
|
484
|
+
const isInvestigationEnabled = cluster.isAiInvestigationEnabled === true;
|
|
485
|
+
const agentRow = data.aiAgentRow !== undefined
|
|
486
|
+
? data.aiAgentRow
|
|
487
|
+
: await this.findAiAgentRowForStatus(cluster);
|
|
488
|
+
const loaded = await this.loadAccessTarget({
|
|
489
|
+
cluster,
|
|
490
|
+
agentRow,
|
|
491
|
+
});
|
|
492
|
+
const access = await this.getTargetAccess({
|
|
493
|
+
cluster,
|
|
494
|
+
loaded,
|
|
495
|
+
remediationMode,
|
|
496
|
+
});
|
|
497
|
+
gaps.push(...access.gaps);
|
|
380
498
|
if (!isInvestigationEnabled) {
|
|
381
499
|
gaps.push({
|
|
382
500
|
code: "investigation_disabled",
|
|
383
501
|
title: "AI investigation is turned off for this cluster",
|
|
384
502
|
description: "OneUptime AI will investigate incidents and alerts on this cluster with OneUptime data only — it will not run kubectl.",
|
|
385
|
-
nextStep:
|
|
503
|
+
nextStep: `Turn on "Investigate with kubectl" on ${CLUSTER_AI_AGENT_PAGE}.`,
|
|
386
504
|
blocks: "investigation",
|
|
387
505
|
});
|
|
388
506
|
}
|
|
389
507
|
if (remediationMode === KubernetesAiRemediationMode.Disabled) {
|
|
390
508
|
gaps.push({
|
|
391
509
|
code: "remediation_disabled",
|
|
392
|
-
title: "AI
|
|
510
|
+
title: "AI fixes are turned off for this cluster",
|
|
393
511
|
description: "OneUptime AI will diagnose but never propose or apply a fix on this cluster.",
|
|
394
|
-
nextStep:
|
|
512
|
+
nextStep: `Set "Fixes" to "Ask for approval", "Automatic" or "Bypass approval" on ${CLUSTER_AI_AGENT_PAGE}.`,
|
|
395
513
|
blocks: "remediation",
|
|
396
514
|
});
|
|
397
515
|
}
|
|
@@ -400,7 +518,7 @@ class KubernetesClusterAiAccessServiceClass {
|
|
|
400
518
|
code: "project_ai_disabled",
|
|
401
519
|
title: "AI is disabled for this project",
|
|
402
520
|
description: "OneUptime AI is switched off at the project level.",
|
|
403
|
-
nextStep: "Enable AI under Project Settings → AI.",
|
|
521
|
+
nextStep: "Enable AI under Project Settings → AI Features.",
|
|
404
522
|
blocks: "both",
|
|
405
523
|
});
|
|
406
524
|
}
|
|
@@ -413,21 +531,38 @@ class KubernetesClusterAiAccessServiceClass {
|
|
|
413
531
|
blocks: "both",
|
|
414
532
|
});
|
|
415
533
|
}
|
|
534
|
+
if (gates.aiBalanceBlocker) {
|
|
535
|
+
gaps.push({
|
|
536
|
+
code: "ai_balance_insufficient",
|
|
537
|
+
title: "The project is out of AI credits",
|
|
538
|
+
description: gates.aiBalanceBlocker,
|
|
539
|
+
nextStep: AI_BALANCE_INSUFFICIENT_NEXT_STEP,
|
|
540
|
+
blocks: "both",
|
|
541
|
+
});
|
|
542
|
+
}
|
|
416
543
|
if (!gates.isAutoRemediationEnabled) {
|
|
417
544
|
gaps.push({
|
|
418
545
|
code: "project_auto_remediation_disabled",
|
|
419
546
|
title: "Auto-remediation is disabled for this project",
|
|
420
547
|
description: "The project-level auto-remediation kill switch is off, so no AI fix can be proposed or run.",
|
|
421
|
-
nextStep: "Enable auto-remediation under Project Settings → AI.",
|
|
548
|
+
nextStep: "Enable auto-remediation under Project Settings → AI Features.",
|
|
422
549
|
blocks: "remediation",
|
|
423
550
|
});
|
|
424
551
|
}
|
|
425
|
-
|
|
552
|
+
/*
|
|
553
|
+
* The project's command-execution opt-in governs AI-composed commands
|
|
554
|
+
* on Runners. A cluster reached through its Kubernetes AI agent (or the
|
|
555
|
+
* chart's previous in-cluster Runner) is governed by the cluster's own
|
|
556
|
+
* Fixes setting and the chart's write RBAC instead, so the opt-in only
|
|
557
|
+
* gates a cluster reached through an advanced Runner and credential.
|
|
558
|
+
*/
|
|
559
|
+
if (loaded.target.type === "advanced_runner" &&
|
|
560
|
+
!gates.isAiCommandExecutionEnabled) {
|
|
426
561
|
gaps.push({
|
|
427
562
|
code: "project_ai_command_execution_disabled",
|
|
428
563
|
title: "AI command execution is not enabled for this project",
|
|
429
|
-
description: "AI-composed commands (
|
|
430
|
-
nextStep: 'Turn on "Enable AI Command Execution" under Project Settings → AI.',
|
|
564
|
+
description: "This cluster is reached through a Runner, and AI-composed commands (kubectl fixes included) never run on a Runner in a project that has not opted in.",
|
|
565
|
+
nextStep: 'Turn on "Enable AI Command Execution" under Project Settings → AI Features.',
|
|
431
566
|
blocks: "remediation",
|
|
432
567
|
});
|
|
433
568
|
}
|
|
@@ -441,10 +576,17 @@ class KubernetesClusterAiAccessServiceClass {
|
|
|
441
576
|
clusterId: cluster.id.toString(),
|
|
442
577
|
clusterName: cluster.name || cluster.clusterIdentifier || "cluster",
|
|
443
578
|
clusterIdentifier: cluster.clusterIdentifier,
|
|
444
|
-
runner:
|
|
445
|
-
accessMethod,
|
|
446
|
-
|
|
447
|
-
|
|
579
|
+
runner: access.runner,
|
|
580
|
+
accessMethod: access.accessMethod,
|
|
581
|
+
aiAgent: loaded.agent
|
|
582
|
+
? KubernetesAiAgentService.toSummary(loaded.agent)
|
|
583
|
+
: null,
|
|
584
|
+
automaticInvestigation: {
|
|
585
|
+
incidents: ((_a = gates.automaticInvestigation) === null || _a === void 0 ? void 0 : _a.incidents) === true,
|
|
586
|
+
alerts: ((_b = gates.automaticInvestigation) === null || _b === void 0 ? void 0 : _b.alerts) === true,
|
|
587
|
+
},
|
|
588
|
+
credentialId: access.credentialId,
|
|
589
|
+
credentialName: access.credentialName,
|
|
448
590
|
kubectlAllowlist: this.normalizeAllowlist(cluster.aiKubectlCommandAllowlist),
|
|
449
591
|
isInvestigationEnabled,
|
|
450
592
|
isInvestigationReady: isInvestigationEnabled && !blocksInvestigation,
|
|
@@ -460,18 +602,316 @@ class KubernetesClusterAiAccessServiceClass {
|
|
|
460
602
|
};
|
|
461
603
|
}
|
|
462
604
|
/*
|
|
463
|
-
*
|
|
464
|
-
*
|
|
465
|
-
*
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
605
|
+
* The cluster's agent row for a status. Never throws: a failed read is
|
|
606
|
+
* logged and reads as "no agent", which can only make the status say
|
|
607
|
+
* less is reachable (or fall back to a bound Runner), never more.
|
|
608
|
+
*/
|
|
609
|
+
async findAiAgentRowForStatus(cluster) {
|
|
610
|
+
if (!cluster.id || !cluster.projectId) {
|
|
611
|
+
return null;
|
|
612
|
+
}
|
|
613
|
+
try {
|
|
614
|
+
return await KubernetesAiAgentService.findForCluster({
|
|
615
|
+
projectId: cluster.projectId,
|
|
616
|
+
kubernetesClusterId: cluster.id,
|
|
617
|
+
});
|
|
618
|
+
}
|
|
619
|
+
catch (error) {
|
|
620
|
+
logger.error(`KubernetesClusterAiAccess: could not read the Kubernetes AI agent of cluster ${cluster.id.toString()}: ${error}`);
|
|
621
|
+
return null;
|
|
622
|
+
}
|
|
623
|
+
}
|
|
624
|
+
// How the resolved target reaches the cluster, and what stops it.
|
|
625
|
+
async getTargetAccess(data) {
|
|
626
|
+
const { cluster, loaded, remediationMode } = data;
|
|
627
|
+
const target = loaded.target;
|
|
628
|
+
switch (target.type) {
|
|
629
|
+
case "ai_agent":
|
|
630
|
+
return this.getAgentAccess({
|
|
631
|
+
cluster,
|
|
632
|
+
agent: target.agent,
|
|
633
|
+
isOnline: target.isOnline,
|
|
634
|
+
remediationMode,
|
|
635
|
+
});
|
|
636
|
+
case "legacy_runner":
|
|
637
|
+
case "advanced_runner":
|
|
638
|
+
return this.getRunnerAccess({
|
|
639
|
+
cluster,
|
|
640
|
+
runner: target.runner,
|
|
641
|
+
isLegacy: target.type === "legacy_runner",
|
|
642
|
+
remediationMode,
|
|
643
|
+
});
|
|
644
|
+
default:
|
|
645
|
+
return {
|
|
646
|
+
runner: null,
|
|
647
|
+
accessMethod: "none",
|
|
648
|
+
gaps: [
|
|
649
|
+
/*
|
|
650
|
+
* A bound id with no Runner row is only the race with a Runner
|
|
651
|
+
* delete: the binding's foreign key is ON DELETE SET NULL, so
|
|
652
|
+
* the next read has no binding at all and reads as not
|
|
653
|
+
* connected.
|
|
654
|
+
*/
|
|
655
|
+
cluster.aiAccessRunnerId && !loaded.boundRunner
|
|
656
|
+
? {
|
|
657
|
+
code: "runner_missing",
|
|
658
|
+
title: "The bound Runner was just deleted",
|
|
659
|
+
description: "The Runner this cluster was bound to was deleted while its status was being read.",
|
|
660
|
+
nextStep: `Reload ${CLUSTER_AI_AGENT_PAGE}.`,
|
|
661
|
+
blocks: "both",
|
|
662
|
+
}
|
|
663
|
+
: {
|
|
664
|
+
code: "ai_agent_not_connected",
|
|
665
|
+
title: "The Kubernetes AI agent is not connected",
|
|
666
|
+
description: `OneUptime AI runs kubectl on this cluster through the Kubernetes AI agent, and no agent has connected for this cluster yet.${this.getIgnoredBoundRunnerNote({ cluster, boundRunner: loaded.boundRunner })}`,
|
|
667
|
+
nextStep: AI_AGENT_NOT_CONNECTED_NEXT_STEP,
|
|
668
|
+
blocks: "both",
|
|
669
|
+
},
|
|
670
|
+
],
|
|
671
|
+
};
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
/*
|
|
675
|
+
* A Runner still bound to a cluster that has no access target is another
|
|
676
|
+
* cluster's in-cluster Runner (a kubernetes-agent row that is not this
|
|
677
|
+
* cluster's): its ServiceAccount can never reach this cluster, so it is
|
|
678
|
+
* ignored. Said, so the status does not read as if nothing were
|
|
679
|
+
* selected; installing the agent (the gap's step) is still the fix.
|
|
680
|
+
* Empty when nothing is bound.
|
|
681
|
+
*/
|
|
682
|
+
getIgnoredBoundRunnerNote(data) {
|
|
683
|
+
var _a, _b;
|
|
684
|
+
const { cluster, boundRunner } = data;
|
|
685
|
+
if (!cluster.aiAccessRunnerId || !boundRunner) {
|
|
686
|
+
return "";
|
|
687
|
+
}
|
|
688
|
+
const reportedCluster = ((_b = (_a = parseKubernetesRunnerPosture(boundRunner.hostInfo)) === null || _a === void 0 ? void 0 : _a.clusterIdentifier) === null || _b === void 0 ? void 0 : _b.trim()) || undefined;
|
|
689
|
+
return ` Runner "${boundRunner.name || "Runner"}" is still selected for this cluster, but it is not this cluster's in-cluster Runner${reportedCluster ? ` (it reports cluster "${reportedCluster}")` : ""}, so OneUptime AI does not use it.`;
|
|
690
|
+
}
|
|
691
|
+
/*
|
|
692
|
+
* The cluster's Kubernetes AI agent as the target. It runs kubectl with
|
|
693
|
+
* its own ServiceAccount (accessMethod "in_cluster"), always accepts AI
|
|
694
|
+
* commands and never carries a credential.
|
|
695
|
+
*/
|
|
696
|
+
getAgentAccess(data) {
|
|
697
|
+
const { cluster, agent, isOnline, remediationMode } = data;
|
|
698
|
+
const gaps = [];
|
|
699
|
+
const posture = parseKubernetesAgentPosture(agent.posture);
|
|
700
|
+
const runner = {
|
|
701
|
+
id: agent.id.toString(),
|
|
702
|
+
name: KUBERNETES_AI_AGENT_DISPLAY_NAME,
|
|
703
|
+
kind: "ai_agent",
|
|
704
|
+
isOnline,
|
|
705
|
+
lastAliveAt: agent.lastAliveAt
|
|
706
|
+
? OneUptimeDate.toString(agent.lastAliveAt)
|
|
707
|
+
: undefined,
|
|
708
|
+
canRunAiCommands: true,
|
|
709
|
+
posture,
|
|
710
|
+
};
|
|
711
|
+
if (!isOnline) {
|
|
712
|
+
const lastAliveText = agent.lastAliveAt
|
|
713
|
+
? OneUptimeDate.getDateAsFormattedString(agent.lastAliveAt)
|
|
714
|
+
: "an unknown time";
|
|
715
|
+
gaps.push({
|
|
716
|
+
code: "ai_agent_offline",
|
|
717
|
+
title: "The Kubernetes AI agent is offline",
|
|
718
|
+
description: agent.connectionStatus === "disconnected"
|
|
719
|
+
? `The Kubernetes AI agent signed off after its last report at ${lastAliveText}: it was stopped, uninstalled, turned off with aiAgent.enabled=false, or reset, or its pod is being replaced.`
|
|
720
|
+
: `The Kubernetes AI agent last reported in at ${lastAliveText}.`,
|
|
721
|
+
nextStep: `Check the agent's pod: ${getAiAgentLogsCommand(posture === null || posture === void 0 ? void 0 : posture.podNamespace)}. It must be able to reach your OneUptime URL.`,
|
|
722
|
+
blocks: "both",
|
|
723
|
+
});
|
|
724
|
+
}
|
|
725
|
+
/*
|
|
726
|
+
* The server stamps the cluster's identifier on the agent's posture
|
|
727
|
+
* every time it reports, so this only fails for a cluster row without
|
|
728
|
+
* an identifier. The enqueue chokepoint refuses the same case, so the
|
|
729
|
+
* status must not call it ready.
|
|
730
|
+
*/
|
|
731
|
+
const isInClusterForThisCluster = isInClusterPostureForCluster(posture, cluster.clusterIdentifier);
|
|
732
|
+
if (isOnline && !isInClusterForThisCluster) {
|
|
733
|
+
gaps.push({
|
|
734
|
+
code: "runner_cluster_mismatch",
|
|
735
|
+
title: "The Kubernetes AI agent has not reported this cluster",
|
|
736
|
+
description: "The agent's last report does not name this cluster, so OneUptime AI does not use it yet.",
|
|
737
|
+
nextStep: `Reset the agent on ${CLUSTER_AI_AGENT_PAGE}; it reconnects on its own within a few minutes.`,
|
|
738
|
+
blocks: "both",
|
|
739
|
+
});
|
|
740
|
+
}
|
|
741
|
+
if (remediationMode !== KubernetesAiRemediationMode.Disabled &&
|
|
742
|
+
(posture === null || posture === void 0 ? void 0 : posture.allowWrites) !== true) {
|
|
743
|
+
gaps.push({
|
|
744
|
+
code: "remediation_write_access_missing",
|
|
745
|
+
title: "The Kubernetes AI agent is read-only",
|
|
746
|
+
description: "The Kubernetes AI agent was installed without write access, so it cannot apply fixes.",
|
|
747
|
+
nextStep: getRemediationWriteAccessNextStep("ai_agent"),
|
|
748
|
+
blocks: "remediation",
|
|
749
|
+
});
|
|
750
|
+
}
|
|
751
|
+
return {
|
|
752
|
+
runner,
|
|
753
|
+
accessMethod: isInClusterForThisCluster ? "in_cluster" : "none",
|
|
754
|
+
gaps,
|
|
755
|
+
};
|
|
756
|
+
}
|
|
757
|
+
/*
|
|
758
|
+
* A Runner as the target: the chart's previous in-cluster Runner of this
|
|
759
|
+
* cluster (isLegacy), or a Runner an operator bound, which reaches the
|
|
760
|
+
* cluster with the cluster's Kubernetes credential.
|
|
472
761
|
*/
|
|
762
|
+
async getRunnerAccess(data) {
|
|
763
|
+
var _a;
|
|
764
|
+
const { cluster, runner, isLegacy, remediationMode } = data;
|
|
765
|
+
const gaps = [];
|
|
766
|
+
const posture = parseKubernetesRunnerPosture(runner.hostInfo);
|
|
767
|
+
const presence = this.getRunnerPresence(runner);
|
|
768
|
+
let accessMethod = "none";
|
|
769
|
+
let credentialId = undefined;
|
|
770
|
+
let credentialName = undefined;
|
|
771
|
+
const summary = {
|
|
772
|
+
id: runner.id.toString(),
|
|
773
|
+
name: runner.name || "Runner",
|
|
774
|
+
kind: "runner",
|
|
775
|
+
isOnline: presence.isOnline,
|
|
776
|
+
lastAliveAt: runner.lastAlive
|
|
777
|
+
? OneUptimeDate.toString(runner.lastAlive)
|
|
778
|
+
: undefined,
|
|
779
|
+
canRunAiCommands: runner.canRunAiCommands === true,
|
|
780
|
+
posture,
|
|
781
|
+
};
|
|
782
|
+
if (!presence.isOnline) {
|
|
783
|
+
gaps.push(this.getRunnerOfflineGap({ runner, presence, isLegacy }));
|
|
784
|
+
}
|
|
785
|
+
if (runner.canRunAiCommands !== true) {
|
|
786
|
+
gaps.push({
|
|
787
|
+
code: "runner_ai_commands_disabled",
|
|
788
|
+
title: "The Runner does not accept AI commands",
|
|
789
|
+
description: `"Runs AI Remediation Commands" is turned off on Runner "${runner.name}", so it will not be served kubectl work.`,
|
|
790
|
+
nextStep: 'Turn on "Runs AI Remediation Commands" on the Runner (Project Settings → Runners).',
|
|
791
|
+
blocks: "both",
|
|
792
|
+
});
|
|
793
|
+
}
|
|
794
|
+
/*
|
|
795
|
+
* In-cluster access means "kubectl with the pod's own ServiceAccount",
|
|
796
|
+
* which reaches whatever cluster the pod lives in. So it is usable only
|
|
797
|
+
* when the Runner's posture names THIS cluster — a Runner that is
|
|
798
|
+
* in-cluster somewhere else would run every command for this cluster
|
|
799
|
+
* against the wrong one. The previous in-cluster Runner of this cluster
|
|
800
|
+
* ignores a credential still selected: in-cluster access wins.
|
|
801
|
+
*/
|
|
802
|
+
const isInClusterForThisCluster = isInClusterPostureForCluster(posture, cluster.clusterIdentifier);
|
|
803
|
+
if (isInClusterForThisCluster) {
|
|
804
|
+
accessMethod = "in_cluster";
|
|
805
|
+
}
|
|
806
|
+
else if (isLegacy) {
|
|
807
|
+
/*
|
|
808
|
+
* This cluster's previous in-cluster Runner by its name, but its last
|
|
809
|
+
* report does not say it runs here (a heartbeat that dropped its
|
|
810
|
+
* posture). It is never given a credential, so it cannot be used —
|
|
811
|
+
* and the AI agent, which needs neither, is the way forward.
|
|
812
|
+
*/
|
|
813
|
+
gaps.push({
|
|
814
|
+
code: "runner_cluster_mismatch",
|
|
815
|
+
title: "The previous in-cluster Runner has not reported this cluster",
|
|
816
|
+
description: `Runner "${runner.name}" has not reported that it runs in this cluster, so OneUptime AI does not use it.`,
|
|
817
|
+
nextStep: `Upgrade the Kubernetes agent chart: the Kubernetes AI agent replaces this Runner and your settings carry over.\n\n${AI_AGENT_INSTALL_COMMAND}`,
|
|
818
|
+
blocks: "both",
|
|
819
|
+
});
|
|
820
|
+
}
|
|
821
|
+
else if (cluster.aiAccessCredentialId) {
|
|
822
|
+
const credential = await RunbookCredentialService.findOneBy({
|
|
823
|
+
query: {
|
|
824
|
+
_id: cluster.aiAccessCredentialId.toString(),
|
|
825
|
+
projectId: cluster.projectId,
|
|
826
|
+
},
|
|
827
|
+
select: {
|
|
828
|
+
_id: true,
|
|
829
|
+
name: true,
|
|
830
|
+
credentialType: true,
|
|
831
|
+
runners: { _id: true },
|
|
832
|
+
},
|
|
833
|
+
props: { isRoot: true },
|
|
834
|
+
});
|
|
835
|
+
const isAssignedToRunner = Boolean((_a = credential === null || credential === void 0 ? void 0 : credential.runners) === null || _a === void 0 ? void 0 : _a.some((assigned) => {
|
|
836
|
+
var _a, _b;
|
|
837
|
+
return ((_a = assigned.id) === null || _a === void 0 ? void 0 : _a.toString()) === ((_b = runner.id) === null || _b === void 0 ? void 0 : _b.toString());
|
|
838
|
+
}));
|
|
839
|
+
if (!credential ||
|
|
840
|
+
credential.credentialType !== RunbookCredentialType.Kubernetes ||
|
|
841
|
+
!isAssignedToRunner) {
|
|
842
|
+
gaps.push({
|
|
843
|
+
code: "credential_missing",
|
|
844
|
+
title: "The Kubernetes credential is not usable by the Runner",
|
|
845
|
+
description: !credential
|
|
846
|
+
? "The credential bound to this cluster no longer exists."
|
|
847
|
+
: credential.credentialType !== RunbookCredentialType.Kubernetes
|
|
848
|
+
? `"${credential.name}" is not a Kubernetes credential.`
|
|
849
|
+
: `"${credential.name}" is not assigned to Runner "${runner.name}".`,
|
|
850
|
+
nextStep: `Create a Kubernetes credential (API server URL + ServiceAccount token) under Project Settings → Runner Credentials, assign it to the Runner, and select it on ${CLUSTER_AI_AGENT_PAGE}.`,
|
|
851
|
+
blocks: "both",
|
|
852
|
+
});
|
|
853
|
+
}
|
|
854
|
+
else {
|
|
855
|
+
accessMethod = "credential";
|
|
856
|
+
credentialId = credential.id.toString();
|
|
857
|
+
credentialName = credential.name;
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
else if (posture === null || posture === void 0 ? void 0 : posture.inCluster) {
|
|
861
|
+
/*
|
|
862
|
+
* In-cluster, but for no named cluster. Say so explicitly: the
|
|
863
|
+
* operator picked this Runner believing "in-cluster" meant "in this
|
|
864
|
+
* cluster". (A Runner that names a cluster reports an agent posture,
|
|
865
|
+
* so it is a kubernetes-agent row and never reaches this branch:
|
|
866
|
+
* another cluster's is no target at all — see
|
|
867
|
+
* getIgnoredBoundRunnerNote.)
|
|
868
|
+
*/
|
|
869
|
+
gaps.push({
|
|
870
|
+
code: "runner_cluster_mismatch",
|
|
871
|
+
title: "The bound Runner did not report which cluster it runs in",
|
|
872
|
+
description: `Runner "${runner.name}" reports that it runs inside a Kubernetes cluster but not which one, so OneUptime AI cannot tell whether that is this cluster.`,
|
|
873
|
+
nextStep: `Clear the Runner on ${CLUSTER_AI_AGENT_PAGE} to use this cluster's Kubernetes AI agent, or select a Kubernetes credential for this cluster that is assigned to the Runner.`,
|
|
874
|
+
blocks: "both",
|
|
875
|
+
});
|
|
876
|
+
}
|
|
877
|
+
else {
|
|
878
|
+
gaps.push({
|
|
879
|
+
code: "credential_missing",
|
|
880
|
+
title: "The Runner has no credential for this cluster",
|
|
881
|
+
description: `Runner "${runner.name}" runs outside the cluster, so it needs a Kubernetes credential to reach the API server.`,
|
|
882
|
+
nextStep: `Select a Kubernetes credential assigned to this Runner on ${CLUSTER_AI_AGENT_PAGE} — or clear the Runner there to use the Kubernetes AI agent, which needs no credential.`,
|
|
883
|
+
blocks: "both",
|
|
884
|
+
});
|
|
885
|
+
}
|
|
886
|
+
if (remediationMode !== KubernetesAiRemediationMode.Disabled &&
|
|
887
|
+
(posture === null || posture === void 0 ? void 0 : posture.inCluster) &&
|
|
888
|
+
posture.allowWrites !== true) {
|
|
889
|
+
gaps.push({
|
|
890
|
+
code: "remediation_write_access_missing",
|
|
891
|
+
title: isLegacy
|
|
892
|
+
? "The previous in-cluster Runner is read-only"
|
|
893
|
+
: "The Runner is read-only",
|
|
894
|
+
description: isLegacy
|
|
895
|
+
? "The Kubernetes agent was installed without write access, so kubectl changes would be refused by the cluster."
|
|
896
|
+
: `Runner "${runner.name}" reports that it may not change the cluster, so kubectl changes would be refused.`,
|
|
897
|
+
nextStep: getRemediationWriteAccessNextStep(isLegacy ? "legacy_runner" : "credential_runner"),
|
|
898
|
+
blocks: "remediation",
|
|
899
|
+
});
|
|
900
|
+
}
|
|
901
|
+
return {
|
|
902
|
+
runner: summary,
|
|
903
|
+
accessMethod,
|
|
904
|
+
credentialId,
|
|
905
|
+
credentialName,
|
|
906
|
+
gaps,
|
|
907
|
+
};
|
|
908
|
+
}
|
|
473
909
|
getRunnerPresence(runner) {
|
|
474
910
|
const liveStatus = getRunnerLiveStatus(runner.lastAlive);
|
|
911
|
+
/*
|
|
912
|
+
* A freshly created row is Disconnected with no heartbeat yet: that is
|
|
913
|
+
* "never connected", not a sign-off.
|
|
914
|
+
*/
|
|
475
915
|
const isSignedOff = runner.connectionStatus === RunnerConnectionStatus.Disconnected &&
|
|
476
916
|
liveStatus !== RunnerLiveStatus.NeverConnected;
|
|
477
917
|
return {
|
|
@@ -481,22 +921,34 @@ class KubernetesClusterAiAccessServiceClass {
|
|
|
481
921
|
};
|
|
482
922
|
}
|
|
483
923
|
getRunnerOfflineGap(data) {
|
|
484
|
-
const { runner, presence,
|
|
924
|
+
const { runner, presence, isLegacy } = data;
|
|
485
925
|
const lastAliveText = runner.lastAlive
|
|
486
926
|
? OneUptimeDate.getDateAsFormattedString(runner.lastAlive)
|
|
487
927
|
: "an unknown time";
|
|
928
|
+
/*
|
|
929
|
+
* The previous in-cluster Runner is not coming back by itself after a
|
|
930
|
+
* chart upgrade (the new chart does not install it), and there is
|
|
931
|
+
* nothing to fix in it: the step is the upgrade to the AI agent.
|
|
932
|
+
*/
|
|
933
|
+
if (isLegacy) {
|
|
934
|
+
return {
|
|
935
|
+
code: "runner_offline",
|
|
936
|
+
title: presence.isSignedOff
|
|
937
|
+
? "The previous in-cluster Runner signed off"
|
|
938
|
+
: "The previous in-cluster Runner is offline",
|
|
939
|
+
description: presence.isSignedOff
|
|
940
|
+
? `Runner "${runner.name}" shut down after its last report at ${lastAliveText}.`
|
|
941
|
+
: `Runner "${runner.name}" last reported in at ${lastAliveText}.`,
|
|
942
|
+
nextStep: `Upgrade the Kubernetes agent chart: the Kubernetes AI agent replaces this Runner and your settings carry over.\n\n${AI_AGENT_INSTALL_COMMAND}`,
|
|
943
|
+
blocks: "both",
|
|
944
|
+
};
|
|
945
|
+
}
|
|
488
946
|
if (presence.isSignedOff) {
|
|
489
947
|
return {
|
|
490
948
|
code: "runner_offline",
|
|
491
|
-
title:
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
description: isAgentRunner
|
|
495
|
-
? `Runner "${runner.name}" shut down cleanly after its last heartbeat at ${lastAliveText}: the Kubernetes agent was uninstalled or upgraded with aiAccess turned off, or its Runner pod is being replaced.`
|
|
496
|
-
: `Runner "${runner.name}" shut down cleanly after its last heartbeat at ${lastAliveText}: its container was stopped.`,
|
|
497
|
-
nextStep: isAgentRunner
|
|
498
|
-
? "If the agent was uninstalled or aiAccess was turned off on purpose, clear the Runner on the cluster's AI page. Otherwise upgrade the agent with --set aiAccess.enabled=true and the Runner reconnects within a minute."
|
|
499
|
-
: "Start the Runner container again, or bind another Runner on the cluster's AI page.",
|
|
949
|
+
title: "The Runner signed off",
|
|
950
|
+
description: `Runner "${runner.name}" shut down cleanly after its last heartbeat at ${lastAliveText}: its container was stopped.`,
|
|
951
|
+
nextStep: `Start the Runner container again, or clear the Runner on ${CLUSTER_AI_AGENT_PAGE} to use the Kubernetes AI agent.`,
|
|
500
952
|
blocks: "both",
|
|
501
953
|
};
|
|
502
954
|
}
|
|
@@ -509,48 +961,7 @@ class KubernetesClusterAiAccessServiceClass {
|
|
|
509
961
|
description: isNeverConnected
|
|
510
962
|
? `Runner "${runner.name}" exists but has not reported in yet.`
|
|
511
963
|
: `Runner "${runner.name}" last reported in at ${lastAliveText}.`,
|
|
512
|
-
nextStep:
|
|
513
|
-
? "Check the in-cluster Runner pod: kubectl get pods -n <agent-namespace> -l component=ai-runner, then its logs. It must be able to reach your OneUptime URL."
|
|
514
|
-
: "Start the Runner container and make sure it can reach your OneUptime URL.",
|
|
515
|
-
blocks: "both",
|
|
516
|
-
};
|
|
517
|
-
}
|
|
518
|
-
/*
|
|
519
|
-
* The gap for an offline agent Runner of this cluster that holds more than
|
|
520
|
-
* the agent defaults, or null when it holds nothing extra. Such a row is
|
|
521
|
-
* refused on every registration that cannot present its current key — and
|
|
522
|
-
* a restarted pod never can, it keeps the key in memory only — so the
|
|
523
|
-
* Runner will not come back until an operator removes what it holds.
|
|
524
|
-
* Never throws: a failed lookup falls back to the ordinary offline gap.
|
|
525
|
-
*/
|
|
526
|
-
async getAgentRunnerHoldingsGap(data) {
|
|
527
|
-
var _a;
|
|
528
|
-
let holdings = [];
|
|
529
|
-
try {
|
|
530
|
-
holdings = await this.getRunnerHoldingsBeyondDefaults({
|
|
531
|
-
runner: data.runner,
|
|
532
|
-
clusterId: data.cluster.id,
|
|
533
|
-
projectId: data.cluster.projectId,
|
|
534
|
-
});
|
|
535
|
-
}
|
|
536
|
-
catch (error) {
|
|
537
|
-
logger.error(`KubernetesClusterAiAccess: could not read what the agent Runner of cluster ${(_a = data.cluster.id) === null || _a === void 0 ? void 0 : _a.toString()} holds: ${error}`);
|
|
538
|
-
return null;
|
|
539
|
-
}
|
|
540
|
-
if (holdings.length === 0) {
|
|
541
|
-
return null;
|
|
542
|
-
}
|
|
543
|
-
return {
|
|
544
|
-
code: "runner_offline",
|
|
545
|
-
title: "The in-cluster Runner cannot re-register until it holds less",
|
|
546
|
-
description: `Runner "${data.runner.name}" is offline, and it holds more than an in-cluster Runner's defaults (${this.describeHoldings(holdings)}). A restarted in-cluster Runner cannot prove it is the same Runner, so every registration it attempts is refused and it will not reconnect on its own.`,
|
|
547
|
-
/*
|
|
548
|
-
* Removing what it holds comes first: the Runner row survives, so the
|
|
549
|
-
* cluster stays bound to it and it reconnects on its next retry.
|
|
550
|
-
* Deleting it works too, but only with the second step — the fresh
|
|
551
|
-
* Runner is not bound to this cluster until someone selects it.
|
|
552
|
-
*/
|
|
553
|
-
nextStep: `Under Project Settings → Runners, on Runner "${data.runner.name}": ${this.describeHoldingRemedies(holdings)}. The in-cluster Runner then reconnects on its next retry, still bound to this cluster. Or delete the Runner and, once the in-cluster Runner registers a fresh one (within a minute), select it on the cluster's AI page as its Runner. ${getDeletedAgentRunnerRebindNote()}`,
|
|
964
|
+
nextStep: "Start the Runner container and make sure it can reach your OneUptime URL.",
|
|
554
965
|
blocks: "both",
|
|
555
966
|
};
|
|
556
967
|
}
|
|
@@ -568,73 +979,6 @@ class KubernetesClusterAiAccessServiceClass {
|
|
|
568
979
|
})
|
|
569
980
|
.join("; ");
|
|
570
981
|
}
|
|
571
|
-
/*
|
|
572
|
-
* The gap for a cluster with no Runner bound. What to do depends on
|
|
573
|
-
* whether this cluster's in-cluster Runner is already registered: a
|
|
574
|
-
* registering Runner never binds a cluster whose AI access was configured
|
|
575
|
-
* before (an operator cleared the binding, or the Runner it was bound to
|
|
576
|
-
* was deleted), so re-running the helm upgrade would change nothing —
|
|
577
|
-
* selecting the Runner on the AI page is the step that works. Never
|
|
578
|
-
* throws: a failed lookup falls back to the install instruction.
|
|
579
|
-
*/
|
|
580
|
-
async getNoRunnerBoundGap(cluster) {
|
|
581
|
-
const agentRunner = await this.findAgentRunnerForCluster(cluster);
|
|
582
|
-
if (agentRunner) {
|
|
583
|
-
const isOnline = this.getRunnerPresence(agentRunner).isOnline;
|
|
584
|
-
return {
|
|
585
|
-
code: "no_runner_bound",
|
|
586
|
-
title: "The in-cluster Runner is installed but not selected",
|
|
587
|
-
description: `Runner "${agentRunner.name}", this cluster's in-cluster Runner, is registered${isOnline ? " and online" : " but not online right now"}, but no Runner is bound to this cluster, so OneUptime AI does not use it. A registering Runner never re-binds a cluster that had a Runner bound before (or already ran kubectl) — its binding was cleared by an operator, or the Runner it was bound to was deleted.`,
|
|
588
|
-
nextStep: `Select the kubernetes-agent Runner "${agentRunner.name}" on the cluster's AI page as its Runner (leave the credential empty). No helm change is needed.`,
|
|
589
|
-
blocks: "both",
|
|
590
|
-
};
|
|
591
|
-
}
|
|
592
|
-
return {
|
|
593
|
-
code: "no_runner_bound",
|
|
594
|
-
title: "No Runner can reach this cluster",
|
|
595
|
-
description: "OneUptime AI runs kubectl through a Runner. None is bound to this cluster yet.",
|
|
596
|
-
nextStep: "Upgrade the Kubernetes agent with --set aiAccess.enabled=true to install an in-cluster Runner (one command), or bind an existing Runner and a Kubernetes credential on the cluster's AI page.",
|
|
597
|
-
blocks: "both",
|
|
598
|
-
};
|
|
599
|
-
}
|
|
600
|
-
/*
|
|
601
|
-
* This cluster's agent Runner row, by its (bounded) name, matched
|
|
602
|
-
* case-insensitively like registration matches it. A row whose posture
|
|
603
|
-
* names a DIFFERENT cluster is not this cluster's agent (a shortened
|
|
604
|
-
* name's hash collision, or a posture rewritten on heartbeat).
|
|
605
|
-
*/
|
|
606
|
-
async findAgentRunnerForCluster(cluster) {
|
|
607
|
-
var _a;
|
|
608
|
-
const clusterIdentifier = (cluster.clusterIdentifier || "").trim();
|
|
609
|
-
if (!clusterIdentifier || !cluster.projectId) {
|
|
610
|
-
return null;
|
|
611
|
-
}
|
|
612
|
-
try {
|
|
613
|
-
const runner = await RunnerService.findOneBy({
|
|
614
|
-
query: {
|
|
615
|
-
projectId: cluster.projectId,
|
|
616
|
-
name: QueryHelper.findWithSameText(getKubernetesAgentRunnerNameForCluster(clusterIdentifier)),
|
|
617
|
-
},
|
|
618
|
-
select: {
|
|
619
|
-
_id: true,
|
|
620
|
-
name: true,
|
|
621
|
-
lastAlive: true,
|
|
622
|
-
connectionStatus: true,
|
|
623
|
-
hostInfo: true,
|
|
624
|
-
},
|
|
625
|
-
props: { isRoot: true },
|
|
626
|
-
});
|
|
627
|
-
if (!runner ||
|
|
628
|
-
this.postureNamesAnotherCluster({ runner, clusterIdentifier })) {
|
|
629
|
-
return null;
|
|
630
|
-
}
|
|
631
|
-
return runner;
|
|
632
|
-
}
|
|
633
|
-
catch (error) {
|
|
634
|
-
logger.error(`KubernetesClusterAiAccess: could not look up the agent Runner of cluster ${(_a = cluster.id) === null || _a === void 0 ? void 0 : _a.toString()}: ${error}`);
|
|
635
|
-
return null;
|
|
636
|
-
}
|
|
637
|
-
}
|
|
638
982
|
// The Runner's reported posture names a cluster, and it is not this one.
|
|
639
983
|
postureNamesAnotherCluster(data) {
|
|
640
984
|
var _a, _b;
|
|
@@ -755,19 +1099,57 @@ class KubernetesClusterAiAccessServiceClass {
|
|
|
755
1099
|
return [];
|
|
756
1100
|
}
|
|
757
1101
|
const gates = await this.getProjectGates(data.projectId);
|
|
1102
|
+
return this.getStatusesForClusters({
|
|
1103
|
+
projectId: data.projectId,
|
|
1104
|
+
clusters,
|
|
1105
|
+
gates,
|
|
1106
|
+
});
|
|
1107
|
+
}
|
|
1108
|
+
/*
|
|
1109
|
+
* The status of several clusters of one project, with every cluster's
|
|
1110
|
+
* agent row read in ONE query instead of one per cluster. When that read
|
|
1111
|
+
* fails, each status reads its own row (and treats a failure there as no
|
|
1112
|
+
* agent), exactly as a single status would.
|
|
1113
|
+
*/
|
|
1114
|
+
async getStatusesForClusters(data) {
|
|
1115
|
+
var _a;
|
|
1116
|
+
let agentRows = null;
|
|
1117
|
+
try {
|
|
1118
|
+
agentRows = await KubernetesAiAgentService.findForClusters({
|
|
1119
|
+
projectId: data.projectId,
|
|
1120
|
+
kubernetesClusterIds: data.clusters
|
|
1121
|
+
.map((cluster) => {
|
|
1122
|
+
return cluster.id || undefined;
|
|
1123
|
+
})
|
|
1124
|
+
.filter((id) => {
|
|
1125
|
+
return Boolean(id);
|
|
1126
|
+
}),
|
|
1127
|
+
});
|
|
1128
|
+
}
|
|
1129
|
+
catch (error) {
|
|
1130
|
+
logger.error(`KubernetesClusterAiAccess: could not read the Kubernetes AI agents of project ${data.projectId.toString()}; reading them one cluster at a time: ${error}`);
|
|
1131
|
+
}
|
|
758
1132
|
const statuses = [];
|
|
759
|
-
for (const cluster of clusters) {
|
|
760
|
-
statuses.push(await this.getStatusForClusterModel({
|
|
1133
|
+
for (const cluster of data.clusters) {
|
|
1134
|
+
statuses.push(await this.getStatusForClusterModel({
|
|
1135
|
+
cluster,
|
|
1136
|
+
gates: data.gates,
|
|
1137
|
+
aiAgentRow: agentRows
|
|
1138
|
+
? agentRows.get(((_a = cluster.id) === null || _a === void 0 ? void 0 : _a.toString()) || "") || null
|
|
1139
|
+
: undefined,
|
|
1140
|
+
}));
|
|
761
1141
|
}
|
|
762
1142
|
return statuses;
|
|
763
1143
|
}
|
|
764
1144
|
/*
|
|
765
1145
|
* ------------------------------------------------------------------
|
|
766
|
-
*
|
|
1146
|
+
* Previous in-cluster Runner registration
|
|
767
1147
|
* ------------------------------------------------------------------
|
|
768
1148
|
*/
|
|
769
1149
|
/*
|
|
770
|
-
* Called by the Runner
|
|
1150
|
+
* Called by the in-cluster Runner older kubernetes-agent charts deploy
|
|
1151
|
+
* (the Kubernetes AI agent replaces it and registers through
|
|
1152
|
+
* KubernetesAiAgentService instead). Authenticated
|
|
771
1153
|
* by the project's telemetry ingestion key (the same key the agent ships
|
|
772
1154
|
* telemetry with), so installing the chart with one extra flag is the
|
|
773
1155
|
* whole setup. Idempotent per (project, cluster): a restarted pod gets a
|
|
@@ -798,15 +1180,30 @@ class KubernetesClusterAiAccessServiceClass {
|
|
|
798
1180
|
* secret assigned to it, runbooks or code fixes turned on, or another
|
|
799
1181
|
* cluster bound to it — is refused: re-keying it would hand all of that
|
|
800
1182
|
* to whoever holds the ingestion key. The operator removes the extras
|
|
801
|
-
* (the Runner then comes back still bound), or
|
|
802
|
-
* the
|
|
803
|
-
* page — a deleted Runner's cluster is left unbound, see below.
|
|
1183
|
+
* (the Runner then comes back still bound), or upgrades the chart to
|
|
1184
|
+
* the Kubernetes AI agent, which needs no Runner at all.
|
|
804
1185
|
* - It finds the row it may re-key by this cluster's agent Runner NAME
|
|
805
1186
|
* only — never by the posture a Runner reports about itself — and only
|
|
806
1187
|
* binds a cluster that never had a Runner bound: a cluster whose
|
|
807
1188
|
* binding was cleared (or whose Runner was deleted) stays unbound, and
|
|
808
1189
|
* an operator's AI settings are never overwritten, only the chart's
|
|
809
1190
|
* defaults fill in a cluster nobody configured.
|
|
1191
|
+
* - While the cluster's Kubernetes AI agent is online the Runner is
|
|
1192
|
+
* refused (superseded_by_ai_agent) before anything is written: the
|
|
1193
|
+
* agent replaces it. The refusal clears on its own once the agent
|
|
1194
|
+
* stops, so a helm rollback to a chart with the Runner works again for
|
|
1195
|
+
* a cluster still bound to that Runner (already_bound — every cluster
|
|
1196
|
+
* the Runner served before the upgrade).
|
|
1197
|
+
* - A cluster that has a Kubernetes AI agent row is never given the
|
|
1198
|
+
* chart's defaults by a Runner's first bind (the agent's own first
|
|
1199
|
+
* connection decides those). The binding rules below are unchanged by
|
|
1200
|
+
* the agent row: a cluster that never had a Runner bound and never ran
|
|
1201
|
+
* kubectl is bound with no switch moved, but one where AI already ran
|
|
1202
|
+
* kubectl — through the agent too: its commands and "Test connection"
|
|
1203
|
+
* record the same history — stays unbound (left_unbound_by_operator).
|
|
1204
|
+
* That history cannot tell the agent's commands from a revoked
|
|
1205
|
+
* Runner's, so it fails closed: nothing reaches the cluster until its
|
|
1206
|
+
* agent is back online.
|
|
810
1207
|
* - Every refusal is a KubernetesAgentRegistrationRefusedException whose
|
|
811
1208
|
* reason tells the Runner whether waiting helps.
|
|
812
1209
|
*
|
|
@@ -815,7 +1212,7 @@ class KubernetesClusterAiAccessServiceClass {
|
|
|
815
1212
|
* — so an operator can see when the identity behind AI access changed.
|
|
816
1213
|
*/
|
|
817
1214
|
async registerKubernetesAgentRunner(data) {
|
|
818
|
-
var _a;
|
|
1215
|
+
var _a, _b;
|
|
819
1216
|
const clusterIdentifier = (data.clusterIdentifier || "").trim();
|
|
820
1217
|
if (!clusterIdentifier) {
|
|
821
1218
|
throw new BadDataException("clusterName is required.");
|
|
@@ -841,6 +1238,24 @@ class KubernetesClusterAiAccessServiceClass {
|
|
|
841
1238
|
if (!cluster) {
|
|
842
1239
|
throw new BadDataException("Cluster could not be resolved.");
|
|
843
1240
|
}
|
|
1241
|
+
/*
|
|
1242
|
+
* The Kubernetes AI agent replaces this Runner: while the cluster's
|
|
1243
|
+
* agent is online nothing is created, re-keyed or bound. Checked
|
|
1244
|
+
* first, so a rolled-back pod that keeps retrying during an upgrade
|
|
1245
|
+
* never takes the cluster back from a working agent.
|
|
1246
|
+
*/
|
|
1247
|
+
const aiAgent = await KubernetesAiAgentService.findForCluster({
|
|
1248
|
+
projectId: data.projectId,
|
|
1249
|
+
kubernetesClusterId: cluster.id,
|
|
1250
|
+
});
|
|
1251
|
+
if (aiAgent && KubernetesAiAgentService.isOnline(aiAgent)) {
|
|
1252
|
+
logger.warn(`KubernetesClusterAiAccess: refused to register the in-cluster Runner of cluster "${clusterIdentifier}" in project ${data.projectId.toString()}: the cluster's Kubernetes AI agent is online and replaces it.`);
|
|
1253
|
+
throw new KubernetesAgentRegistrationRefusedException({
|
|
1254
|
+
reason: "superseded_by_ai_agent",
|
|
1255
|
+
retryAfterSeconds: SUPERSEDED_BY_AI_AGENT_RETRY_AFTER_SECONDS,
|
|
1256
|
+
message: getSupersededByAiAgentMessage(clusterIdentifier),
|
|
1257
|
+
});
|
|
1258
|
+
}
|
|
844
1259
|
/*
|
|
845
1260
|
* What the row stores: the body's posture, with the cluster and
|
|
846
1261
|
* in-cluster set by the service. A re-key may fill in the write scope
|
|
@@ -891,7 +1306,7 @@ class KubernetesClusterAiAccessServiceClass {
|
|
|
891
1306
|
logger.warn(`KubernetesClusterAiAccess: refused to register an agent Runner for cluster "${clusterIdentifier}" in project ${data.projectId.toString()}: Runner "${runner.name}" (${(_a = runner.id) === null || _a === void 0 ? void 0 : _a.toString()}) reports that it belongs to a different cluster.`);
|
|
892
1307
|
throw new KubernetesAgentRegistrationRefusedException({
|
|
893
1308
|
reason: "runner_belongs_to_another_cluster",
|
|
894
|
-
message: `
|
|
1309
|
+
message: `Upgrade the Kubernetes agent chart of cluster "${clusterIdentifier}": its Kubernetes AI agent replaces the in-cluster Runner and does not need Runner "${runner.name}". That Runner already exists in this project but reports that it is the in-cluster Runner of a different cluster, so it was not reused for cluster "${clusterIdentifier}".`,
|
|
895
1310
|
});
|
|
896
1311
|
}
|
|
897
1312
|
const agentRunnerExistedBefore = Boolean(runner);
|
|
@@ -959,13 +1374,21 @@ class KubernetesClusterAiAccessServiceClass {
|
|
|
959
1374
|
* binding's foreign key is ON DELETE SET NULL, so Postgres clears
|
|
960
1375
|
* aiAccessRunnerId in the same statement. Deleting the Runner is
|
|
961
1376
|
* how an operator revokes or resets it, so it must not come back
|
|
962
|
-
* bound a few heartbeats later.
|
|
963
|
-
*
|
|
1377
|
+
* bound a few heartbeats later. Such a cluster uses its
|
|
1378
|
+
* Kubernetes AI agent instead.
|
|
1379
|
+
* History counts whoever made it: with a Kubernetes AI agent row
|
|
1380
|
+
* it is usually the agent's (it records every command and "Test
|
|
1381
|
+
* connection" on the cluster), but it cannot be told apart from a
|
|
1382
|
+
* revoked Runner's, so such a cluster stays unbound too and is
|
|
1383
|
+
* reached again once its agent is back online. A rollback keeps
|
|
1384
|
+
* working through the Runner a cluster is still bound to
|
|
1385
|
+
* (already_bound above), not through a new binding here.
|
|
964
1386
|
* - that never had a Runner bound but was configured on the AI page
|
|
965
1387
|
* (aiAccessConfiguredAt: an operator chose a mode, the switches
|
|
966
|
-
* or an allowlist BEFORE installing the chart)
|
|
967
|
-
*
|
|
968
|
-
*
|
|
1388
|
+
* or an allowlist BEFORE installing the chart), or that already
|
|
1389
|
+
* has a Kubernetes AI agent row that never ran kubectl here, is
|
|
1390
|
+
* bound to this agent Runner with every setting left exactly as
|
|
1391
|
+
* it is — the one-flag install still just works.
|
|
969
1392
|
* - that nobody ever configured takes the chart's intent:
|
|
970
1393
|
* investigation on, remediation "ask for approval" when the chart
|
|
971
1394
|
* also granted write RBAC (a mode already on the row is kept).
|
|
@@ -1002,7 +1425,14 @@ class KubernetesClusterAiAccessServiceClass {
|
|
|
1002
1425
|
else if (hadRunnerBound || hasCommandHistory) {
|
|
1003
1426
|
bindingState = "left_unbound_by_operator";
|
|
1004
1427
|
}
|
|
1005
|
-
else if (cluster.aiAccessConfiguredAt) {
|
|
1428
|
+
else if (cluster.aiAccessConfiguredAt || aiAgent) {
|
|
1429
|
+
/*
|
|
1430
|
+
* Configured by an operator before the chart was installed, or the
|
|
1431
|
+
* cluster already has a Kubernetes AI agent (offline, or this
|
|
1432
|
+
* registration would have been refused) that has not run kubectl
|
|
1433
|
+
* here: bind, so AI works through this Runner, but leave every
|
|
1434
|
+
* switch — and the configured marker — exactly as they are.
|
|
1435
|
+
*/
|
|
1006
1436
|
bindingState = "bound_keeping_operator_settings";
|
|
1007
1437
|
// Only the binding: not one of the operator's switches moves.
|
|
1008
1438
|
await KubernetesClusterService.updateOneById({
|
|
@@ -1034,7 +1464,7 @@ class KubernetesClusterAiAccessServiceClass {
|
|
|
1034
1464
|
});
|
|
1035
1465
|
}
|
|
1036
1466
|
if (bindingState === "left_unbound_by_operator") {
|
|
1037
|
-
logger.info(`KubernetesClusterAiAccess: cluster "${clusterIdentifier}" in project ${data.projectId.toString()} had a Runner bound before (or has run kubectl
|
|
1467
|
+
logger.info(`KubernetesClusterAiAccess: cluster "${clusterIdentifier}" in project ${data.projectId.toString()} had a Runner bound before (or has run kubectl${aiAgent ? ", possibly through its Kubernetes AI agent" : ""}) but has none bound now; the in-cluster Runner registered without binding it.`);
|
|
1038
1468
|
}
|
|
1039
1469
|
const isBoundToCluster = bindingState === "first_bind" ||
|
|
1040
1470
|
bindingState === "bound_keeping_operator_settings" ||
|
|
@@ -1047,6 +1477,11 @@ class KubernetesClusterAiAccessServiceClass {
|
|
|
1047
1477
|
agentRunnerExistedBefore,
|
|
1048
1478
|
appliedRemediationMode,
|
|
1049
1479
|
reKeyAdmission,
|
|
1480
|
+
hasAiAgent: Boolean(aiAgent),
|
|
1481
|
+
hadRunnerBound,
|
|
1482
|
+
aiAgentPodNamespace: aiAgent
|
|
1483
|
+
? (_b = parseKubernetesAgentPosture(aiAgent.posture)) === null || _b === void 0 ? void 0 : _b.podNamespace
|
|
1484
|
+
: undefined,
|
|
1050
1485
|
});
|
|
1051
1486
|
return {
|
|
1052
1487
|
runnerId: runner.id,
|
|
@@ -1163,7 +1598,7 @@ class KubernetesClusterAiAccessServiceClass {
|
|
|
1163
1598
|
*/
|
|
1164
1599
|
throw new KubernetesAgentRegistrationRefusedException({
|
|
1165
1600
|
reason: "runner_holds_more_than_defaults",
|
|
1166
|
-
message: `
|
|
1601
|
+
message: `Upgrade the Kubernetes agent chart: its Kubernetes AI agent replaces this in-cluster Runner. Or, under Project Settings → Runners, on Runner "${data.runner.name}": ${this.describeHoldingRemedies(holdings)}. It is offline, but it holds more than an in-cluster Runner's defaults (${this.describeHoldings(holdings)}), so a registration for cluster "${data.clusterIdentifier}" that does not present its current key may not take it over, and its key was not changed.`,
|
|
1167
1602
|
});
|
|
1168
1603
|
}
|
|
1169
1604
|
if (presence.isSignedOff) {
|
|
@@ -1179,7 +1614,8 @@ class KubernetesClusterAiAccessServiceClass {
|
|
|
1179
1614
|
* kubectl access only (no runbooks, no code fixes, nothing assigned) bound
|
|
1180
1615
|
* to its own cluster; anything else was entrusted to the row by an
|
|
1181
1616
|
* operator. "Runs Runbooks" is read the way the claim path reads it: on
|
|
1182
|
-
* unless explicitly false.
|
|
1617
|
+
* unless explicitly false. Also what decides whether an unused previous
|
|
1618
|
+
* in-cluster Runner may be retired (KubernetesAiAgentService).
|
|
1183
1619
|
*/
|
|
1184
1620
|
async getRunnerHoldingsBeyondDefaults(data) {
|
|
1185
1621
|
const holdings = [];
|
|
@@ -1232,7 +1668,7 @@ class KubernetesClusterAiAccessServiceClass {
|
|
|
1232
1668
|
if (otherBoundClusters > 0) {
|
|
1233
1669
|
holdings.push({
|
|
1234
1670
|
description: `the AI access Runner of ${otherBoundClusters} other cluster(s)`,
|
|
1235
|
-
remedy: `
|
|
1671
|
+
remedy: `clear the Runner on the AI agent page of the ${otherBoundClusters} other cluster(s) bound to it`,
|
|
1236
1672
|
});
|
|
1237
1673
|
}
|
|
1238
1674
|
return holdings;
|
|
@@ -1282,12 +1718,29 @@ class KubernetesClusterAiAccessServiceClass {
|
|
|
1282
1718
|
displayColor = Green500;
|
|
1283
1719
|
feedInfoInMarkdown = `🤖 The in-cluster Runner **${runnerName}** registered from the Kubernetes agent chart (${writes}) and was bound as this cluster's AI access Runner. AI investigation is on; AI remediation is ${this.describeRemediationMode(data.appliedRemediationMode)}.`;
|
|
1284
1720
|
}
|
|
1721
|
+
else if (data.bindingState === "bound_keeping_operator_settings" &&
|
|
1722
|
+
data.hasAiAgent &&
|
|
1723
|
+
!data.cluster.aiAccessConfiguredAt) {
|
|
1724
|
+
displayColor = Green500;
|
|
1725
|
+
feedInfoInMarkdown = `🤖 The in-cluster Runner **${runnerName}** ${registered} from the Kubernetes agent chart (${writes}) while this cluster's Kubernetes AI agent is offline, and was bound so AI works through it: no Runner was bound here before and AI had not run kubectl here yet. No AI setting was changed. The Kubernetes AI agent takes over again as soon as it is back online.`;
|
|
1726
|
+
}
|
|
1285
1727
|
else if (data.bindingState === "bound_keeping_operator_settings") {
|
|
1286
1728
|
displayColor = Green500;
|
|
1287
|
-
feedInfoInMarkdown = `🤖 The in-cluster Runner **${runnerName}** ${registered} from the Kubernetes agent chart (${writes}) and was bound as this cluster's AI access Runner. AI access had already been configured on the cluster's AI page, so no AI setting was changed: AI investigation with kubectl is ${data.cluster.isAiInvestigationEnabled === true ? "on" : "off"} and AI remediation is ${this.describeRemediationMode(data.cluster.aiRemediationMode)}, as an operator chose.`;
|
|
1729
|
+
feedInfoInMarkdown = `🤖 The in-cluster Runner **${runnerName}** ${registered} from the Kubernetes agent chart (${writes}) and was bound as this cluster's AI access Runner. AI access had already been configured on the cluster's AI agent page, so no AI setting was changed: AI investigation with kubectl is ${data.cluster.isAiInvestigationEnabled === true ? "on" : "off"} and AI remediation is ${this.describeRemediationMode(data.cluster.aiRemediationMode)}, as an operator chose.`;
|
|
1730
|
+
}
|
|
1731
|
+
else if (data.bindingState === "left_unbound_by_operator" &&
|
|
1732
|
+
data.hasAiAgent &&
|
|
1733
|
+
!data.hadRunnerBound &&
|
|
1734
|
+
!data.cluster.aiAccessRunnerId) {
|
|
1735
|
+
/*
|
|
1736
|
+
* No Runner was ever bound, so the history that kept this one
|
|
1737
|
+
* unbound is most likely the agent's own — not an operator's
|
|
1738
|
+
* doing. Say that, and where AI access comes back from.
|
|
1739
|
+
*/
|
|
1740
|
+
feedInfoInMarkdown = `🤖 The in-cluster Runner **${runnerName}** ${registered} (${writes}) while this cluster's Kubernetes AI agent is offline, and was left unbound: AI has already run kubectl on this cluster (through its Kubernetes AI agent, or a Runner that is no longer bound), and a registering Runner is never bound over that history. No AI setting was changed. AI reaches this cluster again when its Kubernetes AI agent is back online: check the agent's pod with \`${getAiAgentLogsCommand(data.aiAgentPodNamespace)}\`, or upgrade the Kubernetes agent chart again.`;
|
|
1288
1741
|
}
|
|
1289
1742
|
else if (data.bindingState === "left_unbound_by_operator") {
|
|
1290
|
-
feedInfoInMarkdown = `🤖 The in-cluster Runner **${runnerName}** ${registered} (${writes}), but no Runner is bound to this cluster although one was before (or AI already ran kubectl here) — the binding was cleared by an operator, or the Runner it was bound to was deleted — so it was left unbound and no AI switch was changed.
|
|
1743
|
+
feedInfoInMarkdown = `🤖 The in-cluster Runner **${runnerName}** ${registered} (${writes}), but no Runner is bound to this cluster although one was before (or AI already ran kubectl here) — the binding was cleared by an operator, or the Runner it was bound to was deleted — so it was left unbound and no AI switch was changed. Upgrade the Kubernetes agent chart to use the Kubernetes AI agent instead.`;
|
|
1291
1744
|
}
|
|
1292
1745
|
else if (data.bindingState === "bound_to_other_runner") {
|
|
1293
1746
|
feedInfoInMarkdown = `🤖 The in-cluster Runner **${runnerName}** ${registered} (${writes}), but this cluster is bound to a different Runner in the dashboard, so it was not used.`;
|
|
@@ -1435,6 +1888,18 @@ __decorate([
|
|
|
1435
1888
|
__metadata("design:paramtypes", [Object]),
|
|
1436
1889
|
__metadata("design:returntype", Promise)
|
|
1437
1890
|
], KubernetesClusterAiAccessServiceClass.prototype, "getStatusForCluster", null);
|
|
1891
|
+
__decorate([
|
|
1892
|
+
CaptureSpan(),
|
|
1893
|
+
__metadata("design:type", Function),
|
|
1894
|
+
__metadata("design:paramtypes", [Object]),
|
|
1895
|
+
__metadata("design:returntype", Promise)
|
|
1896
|
+
], KubernetesClusterAiAccessServiceClass.prototype, "loadAccessTarget", null);
|
|
1897
|
+
__decorate([
|
|
1898
|
+
CaptureSpan(),
|
|
1899
|
+
__metadata("design:type", Function),
|
|
1900
|
+
__metadata("design:paramtypes", [Object]),
|
|
1901
|
+
__metadata("design:returntype", Promise)
|
|
1902
|
+
], KubernetesClusterAiAccessServiceClass.prototype, "getLegacyAgentRunnerForCluster", null);
|
|
1438
1903
|
__decorate([
|
|
1439
1904
|
CaptureSpan(),
|
|
1440
1905
|
__metadata("design:type", Function),
|
|
@@ -1453,6 +1918,12 @@ __decorate([
|
|
|
1453
1918
|
__metadata("design:paramtypes", [Object]),
|
|
1454
1919
|
__metadata("design:returntype", Promise)
|
|
1455
1920
|
], KubernetesClusterAiAccessServiceClass.prototype, "getStatusesForSubject", null);
|
|
1921
|
+
__decorate([
|
|
1922
|
+
CaptureSpan(),
|
|
1923
|
+
__metadata("design:type", Function),
|
|
1924
|
+
__metadata("design:paramtypes", [Object]),
|
|
1925
|
+
__metadata("design:returntype", Promise)
|
|
1926
|
+
], KubernetesClusterAiAccessServiceClass.prototype, "getStatusesForClusters", null);
|
|
1456
1927
|
__decorate([
|
|
1457
1928
|
CaptureSpan(),
|
|
1458
1929
|
__metadata("design:type", Function),
|