@oneuptime/common 14.0.9 → 14.0.11
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/AIConversation.ts +127 -1
- package/Models/DatabaseModels/AutoRemediationSuggestion.ts +60 -0
- package/Models/DatabaseModels/CephCluster.ts +225 -0
- package/Models/DatabaseModels/CloudResource.ts +12 -0
- package/Models/DatabaseModels/DatabaseServer.ts +225 -0
- package/Models/DatabaseModels/DockerHost.ts +225 -0
- package/Models/DatabaseModels/DockerSwarmCluster.ts +225 -0
- package/Models/DatabaseModels/GlobalConfig.ts +1 -1
- package/Models/DatabaseModels/GlobalOidc.ts +0 -4
- package/Models/DatabaseModels/GlobalOidcProject.ts +0 -4
- package/Models/DatabaseModels/GlobalSso.ts +0 -4
- package/Models/DatabaseModels/GlobalSsoProject.ts +0 -4
- package/Models/DatabaseModels/Host.ts +225 -0
- package/Models/DatabaseModels/IncidentForm.ts +594 -0
- package/Models/DatabaseModels/IncidentFormSubmission.ts +283 -0
- package/Models/DatabaseModels/IncidentTemplate.ts +59 -0
- package/Models/DatabaseModels/Index.ts +16 -0
- package/Models/DatabaseModels/IoTFleet.ts +12 -0
- package/Models/DatabaseModels/KubernetesCluster.ts +12 -0
- package/Models/DatabaseModels/MessageQueue.ts +1102 -0
- package/Models/DatabaseModels/MessageQueueLabelRule.ts +553 -0
- package/Models/DatabaseModels/MessageQueueOwnerRule.ts +633 -0
- package/Models/DatabaseModels/MessageQueueOwnerTeam.ts +491 -0
- package/Models/DatabaseModels/MessageQueueOwnerUser.ts +490 -0
- package/Models/DatabaseModels/PodmanHost.ts +225 -0
- package/Models/DatabaseModels/Project.ts +59 -0
- package/Models/DatabaseModels/ProjectOidc.ts +0 -4
- package/Models/DatabaseModels/ProjectSso.ts +0 -4
- package/Models/DatabaseModels/ProxmoxCluster.ts +225 -0
- package/Models/DatabaseModels/ResourceAiAgent.ts +419 -0
- package/Models/DatabaseModels/RumApplication.ts +12 -0
- package/Models/DatabaseModels/RunnerJob.ts +144 -0
- package/Models/DatabaseModels/ServerlessFunction.ts +12 -0
- package/Models/DatabaseModels/Service.ts +12 -0
- package/Models/DatabaseModels/StatusPageOidc.ts +0 -4
- package/Models/DatabaseModels/StatusPageSso.ts +0 -4
- package/Models/DatabaseModels/TeamComplianceSetting.ts +47 -2
- package/Models/DatabaseModels/VMwareVCenter.ts +225 -0
- package/Server/API/AIChatAPI.ts +13 -114
- package/Server/API/AIInvestigationAPI.ts +3 -3
- package/Server/API/AIInvestigationConversationAPI.ts +266 -0
- package/Server/API/AutoRemediationAPI.ts +392 -1
- package/Server/API/IncidentFormAPI.ts +376 -0
- package/Server/API/ProjectOIDC.ts +16 -25
- package/Server/API/ProjectSSO.ts +16 -24
- package/Server/API/ResourceAiAccessAPI.ts +1669 -0
- package/Server/API/StatusPageAPI.ts +42 -77
- package/Server/Enterprise/EnterpriseEdition.ts +93 -28
- package/Server/Enterprise/EnterpriseFeature.ts +25 -3
- package/Server/Enterprise/EnterpriseLicenseSnapshot.ts +1 -1
- package/Server/Enterprise/EnterpriseServerModule.ts +4 -1
- package/Server/EnvironmentConfig.ts +1 -1
- package/Server/Infrastructure/Postgres/SchemaMigrations/1796300000000-AddResourceAiAgents.ts +423 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1796400000000-AddIncidentForms.ts +129 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1796500000000-AddTeamComplianceRuleNotificationChannels.ts +52 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1796600000000-AddAIInvestigationConversationAndTimeLimits.ts +75 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1796700000000-AddMessageQueueTables.ts +477 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +10 -0
- package/Server/Infrastructure/Semaphore.ts +22 -0
- package/Server/Middleware/IncidentFormRateLimit.ts +847 -0
- package/Server/Middleware/TelemetryIngest.ts +15 -5
- package/Server/Middleware/UserAuthorization.ts +16 -38
- package/Server/Services/AIService.ts +10 -13
- package/Server/Services/AnalyticsDatabaseService.ts +45 -1
- package/Server/Services/AutoRemediationRuleEngineService.ts +940 -112
- package/Server/Services/CephClusterService.ts +109 -1
- package/Server/Services/DatabaseServerService.ts +116 -1
- package/Server/Services/DockerHostService.ts +109 -1
- package/Server/Services/DockerSwarmClusterService.ts +113 -1
- package/Server/Services/HostService.ts +126 -4
- package/Server/Services/IncidentCustomFieldService.ts +112 -2
- package/Server/Services/IncidentEpisodeMemberService.ts +24 -4
- package/Server/Services/IncidentEpisodeService.ts +10 -1
- package/Server/Services/IncidentFormService.ts +1566 -0
- package/Server/Services/IncidentFormSubmissionService.ts +97 -0
- package/Server/Services/IncidentGroupingEngineService.ts +45 -8
- package/Server/Services/IncidentService.ts +123 -5
- package/Server/Services/IncidentTemplateService.ts +22 -0
- package/Server/Services/Index.ts +14 -0
- package/Server/Services/MessageQueueLabelRuleEngineService.ts +321 -0
- package/Server/Services/MessageQueueLabelRuleService.ts +14 -0
- package/Server/Services/MessageQueueOwnerRuleEngineService.ts +412 -0
- package/Server/Services/MessageQueueOwnerRuleService.ts +14 -0
- package/Server/Services/MessageQueueOwnerTeamService.ts +62 -0
- package/Server/Services/MessageQueueOwnerUserService.ts +62 -0
- package/Server/Services/MessageQueueService.ts +1463 -0
- package/Server/Services/MetricRecordingRuleService.ts +47 -0
- package/Server/Services/OpenTelemetryIngestService.ts +37 -4
- package/Server/Services/PodmanHostService.ts +109 -1
- package/Server/Services/ProjectService.ts +0 -59
- package/Server/Services/ProxmoxClusterService.ts +110 -1
- package/Server/Services/ResourceAiAccessService.ts +1439 -0
- package/Server/Services/ResourceAiAgentJobService.ts +202 -0
- package/Server/Services/ResourceAiAgentService.ts +2432 -0
- package/Server/Services/RunnerJobService.ts +611 -4
- package/Server/Services/StatusPagePrivateUserService.ts +1 -4
- package/Server/Services/StatusPageService.ts +1 -51
- package/Server/Services/TeamComplianceSettingService.ts +163 -42
- package/Server/Services/TelemetryUsageBillingService.ts +28 -0
- package/Server/Services/TraceRecordingRuleService.ts +33 -0
- package/Server/Services/UserNotificationRuleService.ts +8 -1
- package/Server/Services/VMwareVCenterService.ts +110 -1
- package/Server/Services/WorkspaceNotificationSummaryService.ts +12 -3
- package/Server/Types/Database/Permissions/CreatePermission.ts +17 -3
- package/Server/Types/Database/Permissions/EditionPermission.ts +140 -38
- package/Server/Types/Database/Permissions/OwnerTableRegistry.ts +16 -0
- package/Server/Types/Database/Permissions/TablePermission.ts +3 -3
- package/Server/Types/Database/Permissions/UpdatePermission.ts +20 -6
- package/Server/Utils/AI/Chat/AgentContextCompactor.ts +200 -0
- package/Server/Utils/AI/Chat/ChatAgentRunner.ts +307 -48
- package/Server/Utils/AI/Chat/ChatRunCancellation.ts +156 -0
- package/Server/Utils/AI/Chat/ObservabilityAssistant.ts +78 -18
- package/Server/Utils/AI/Chat/ObservabilityChatPrompt.ts +1 -1
- package/Server/Utils/AI/Chat/ToolOutputPager.ts +322 -0
- package/Server/Utils/AI/ClusterAccess/KubectlInvestigationToolkit.ts +88 -30
- package/Server/Utils/AI/ClusterAccess/KubectlJobRunner.ts +13 -1
- package/Server/Utils/AI/CodeFix/CodeFixReadiness.ts +0 -32
- package/Server/Utils/AI/CodeFix/FixRunBudget.ts +27 -25
- package/Server/Utils/AI/Remediation/RemediationCommandTools.ts +1442 -34
- package/Server/Utils/AI/Remediation/RemediationExecutionRunner.ts +968 -34
- package/Server/Utils/AI/Remediation/RemediationPlanRunner.ts +25 -1
- package/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.ts +622 -0
- package/Server/Utils/AI/ResourceAccess/ResourceAccessContext.ts +271 -0
- package/Server/Utils/AI/ResourceAccess/ResourceAccessToolNames.ts +45 -0
- package/Server/Utils/AI/ResourceAccess/ResourceAiAccessSettings.ts +964 -0
- package/Server/Utils/AI/ResourceAccess/ResourceAiDeleteCleanup.ts +333 -0
- package/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.ts +882 -0
- package/Server/Utils/AI/SRE/AIInvestigationEngine.ts +125 -12
- package/Server/Utils/AI/SRE/AlertInvestigationRunner.ts +99 -15
- package/Server/Utils/AI/SRE/IncidentInvestigationRunner.ts +99 -15
- package/Server/Utils/AI/SRE/InvestigationQueue.ts +16 -19
- package/Server/Utils/AI/SRE/InvestigationThread.ts +646 -0
- package/Server/Utils/AI/SRE/InvestigationThreadService.ts +715 -0
- package/Server/Utils/AI/Toolbox/Serializer.ts +10 -3
- package/Server/Utils/AutoRemediation/CommandPlanExecutor.ts +396 -13
- package/Server/Utils/AutoRemediation/RemediationVerifier.ts +35 -2
- package/Server/Utils/Database/ProjectScopedReferenceValidator.ts +9 -1
- package/Server/Utils/EditionEnforcement.ts +19 -202
- package/Server/Utils/LLM/LLMService.ts +259 -63
- package/Server/Utils/RelaxedScimTeamLocksReport.ts +245 -0
- package/Server/Utils/Rules/RuleRun/RuleRunRegistry.ts +25 -0
- package/Server/Utils/SameOriginRequest.ts +203 -0
- package/Server/Utils/SessionReplay/SessionReplayBudgetMetrics.ts +920 -0
- package/Server/Utils/SessionReplay/SessionReplayUsage.ts +84 -6
- package/Server/Utils/TeamMember/ProjectLeaveResourceCleanup.ts +2 -0
- package/Server/Utils/Telemetry/EntityRegistry.ts +4 -1
- package/Server/Utils/Telemetry/MessageQueueDiscovery.ts +1402 -0
- package/Server/Utils/Telemetry/ResourceEntityFilter.ts +4 -1
- package/Server/Utils/VendorAssets.ts +3 -3
- package/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.ts +35 -15
- package/Server/Utils/Workspace/MicrosoftTeams/Actions/AlertEpisode.ts +33 -15
- package/Server/Utils/Workspace/MicrosoftTeams/Actions/Auth.ts +21 -1
- package/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.ts +301 -225
- package/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.ts +38 -16
- package/Server/Utils/Workspace/MicrosoftTeams/Actions/ScheduledMaintenance.ts +389 -175
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +376 -144
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsActivityDeduplicator.ts +163 -0
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCardChoices.ts +396 -0
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateCommands.ts +418 -0
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsMessageSize.ts +152 -0
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsReplies.ts +251 -0
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsTimezone.ts +214 -0
- package/Tests/App/Accounts/IncidentFormPage.test.tsx +2036 -0
- package/Tests/App/Accounts/IncidentFormServerMessages.test.ts +119 -0
- package/Tests/App/Accounts/IncidentFormUtils.test.ts +1157 -0
- package/Tests/App/Accounts/LoginPasskey.test.tsx +6 -4
- package/Tests/App/Accounts/LoginSso.test.tsx +724 -0
- package/Tests/App/AdminDashboard/AdminAuthenticationRequireSso.test.tsx +338 -0
- package/Tests/App/AdminDashboard/AdminAuthenticationSsoCardLocales.test.tsx +331 -0
- package/Tests/App/AdminDashboard/AdminEnterprisePluginPage.test.tsx +47 -33
- package/Tests/App/AdminDashboard/GlobalSsoOidcPages.test.tsx +1021 -0
- package/Tests/App/Dashboard/AffectedResourcesDisplay.test.tsx +876 -78
- package/Tests/App/Dashboard/AffectedResourcesSlo.test.tsx +20 -3
- package/Tests/App/Dashboard/CephProxmoxVMwareDocumentationCards.test.tsx +359 -0
- package/Tests/App/Dashboard/CephSetupGuide.test.ts +961 -0
- package/Tests/App/Dashboard/CloudDocumentationCard.test.tsx +381 -95
- package/Tests/App/Dashboard/CloudSetupGuide.test.ts +1463 -0
- package/Tests/App/Dashboard/ClusterAccessNotice.test.tsx +267 -12
- package/Tests/App/Dashboard/ContainerSetupGuideCards.test.tsx +345 -0
- package/Tests/App/Dashboard/CoreListEmptyStates.test.tsx +501 -0
- package/Tests/App/Dashboard/DashboardLazyPages.test.tsx +0 -1
- package/Tests/App/Dashboard/DatabaseDocumentationCard.test.tsx +400 -0
- package/Tests/App/Dashboard/DatabaseDocumentationMarkdown.test.ts +23 -6
- package/Tests/App/Dashboard/DatabaseSetupGuide.test.ts +1869 -0
- package/Tests/App/Dashboard/DatabaseTelemetryScope.test.ts +44 -0
- package/Tests/App/Dashboard/DatabaseTelemetryTabs.test.tsx +50 -9
- package/Tests/App/Dashboard/DockerSetupGuide.test.ts +899 -0
- package/Tests/App/Dashboard/DockerSwarmSetupGuide.test.ts +964 -0
- package/Tests/App/Dashboard/EnterpriseFeatureUpgrade.test.tsx +141 -7
- package/Tests/App/Dashboard/EnterprisePluginPage.test.tsx +52 -39
- package/Tests/App/Dashboard/EventOverviewPages.test.tsx +7 -1
- package/Tests/App/Dashboard/GettingStartedTaskRoutes.test.tsx +331 -0
- package/Tests/App/Dashboard/HomeOverviewStatsFirstRun.test.tsx +925 -0
- package/Tests/App/Dashboard/HostDocumentationCard.test.tsx +225 -0
- package/Tests/App/Dashboard/HostSetupGuide.test.ts +1183 -0
- package/Tests/App/Dashboard/IdentityEnterpriseShells.test.tsx +69 -45
- package/Tests/App/Dashboard/IncidentCreateTemplateCustomFieldSettings.test.tsx +745 -0
- package/Tests/App/Dashboard/IncidentCreateTemplateOwners.test.tsx +414 -0
- package/Tests/App/Dashboard/IncidentCustomFieldCreateSettingsForm.test.ts +1042 -0
- package/Tests/App/Dashboard/IncidentCustomFieldSettingsCard.test.tsx +1816 -0
- package/Tests/App/Dashboard/IncidentFormPlan.test.ts +89 -0
- package/Tests/App/Dashboard/IncidentFormShareLinkCard.test.tsx +846 -0
- package/Tests/App/Dashboard/IncidentFormsPages.test.tsx +1324 -0
- package/Tests/App/Dashboard/IncidentTemplateCustomFieldSettings.test.tsx +630 -0
- package/Tests/App/Dashboard/IncidentsSideMenu.test.tsx +13 -0
- package/Tests/App/Dashboard/IncomingEmailMonitorLinkVerifyHint.test.tsx +104 -0
- package/Tests/App/Dashboard/InvestigationConversation.test.tsx +1107 -0
- package/Tests/App/Dashboard/InvestigationConversationData.test.ts +546 -0
- package/Tests/App/Dashboard/InvestigationEvidenceList.test.tsx +170 -5
- package/Tests/App/Dashboard/InvestigationInfrastructureTools.test.tsx +506 -0
- package/Tests/App/Dashboard/InvestigationNotStarted.test.tsx +207 -2
- package/Tests/App/Dashboard/InvestigationPanel.test.tsx +729 -34
- package/Tests/App/Dashboard/InvestigationPanelStatus.test.tsx +9 -21
- package/Tests/App/Dashboard/InvestigationReportView.test.tsx +274 -37
- package/Tests/App/Dashboard/InvestigationStatusBadge.test.tsx +130 -0
- package/Tests/App/Dashboard/IoTDocumentationCard.test.tsx +218 -0
- package/Tests/App/Dashboard/IoTSetupGuide.test.ts +1124 -0
- package/Tests/App/Dashboard/KubernetesClusterAiAccessSettings.test.ts +20 -6
- package/Tests/App/Dashboard/KubernetesClusterAiDocumentationMarkdown.test.ts +107 -83
- package/Tests/App/Dashboard/KubernetesSetupGuide.test.ts +787 -0
- package/Tests/App/Dashboard/MessageQueueBreadcrumbs.test.tsx +228 -0
- package/Tests/App/Dashboard/MessageQueueBrokerHealth.test.tsx +1538 -0
- package/Tests/App/Dashboard/MessageQueueBrokerHealthMetricChart.test.tsx +969 -0
- package/Tests/App/Dashboard/MessageQueueBrokerHealthReads.test.ts +889 -0
- package/Tests/App/Dashboard/MessageQueueBrokerMetricsReach.test.ts +236 -0
- package/Tests/App/Dashboard/MessageQueueDocumentationCard.test.tsx +479 -0
- package/Tests/App/Dashboard/MessageQueueListPages.test.tsx +1232 -0
- package/Tests/App/Dashboard/MessageQueueMetricDescriptions.test.ts +244 -0
- package/Tests/App/Dashboard/MessageQueueMonitorLink.test.ts +952 -0
- package/Tests/App/Dashboard/MessageQueueMonitorLinkMonitorCreate.test.tsx +859 -0
- package/Tests/App/Dashboard/MessageQueueOverview.test.tsx +1773 -0
- package/Tests/App/Dashboard/MessageQueueOverviewPresentation.test.ts +196 -0
- package/Tests/App/Dashboard/MessageQueuePresentation.test.ts +799 -0
- package/Tests/App/Dashboard/MessageQueueProducersConsumers.test.tsx +680 -0
- package/Tests/App/Dashboard/MessageQueueRoutes.test.tsx +383 -0
- package/Tests/App/Dashboard/MessageQueueRulePages.test.tsx +278 -0
- package/Tests/App/Dashboard/MessageQueueSetupGuide.test.ts +2778 -0
- package/Tests/App/Dashboard/MessageQueueSideMenus.test.tsx +273 -0
- package/Tests/App/Dashboard/MessageQueueSpanPopulations.test.ts +930 -0
- package/Tests/App/Dashboard/MessageQueueSpanStore.ts +351 -0
- package/Tests/App/Dashboard/MessageQueueTelemetryScope.test.ts +375 -0
- package/Tests/App/Dashboard/MessageQueueTelemetryScopeTabs.test.tsx +668 -0
- package/Tests/App/Dashboard/MessageQueueViewPages.test.tsx +685 -0
- package/Tests/App/Dashboard/MonitorAndHomeNotOperationalMenus.test.tsx +342 -0
- package/Tests/App/Dashboard/MonitorCreateFirstRunDefaults.test.tsx +623 -0
- package/Tests/App/Dashboard/MonitorCreateFromMonitorBackedDevice.test.tsx +442 -0
- package/Tests/App/Dashboard/MonitorLogsPageViewSummary.test.tsx +814 -0
- package/Tests/App/Dashboard/MonitorSetupCardBodies.test.tsx +246 -0
- package/Tests/App/Dashboard/NavigationSearchKeywords.test.tsx +8 -0
- package/Tests/App/Dashboard/OnboardingSsoEmptyState.test.tsx +27 -12
- package/Tests/App/Dashboard/PlanGatedPage.test.tsx +292 -0
- package/Tests/App/Dashboard/PodmanSetupGuide.test.ts +948 -0
- package/Tests/App/Dashboard/ProductOrientation.test.tsx +5 -4
- package/Tests/App/Dashboard/ProductSettingsSectionCollapsed.test.tsx +266 -0
- package/Tests/App/Dashboard/ProxmoxSetupGuide.test.ts +1318 -0
- package/Tests/App/Dashboard/RemediationSuggestionCardDescription.test.tsx +209 -0
- package/Tests/App/Dashboard/RemediationSuggestionCardResource.test.tsx +317 -0
- package/Tests/App/Dashboard/ResourceAiAccessSettingsUtil.test.ts +921 -0
- package/Tests/App/Dashboard/ResourceAiAgentAttentionServerParity.test.ts +555 -0
- package/Tests/App/Dashboard/ResourceAiAgentInstall.test.ts +860 -0
- package/Tests/App/Dashboard/ResourceAiAgentPage.test.tsx +2010 -0
- package/Tests/App/Dashboard/ResourceAiAgentStatus.test.ts +1455 -0
- package/Tests/App/Dashboard/ResourceAiInsightsPage.test.tsx +931 -0
- package/Tests/App/Dashboard/ResourceAiNavigation.test.tsx +575 -0
- package/Tests/App/Dashboard/ResourceArchiveSettings.test.tsx +16 -0
- package/Tests/App/Dashboard/ResourceConnectionGuideCard.test.tsx +444 -0
- package/Tests/App/Dashboard/ResourceConnectionGuideOverviewsInfra.test.tsx +798 -0
- package/Tests/App/Dashboard/ResourceConnectionGuideOverviewsPlatforms.test.tsx +717 -0
- package/Tests/App/Dashboard/ResourceConnectionGuides.test.ts +981 -0
- package/Tests/App/Dashboard/ResourceConnectionState.test.ts +132 -0
- package/Tests/App/Dashboard/RumDocumentationCard.test.tsx +293 -0
- package/Tests/App/Dashboard/RumSessionReplayRetentionSettings.test.tsx +467 -0
- package/Tests/App/Dashboard/RumSetupGuide.test.ts +758 -0
- package/Tests/App/Dashboard/RunbookStepTypeMaps.test.ts +38 -7
- package/Tests/App/Dashboard/ScheduledMaintenanceOverviewPage.test.tsx +25 -0
- package/Tests/App/Dashboard/ServerlessDocumentationCard.test.tsx +254 -0
- package/Tests/App/Dashboard/ServerlessSetupGuide.test.ts +1074 -0
- package/Tests/App/Dashboard/SetupGuide.test.ts +246 -0
- package/Tests/App/Dashboard/SetupGuideCard.test.tsx +756 -0
- package/Tests/App/Dashboard/SloListSideMenu.test.tsx +120 -0
- package/Tests/App/Dashboard/SsoPages.test.tsx +833 -0
- package/Tests/App/Dashboard/TelemetryDocumentation.test.tsx +253 -0
- package/Tests/App/Dashboard/TelemetryRetentionShells.test.tsx +730 -0
- package/Tests/App/Dashboard/VMwareSetupGuide.test.ts +1033 -0
- package/Tests/App/StatusPage/StatusPageSsoEmptyState.test.tsx +87 -7
- package/Tests/Models/DatabaseModels/DatabaseServerModels.test.ts +61 -10
- package/Tests/Models/DatabaseModels/IncidentFormModel.test.ts +1250 -0
- package/Tests/Models/DatabaseModels/MessageQueueModels.test.ts +1983 -0
- package/Tests/Models/DatabaseModels/ResourceAiAccessColumns.test.ts +738 -0
- package/Tests/Models/DatabaseModels/ResourceAiAgentModel.test.ts +842 -0
- package/Tests/Models/DatabaseModels/StaticRuleCriteriaInheritance.test.ts +4 -2
- package/Tests/Models/DatabaseModels/TeamComplianceSettingModel.test.ts +190 -14
- package/Tests/Models/IncidentTemplateCustomFieldSettingsColumn.test.ts +291 -0
- package/Tests/Server/API/AIInvestigationConversationAPI.test.ts +412 -0
- package/Tests/Server/API/AutoRemediationApproveResourceRound.test.ts +835 -0
- package/Tests/Server/API/GlobalConfigLicense.test.ts +38 -9
- package/Tests/Server/API/IncidentFormAPI.test.ts +942 -0
- package/Tests/Server/API/IncidentFormPublicRoutes.test.ts +1653 -0
- package/Tests/Server/API/KubernetesClusterAiAccessAPI.test.ts +2 -1
- package/Tests/Server/API/ResourceAiAccessAPI.test.ts +2730 -0
- package/Tests/Server/API/{SsoProviderListingsEdition.test.ts → SsoProviderListings.test.ts} +164 -110
- package/Tests/Server/Enterprise/EnterpriseEdition.test.ts +76 -54
- package/Tests/Server/Enterprise/EnterpriseFeatureActive.test.ts +125 -42
- package/Tests/Server/Enterprise/EnterpriseLicenseSnapshot.test.ts +36 -10
- package/Tests/Server/Enterprise/EnterpriseModelFeatureMap.test.ts +51 -9
- package/Tests/Server/Enterprise/FakeEnterpriseModule.ts +13 -8
- package/Tests/Server/Enterprise/SsoInCommunityEdition.test.ts +540 -0
- package/Tests/Server/Infrastructure/Postgres/AddConfigurableRuleCriteriaMigration.test.ts +3 -0
- package/Tests/Server/Infrastructure/Postgres/AddDatabaseServerTablesMigration.test.ts +60 -0
- package/Tests/Server/Infrastructure/Postgres/AddIncidentFormsMigration.test.ts +438 -0
- package/Tests/Server/Infrastructure/Postgres/AddResourceAiAgentsMigration.test.ts +659 -0
- package/Tests/Server/Infrastructure/Postgres/AddTeamComplianceRuleNotificationChannelsMigration.test.ts +255 -0
- package/Tests/Server/Infrastructure/Postgres/MessageQueueTablesMigration.test.ts +637 -0
- package/Tests/Server/Infrastructure/SemaphoreMutex.test.ts +31 -0
- package/Tests/Server/Middleware/IncidentFormRateLimit.test.ts +1630 -0
- package/Tests/Server/Middleware/TelemetryIngestBrowserKey.test.ts +63 -5
- package/Tests/Server/Middleware/TelemetryIngestKubernetesAgentRunnerPinnedKey.test.ts +103 -5
- package/Tests/Server/Middleware/TelemetryIngestKubernetesAgentRunnerRateLimit.test.ts +19 -1
- package/Tests/Server/Middleware/UserAuthorization.test.ts +16 -17
- package/Tests/Server/Middleware/UserAuthorizationSsoEnforcement.test.ts +544 -0
- package/Tests/Server/Services/AIServiceDailyBudget.test.ts +37 -8
- package/Tests/Server/Services/AutoRemediationResourceRuleEngine.test.ts +1279 -0
- package/Tests/Server/Services/DatabaseServerService.test.ts +55 -0
- package/Tests/Server/Services/GroupTelemetryUsageExcludeNames.test.ts +299 -0
- package/Tests/Server/Services/HostServiceFindOrCreateMemo.test.ts +44 -0
- package/Tests/Server/Services/IncidentCreatedFeedTitle.test.ts +212 -0
- package/Tests/Server/Services/IncidentCustomFieldDeleteFormQuestions.test.ts +297 -0
- package/Tests/Server/Services/IncidentFormOwnersCreatedNotification.test.ts +497 -0
- package/Tests/Server/Services/IncidentFormPostgres.test.ts +958 -0
- package/Tests/Server/Services/IncidentFormPublicForm.test.ts +1260 -0
- package/Tests/Server/Services/IncidentFormPublicSubmission.test.ts +2520 -0
- package/Tests/Server/Services/IncidentFormRegistration.test.ts +159 -0
- package/Tests/Server/Services/IncidentFormService.test.ts +663 -0
- package/Tests/Server/Services/IncidentFormSubmissionService.test.ts +430 -0
- package/Tests/Server/Services/IncidentFormSubmissionTemplateBranch.test.ts +473 -0
- package/Tests/Server/Services/IncidentGroupingTemplateSubstitution.test.ts +81 -0
- package/Tests/Server/Services/IncidentTemplateCustomFieldSettings.test.ts +262 -0
- package/Tests/Server/Services/IncidentTemplateOwnersOnDeclare.test.ts +566 -0
- package/Tests/Server/Services/IncidentTitleMarkdownSinks.test.ts +640 -0
- package/Tests/Server/Services/LlmLogServiceTokenAggregateParams.test.ts +3 -3
- package/Tests/Server/Services/MessageQueueOwnerServices.test.ts +440 -0
- package/Tests/Server/Services/MessageQueueRegistries.test.ts +577 -0
- package/Tests/Server/Services/MessageQueueRuleEngines.test.ts +900 -0
- package/Tests/Server/Services/MessageQueueService.test.ts +2210 -0
- package/Tests/Server/Services/MessageQueueSqlPostgres.test.ts +1271 -0
- package/Tests/Server/Services/MonitorProbeServiceIntervalScheduling.test.ts +45 -6
- package/Tests/Server/Services/OpenTelemetryResourceRetentionMemo.test.ts +28 -1
- package/Tests/Server/Services/OpenTelemetryRetentionOverrideEdition.test.ts +474 -0
- package/Tests/Server/Services/OpenTelemetryServiceResolutionCache.test.ts +21 -0
- package/Tests/Server/Services/OwnerRowUniqueness.test.ts +3 -0
- package/Tests/Server/Services/ProjectServiceAuditLogLicense.test.ts +0 -1
- package/Tests/Server/Services/RecordingRuleReservedMetricName.test.ts +171 -0
- package/Tests/Server/Services/ResourceAiAccessChangeAuthorization.test.ts +256 -0
- package/Tests/Server/Services/ResourceAiAccessService.test.ts +1373 -0
- package/Tests/Server/Services/ResourceAiAgentJobService.test.ts +375 -0
- package/Tests/Server/Services/ResourceAiAgentServiceHelpers.test.ts +1114 -0
- package/Tests/Server/Services/ResourceAiAgentServiceLifecycle.test.ts +1050 -0
- package/Tests/Server/Services/ResourceAiAgentServiceRegister.test.ts +2251 -0
- package/Tests/Server/Services/ResourceAiSettingsCreate.test.ts +373 -0
- package/Tests/Server/Services/ResourceAiSettingsPermission.test.ts +1042 -0
- package/Tests/Server/Services/ResourceServiceDeleteCleansUpAi.test.ts +319 -0
- package/Tests/Server/Services/RuleRun/LabelRuleEnginesGroupBRun.test.ts +56 -6
- package/Tests/Server/Services/RuleRun/OwnerRuleEnginesGroupBRun.test.ts +30 -1
- package/Tests/Server/Services/RunnerJobEnqueueKubectl.test.ts +105 -0
- package/Tests/Server/Services/RunnerJobEnqueueResourceCommand.test.ts +986 -0
- package/Tests/Server/Services/RunnerJobResourceCommandLane.test.ts +211 -0
- package/Tests/Server/Services/RunnerJobResourceCommandTimeoutAndRedaction.test.ts +352 -0
- package/Tests/Server/Services/SsoRequirementReads.test.ts +454 -0
- package/Tests/Server/Services/SsoRequirementWrites.test.ts +529 -0
- package/Tests/Server/Services/StaticRuleCriteriaRuntimeCoverage.test.ts +3 -3
- package/Tests/Server/Services/StatusPagePrivateUserInvitationPolicy.test.ts +107 -89
- package/Tests/Server/Services/TeamComplianceSettingPostgres.test.ts +1068 -176
- package/Tests/Server/Services/TeamComplianceSettingService.test.ts +1962 -200
- package/Tests/Server/Services/TelemetryUsageBillingSloExclusion.test.ts +218 -0
- package/Tests/Server/TestingUtils/Services/FakeRunnerJobCount.ts +145 -0
- package/Tests/Server/Types/Database/Permissions/EditionPermission.test.ts +654 -297
- package/Tests/Server/Types/Database/Permissions/RetentionOverrideColumns.test.ts +784 -0
- package/Tests/Server/Types/Database/Permissions/SsoScalePlanGate.test.ts +418 -0
- package/Tests/Server/Utils/AI/AIAlertGating.test.ts +0 -1
- package/Tests/Server/Utils/AI/AIInvestigationEngineRunLimits.test.ts +136 -0
- package/Tests/Server/Utils/AI/AIInvestigationQueue.test.ts +15 -14
- package/Tests/Server/Utils/AI/AgentContextCompactor.test.ts +351 -0
- package/Tests/Server/Utils/AI/ChatAgentRunnerSharedThread.test.ts +842 -0
- package/Tests/Server/Utils/AI/ChatRunCancellation.test.ts +195 -0
- package/Tests/Server/Utils/AI/CodeFixReadiness.test.ts +10 -57
- package/Tests/Server/Utils/AI/FixRunBudget.test.ts +20 -24
- package/Tests/Server/Utils/AI/Insights/InvestigationQueueInsightSubject.test.ts +7 -30
- package/Tests/Server/Utils/AI/InvestigationClusterAccessWiring.test.ts +225 -29
- package/Tests/Server/Utils/AI/InvestigationInfrastructureAccessWiring.test.ts +694 -0
- package/Tests/Server/Utils/AI/InvestigationInfrastructureReport.test.ts +721 -0
- package/Tests/Server/Utils/AI/InvestigationThread.test.ts +580 -0
- package/Tests/Server/Utils/AI/InvestigationThreadService.test.ts +801 -0
- package/Tests/Server/Utils/AI/KubectlInvestigationToolkit.test.ts +525 -43
- package/Tests/Server/Utils/AI/KubectlJobRunner.test.ts +4 -2
- package/Tests/Server/Utils/AI/LLMServiceUnreachableProvider.test.ts +435 -0
- package/Tests/Server/Utils/AI/ObservabilityAssistantLimits.test.ts +462 -0
- package/Tests/Server/Utils/AI/RemediationCommandTools.test.ts +94 -1
- package/Tests/Server/Utils/AI/RemediationCommandToolsResource.test.ts +1530 -0
- package/Tests/Server/Utils/AI/RemediationExecutionRunner.test.ts +14 -25
- package/Tests/Server/Utils/AI/RemediationExecutionRunnerResourceMode.test.ts +1251 -0
- package/Tests/Server/Utils/AI/RemediationPlanRunner.test.ts +117 -0
- package/Tests/Server/Utils/AI/RemediationResourceCopyParity.test.ts +463 -0
- package/Tests/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.test.ts +1004 -0
- package/Tests/Server/Utils/AI/ResourceAccess/ResourceAccessContext.test.ts +266 -0
- package/Tests/Server/Utils/AI/ResourceAccess/ResourceAiAccessSettings.test.ts +1220 -0
- package/Tests/Server/Utils/AI/ResourceAccess/ResourceAiDeleteCleanup.test.ts +569 -0
- package/Tests/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.test.ts +834 -0
- package/Tests/Server/Utils/AI/ToolOutputPager.test.ts +382 -0
- package/Tests/Server/Utils/AI/ToolResultSerializer.test.ts +23 -4
- package/Tests/Server/Utils/AI/Toolbox/LogTools.test.ts +25 -6
- package/Tests/Server/Utils/AI/Toolbox/Serializer.test.ts +14 -3
- package/Tests/Server/Utils/AutoRemediation/CommandPlanExecutorResource.test.ts +717 -0
- package/Tests/Server/Utils/AutoRemediation/RemediationVerifierResourceFollowUp.test.ts +338 -0
- package/Tests/Server/Utils/EditionEnforcement.test.ts +107 -147
- package/Tests/Server/Utils/Monitor/Criteria/SessionReplayBudgetTemplateCriteria.test.ts +422 -0
- package/Tests/Server/Utils/{CommunityEditionSsoReport.test.ts → RelaxedScimTeamLocksReport.test.ts} +212 -208
- package/Tests/Server/Utils/SameOriginRequest.test.ts +372 -0
- package/Tests/Server/Utils/SessionReplay/SessionReplayBudgetMetrics.test.ts +1647 -0
- package/Tests/Server/Utils/SessionReplay/SessionReplayUsage.test.ts +143 -1
- package/Tests/Server/Utils/Telemetry/EntityRegistry.test.ts +20 -0
- package/Tests/Server/Utils/Telemetry/MessageQueueDiscovery.test.ts +2590 -0
- package/Tests/Server/Utils/Telemetry/MessageQueueSpanQueryTwin.ts +246 -0
- package/Tests/Server/Utils/Telemetry/TelemetryEntity.test.ts +23 -0
- package/Tests/Server/Utils/Telemetry/TelemetryIngestionKeyGuard.test.ts +33 -3
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsAccountNotLinked.test.ts +1093 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsActivityDeduplicator.test.ts +1049 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCardChoices.test.ts +1676 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateCards.test.ts +2884 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateCommands.test.ts +2490 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateSubmit.test.ts +2293 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateSubmitServerTimezone.test.ts +386 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsMessageSize.test.ts +1477 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsReplies.test.ts +1967 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsStripHtmlTags.test.ts +92 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsSubmittedFormRemoval.test.ts +1819 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsTimezone.test.ts +1033 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsTimezoneServerZone.test.ts +610 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsBotMessageHandling.test.ts +2610 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsCreateCommandsEndToEnd.test.ts +4672 -0
- package/Tests/Server/Utils/Workspace/WorkspaceCreateProjectReferences.test.ts +190 -65
- package/Tests/Types/AI/AIAgentRunLimits.test.ts +255 -0
- package/Tests/Types/AutoRemediation/AiRemediationCommandPlan.test.ts +10 -4
- package/Tests/Types/AutoRemediation/AiRemediationCommandPlanResourceCommand.test.ts +305 -0
- package/Tests/Types/Code/JsonSyntax.test.ts +1300 -0
- package/Tests/Types/CustomField/CustomFieldCreateSettings.test.ts +1113 -0
- package/Tests/Types/CustomField/CustomFieldMappingCatalog.test.ts +91 -0
- package/Tests/Types/CustomField/CustomFieldValueValidator.test.ts +30 -0
- package/Tests/Types/Incident/IncidentFormIpAllowlist.test.ts +227 -0
- package/Tests/Types/Incident/IncidentFormPublic.test.ts +1916 -0
- package/Tests/Types/MessageQueue/MessageQueueEntityKey.test.ts +916 -0
- package/Tests/Types/MessageQueue/MessageQueueIdentity.test.ts +567 -0
- package/Tests/Types/MessageQueue/MessageQueueManualIdentity.test.ts +686 -0
- package/Tests/Types/MessageQueue/MessageQueueMetricCatalog.test.ts +1726 -0
- package/Tests/Types/MessageQueue/MessageQueueMetricResolution.test.ts +1758 -0
- package/Tests/Types/MessageQueue/MessagingInstrumentationFixtures.test.ts +4686 -0
- package/Tests/Types/MessageQueue/MessagingSystem.test.ts +840 -0
- package/Tests/Types/MessageQueue/MessagingTelemetryFixtures.ts +3287 -0
- package/Tests/Types/MessageQueue/MessagingTelemetryResolver.test.ts +2966 -0
- package/Tests/Types/Monitor/MessageQueueAlertTemplates.test.ts +5401 -0
- package/Tests/Types/Monitor/MetricEngineFold.ts +154 -0
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCatalog.test.ts +277 -13
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationUtil.test.ts +113 -0
- package/Tests/Types/Monitor/RumAlertTemplates.test.ts +773 -2
- package/Tests/Types/ResourceAiAgent/AiResourceType.test.ts +419 -0
- package/Tests/Types/ResourceAiAgent/ResourceAiAccess.test.ts +519 -0
- package/Tests/Types/Runbook/RunbookStepType.test.ts +147 -8
- package/Tests/Types/Team/ComplianceRule.test.ts +588 -37
- package/Tests/Types/Team/TeamComplianceStatus.test.ts +64 -11
- package/Tests/Types/XML.test.ts +51 -0
- package/Tests/UI/Components/CodeEditor/CodeEditor.test.tsx +2362 -0
- package/Tests/UI/Components/CodeEditor/CodeEditorCommands.test.ts +810 -0
- package/Tests/UI/Components/CodeEditor/CodeEditorHighlight.test.ts +338 -0
- package/Tests/UI/Components/CodeEditor/CodeEditorLanguages.test.ts +222 -0
- package/Tests/UI/Components/CodeEditor/CodeEditorStyles.test.ts +807 -0
- package/Tests/UI/Components/CodeEditor/NoMonaco.test.ts +245 -0
- package/Tests/UI/Components/CodeEditor/YamlEditor.test.tsx +729 -0
- package/Tests/UI/Components/CopyTextButton.test.tsx +76 -0
- package/Tests/UI/Components/EditionLabelLapseCopy.ts +51 -14
- package/Tests/UI/Components/EditionLabelLicenseStatus.test.tsx +131 -23
- package/Tests/UI/Components/ErrorMessageAction.test.tsx +142 -0
- package/Tests/UI/Components/FacetSidebarInScope.test.tsx +459 -0
- package/Tests/UI/Components/FacetValuesInScope.test.ts +270 -0
- package/Tests/UI/Components/Forms/FormFieldCodeEditors.test.tsx +294 -0
- package/Tests/UI/Components/Forms/FormFieldMarkdown.test.tsx +126 -0
- package/Tests/UI/Components/Forms/FormFieldYaml.test.tsx +22 -75
- package/Tests/UI/Components/Forms/ModelFormOnBeforeCreateMiscData.test.tsx +254 -0
- package/Tests/UI/Components/Icon.test.tsx +32 -0
- package/Tests/UI/Components/Input.test.tsx +31 -0
- package/Tests/UI/Components/LockedFilterChipScope.test.tsx +501 -0
- package/Tests/UI/Components/MarkdownConverters.test.ts +253 -1
- package/Tests/UI/Components/MarkdownEditor.test.tsx +2785 -2
- package/Tests/UI/Components/MarkdownEditorHistory.test.ts +243 -0
- package/Tests/UI/Components/MarkdownListEditing.test.ts +1118 -0
- package/Tests/UI/Components/MarkdownPaste.test.ts +1180 -0
- package/Tests/UI/Components/MarkdownViewerCopy.test.tsx +466 -0
- package/Tests/UI/Components/MarkdownVisualEditing.test.ts +1089 -0
- package/Tests/UI/Components/ModelTable/BaseModelTableEmptyStateAction.test.tsx +623 -0
- package/Tests/UI/Components/ResetObjectID.test.tsx +282 -0
- package/Tests/UI/Components/RuleCriteria/RuleCriteriaModelTable.test.tsx +3 -3
- package/Tests/UI/Components/Table/EmptyTableMessage.test.ts +439 -0
- package/Tests/UI/Components/Table/TableEmptyState.test.tsx +352 -0
- package/Tests/UI/Components/TableRowMobileTitles.test.tsx +78 -0
- package/Tests/UI/Components/TextArea.test.tsx +19 -0
- package/Tests/UI/Components/Workflow/ModelColumnEditor.render.test.tsx +12 -29
- package/Tests/UI/Components/fixtures/MarkdownPasteFixtures.ts +460 -0
- package/Tests/UI/EsbuildConfig.test.ts +115 -39
- package/Tests/UI/EsbuildEnterpriseAlias.test.ts +4 -4
- package/Tests/UI/Monitor/MonitorLogSummaryRender.test.tsx +377 -0
- package/Tests/UI/Rum/RecordingHealthDashboard.test.tsx +769 -1
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +81 -1
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +17 -0
- package/Tests/Utils/AiRemediation/Resource/CephCommandPolicy.test.ts +1653 -0
- package/Tests/Utils/AiRemediation/Resource/CephOutputRedaction.test.ts +204 -0
- package/Tests/Utils/AiRemediation/Resource/DatabaseCommandPolicy.test.ts +1077 -0
- package/Tests/Utils/AiRemediation/Resource/DatabaseDiagnosticCatalog.test.ts +558 -0
- package/Tests/Utils/AiRemediation/Resource/DatabaseQueryRedactor.test.ts +834 -0
- package/Tests/Utils/AiRemediation/Resource/DockerCliGrammar.test.ts +747 -0
- package/Tests/Utils/AiRemediation/Resource/DockerEngineCommandPolicy.test.ts +1259 -0
- package/Tests/Utils/AiRemediation/Resource/DockerOutputRedaction.test.ts +386 -0
- package/Tests/Utils/AiRemediation/Resource/DockerSwarmCommandPolicy.test.ts +782 -0
- package/Tests/Utils/AiRemediation/Resource/GovcCommandPolicy.test.ts +2259 -0
- package/Tests/Utils/AiRemediation/Resource/HostCommandPolicy.test.ts +2019 -0
- package/Tests/Utils/AiRemediation/Resource/ProxmoxCommandPolicy.test.ts +2497 -0
- package/Tests/Utils/AiRemediation/Resource/ResourceCommandPolicy.test.ts +1305 -0
- package/Tests/Utils/AiRemediation/Resource/ResourceCommandPolicyCore.test.ts +585 -0
- package/Tests/Utils/AiRemediation/Resource/ResourceOutputRedactor.test.ts +334 -0
- package/Tests/Utils/AiRemediation/Resource/ResourceOutputRedactorCopyParity.test.ts +98 -0
- package/Tests/Utils/AiRemediation/Resource/ResourcePolicyImportClosure.test.ts +391 -0
- package/Tests/Utils/AiRemediation/ResourceAiAgentPolicyCopyParity.test.ts +497 -0
- package/Tests/Utils/LabelRuleImportExport.test.ts +5 -0
- package/Tests/Utils/Markdown/DashboardMarkdownRenderer.ts +81 -0
- package/Tests/Utils/Markdown/UntrustedMarkdown.test.ts +1339 -0
- package/Tests/Utils/Monitor/MonitorLogSummaryUtil.test.ts +862 -0
- package/Tests/Utils/SessionReplay/SessionReplayBudgetMetricType.test.ts +383 -0
- package/Types/AI/AIAgentRunLimits.ts +146 -0
- package/Types/AI/ResourceAiAccessApi.ts +140 -0
- package/Types/AI/ResourceAiAccessPermissions.ts +126 -0
- package/Types/AutoRemediation/AiRemediationCommandPlan.ts +183 -2
- package/Types/Code/CodeType.ts +2 -0
- package/Types/Code/JsonSyntax.ts +923 -0
- package/Types/CustomField/CustomFieldCreateSettings.ts +549 -0
- package/Types/CustomField/CustomFieldMappingCatalog.ts +77 -0
- package/Types/CustomField/CustomFieldValueValidator.ts +10 -7
- package/Types/EnterpriseLicense/EnterpriseLicensePeriods.ts +1 -1
- package/Types/Icon/IconProp.ts +2 -0
- package/Types/Incident/IncidentFormIpAllowlist.ts +206 -0
- package/Types/Incident/IncidentFormPublic.ts +1145 -0
- package/Types/Kubernetes/KubernetesClusterAiAccess.ts +10 -3
- package/Types/MessageQueue/MessageQueueIdentity.ts +256 -0
- package/Types/MessageQueue/MessageQueueManualIdentity.ts +325 -0
- package/Types/MessageQueue/MessageQueueMetricCatalog.ts +1357 -0
- package/Types/MessageQueue/MessagingSystem.ts +518 -0
- package/Types/MessageQueue/MessagingTelemetryResolver.ts +2311 -0
- package/Types/Monitor/MessageQueueAlertTemplates.ts +2128 -0
- package/Types/Monitor/Recommendation/MonitorRecommendationCatalog.ts +55 -22
- package/Types/Monitor/Recommendation/MonitorRecommendationTypes.ts +35 -3
- package/Types/Monitor/RumAlertTemplates.ts +351 -4
- package/Types/Permission.ts +310 -0
- package/Types/ResourceAiAgent/AiResourceType.ts +310 -0
- package/Types/ResourceAiAgent/ResourceAiAccess.ts +580 -0
- package/Types/Rules/RuleCriteriaFieldRegistry.ts +12 -0
- package/Types/Rules/RuleRun.ts +4 -0
- package/Types/Rum/SessionReplayBudgetMetricType.ts +47 -0
- package/Types/Runbook/RunbookStepType.ts +29 -0
- package/Types/Team/ComplianceNotificationChannel.ts +4 -3
- package/Types/Team/ComplianceRule.ts +71 -18
- package/Types/Team/ComplianceRuleType.ts +2 -2
- package/Types/Team/TeamComplianceStatus.ts +6 -2
- package/Types/Telemetry/EntityType.ts +16 -0
- package/Types/Telemetry/LockedFilterDetail.ts +22 -0
- package/Types/Telemetry/TelemetryIngestSurface.ts +14 -2
- package/Types/XML.ts +26 -0
- package/UI/Components/CodeEditor/CodeEditor.css +379 -0
- package/UI/Components/CodeEditor/CodeEditor.tsx +1128 -294
- package/UI/Components/CodeEditor/CodeEditorCommands.ts +774 -0
- package/UI/Components/CodeEditor/CodeEditorHighlight.ts +106 -0
- package/UI/Components/CodeEditor/CodeEditorLanguages.ts +164 -0
- package/UI/Components/CodeEditor/YamlEditor.tsx +28 -326
- package/UI/Components/CopyTextButton/CopyTextButton.tsx +5 -1
- package/UI/Components/CustomFields/CustomFieldModelFormFields.tsx +6 -25
- package/UI/Components/EditionLabel/EditionLabel.tsx +14 -13
- package/UI/Components/ErrorMessage/ErrorMessage.tsx +11 -1
- package/UI/Components/Forms/Fields/FormField.tsx +8 -0
- package/UI/Components/Forms/Types/Field.ts +8 -0
- package/UI/Components/Icon/Icon.tsx +18 -0
- package/UI/Components/Input/Input.tsx +11 -4
- package/UI/Components/LogsViewer/LogsViewer.tsx +4 -0
- package/UI/Components/LogsViewer/components/LogsFacetSidebar.tsx +21 -3
- package/UI/Components/Markdown.tsx/MarkdownConverters.ts +0 -0
- package/UI/Components/Markdown.tsx/MarkdownEditor.tsx +877 -79
- package/UI/Components/Markdown.tsx/MarkdownEditorHistory.ts +284 -0
- package/UI/Components/Markdown.tsx/MarkdownListEditing.ts +1362 -0
- package/UI/Components/Markdown.tsx/MarkdownPaste.ts +1326 -0
- package/UI/Components/Markdown.tsx/MarkdownViewer.tsx +106 -10
- package/UI/Components/Markdown.tsx/MarkdownVisualEditing.ts +1032 -0
- package/UI/Components/ModelTable/BaseModelTable.tsx +85 -7
- package/UI/Components/ResetObjectID/ResetObjectID.tsx +35 -9
- package/UI/Components/Table/EmptyTableMessage.ts +81 -0
- package/UI/Components/Table/Table.tsx +50 -21
- package/UI/Components/Table/TableRow.tsx +9 -1
- package/UI/Components/TelemetryViewer/FacetVisibility.ts +97 -2
- package/UI/Components/TelemetryViewer/TelemetryViewer.tsx +13 -0
- package/UI/Components/TelemetryViewer/components/LockedFilterChip.tsx +214 -7
- package/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.tsx +21 -3
- package/UI/Components/TextArea/TextArea.tsx +9 -2
- package/UI/Components/Workflow/ModelFieldPicker.tsx +10 -12
- package/UI/Styles/Theme.css +8 -0
- package/UI/esbuild-config.js +2 -32
- package/Utils/AI/InvestigationReport.ts +121 -15
- package/Utils/AiRemediation/Resource/CephCommandPolicy.ts +1936 -0
- package/Utils/AiRemediation/Resource/DatabaseCommandPolicy.ts +166 -0
- package/Utils/AiRemediation/Resource/DatabaseDiagnosticCatalog.ts +1532 -0
- package/Utils/AiRemediation/Resource/DatabaseQueryRedactor.ts +1394 -0
- package/Utils/AiRemediation/Resource/DockerCliGrammar.ts +1839 -0
- package/Utils/AiRemediation/Resource/DockerEngineCommandPolicy.ts +490 -0
- package/Utils/AiRemediation/Resource/DockerSwarmCommandPolicy.ts +687 -0
- package/Utils/AiRemediation/Resource/GovcCommandPolicy.ts +2096 -0
- package/Utils/AiRemediation/Resource/HostCommandPolicy.ts +2982 -0
- package/Utils/AiRemediation/Resource/ProxmoxCommandPolicy.ts +1679 -0
- package/Utils/AiRemediation/Resource/ResourceCommandPolicy.ts +851 -0
- package/Utils/AiRemediation/Resource/ResourceCommandPolicyCore.ts +593 -0
- package/Utils/AiRemediation/Resource/ResourceOutputRedactor.ts +2812 -0
- package/Utils/LabelRuleImportExport.ts +2 -0
- package/Utils/Markdown/UntrustedMarkdown.ts +1513 -0
- package/Utils/Monitor/IncomingEmailMonitorRequestUtil.ts +41 -0
- package/Utils/Monitor/MonitorLogSummaryUtil.ts +212 -0
- package/Utils/SessionReplay/SessionReplayBudgetMetricType.ts +184 -0
- package/Utils/Telemetry/EntityKey.ts +48 -0
- package/build/dist/Models/DatabaseModels/AIConversation.js +125 -1
- package/build/dist/Models/DatabaseModels/AIConversation.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AutoRemediationSuggestion.js +62 -0
- package/build/dist/Models/DatabaseModels/AutoRemediationSuggestion.js.map +1 -1
- package/build/dist/Models/DatabaseModels/CephCluster.js +231 -0
- package/build/dist/Models/DatabaseModels/CephCluster.js.map +1 -1
- package/build/dist/Models/DatabaseModels/CloudResource.js +12 -0
- package/build/dist/Models/DatabaseModels/CloudResource.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DatabaseServer.js +231 -0
- package/build/dist/Models/DatabaseModels/DatabaseServer.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DockerHost.js +231 -0
- package/build/dist/Models/DatabaseModels/DockerHost.js.map +1 -1
- package/build/dist/Models/DatabaseModels/DockerSwarmCluster.js +231 -0
- package/build/dist/Models/DatabaseModels/DockerSwarmCluster.js.map +1 -1
- package/build/dist/Models/DatabaseModels/GlobalConfig.js +1 -1
- package/build/dist/Models/DatabaseModels/GlobalConfig.js.map +1 -1
- package/build/dist/Models/DatabaseModels/GlobalOidc.js +0 -4
- package/build/dist/Models/DatabaseModels/GlobalOidc.js.map +1 -1
- package/build/dist/Models/DatabaseModels/GlobalOidcProject.js +0 -4
- package/build/dist/Models/DatabaseModels/GlobalOidcProject.js.map +1 -1
- package/build/dist/Models/DatabaseModels/GlobalSso.js +0 -4
- package/build/dist/Models/DatabaseModels/GlobalSso.js.map +1 -1
- package/build/dist/Models/DatabaseModels/GlobalSsoProject.js +0 -4
- package/build/dist/Models/DatabaseModels/GlobalSsoProject.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Host.js +231 -0
- package/build/dist/Models/DatabaseModels/Host.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentForm.js +605 -0
- package/build/dist/Models/DatabaseModels/IncidentForm.js.map +1 -0
- package/build/dist/Models/DatabaseModels/IncidentFormSubmission.js +299 -0
- package/build/dist/Models/DatabaseModels/IncidentFormSubmission.js.map +1 -0
- package/build/dist/Models/DatabaseModels/IncidentTemplate.js +60 -0
- package/build/dist/Models/DatabaseModels/IncidentTemplate.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Index.js +16 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IoTFleet.js +12 -0
- package/build/dist/Models/DatabaseModels/IoTFleet.js.map +1 -1
- package/build/dist/Models/DatabaseModels/KubernetesCluster.js +12 -0
- package/build/dist/Models/DatabaseModels/KubernetesCluster.js.map +1 -1
- package/build/dist/Models/DatabaseModels/MessageQueue.js +1106 -0
- package/build/dist/Models/DatabaseModels/MessageQueue.js.map +1 -0
- package/build/dist/Models/DatabaseModels/MessageQueueLabelRule.js +562 -0
- package/build/dist/Models/DatabaseModels/MessageQueueLabelRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/MessageQueueOwnerRule.js +643 -0
- package/build/dist/Models/DatabaseModels/MessageQueueOwnerRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/MessageQueueOwnerTeam.js +506 -0
- package/build/dist/Models/DatabaseModels/MessageQueueOwnerTeam.js.map +1 -0
- package/build/dist/Models/DatabaseModels/MessageQueueOwnerUser.js +505 -0
- package/build/dist/Models/DatabaseModels/MessageQueueOwnerUser.js.map +1 -0
- package/build/dist/Models/DatabaseModels/PodmanHost.js +231 -0
- package/build/dist/Models/DatabaseModels/PodmanHost.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Project.js +61 -0
- package/build/dist/Models/DatabaseModels/Project.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ProjectOidc.js +0 -4
- package/build/dist/Models/DatabaseModels/ProjectOidc.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ProjectSso.js +0 -4
- package/build/dist/Models/DatabaseModels/ProjectSso.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ProxmoxCluster.js +231 -0
- package/build/dist/Models/DatabaseModels/ProxmoxCluster.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ResourceAiAgent.js +439 -0
- package/build/dist/Models/DatabaseModels/ResourceAiAgent.js.map +1 -0
- package/build/dist/Models/DatabaseModels/RumApplication.js +12 -0
- package/build/dist/Models/DatabaseModels/RumApplication.js.map +1 -1
- package/build/dist/Models/DatabaseModels/RunnerJob.js +145 -0
- package/build/dist/Models/DatabaseModels/RunnerJob.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ServerlessFunction.js +12 -0
- package/build/dist/Models/DatabaseModels/ServerlessFunction.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Service.js +12 -0
- package/build/dist/Models/DatabaseModels/Service.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageOidc.js +0 -4
- package/build/dist/Models/DatabaseModels/StatusPageOidc.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageSso.js +0 -4
- package/build/dist/Models/DatabaseModels/StatusPageSso.js.map +1 -1
- package/build/dist/Models/DatabaseModels/TeamComplianceSetting.js +49 -3
- package/build/dist/Models/DatabaseModels/TeamComplianceSetting.js.map +1 -1
- package/build/dist/Models/DatabaseModels/VMwareVCenter.js +231 -0
- package/build/dist/Models/DatabaseModels/VMwareVCenter.js.map +1 -1
- package/build/dist/Server/API/AIChatAPI.js +9 -103
- package/build/dist/Server/API/AIChatAPI.js.map +1 -1
- package/build/dist/Server/API/AIInvestigationAPI.js +3 -3
- package/build/dist/Server/API/AIInvestigationAPI.js.map +1 -1
- package/build/dist/Server/API/AIInvestigationConversationAPI.js +162 -0
- package/build/dist/Server/API/AIInvestigationConversationAPI.js.map +1 -0
- package/build/dist/Server/API/AutoRemediationAPI.js +231 -1
- package/build/dist/Server/API/AutoRemediationAPI.js.map +1 -1
- package/build/dist/Server/API/IncidentFormAPI.js +245 -0
- package/build/dist/Server/API/IncidentFormAPI.js.map +1 -0
- package/build/dist/Server/API/ProjectOIDC.js +16 -24
- package/build/dist/Server/API/ProjectOIDC.js.map +1 -1
- package/build/dist/Server/API/ProjectSSO.js +16 -24
- package/build/dist/Server/API/ProjectSSO.js.map +1 -1
- package/build/dist/Server/API/ResourceAiAccessAPI.js +1119 -0
- package/build/dist/Server/API/ResourceAiAccessAPI.js.map +1 -0
- package/build/dist/Server/API/StatusPageAPI.js +42 -75
- package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
- package/build/dist/Server/Enterprise/EnterpriseEdition.js +79 -25
- package/build/dist/Server/Enterprise/EnterpriseEdition.js.map +1 -1
- package/build/dist/Server/Enterprise/EnterpriseFeature.js +24 -3
- package/build/dist/Server/Enterprise/EnterpriseFeature.js.map +1 -1
- package/build/dist/Server/Enterprise/EnterpriseLicenseSnapshot.js +1 -1
- package/build/dist/Server/Enterprise/EnterpriseServerModule.js.map +1 -1
- package/build/dist/Server/EnvironmentConfig.js +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796300000000-AddResourceAiAgents.js +168 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796300000000-AddResourceAiAgents.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796400000000-AddIncidentForms.js +63 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796400000000-AddIncidentForms.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796500000000-AddTeamComplianceRuleNotificationChannels.js +41 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796500000000-AddTeamComplianceRuleNotificationChannels.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796600000000-AddAIInvestigationConversationAndTimeLimits.js +40 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796600000000-AddAIInvestigationConversationAndTimeLimits.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796700000000-AddMessageQueueTables.js +183 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1796700000000-AddMessageQueueTables.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +10 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Infrastructure/Semaphore.js +6 -0
- package/build/dist/Server/Infrastructure/Semaphore.js.map +1 -1
- package/build/dist/Server/Middleware/IncidentFormRateLimit.js +559 -0
- package/build/dist/Server/Middleware/IncidentFormRateLimit.js.map +1 -0
- package/build/dist/Server/Middleware/TelemetryIngest.js +12 -5
- package/build/dist/Server/Middleware/TelemetryIngest.js.map +1 -1
- package/build/dist/Server/Middleware/UserAuthorization.js +11 -30
- package/build/dist/Server/Middleware/UserAuthorization.js.map +1 -1
- package/build/dist/Server/Services/AIService.js +10 -13
- package/build/dist/Server/Services/AIService.js.map +1 -1
- package/build/dist/Server/Services/AnalyticsDatabaseService.js +26 -1
- package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
- package/build/dist/Server/Services/AutoRemediationRuleEngineService.js +601 -3
- package/build/dist/Server/Services/AutoRemediationRuleEngineService.js.map +1 -1
- package/build/dist/Server/Services/CephClusterService.js +104 -0
- package/build/dist/Server/Services/CephClusterService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseServerService.js +99 -0
- package/build/dist/Server/Services/DatabaseServerService.js.map +1 -1
- package/build/dist/Server/Services/DockerHostService.js +104 -0
- package/build/dist/Server/Services/DockerHostService.js.map +1 -1
- package/build/dist/Server/Services/DockerSwarmClusterService.js +104 -0
- package/build/dist/Server/Services/DockerSwarmClusterService.js.map +1 -1
- package/build/dist/Server/Services/HostService.js +114 -2
- package/build/dist/Server/Services/HostService.js.map +1 -1
- package/build/dist/Server/Services/IncidentCustomFieldService.js +83 -0
- package/build/dist/Server/Services/IncidentCustomFieldService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodeMemberService.js +8 -4
- package/build/dist/Server/Services/IncidentEpisodeMemberService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodeService.js +10 -1
- package/build/dist/Server/Services/IncidentEpisodeService.js.map +1 -1
- package/build/dist/Server/Services/IncidentFormService.js +1202 -0
- package/build/dist/Server/Services/IncidentFormService.js.map +1 -0
- package/build/dist/Server/Services/IncidentFormSubmissionService.js +91 -0
- package/build/dist/Server/Services/IncidentFormSubmissionService.js.map +1 -0
- package/build/dist/Server/Services/IncidentGroupingEngineService.js +20 -8
- package/build/dist/Server/Services/IncidentGroupingEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentService.js +106 -4
- package/build/dist/Server/Services/IncidentService.js.map +1 -1
- package/build/dist/Server/Services/IncidentTemplateService.js +18 -0
- package/build/dist/Server/Services/IncidentTemplateService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +14 -0
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/MessageQueueLabelRuleEngineService.js +262 -0
- package/build/dist/Server/Services/MessageQueueLabelRuleEngineService.js.map +1 -0
- package/build/dist/Server/Services/MessageQueueLabelRuleService.js +13 -0
- package/build/dist/Server/Services/MessageQueueLabelRuleService.js.map +1 -0
- package/build/dist/Server/Services/MessageQueueOwnerRuleEngineService.js +334 -0
- package/build/dist/Server/Services/MessageQueueOwnerRuleEngineService.js.map +1 -0
- package/build/dist/Server/Services/MessageQueueOwnerRuleService.js +13 -0
- package/build/dist/Server/Services/MessageQueueOwnerRuleService.js.map +1 -0
- package/build/dist/Server/Services/MessageQueueOwnerTeamService.js +62 -0
- package/build/dist/Server/Services/MessageQueueOwnerTeamService.js.map +1 -0
- package/build/dist/Server/Services/MessageQueueOwnerUserService.js +62 -0
- package/build/dist/Server/Services/MessageQueueOwnerUserService.js.map +1 -0
- package/build/dist/Server/Services/MessageQueueService.js +1140 -0
- package/build/dist/Server/Services/MessageQueueService.js.map +1 -0
- package/build/dist/Server/Services/MetricRecordingRuleService.js +46 -0
- package/build/dist/Server/Services/MetricRecordingRuleService.js.map +1 -1
- package/build/dist/Server/Services/OpenTelemetryIngestService.js +25 -4
- package/build/dist/Server/Services/OpenTelemetryIngestService.js.map +1 -1
- package/build/dist/Server/Services/PodmanHostService.js +104 -0
- package/build/dist/Server/Services/PodmanHostService.js.map +1 -1
- package/build/dist/Server/Services/ProjectService.js +0 -54
- package/build/dist/Server/Services/ProjectService.js.map +1 -1
- package/build/dist/Server/Services/ProxmoxClusterService.js +104 -0
- package/build/dist/Server/Services/ProxmoxClusterService.js.map +1 -1
- package/build/dist/Server/Services/ResourceAiAccessService.js +1028 -0
- package/build/dist/Server/Services/ResourceAiAccessService.js.map +1 -0
- package/build/dist/Server/Services/ResourceAiAgentJobService.js +173 -0
- package/build/dist/Server/Services/ResourceAiAgentJobService.js.map +1 -0
- package/build/dist/Server/Services/ResourceAiAgentService.js +1687 -0
- package/build/dist/Server/Services/ResourceAiAgentService.js.map +1 -0
- package/build/dist/Server/Services/RunnerJobService.js +344 -5
- package/build/dist/Server/Services/RunnerJobService.js.map +1 -1
- package/build/dist/Server/Services/StatusPagePrivateUserService.js +1 -4
- package/build/dist/Server/Services/StatusPagePrivateUserService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageService.js +0 -46
- package/build/dist/Server/Services/StatusPageService.js.map +1 -1
- package/build/dist/Server/Services/TeamComplianceSettingService.js +120 -31
- package/build/dist/Server/Services/TeamComplianceSettingService.js.map +1 -1
- package/build/dist/Server/Services/TelemetryUsageBillingService.js +26 -0
- package/build/dist/Server/Services/TelemetryUsageBillingService.js.map +1 -1
- package/build/dist/Server/Services/TraceRecordingRuleService.js +37 -0
- package/build/dist/Server/Services/TraceRecordingRuleService.js.map +1 -1
- package/build/dist/Server/Services/UserNotificationRuleService.js +8 -1
- package/build/dist/Server/Services/UserNotificationRuleService.js.map +1 -1
- package/build/dist/Server/Services/VMwareVCenterService.js +104 -0
- package/build/dist/Server/Services/VMwareVCenterService.js.map +1 -1
- package/build/dist/Server/Services/WorkspaceNotificationSummaryService.js +12 -3
- package/build/dist/Server/Services/WorkspaceNotificationSummaryService.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/CreatePermission.js +6 -3
- package/build/dist/Server/Types/Database/Permissions/CreatePermission.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/EditionPermission.js +109 -37
- package/build/dist/Server/Types/Database/Permissions/EditionPermission.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js +16 -0
- package/build/dist/Server/Types/Database/Permissions/OwnerTableRegistry.js.map +1 -1
- package/build/dist/Server/Types/Database/Permissions/TablePermission.js +3 -3
- package/build/dist/Server/Types/Database/Permissions/UpdatePermission.js +9 -6
- package/build/dist/Server/Types/Database/Permissions/UpdatePermission.js.map +1 -1
- package/build/dist/Server/Utils/AI/Chat/AgentContextCompactor.js +128 -0
- package/build/dist/Server/Utils/AI/Chat/AgentContextCompactor.js.map +1 -0
- package/build/dist/Server/Utils/AI/Chat/ChatAgentRunner.js +192 -50
- package/build/dist/Server/Utils/AI/Chat/ChatAgentRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/Chat/ChatRunCancellation.js +133 -0
- package/build/dist/Server/Utils/AI/Chat/ChatRunCancellation.js.map +1 -0
- package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js +53 -13
- package/build/dist/Server/Utils/AI/Chat/ObservabilityAssistant.js.map +1 -1
- package/build/dist/Server/Utils/AI/Chat/ObservabilityChatPrompt.js +1 -1
- package/build/dist/Server/Utils/AI/Chat/ToolOutputPager.js +206 -0
- package/build/dist/Server/Utils/AI/Chat/ToolOutputPager.js.map +1 -0
- package/build/dist/Server/Utils/AI/ClusterAccess/KubectlInvestigationToolkit.js +53 -26
- package/build/dist/Server/Utils/AI/ClusterAccess/KubectlInvestigationToolkit.js.map +1 -1
- package/build/dist/Server/Utils/AI/ClusterAccess/KubectlJobRunner.js +4 -2
- package/build/dist/Server/Utils/AI/ClusterAccess/KubectlJobRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/CodeFix/CodeFixReadiness.js +1 -29
- package/build/dist/Server/Utils/AI/CodeFix/CodeFixReadiness.js.map +1 -1
- package/build/dist/Server/Utils/AI/CodeFix/FixRunBudget.js +24 -24
- package/build/dist/Server/Utils/AI/CodeFix/FixRunBudget.js.map +1 -1
- package/build/dist/Server/Utils/AI/Remediation/RemediationCommandTools.js +1036 -32
- package/build/dist/Server/Utils/AI/Remediation/RemediationCommandTools.js.map +1 -1
- package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js +661 -41
- package/build/dist/Server/Utils/AI/Remediation/RemediationExecutionRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/Remediation/RemediationPlanRunner.js +21 -1
- package/build/dist/Server/Utils/AI/Remediation/RemediationPlanRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.js +354 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/InfrastructureInvestigationToolkit.js.map +1 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAccessContext.js +160 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAccessContext.js.map +1 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAccessToolNames.js +33 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAccessToolNames.js.map +1 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAiAccessSettings.js +640 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAiAccessSettings.js.map +1 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAiDeleteCleanup.js +226 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceAiDeleteCleanup.js.map +1 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.js +602 -0
- package/build/dist/Server/Utils/AI/ResourceAccess/ResourceCommandJobRunner.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js +90 -14
- package/build/dist/Server/Utils/AI/SRE/AIInvestigationEngine.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js +73 -10
- package/build/dist/Server/Utils/AI/SRE/AlertInvestigationRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js +73 -10
- package/build/dist/Server/Utils/AI/SRE/IncidentInvestigationRunner.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/InvestigationQueue.js +15 -18
- package/build/dist/Server/Utils/AI/SRE/InvestigationQueue.js.map +1 -1
- package/build/dist/Server/Utils/AI/SRE/InvestigationThread.js +412 -0
- package/build/dist/Server/Utils/AI/SRE/InvestigationThread.js.map +1 -0
- package/build/dist/Server/Utils/AI/SRE/InvestigationThreadService.js +495 -0
- package/build/dist/Server/Utils/AI/SRE/InvestigationThreadService.js.map +1 -0
- package/build/dist/Server/Utils/AI/Toolbox/Serializer.js +10 -3
- package/build/dist/Server/Utils/AI/Toolbox/Serializer.js.map +1 -1
- package/build/dist/Server/Utils/AutoRemediation/CommandPlanExecutor.js +290 -13
- package/build/dist/Server/Utils/AutoRemediation/CommandPlanExecutor.js.map +1 -1
- package/build/dist/Server/Utils/AutoRemediation/RemediationVerifier.js +29 -1
- package/build/dist/Server/Utils/AutoRemediation/RemediationVerifier.js.map +1 -1
- package/build/dist/Server/Utils/Database/ProjectScopedReferenceValidator.js +9 -1
- package/build/dist/Server/Utils/Database/ProjectScopedReferenceValidator.js.map +1 -1
- package/build/dist/Server/Utils/EditionEnforcement.js +20 -158
- package/build/dist/Server/Utils/EditionEnforcement.js.map +1 -1
- package/build/dist/Server/Utils/LLM/LLMService.js +193 -54
- package/build/dist/Server/Utils/LLM/LLMService.js.map +1 -1
- package/build/dist/Server/Utils/RelaxedScimTeamLocksReport.js +160 -0
- package/build/dist/Server/Utils/RelaxedScimTeamLocksReport.js.map +1 -0
- package/build/dist/Server/Utils/Rules/RuleRun/RuleRunRegistry.js +25 -0
- package/build/dist/Server/Utils/Rules/RuleRun/RuleRunRegistry.js.map +1 -1
- package/build/dist/Server/Utils/SameOriginRequest.js +151 -0
- package/build/dist/Server/Utils/SameOriginRequest.js.map +1 -0
- package/build/dist/Server/Utils/SessionReplay/SessionReplayBudgetMetrics.js +627 -0
- package/build/dist/Server/Utils/SessionReplay/SessionReplayBudgetMetrics.js.map +1 -0
- package/build/dist/Server/Utils/SessionReplay/SessionReplayUsage.js +60 -5
- package/build/dist/Server/Utils/SessionReplay/SessionReplayUsage.js.map +1 -1
- package/build/dist/Server/Utils/TeamMember/ProjectLeaveResourceCleanup.js +2 -0
- package/build/dist/Server/Utils/TeamMember/ProjectLeaveResourceCleanup.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/EntityRegistry.js +4 -1
- package/build/dist/Server/Utils/Telemetry/EntityRegistry.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/MessageQueueDiscovery.js +1015 -0
- package/build/dist/Server/Utils/Telemetry/MessageQueueDiscovery.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/ResourceEntityFilter.js +4 -1
- package/build/dist/Server/Utils/Telemetry/ResourceEntityFilter.js.map +1 -1
- package/build/dist/Server/Utils/VendorAssets.js +3 -3
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.js +19 -15
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/AlertEpisode.js +19 -15
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/AlertEpisode.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Auth.js +17 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Auth.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.js +186 -210
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.js +22 -16
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/IncidentEpisode.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/ScheduledMaintenance.js +233 -167
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/ScheduledMaintenance.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +273 -111
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsActivityDeduplicator.js +129 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsActivityDeduplicator.js.map +1 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCardChoices.js +266 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCardChoices.js.map +1 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateCommands.js +258 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsCreateCommands.js.map +1 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsMessageSize.js +104 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsMessageSize.js.map +1 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsReplies.js +183 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsReplies.js.map +1 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsTimezone.js +123 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeamsTimezone.js.map +1 -0
- package/build/dist/Types/AI/AIAgentRunLimits.js +91 -0
- package/build/dist/Types/AI/AIAgentRunLimits.js.map +1 -0
- package/build/dist/Types/AI/ResourceAiAccessApi.js +30 -0
- package/build/dist/Types/AI/ResourceAiAccessApi.js.map +1 -0
- package/build/dist/Types/AI/ResourceAiAccessPermissions.js +98 -0
- package/build/dist/Types/AI/ResourceAiAccessPermissions.js.map +1 -0
- package/build/dist/Types/AutoRemediation/AiRemediationCommandPlan.js +116 -29
- package/build/dist/Types/AutoRemediation/AiRemediationCommandPlan.js.map +1 -1
- package/build/dist/Types/Code/CodeType.js +2 -0
- package/build/dist/Types/Code/CodeType.js.map +1 -1
- package/build/dist/Types/Code/JsonSyntax.js +604 -0
- package/build/dist/Types/Code/JsonSyntax.js.map +1 -0
- package/build/dist/Types/CustomField/CustomFieldCreateSettings.js +310 -0
- package/build/dist/Types/CustomField/CustomFieldCreateSettings.js.map +1 -0
- package/build/dist/Types/CustomField/CustomFieldMappingCatalog.js +38 -0
- package/build/dist/Types/CustomField/CustomFieldMappingCatalog.js.map +1 -1
- package/build/dist/Types/CustomField/CustomFieldValueValidator.js +10 -7
- package/build/dist/Types/CustomField/CustomFieldValueValidator.js.map +1 -1
- package/build/dist/Types/EnterpriseLicense/EnterpriseLicensePeriods.js +1 -1
- package/build/dist/Types/Icon/IconProp.js +2 -0
- package/build/dist/Types/Icon/IconProp.js.map +1 -1
- package/build/dist/Types/Incident/IncidentFormIpAllowlist.js +119 -0
- package/build/dist/Types/Incident/IncidentFormIpAllowlist.js.map +1 -0
- package/build/dist/Types/Incident/IncidentFormPublic.js +678 -0
- package/build/dist/Types/Incident/IncidentFormPublic.js.map +1 -0
- package/build/dist/Types/Kubernetes/KubernetesClusterAiAccess.js +10 -3
- package/build/dist/Types/Kubernetes/KubernetesClusterAiAccess.js.map +1 -1
- package/build/dist/Types/MessageQueue/MessageQueueIdentity.js +184 -0
- package/build/dist/Types/MessageQueue/MessageQueueIdentity.js.map +1 -0
- package/build/dist/Types/MessageQueue/MessageQueueManualIdentity.js +190 -0
- package/build/dist/Types/MessageQueue/MessageQueueManualIdentity.js.map +1 -0
- package/build/dist/Types/MessageQueue/MessageQueueMetricCatalog.js +1057 -0
- package/build/dist/Types/MessageQueue/MessageQueueMetricCatalog.js.map +1 -0
- package/build/dist/Types/MessageQueue/MessagingSystem.js +394 -0
- package/build/dist/Types/MessageQueue/MessagingSystem.js.map +1 -0
- package/build/dist/Types/MessageQueue/MessagingTelemetryResolver.js +1768 -0
- package/build/dist/Types/MessageQueue/MessagingTelemetryResolver.js.map +1 -0
- package/build/dist/Types/Monitor/MessageQueueAlertTemplates.js +1207 -0
- package/build/dist/Types/Monitor/MessageQueueAlertTemplates.js.map +1 -0
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js +47 -21
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js +5 -0
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js.map +1 -1
- package/build/dist/Types/Monitor/RumAlertTemplates.js +199 -3
- package/build/dist/Types/Monitor/RumAlertTemplates.js.map +1 -1
- package/build/dist/Types/Permission.js +274 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/ResourceAiAgent/AiResourceType.js +242 -0
- package/build/dist/Types/ResourceAiAgent/AiResourceType.js.map +1 -0
- package/build/dist/Types/ResourceAiAgent/ResourceAiAccess.js +281 -0
- package/build/dist/Types/ResourceAiAgent/ResourceAiAccess.js.map +1 -0
- package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js +12 -0
- package/build/dist/Types/Rules/RuleCriteriaFieldRegistry.js.map +1 -1
- package/build/dist/Types/Rules/RuleRun.js +4 -0
- package/build/dist/Types/Rules/RuleRun.js.map +1 -1
- package/build/dist/Types/Rum/SessionReplayBudgetMetricType.js +45 -0
- package/build/dist/Types/Rum/SessionReplayBudgetMetricType.js.map +1 -0
- package/build/dist/Types/Runbook/RunbookStepType.js +27 -0
- package/build/dist/Types/Runbook/RunbookStepType.js.map +1 -1
- package/build/dist/Types/Team/ComplianceNotificationChannel.js +4 -3
- package/build/dist/Types/Team/ComplianceNotificationChannel.js.map +1 -1
- package/build/dist/Types/Team/ComplianceRule.js +48 -14
- package/build/dist/Types/Team/ComplianceRule.js.map +1 -1
- package/build/dist/Types/Team/ComplianceRuleType.js +2 -2
- package/build/dist/Types/Telemetry/EntityType.js +16 -0
- package/build/dist/Types/Telemetry/EntityType.js.map +1 -1
- package/build/dist/Types/Telemetry/TelemetryIngestSurface.js +13 -2
- package/build/dist/Types/Telemetry/TelemetryIngestSurface.js.map +1 -1
- package/build/dist/Types/XML.js +23 -0
- package/build/dist/Types/XML.js.map +1 -1
- package/build/dist/UI/Components/CodeEditor/CodeEditor.js +641 -266
- package/build/dist/UI/Components/CodeEditor/CodeEditor.js.map +1 -1
- package/build/dist/UI/Components/CodeEditor/CodeEditorCommands.js +464 -0
- package/build/dist/UI/Components/CodeEditor/CodeEditorCommands.js.map +1 -0
- package/build/dist/UI/Components/CodeEditor/CodeEditorHighlight.js +69 -0
- package/build/dist/UI/Components/CodeEditor/CodeEditorHighlight.js.map +1 -0
- package/build/dist/UI/Components/CodeEditor/CodeEditorLanguages.js +108 -0
- package/build/dist/UI/Components/CodeEditor/CodeEditorLanguages.js.map +1 -0
- package/build/dist/UI/Components/CodeEditor/YamlEditor.js +14 -186
- package/build/dist/UI/Components/CodeEditor/YamlEditor.js.map +1 -1
- package/build/dist/UI/Components/CopyTextButton/CopyTextButton.js +5 -1
- package/build/dist/UI/Components/CopyTextButton/CopyTextButton.js.map +1 -1
- package/build/dist/UI/Components/CustomFields/CustomFieldModelFormFields.js +5 -14
- package/build/dist/UI/Components/CustomFields/CustomFieldModelFormFields.js.map +1 -1
- package/build/dist/UI/Components/EditionLabel/EditionLabel.js +14 -13
- package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -1
- package/build/dist/UI/Components/ErrorMessage/ErrorMessage.js +1 -1
- package/build/dist/UI/Components/ErrorMessage/ErrorMessage.js.map +1 -1
- package/build/dist/UI/Components/Forms/Fields/FormField.js +8 -3
- package/build/dist/UI/Components/Forms/Fields/FormField.js.map +1 -1
- package/build/dist/UI/Components/Icon/Icon.js +8 -0
- package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
- package/build/dist/UI/Components/Input/Input.js +11 -3
- package/build/dist/UI/Components/Input/Input.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/LogsViewer.js +2 -1
- package/build/dist/UI/Components/LogsViewer/LogsViewer.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsFacetSidebar.js +14 -4
- package/build/dist/UI/Components/LogsViewer/components/LogsFacetSidebar.js.map +1 -1
- package/build/dist/UI/Components/Markdown.tsx/MarkdownConverters.js +0 -0
- package/build/dist/UI/Components/Markdown.tsx/MarkdownConverters.js.map +1 -1
- package/build/dist/UI/Components/Markdown.tsx/MarkdownEditor.js +710 -65
- package/build/dist/UI/Components/Markdown.tsx/MarkdownEditor.js.map +1 -1
- package/build/dist/UI/Components/Markdown.tsx/MarkdownEditorHistory.js +238 -0
- package/build/dist/UI/Components/Markdown.tsx/MarkdownEditorHistory.js.map +1 -0
- package/build/dist/UI/Components/Markdown.tsx/MarkdownListEditing.js +1028 -0
- package/build/dist/UI/Components/Markdown.tsx/MarkdownListEditing.js.map +1 -0
- package/build/dist/UI/Components/Markdown.tsx/MarkdownPaste.js +1088 -0
- package/build/dist/UI/Components/Markdown.tsx/MarkdownPaste.js.map +1 -0
- package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js +70 -10
- package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js.map +1 -1
- package/build/dist/UI/Components/Markdown.tsx/MarkdownVisualEditing.js +887 -0
- package/build/dist/UI/Components/Markdown.tsx/MarkdownVisualEditing.js.map +1 -0
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js +57 -6
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
- package/build/dist/UI/Components/ResetObjectID/ResetObjectID.js +7 -5
- package/build/dist/UI/Components/ResetObjectID/ResetObjectID.js.map +1 -1
- package/build/dist/UI/Components/Table/EmptyTableMessage.js +51 -0
- package/build/dist/UI/Components/Table/EmptyTableMessage.js.map +1 -0
- package/build/dist/UI/Components/Table/Table.js +30 -11
- package/build/dist/UI/Components/Table/Table.js.map +1 -1
- package/build/dist/UI/Components/Table/TableRow.js +9 -2
- package/build/dist/UI/Components/Table/TableRow.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/FacetVisibility.js +63 -1
- package/build/dist/UI/Components/TelemetryViewer/FacetVisibility.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js +4 -2
- package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/LockedFilterChip.js +91 -10
- package/build/dist/UI/Components/TelemetryViewer/components/LockedFilterChip.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.js +14 -4
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryFacetSidebar.js.map +1 -1
- package/build/dist/UI/Components/TextArea/TextArea.js +9 -3
- package/build/dist/UI/Components/TextArea/TextArea.js.map +1 -1
- package/build/dist/UI/Components/Workflow/ModelFieldPicker.js +1 -2
- package/build/dist/UI/Components/Workflow/ModelFieldPicker.js.map +1 -1
- package/build/dist/Utils/AI/InvestigationReport.js +71 -11
- package/build/dist/Utils/AI/InvestigationReport.js.map +1 -1
- package/build/dist/Utils/AiRemediation/Resource/CephCommandPolicy.js +1462 -0
- package/build/dist/Utils/AiRemediation/Resource/CephCommandPolicy.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/DatabaseCommandPolicy.js +122 -0
- package/build/dist/Utils/AiRemediation/Resource/DatabaseCommandPolicy.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/DatabaseDiagnosticCatalog.js +1139 -0
- package/build/dist/Utils/AiRemediation/Resource/DatabaseDiagnosticCatalog.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/DatabaseQueryRedactor.js +1060 -0
- package/build/dist/Utils/AiRemediation/Resource/DatabaseQueryRedactor.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/DockerCliGrammar.js +1301 -0
- package/build/dist/Utils/AiRemediation/Resource/DockerCliGrammar.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/DockerEngineCommandPolicy.js +370 -0
- package/build/dist/Utils/AiRemediation/Resource/DockerEngineCommandPolicy.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/DockerSwarmCommandPolicy.js +498 -0
- package/build/dist/Utils/AiRemediation/Resource/DockerSwarmCommandPolicy.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/GovcCommandPolicy.js +1565 -0
- package/build/dist/Utils/AiRemediation/Resource/GovcCommandPolicy.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/HostCommandPolicy.js +2206 -0
- package/build/dist/Utils/AiRemediation/Resource/HostCommandPolicy.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/ProxmoxCommandPolicy.js +1129 -0
- package/build/dist/Utils/AiRemediation/Resource/ProxmoxCommandPolicy.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/ResourceCommandPolicy.js +565 -0
- package/build/dist/Utils/AiRemediation/Resource/ResourceCommandPolicy.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/ResourceCommandPolicyCore.js +408 -0
- package/build/dist/Utils/AiRemediation/Resource/ResourceCommandPolicyCore.js.map +1 -0
- package/build/dist/Utils/AiRemediation/Resource/ResourceOutputRedactor.js +1910 -0
- package/build/dist/Utils/AiRemediation/Resource/ResourceOutputRedactor.js.map +1 -0
- package/build/dist/Utils/LabelRuleImportExport.js +2 -0
- package/build/dist/Utils/LabelRuleImportExport.js.map +1 -1
- package/build/dist/Utils/Markdown/UntrustedMarkdown.js +988 -0
- package/build/dist/Utils/Markdown/UntrustedMarkdown.js.map +1 -0
- package/build/dist/Utils/Monitor/IncomingEmailMonitorRequestUtil.js +34 -0
- package/build/dist/Utils/Monitor/IncomingEmailMonitorRequestUtil.js.map +1 -0
- package/build/dist/Utils/Monitor/MonitorLogSummaryUtil.js +148 -0
- package/build/dist/Utils/Monitor/MonitorLogSummaryUtil.js.map +1 -0
- package/build/dist/Utils/SessionReplay/SessionReplayBudgetMetricType.js +160 -0
- package/build/dist/Utils/SessionReplay/SessionReplayBudgetMetricType.js.map +1 -0
- package/build/dist/Utils/Telemetry/EntityKey.js +36 -0
- package/build/dist/Utils/Telemetry/EntityKey.js.map +1 -1
- package/package.json +1 -3
- package/Server/Utils/CommunityEditionSsoReport.ts +0 -361
- package/Tests/App/Accounts/LoginSsoEdition.test.tsx +0 -616
- package/Tests/App/AdminDashboard/AdminAuthenticationSsoEdition.test.tsx +0 -217
- package/Tests/App/AdminDashboard/GlobalSSOEnterpriseShells.test.tsx +0 -271
- package/Tests/App/Dashboard/CloudDocumentationMarkdown.test.ts +0 -215
- package/Tests/App/Dashboard/TelemetryResourceRetentionSettings.test.tsx +0 -784
- package/Tests/Server/Middleware/UserAuthorizationEditionEnforcement.test.ts +0 -518
- package/Tests/Server/Services/SsoRequirementReadMasking.test.ts +0 -419
- package/Tests/Server/Services/SsoRequirementWriteGuard.test.ts +0 -769
- package/Tests/UI/Components/CodeEditor.test.tsx +0 -638
- package/Tests/UI/Components/MonacoLoader.test.ts +0 -67
- package/Tests/UI/Components/MonacoRuntime.test.ts +0 -121
- package/Tests/UI/Components/Telemetry/TelemetryRetentionConfigForm.test.tsx +0 -329
- package/Tests/UI/Components/YamlEditor.test.tsx +0 -847
- package/UI/Components/CodeEditor/MonacoLoader.ts +0 -36
- package/UI/Components/Telemetry/TelemetryRetentionConfigForm.tsx +0 -319
- package/UI/Components/Telemetry/TelemetryRetentionConfigSummary.tsx +0 -223
- package/build/dist/Server/Utils/CommunityEditionSsoReport.js +0 -223
- package/build/dist/Server/Utils/CommunityEditionSsoReport.js.map +0 -1
- package/build/dist/UI/Components/CodeEditor/MonacoLoader.js +0 -34
- package/build/dist/UI/Components/CodeEditor/MonacoLoader.js.map +0 -1
- package/build/dist/UI/Components/Telemetry/TelemetryRetentionConfigForm.js +0 -171
- package/build/dist/UI/Components/Telemetry/TelemetryRetentionConfigForm.js.map +0 -1
- package/build/dist/UI/Components/Telemetry/TelemetryRetentionConfigSummary.js +0 -119
- package/build/dist/UI/Components/Telemetry/TelemetryRetentionConfigSummary.js.map +0 -1
|
@@ -0,0 +1,1869 @@
|
|
|
1
|
+
import { describe, expect, test } from "@jest/globals";
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import yaml from "js-yaml";
|
|
4
|
+
import path from "path";
|
|
5
|
+
import {
|
|
6
|
+
DATABASE_AGENT_CONFIGS,
|
|
7
|
+
DATABASE_AGENT_DOCKER_COMPOSE,
|
|
8
|
+
DATABASE_AGENT_ENGINES,
|
|
9
|
+
DatabaseAgentEngine,
|
|
10
|
+
} from "../../../../App/FeatureSet/Dashboard/src/Pages/Database/Utils/DatabaseAgentConfigs";
|
|
11
|
+
import {
|
|
12
|
+
DATABASE_AGENT_INSTALL_DIRECTORY,
|
|
13
|
+
DATABASE_AGENT_RAW_URL,
|
|
14
|
+
DATABASE_AGENT_SYSTEM_OPTIONS,
|
|
15
|
+
DEFAULT_DATABASE_AGENT_SYSTEM,
|
|
16
|
+
DatabaseDocumentationTarget,
|
|
17
|
+
getDatabaseAgentEngine,
|
|
18
|
+
getDatabaseAgentEnvFile,
|
|
19
|
+
getDatabaseAgentInstallationMarkdown,
|
|
20
|
+
getDatabaseAgentKubernetesManifest,
|
|
21
|
+
getDatabaseAgentSetupGuide,
|
|
22
|
+
getDatabaseAgentSystem,
|
|
23
|
+
getDatabaseAgentSystems,
|
|
24
|
+
getDatabaseDocumentationHeading,
|
|
25
|
+
getDatabaseOwnCollectorMarkdown,
|
|
26
|
+
getDatabaseOwnCollectorSetupGuide,
|
|
27
|
+
resolveDatabaseAgentIdentity,
|
|
28
|
+
resolveDatabaseAgentSystem,
|
|
29
|
+
} from "../../../../App/FeatureSet/Dashboard/src/Pages/Database/Utils/DocumentationMarkdown";
|
|
30
|
+
import {
|
|
31
|
+
SETUP_GUIDE_API_KEY_PLACEHOLDER,
|
|
32
|
+
SETUP_GUIDE_URL_PLACEHOLDER,
|
|
33
|
+
SetupGuideContent,
|
|
34
|
+
SetupGuideOption,
|
|
35
|
+
SetupGuideStep,
|
|
36
|
+
SetupGuideStepVariant,
|
|
37
|
+
SetupGuideTopic,
|
|
38
|
+
getSetupGuideCodeBlocks,
|
|
39
|
+
getSetupGuideMarkdown,
|
|
40
|
+
} from "../../../../App/FeatureSet/Dashboard/src/Components/SetupGuide/SetupGuide";
|
|
41
|
+
import {
|
|
42
|
+
DATABASE_SYSTEMS,
|
|
43
|
+
DatabaseSystemDescriptor,
|
|
44
|
+
getCollectorReceiverComponentName,
|
|
45
|
+
getDatabaseSystemDisplayName,
|
|
46
|
+
} from "../../../Types/DatabaseServer/DatabaseSystem";
|
|
47
|
+
|
|
48
|
+
/*
|
|
49
|
+
* The Database Agent guide as the Documentation card lays it out: an
|
|
50
|
+
* engine picker on the product page, then a few steps — the monitoring
|
|
51
|
+
* user, the install (script, Docker Compose, or a Deployment for a
|
|
52
|
+
* Kubernetes database) and how to check it worked — and everything else
|
|
53
|
+
* folded under Advanced and Troubleshooting.
|
|
54
|
+
*
|
|
55
|
+
* DatabaseDocumentationMarkdown.test.ts pins the identity, quoting and
|
|
56
|
+
* escaping rules on the single-document guide; these tests hold the setup
|
|
57
|
+
* guide to the same pieces (parity), and pin what is new in it: that each
|
|
58
|
+
* engine only shows its own instructions, that the reader's URL and key
|
|
59
|
+
* reach the install command only once a real key is picked, that a
|
|
60
|
+
* Kubernetes database is offered its Deployment first, and that every file,
|
|
61
|
+
* variable and flag it names exists in agents/DatabaseAgent.
|
|
62
|
+
*/
|
|
63
|
+
|
|
64
|
+
const REPO_ROOT: string = path.join(__dirname, "..", "..", "..", "..", "..");
|
|
65
|
+
const AGENT_DIR: string = path.join(REPO_ROOT, "agents", "DatabaseAgent");
|
|
66
|
+
|
|
67
|
+
const URL: string = "https://oneuptime.example.com";
|
|
68
|
+
const KEY: string = "ingest-key-123";
|
|
69
|
+
const DATABASE_ID: string = "3c1e9a52-1f2b-4c3d-9e8f-0a1b2c3d4e5f";
|
|
70
|
+
const HEALTH_URL: string = "/dashboard/p1/monitors/create?monitorType=Database";
|
|
71
|
+
const RECOMMENDATIONS_URL: string = `/dashboard/p1/databases/${DATABASE_ID}/recommendations`;
|
|
72
|
+
|
|
73
|
+
const SYSTEMS: Array<string> = DATABASE_AGENT_SYSTEM_OPTIONS.map(
|
|
74
|
+
(option: SetupGuideOption): string => {
|
|
75
|
+
return option.key;
|
|
76
|
+
},
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
const HEALTH_MONITOR_SYSTEMS: Array<string> = [
|
|
80
|
+
"postgresql",
|
|
81
|
+
"mysql",
|
|
82
|
+
"microsoft.sql_server",
|
|
83
|
+
];
|
|
84
|
+
|
|
85
|
+
function readAgentFile(...segments: Array<string>): string {
|
|
86
|
+
return fs.readFileSync(path.join(AGENT_DIR, ...segments), "utf8");
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function engineOf(system: string): DatabaseAgentEngine {
|
|
90
|
+
const engine: DatabaseAgentEngine | null = getDatabaseAgentEngine(system);
|
|
91
|
+
if (!engine) {
|
|
92
|
+
throw new Error(`No agent config monitors ${system}`);
|
|
93
|
+
}
|
|
94
|
+
return engine;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function productGuide(
|
|
98
|
+
system: string,
|
|
99
|
+
overrides?: { apiKey?: string; hasApiKey?: boolean; oneuptimeUrl?: string },
|
|
100
|
+
): SetupGuideContent {
|
|
101
|
+
return getDatabaseAgentSetupGuide({
|
|
102
|
+
oneuptimeUrl: overrides?.oneuptimeUrl ?? URL,
|
|
103
|
+
apiKey: overrides?.apiKey ?? KEY,
|
|
104
|
+
hasApiKey: overrides?.hasApiKey,
|
|
105
|
+
engine: engineOf(system),
|
|
106
|
+
system: system,
|
|
107
|
+
databaseHealthMonitorUrl: HEALTH_URL,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function rowGuide(
|
|
112
|
+
database: DatabaseDocumentationTarget,
|
|
113
|
+
overrides?: { apiKey?: string; hasApiKey?: boolean },
|
|
114
|
+
): SetupGuideContent {
|
|
115
|
+
return getDatabaseAgentSetupGuide({
|
|
116
|
+
oneuptimeUrl: URL,
|
|
117
|
+
apiKey: overrides?.apiKey ?? KEY,
|
|
118
|
+
hasApiKey: overrides?.hasApiKey,
|
|
119
|
+
engine: engineOf(database.dbSystem || ""),
|
|
120
|
+
system: database.dbSystem,
|
|
121
|
+
database: database,
|
|
122
|
+
databaseHealthMonitorUrl: HEALTH_URL,
|
|
123
|
+
recommendationsUrl: RECOMMENDATIONS_URL,
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function stepTitled(guide: SetupGuideContent, title: string): SetupGuideStep {
|
|
128
|
+
const step: SetupGuideStep | undefined = guide.steps.find(
|
|
129
|
+
(candidate: SetupGuideStep): boolean => {
|
|
130
|
+
return candidate.title === title;
|
|
131
|
+
},
|
|
132
|
+
);
|
|
133
|
+
if (!step) {
|
|
134
|
+
throw new Error(`No step titled "${title}"`);
|
|
135
|
+
}
|
|
136
|
+
return step;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function variantLabels(step: SetupGuideStep): Array<string> {
|
|
140
|
+
return (step.variants || []).map((variant: SetupGuideStepVariant): string => {
|
|
141
|
+
return variant.label;
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function variantOf(guide: SetupGuideContent, label: string): string {
|
|
146
|
+
const variant: SetupGuideStepVariant | undefined = (
|
|
147
|
+
stepTitled(guide, "Install the agent").variants || []
|
|
148
|
+
).find((candidate: SetupGuideStepVariant): boolean => {
|
|
149
|
+
return candidate.label === label;
|
|
150
|
+
});
|
|
151
|
+
if (!variant) {
|
|
152
|
+
throw new Error(`No install variant labelled "${label}"`);
|
|
153
|
+
}
|
|
154
|
+
return variant.markdown;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function topicTitles(
|
|
158
|
+
topics: Array<SetupGuideTopic> | undefined,
|
|
159
|
+
): Array<string> {
|
|
160
|
+
return (topics || []).map((topic: SetupGuideTopic): string => {
|
|
161
|
+
return topic.title;
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function topicOf(
|
|
166
|
+
topics: Array<SetupGuideTopic> | undefined,
|
|
167
|
+
title: string,
|
|
168
|
+
): SetupGuideTopic {
|
|
169
|
+
const topic: SetupGuideTopic | undefined = (topics || []).find(
|
|
170
|
+
(candidate: SetupGuideTopic): boolean => {
|
|
171
|
+
return candidate.title === title;
|
|
172
|
+
},
|
|
173
|
+
);
|
|
174
|
+
if (!topic) {
|
|
175
|
+
throw new Error(`No topic titled "${title}"`);
|
|
176
|
+
}
|
|
177
|
+
return topic;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/* Fenced code blocks of some markdown, with their info string. */
|
|
181
|
+
function codeBlocks(
|
|
182
|
+
markdown: string,
|
|
183
|
+
): Array<{ language: string; body: string }> {
|
|
184
|
+
const blocks: Array<{ language: string; body: string }> = [];
|
|
185
|
+
let current: { language: string; lines: Array<string> } | null = null;
|
|
186
|
+
|
|
187
|
+
for (const line of markdown.split("\n")) {
|
|
188
|
+
const fence: RegExpMatchArray | null = line.match(/^```(\S*)\s*$/);
|
|
189
|
+
if (fence) {
|
|
190
|
+
if (current) {
|
|
191
|
+
blocks.push({
|
|
192
|
+
language: current.language,
|
|
193
|
+
body: current.lines.join("\n"),
|
|
194
|
+
});
|
|
195
|
+
current = null;
|
|
196
|
+
} else {
|
|
197
|
+
current = { language: fence[1] || "", lines: [] };
|
|
198
|
+
}
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
if (current) {
|
|
202
|
+
current.lines.push(line);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
expect(current).toBeNull();
|
|
207
|
+
return blocks;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// The line of some markdown that runs install.sh (the first one).
|
|
211
|
+
function installCommandOf(markdown: string): string {
|
|
212
|
+
const command: string | undefined = markdown
|
|
213
|
+
.split("\n")
|
|
214
|
+
.find((line: string): boolean => {
|
|
215
|
+
return line.endsWith(" bash install.sh");
|
|
216
|
+
});
|
|
217
|
+
if (!command) {
|
|
218
|
+
throw new Error("No install.sh command line");
|
|
219
|
+
}
|
|
220
|
+
return command;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Every line of some markdown that runs install.sh.
|
|
224
|
+
function installCommandsOf(markdown: string): Array<string> {
|
|
225
|
+
return markdown.split("\n").filter((line: string): boolean => {
|
|
226
|
+
return line.endsWith("bash install.sh");
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/* The fenced block that sets ONEUPTIME_URL: the `.env` file. */
|
|
231
|
+
function envBlockOf(markdown: string): string {
|
|
232
|
+
const block: { language: string; body: string } | undefined = codeBlocks(
|
|
233
|
+
markdown,
|
|
234
|
+
).find((candidate: { language: string; body: string }): boolean => {
|
|
235
|
+
return candidate.body.includes("\nONEUPTIME_URL=");
|
|
236
|
+
});
|
|
237
|
+
if (!block) {
|
|
238
|
+
throw new Error("No .env block");
|
|
239
|
+
}
|
|
240
|
+
return block.body;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/*
|
|
244
|
+
* Environment variable names the compose file passes to the collector: its
|
|
245
|
+
* oneuptime-database-agent service only.
|
|
246
|
+
*/
|
|
247
|
+
function composeVariables(): Set<string> {
|
|
248
|
+
const compose: string = readAgentFile("docker-compose.yml");
|
|
249
|
+
const start: number = compose.indexOf("\n oneuptime-database-agent:\n");
|
|
250
|
+
const next: number = compose.slice(start + 1).search(/\n {2}[a-z0-9-]+:\n/);
|
|
251
|
+
const collector: string =
|
|
252
|
+
next < 0 ? compose.slice(start) : compose.slice(start, start + 1 + next);
|
|
253
|
+
|
|
254
|
+
expect(start).toBeGreaterThanOrEqual(0);
|
|
255
|
+
|
|
256
|
+
return new Set<string>(
|
|
257
|
+
Array.from(collector.matchAll(/^\s*-\s*([A-Z_]+)=\$\{/gm)).map(
|
|
258
|
+
(match: RegExpMatchArray): string => {
|
|
259
|
+
return match[1]!;
|
|
260
|
+
},
|
|
261
|
+
),
|
|
262
|
+
);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// The README's grant blocks, which every guide's grants must be.
|
|
266
|
+
const README_BLOCKS: Array<string> = codeBlocks(readAgentFile("README.md"))
|
|
267
|
+
.filter((block: { language: string; body: string }): boolean => {
|
|
268
|
+
return ["sql", "text", "js"].includes(block.language);
|
|
269
|
+
})
|
|
270
|
+
.map((block: { language: string; body: string }): string => {
|
|
271
|
+
return block.body;
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
/*
|
|
275
|
+
* A line each engine's grants carry, so a guide can be checked for showing
|
|
276
|
+
* only its own engine's login.
|
|
277
|
+
*/
|
|
278
|
+
const GRANT_SIGNATURES: Record<DatabaseAgentEngine, string | null> = {
|
|
279
|
+
postgresql: "GRANT pg_monitor TO oneuptime_monitor;",
|
|
280
|
+
mysql: "GRANT PROCESS, REPLICATION CLIENT ON *.*",
|
|
281
|
+
redis: "ACL SETUSER oneuptime_monitor",
|
|
282
|
+
mongodb: 'roles: [{ role: "clusterMonitor", db: "admin" }]',
|
|
283
|
+
sqlserver: "GRANT VIEW SERVER STATE TO oneuptime_monitor;",
|
|
284
|
+
oracledb: "GRANT SELECT_CATALOG_ROLE TO oneuptime_monitor;",
|
|
285
|
+
elasticsearch: "POST /_security/role/oneuptime_monitor",
|
|
286
|
+
memcached: null,
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
function hasQueryEvents(engine: DatabaseAgentEngine): boolean {
|
|
290
|
+
return DATABASE_AGENT_CONFIGS[engine].includes("db.server.top_query:");
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
function expectPlainOneLine(text: string | undefined): void {
|
|
294
|
+
expect(text).toBeTruthy();
|
|
295
|
+
// Rendered as plain text, so no markdown.
|
|
296
|
+
expect(text).not.toMatch(/[`*[\]]/);
|
|
297
|
+
expect(text).not.toContain("\n");
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/*
|
|
301
|
+
* Every "step N" the guide's text refers to is the step on screen with
|
|
302
|
+
* that number: step 1 is the ingestion key (SetupGuideCard's own), and the
|
|
303
|
+
* guide's steps follow from 2. Memcached has no monitoring-user step, so
|
|
304
|
+
* its check is step 3, not 4.
|
|
305
|
+
*/
|
|
306
|
+
function expectStepReferencesToMatch(guide: SetupGuideContent): void {
|
|
307
|
+
const markdown: string = getSetupGuideMarkdown(guide).replace(
|
|
308
|
+
/^## Step \d+: .*$/gm,
|
|
309
|
+
"",
|
|
310
|
+
);
|
|
311
|
+
const references: Array<RegExpMatchArray> = Array.from(
|
|
312
|
+
markdown.matchAll(/[^.:\n]*\bstep (\d+)\b[^.\n]*/g),
|
|
313
|
+
);
|
|
314
|
+
expect(references.length).toBeGreaterThan(0);
|
|
315
|
+
|
|
316
|
+
for (const reference of references) {
|
|
317
|
+
const sentence: string = reference[0];
|
|
318
|
+
const stepNumber: number = Number(reference[1]);
|
|
319
|
+
if (stepNumber === 1) {
|
|
320
|
+
expect({ sentence, aboutTheKey: sentence.includes("key") }).toEqual({
|
|
321
|
+
sentence,
|
|
322
|
+
aboutTheKey: true,
|
|
323
|
+
});
|
|
324
|
+
continue;
|
|
325
|
+
}
|
|
326
|
+
const step: SetupGuideStep | undefined = guide.steps[stepNumber - 2];
|
|
327
|
+
expect({ sentence, exists: Boolean(step) }).toEqual({
|
|
328
|
+
sentence,
|
|
329
|
+
exists: true,
|
|
330
|
+
});
|
|
331
|
+
if (sentence.includes("diagnostic script")) {
|
|
332
|
+
expect({ sentence, title: step!.title }).toEqual({
|
|
333
|
+
sentence,
|
|
334
|
+
title: "Verify the installation",
|
|
335
|
+
});
|
|
336
|
+
} else {
|
|
337
|
+
expect({ sentence, title: step!.title }).toEqual({
|
|
338
|
+
sentence,
|
|
339
|
+
title: "Create a monitoring user",
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
describe("the engine picker", () => {
|
|
346
|
+
test("offers every engine the agent monitors, forks included, in catalog order", () => {
|
|
347
|
+
expect(SYSTEMS).toEqual(getDatabaseAgentSystems());
|
|
348
|
+
expect(SYSTEMS).toEqual([
|
|
349
|
+
"postgresql",
|
|
350
|
+
"mysql",
|
|
351
|
+
"mariadb",
|
|
352
|
+
"microsoft.sql_server",
|
|
353
|
+
"oracle.db",
|
|
354
|
+
"redis",
|
|
355
|
+
"valkey",
|
|
356
|
+
"keydb",
|
|
357
|
+
"dragonfly",
|
|
358
|
+
"memcached",
|
|
359
|
+
"mongodb",
|
|
360
|
+
"elasticsearch",
|
|
361
|
+
"opensearch",
|
|
362
|
+
]);
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
test("labels each engine with the catalog's display name", () => {
|
|
366
|
+
for (const option of DATABASE_AGENT_SYSTEM_OPTIONS) {
|
|
367
|
+
expect(option.label).toBe(getDatabaseSystemDisplayName(option.key));
|
|
368
|
+
}
|
|
369
|
+
expect(
|
|
370
|
+
DATABASE_AGENT_SYSTEM_OPTIONS.map((option: SetupGuideOption): string => {
|
|
371
|
+
return option.label;
|
|
372
|
+
}),
|
|
373
|
+
).toEqual([
|
|
374
|
+
"PostgreSQL",
|
|
375
|
+
"MySQL",
|
|
376
|
+
"MariaDB",
|
|
377
|
+
"SQL Server",
|
|
378
|
+
"Oracle",
|
|
379
|
+
"Redis",
|
|
380
|
+
"Valkey",
|
|
381
|
+
"KeyDB",
|
|
382
|
+
"Dragonfly",
|
|
383
|
+
"Memcached",
|
|
384
|
+
"MongoDB",
|
|
385
|
+
"Elasticsearch",
|
|
386
|
+
"OpenSearch",
|
|
387
|
+
]);
|
|
388
|
+
});
|
|
389
|
+
|
|
390
|
+
test("describes each engine in one line: the receiver it runs, and the name a fork reports", () => {
|
|
391
|
+
for (const option of DATABASE_AGENT_SYSTEM_OPTIONS) {
|
|
392
|
+
const engine: DatabaseAgentEngine = engineOf(option.key);
|
|
393
|
+
expectPlainOneLine(option.description);
|
|
394
|
+
expect(option.description).toContain(
|
|
395
|
+
`${getCollectorReceiverComponentName(engine)} receiver`,
|
|
396
|
+
);
|
|
397
|
+
expect(option.badge).toBeUndefined();
|
|
398
|
+
|
|
399
|
+
const isFork: boolean = getDatabaseAgentSystem(engine) !== option.key;
|
|
400
|
+
expect({
|
|
401
|
+
system: option.key,
|
|
402
|
+
namesItself: (option.description || "").includes(
|
|
403
|
+
`reports the server as ${option.label}`,
|
|
404
|
+
),
|
|
405
|
+
}).toEqual({ system: option.key, namesItself: isFork });
|
|
406
|
+
}
|
|
407
|
+
});
|
|
408
|
+
|
|
409
|
+
test("opens on PostgreSQL, and anything it does not offer resolves to PostgreSQL", () => {
|
|
410
|
+
expect(DEFAULT_DATABASE_AGENT_SYSTEM).toBe("postgresql");
|
|
411
|
+
expect(SYSTEMS[0]).toBe(DEFAULT_DATABASE_AGENT_SYSTEM);
|
|
412
|
+
for (const value of [
|
|
413
|
+
undefined,
|
|
414
|
+
null,
|
|
415
|
+
"",
|
|
416
|
+
"postgres",
|
|
417
|
+
"MySQL",
|
|
418
|
+
"sqlite",
|
|
419
|
+
"couchdb",
|
|
420
|
+
"acmedb",
|
|
421
|
+
]) {
|
|
422
|
+
expect(resolveDatabaseAgentSystem(value)).toBe("postgresql");
|
|
423
|
+
}
|
|
424
|
+
for (const system of SYSTEMS) {
|
|
425
|
+
expect(resolveDatabaseAgentSystem(system)).toBe(system);
|
|
426
|
+
}
|
|
427
|
+
});
|
|
428
|
+
});
|
|
429
|
+
|
|
430
|
+
describe.each(SYSTEMS)("the %s guide on the product page", (system: string) => {
|
|
431
|
+
const engine: DatabaseAgentEngine = engineOf(system);
|
|
432
|
+
const guide: SetupGuideContent = productGuide(system);
|
|
433
|
+
const markdown: string = getSetupGuideMarkdown(guide);
|
|
434
|
+
const label: string = getDatabaseSystemDisplayName(system);
|
|
435
|
+
|
|
436
|
+
test("is the monitoring user, the install and the check — Memcached has no users", () => {
|
|
437
|
+
const titles: Array<string> = guide.steps.map(
|
|
438
|
+
(step: SetupGuideStep): string => {
|
|
439
|
+
return step.title;
|
|
440
|
+
},
|
|
441
|
+
);
|
|
442
|
+
expect(titles).toEqual(
|
|
443
|
+
engine === "memcached"
|
|
444
|
+
? ["Install the agent", "Verify the installation"]
|
|
445
|
+
: [
|
|
446
|
+
"Create a monitoring user",
|
|
447
|
+
"Install the agent",
|
|
448
|
+
"Verify the installation",
|
|
449
|
+
],
|
|
450
|
+
);
|
|
451
|
+
for (const step of guide.steps) {
|
|
452
|
+
expectPlainOneLine(step.description);
|
|
453
|
+
}
|
|
454
|
+
});
|
|
455
|
+
|
|
456
|
+
test("installs with the script or Docker Compose — no Kubernetes Deployment without a database", () => {
|
|
457
|
+
expect(variantLabels(stepTitled(guide, "Install the agent"))).toEqual([
|
|
458
|
+
"Install script",
|
|
459
|
+
"Docker Compose",
|
|
460
|
+
]);
|
|
461
|
+
expect(markdown).not.toContain("kind: Deployment");
|
|
462
|
+
expect(markdown).not.toContain("kubectl");
|
|
463
|
+
});
|
|
464
|
+
|
|
465
|
+
test("the install script gets the URL, the key and the engine up front", () => {
|
|
466
|
+
const script: string = variantOf(guide, "Install script");
|
|
467
|
+
expect(script).toContain(
|
|
468
|
+
`curl -sSL ${DATABASE_AGENT_RAW_URL}/install.sh -o install.sh\n`,
|
|
469
|
+
);
|
|
470
|
+
expect(installCommandOf(script)).toBe(
|
|
471
|
+
`ONEUPTIME_URL=${URL} ONEUPTIME_TELEMETRY_INGESTION_KEY=${KEY} DATABASE_SYSTEM=${system} bash install.sh`,
|
|
472
|
+
);
|
|
473
|
+
// It asks for the rest, never for what the command line already gives.
|
|
474
|
+
expect(script).not.toContain("your OneUptime URL");
|
|
475
|
+
expect(script).not.toContain("the ingestion key from step 1");
|
|
476
|
+
expect(script).toContain("the endpoint to connect to");
|
|
477
|
+
});
|
|
478
|
+
|
|
479
|
+
test("Docker Compose downloads the engine's config and writes the .env with the URL and key", () => {
|
|
480
|
+
const compose: string = variantOf(guide, "Docker Compose");
|
|
481
|
+
expect(compose).toContain(
|
|
482
|
+
`curl -fsSL ${DATABASE_AGENT_RAW_URL}/docker-compose.yml -o docker-compose.yml`,
|
|
483
|
+
);
|
|
484
|
+
expect(compose).toContain(
|
|
485
|
+
`curl -fsSL ${DATABASE_AGENT_RAW_URL}/configs/${engine}.yaml -o otel-collector-config.yaml`,
|
|
486
|
+
);
|
|
487
|
+
expect(envBlockOf(compose)).toBe(
|
|
488
|
+
getDatabaseAgentEnvFile({
|
|
489
|
+
oneuptimeUrl: URL,
|
|
490
|
+
apiKey: KEY,
|
|
491
|
+
engine: engine,
|
|
492
|
+
identity: resolveDatabaseAgentIdentity(system),
|
|
493
|
+
system: system,
|
|
494
|
+
}),
|
|
495
|
+
);
|
|
496
|
+
expect(envBlockOf(compose)).toContain(`\nONEUPTIME_URL=${URL}\n`);
|
|
497
|
+
expect(envBlockOf(compose)).toContain(
|
|
498
|
+
`\nONEUPTIME_TELEMETRY_INGESTION_KEY=${KEY}\n`,
|
|
499
|
+
);
|
|
500
|
+
expect(envBlockOf(compose)).toContain(`\nDATABASE_SYSTEM=${system}\n`);
|
|
501
|
+
expect(envBlockOf(compose)).toMatch(/\nDATABASE_SERVER_ID=$/);
|
|
502
|
+
expect(compose).toContain("```bash\ndocker compose up -d\n```");
|
|
503
|
+
expect(compose).not.toContain("Pick an ingestion key in step 1");
|
|
504
|
+
});
|
|
505
|
+
|
|
506
|
+
test("the .env names exactly the variables the compose file passes to the collector", () => {
|
|
507
|
+
const named: Array<string> = envBlockOf(variantOf(guide, "Docker Compose"))
|
|
508
|
+
.split("\n")
|
|
509
|
+
.filter((line: string): boolean => {
|
|
510
|
+
return !line.startsWith("#");
|
|
511
|
+
})
|
|
512
|
+
.map((line: string): string => {
|
|
513
|
+
return line.split("=")[0]!;
|
|
514
|
+
});
|
|
515
|
+
expect(new Set(named)).toEqual(composeVariables());
|
|
516
|
+
});
|
|
517
|
+
|
|
518
|
+
test("shows only this engine's login, in the README's own words", () => {
|
|
519
|
+
const signature: string | null = GRANT_SIGNATURES[engine];
|
|
520
|
+
const steps: string = guide.steps
|
|
521
|
+
.map((step: SetupGuideStep): string => {
|
|
522
|
+
return step.markdown || "";
|
|
523
|
+
})
|
|
524
|
+
.join("\n");
|
|
525
|
+
|
|
526
|
+
if (signature) {
|
|
527
|
+
const user: string =
|
|
528
|
+
stepTitled(guide, "Create a monitoring user").markdown || "";
|
|
529
|
+
for (const block of codeBlocks(user)) {
|
|
530
|
+
expect({
|
|
531
|
+
system,
|
|
532
|
+
inReadme: README_BLOCKS.includes(block.body),
|
|
533
|
+
}).toEqual({ system, inReadme: true });
|
|
534
|
+
}
|
|
535
|
+
// OpenSearch is not shown Elasticsearch's security API.
|
|
536
|
+
expect(steps.includes(signature)).toBe(system !== "opensearch");
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
for (const other of DATABASE_AGENT_ENGINES) {
|
|
540
|
+
const otherSignature: string | null = GRANT_SIGNATURES[other];
|
|
541
|
+
if (other !== engine && otherSignature) {
|
|
542
|
+
expect({
|
|
543
|
+
system,
|
|
544
|
+
other,
|
|
545
|
+
shown: markdown.includes(otherSignature),
|
|
546
|
+
}).toEqual({ system, other, shown: false });
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
});
|
|
550
|
+
|
|
551
|
+
test("keeps configuration and reference material out of the steps", () => {
|
|
552
|
+
const steps: string = guide.steps
|
|
553
|
+
.map((step: SetupGuideStep): string => {
|
|
554
|
+
return `${step.markdown || ""}${(step.variants || [])
|
|
555
|
+
.map((variant: SetupGuideStepVariant): string => {
|
|
556
|
+
return variant.markdown;
|
|
557
|
+
})
|
|
558
|
+
.join("\n")}`;
|
|
559
|
+
})
|
|
560
|
+
.join("\n");
|
|
561
|
+
for (const advanced of [
|
|
562
|
+
"| Variable | Required | Description |",
|
|
563
|
+
"pg_stat_statements",
|
|
564
|
+
"--force-recreate",
|
|
565
|
+
"docker compose down",
|
|
566
|
+
"INSTALL_DIR=",
|
|
567
|
+
"oneuptime-database-ai-agent",
|
|
568
|
+
DATABASE_AGENT_CONFIGS[engine].trimEnd(),
|
|
569
|
+
DATABASE_AGENT_DOCKER_COMPOSE.trimEnd(),
|
|
570
|
+
]) {
|
|
571
|
+
expect(steps).not.toContain(advanced);
|
|
572
|
+
}
|
|
573
|
+
});
|
|
574
|
+
|
|
575
|
+
test("has no row identity, no alerting and no id", () => {
|
|
576
|
+
expect(guide.intro).toBeUndefined();
|
|
577
|
+
expect(topicTitles(guide.advanced)).not.toContain("Alert on this database");
|
|
578
|
+
expect(markdown).not.toContain("**This database**");
|
|
579
|
+
expect(markdown).not.toContain(DATABASE_ID);
|
|
580
|
+
});
|
|
581
|
+
|
|
582
|
+
test("folds the reference material under Advanced", () => {
|
|
583
|
+
const titles: Array<string> = topicTitles(guide.advanced);
|
|
584
|
+
const expected: Array<string> = ["What the agent collects"];
|
|
585
|
+
if (hasQueryEvents(engine)) {
|
|
586
|
+
expected.push("Query samples and top queries");
|
|
587
|
+
}
|
|
588
|
+
expected.push(
|
|
589
|
+
"Environment variables",
|
|
590
|
+
"The files the agent runs",
|
|
591
|
+
"Upgrade or uninstall the agent",
|
|
592
|
+
);
|
|
593
|
+
if (HEALTH_MONITOR_SYSTEMS.includes(system)) {
|
|
594
|
+
expected.push("No agent? Use a Database Health monitor");
|
|
595
|
+
}
|
|
596
|
+
expect(titles).toEqual(expected);
|
|
597
|
+
expect(titles.length).toBeGreaterThanOrEqual(4);
|
|
598
|
+
expect(titles.length).toBeLessThanOrEqual(8);
|
|
599
|
+
});
|
|
600
|
+
|
|
601
|
+
test("every Advanced topic has a plain one-line summary", () => {
|
|
602
|
+
for (const topic of guide.advanced || []) {
|
|
603
|
+
expectPlainOneLine(topic.summary);
|
|
604
|
+
expect(topic.markdown.trim().length).toBeGreaterThan(0);
|
|
605
|
+
}
|
|
606
|
+
});
|
|
607
|
+
|
|
608
|
+
test("says what the agent collects from this engine", () => {
|
|
609
|
+
const collects: string = topicOf(
|
|
610
|
+
guide.advanced,
|
|
611
|
+
"What the agent collects",
|
|
612
|
+
).markdown;
|
|
613
|
+
expect(collects).toContain(
|
|
614
|
+
`The OneUptime Database Agent collects ${label} engine metrics — `,
|
|
615
|
+
);
|
|
616
|
+
expect(collects).toContain(`(\`configs/${engine}.yaml\`)`);
|
|
617
|
+
expect(collects.includes("query samples")).toBe(hasQueryEvents(engine));
|
|
618
|
+
});
|
|
619
|
+
|
|
620
|
+
test("the files topic embeds the compose file and this engine's config, and no other", () => {
|
|
621
|
+
const files: string = topicOf(
|
|
622
|
+
guide.advanced,
|
|
623
|
+
"The files the agent runs",
|
|
624
|
+
).markdown;
|
|
625
|
+
expect(files).toContain(DATABASE_AGENT_DOCKER_COMPOSE.trimEnd());
|
|
626
|
+
expect(files).toContain(DATABASE_AGENT_CONFIGS[engine].trimEnd());
|
|
627
|
+
for (const other of DATABASE_AGENT_ENGINES) {
|
|
628
|
+
if (other !== engine) {
|
|
629
|
+
expect(files).not.toContain(DATABASE_AGENT_CONFIGS[other].trimEnd());
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
// The embedded config keeps its ${env:...} references literally.
|
|
633
|
+
expect(files).toContain('value: "${env:DATABASE_SYSTEM}"');
|
|
634
|
+
});
|
|
635
|
+
|
|
636
|
+
test("the variables table documents every variable the collector reads", () => {
|
|
637
|
+
const table: string = topicOf(
|
|
638
|
+
guide.advanced,
|
|
639
|
+
"Environment variables",
|
|
640
|
+
).markdown;
|
|
641
|
+
for (const variable of composeVariables()) {
|
|
642
|
+
expect(table).toContain(`| \`${variable}\` |`);
|
|
643
|
+
}
|
|
644
|
+
});
|
|
645
|
+
|
|
646
|
+
test("the check says where the database shows up and how to diagnose it", () => {
|
|
647
|
+
const verify: string =
|
|
648
|
+
stepTitled(guide, "Verify the installation").markdown || "";
|
|
649
|
+
expect(verify).toContain("the database appears under **Databases**");
|
|
650
|
+
expect(verify).toContain(
|
|
651
|
+
`curl -sSL ${DATABASE_AGENT_RAW_URL}/troubleshoot.sh -o troubleshoot.sh\nbash troubleshoot.sh # add -d <dir> if you installed outside ${DATABASE_AGENT_INSTALL_DIRECTORY}`,
|
|
652
|
+
);
|
|
653
|
+
});
|
|
654
|
+
|
|
655
|
+
test("troubleshooting is titled by symptom", () => {
|
|
656
|
+
const titles: Array<string> = topicTitles(guide.troubleshooting);
|
|
657
|
+
expect(titles).toContain("The database does not appear under Databases");
|
|
658
|
+
expect(titles).toContain("The agent cannot connect to the database");
|
|
659
|
+
expect(titles).toContain('The collector log shows "Exporting failed"');
|
|
660
|
+
expect(titles).toContain("The agent container keeps restarting");
|
|
661
|
+
expect(
|
|
662
|
+
titles.some((title: string): boolean => {
|
|
663
|
+
return title.startsWith("Login");
|
|
664
|
+
}),
|
|
665
|
+
).toBe(engine !== "memcached");
|
|
666
|
+
for (const topic of guide.troubleshooting || []) {
|
|
667
|
+
expect(topic.markdown.trim().length).toBeGreaterThan(0);
|
|
668
|
+
}
|
|
669
|
+
});
|
|
670
|
+
|
|
671
|
+
test("has two to four prerequisites, the product page's naming the identity", () => {
|
|
672
|
+
const prerequisites: Array<string> = guide.prerequisites || [];
|
|
673
|
+
expect(prerequisites.length).toBeGreaterThanOrEqual(2);
|
|
674
|
+
expect(prerequisites.length).toBeLessThanOrEqual(4);
|
|
675
|
+
expect(prerequisites[0]).toContain("Docker Engine 20.10+");
|
|
676
|
+
expect(prerequisites.join("\n")).toContain(
|
|
677
|
+
"The host name your applications use",
|
|
678
|
+
);
|
|
679
|
+
expect(prerequisites.join("\n").includes("SASL")).toBe(
|
|
680
|
+
engine === "memcached",
|
|
681
|
+
);
|
|
682
|
+
});
|
|
683
|
+
|
|
684
|
+
test("links to documentation that exists", () => {
|
|
685
|
+
const links: Array<{ title: string; url: string }> = guide.links || [];
|
|
686
|
+
expect(links[0]).toEqual({
|
|
687
|
+
title: "Database Agent documentation",
|
|
688
|
+
url: "/docs/telemetry/databases",
|
|
689
|
+
});
|
|
690
|
+
expect(links.length).toBe(HEALTH_MONITOR_SYSTEMS.includes(system) ? 2 : 1);
|
|
691
|
+
for (const link of links) {
|
|
692
|
+
expect(link.url.startsWith("/docs/")).toBe(true);
|
|
693
|
+
expect(
|
|
694
|
+
fs.existsSync(
|
|
695
|
+
path.join(
|
|
696
|
+
REPO_ROOT,
|
|
697
|
+
"packages/App/FeatureSet/Docs/Content/en",
|
|
698
|
+
`${link.url.replace(/^\/docs\//, "")}.md`,
|
|
699
|
+
),
|
|
700
|
+
),
|
|
701
|
+
).toBe(true);
|
|
702
|
+
}
|
|
703
|
+
});
|
|
704
|
+
|
|
705
|
+
test("with a key picked, no placeholder is left anywhere", () => {
|
|
706
|
+
expect(markdown).not.toContain(SETUP_GUIDE_API_KEY_PLACEHOLDER);
|
|
707
|
+
expect(markdown).not.toContain(SETUP_GUIDE_URL_PLACEHOLDER);
|
|
708
|
+
});
|
|
709
|
+
|
|
710
|
+
test("every step it refers to by number is that step", () => {
|
|
711
|
+
expectStepReferencesToMatch(guide);
|
|
712
|
+
expectStepReferencesToMatch(
|
|
713
|
+
productGuide(system, {
|
|
714
|
+
apiKey: SETUP_GUIDE_API_KEY_PLACEHOLDER,
|
|
715
|
+
hasApiKey: false,
|
|
716
|
+
}),
|
|
717
|
+
);
|
|
718
|
+
expectStepReferencesToMatch(
|
|
719
|
+
rowGuide({
|
|
720
|
+
id: DATABASE_ID,
|
|
721
|
+
dbSystem: system,
|
|
722
|
+
endpoints: ["db.data.svc.cluster.local:1234@prod"],
|
|
723
|
+
kubernetesNamespace: "data",
|
|
724
|
+
isKubernetes: true,
|
|
725
|
+
}),
|
|
726
|
+
);
|
|
727
|
+
});
|
|
728
|
+
});
|
|
729
|
+
|
|
730
|
+
describe("each option shows only its own instructions", () => {
|
|
731
|
+
const userStep: (system: string) => string = (system: string): string => {
|
|
732
|
+
return (
|
|
733
|
+
stepTitled(productGuide(system), "Create a monitoring user").markdown ||
|
|
734
|
+
""
|
|
735
|
+
);
|
|
736
|
+
};
|
|
737
|
+
|
|
738
|
+
test("MariaDB's extra replica-status grant is MariaDB's", () => {
|
|
739
|
+
expect(userStep("mariadb")).toContain(
|
|
740
|
+
"GRANT SLAVE MONITOR ON *.* TO 'oneuptime_monitor'@'%';",
|
|
741
|
+
);
|
|
742
|
+
expect(userStep("mysql")).not.toContain("SLAVE MONITOR");
|
|
743
|
+
expect(userStep("mysql")).not.toContain("MariaDB");
|
|
744
|
+
});
|
|
745
|
+
|
|
746
|
+
test("OpenSearch gets its own permissions, Elasticsearch its security API", () => {
|
|
747
|
+
expect(userStep("opensearch")).toContain(
|
|
748
|
+
"give the monitoring user the cluster permission `cluster_monitor` and the index permission `indices_monitor` on `*`",
|
|
749
|
+
);
|
|
750
|
+
expect(userStep("opensearch")).not.toContain("_security");
|
|
751
|
+
expect(userStep("opensearch")).toContain(
|
|
752
|
+
"On a cluster without security, leave `DATABASE_USERNAME` and `DATABASE_PASSWORD` empty.",
|
|
753
|
+
);
|
|
754
|
+
expect(userStep("elasticsearch")).toContain(
|
|
755
|
+
"POST /_security/role/oneuptime_monitor",
|
|
756
|
+
);
|
|
757
|
+
expect(userStep("elasticsearch")).not.toContain("OpenSearch");
|
|
758
|
+
});
|
|
759
|
+
|
|
760
|
+
test("the Redis forks are told the ACL is the same, Redis is not", () => {
|
|
761
|
+
for (const fork of ["valkey", "keydb", "dragonfly"]) {
|
|
762
|
+
expect(userStep(fork)).toContain(
|
|
763
|
+
"Valkey, KeyDB and Dragonfly take the same ACL.",
|
|
764
|
+
);
|
|
765
|
+
expect(userStep(fork)).toContain("ACL SETUSER oneuptime_monitor");
|
|
766
|
+
}
|
|
767
|
+
expect(userStep("redis")).not.toContain("Valkey");
|
|
768
|
+
});
|
|
769
|
+
|
|
770
|
+
test("query-event requirements wait under their own topic", () => {
|
|
771
|
+
const postgres: SetupGuideContent = productGuide("postgresql");
|
|
772
|
+
const queries: string = topicOf(
|
|
773
|
+
postgres.advanced,
|
|
774
|
+
"Query samples and top queries",
|
|
775
|
+
).markdown;
|
|
776
|
+
expect(userStep("postgresql")).not.toContain("pg_stat_statements");
|
|
777
|
+
expect(queries).toContain(
|
|
778
|
+
"```sql\nCREATE EXTENSION IF NOT EXISTS pg_stat_statements;\n```",
|
|
779
|
+
);
|
|
780
|
+
expect(queries).toContain("explain plans additionally need `SELECT`");
|
|
781
|
+
expect(queries).toContain("`failed to explain`");
|
|
782
|
+
|
|
783
|
+
expect(userStep("mongodb")).not.toContain("Explain plans");
|
|
784
|
+
expect(userStep("mongodb")).toContain(
|
|
785
|
+
"run one agent per replica-set member",
|
|
786
|
+
);
|
|
787
|
+
expect(
|
|
788
|
+
topicOf(productGuide("mongodb").advanced, "Query samples and top queries")
|
|
789
|
+
.markdown,
|
|
790
|
+
).toContain('`{ role: "read", db: "<database>" }`');
|
|
791
|
+
});
|
|
792
|
+
|
|
793
|
+
/*
|
|
794
|
+
* Nothing the single-document guide said about a login is lost: every
|
|
795
|
+
* grant block it showed is in the setup guide of an engine that config
|
|
796
|
+
* monitors, and every sentence either there or in the query-event topic
|
|
797
|
+
* (bar the one OpenSearch sentence the setup guide words for OpenSearch).
|
|
798
|
+
*/
|
|
799
|
+
test("every fact of the single-document grants survives the split", () => {
|
|
800
|
+
for (const engine of DATABASE_AGENT_ENGINES) {
|
|
801
|
+
if (engine === "memcached") {
|
|
802
|
+
// No login to create: the step becomes a prerequisite, reworded.
|
|
803
|
+
const memcached: SetupGuideContent = productGuide("memcached");
|
|
804
|
+
const prerequisite: string = (memcached.prerequisites || []).join("\n");
|
|
805
|
+
expect(topicTitles(memcached.advanced)).not.toContain(
|
|
806
|
+
"Create a monitoring user",
|
|
807
|
+
);
|
|
808
|
+
expect(prerequisite).toContain("Memcached has no users");
|
|
809
|
+
expect(prerequisite).toContain(
|
|
810
|
+
"the agent runs `stats` over the text protocol",
|
|
811
|
+
);
|
|
812
|
+
expect(prerequisite).toContain("without SASL authentication (`-S`)");
|
|
813
|
+
expect(envBlockOf(variantOf(memcached, "Docker Compose"))).toContain(
|
|
814
|
+
"\nDATABASE_USERNAME=\nDATABASE_PASSWORD=\n",
|
|
815
|
+
);
|
|
816
|
+
continue;
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
const document: string = getDatabaseAgentInstallationMarkdown({
|
|
820
|
+
oneuptimeUrl: URL,
|
|
821
|
+
apiKey: KEY,
|
|
822
|
+
engine: engine,
|
|
823
|
+
});
|
|
824
|
+
const section: string = document.substring(
|
|
825
|
+
document.indexOf("## Create a monitoring user"),
|
|
826
|
+
document.indexOf("## Quick Start — Install Script"),
|
|
827
|
+
);
|
|
828
|
+
const structured: string = SYSTEMS.filter((system: string): boolean => {
|
|
829
|
+
return engineOf(system) === engine;
|
|
830
|
+
})
|
|
831
|
+
.map((system: string): string => {
|
|
832
|
+
return getSetupGuideMarkdown(productGuide(system));
|
|
833
|
+
})
|
|
834
|
+
.join("\n");
|
|
835
|
+
|
|
836
|
+
for (const block of codeBlocks(section)) {
|
|
837
|
+
expect({ engine, kept: structured.includes(block.body) }).toEqual({
|
|
838
|
+
engine,
|
|
839
|
+
kept: true,
|
|
840
|
+
});
|
|
841
|
+
}
|
|
842
|
+
|
|
843
|
+
const prose: string = section
|
|
844
|
+
.replace(/```[\s\S]*?```/g, "\n\n")
|
|
845
|
+
.replace(/^## Create a monitoring user$/m, "");
|
|
846
|
+
const sentences: Array<string> = prose
|
|
847
|
+
.split(/\n\s*\n|(?<=\.)\s+(?=[A-Z`])/)
|
|
848
|
+
.map((sentence: string): string => {
|
|
849
|
+
return sentence.trim();
|
|
850
|
+
})
|
|
851
|
+
.filter((sentence: string): boolean => {
|
|
852
|
+
return sentence.length > 0;
|
|
853
|
+
});
|
|
854
|
+
expect(sentences.length).toBeGreaterThan(0);
|
|
855
|
+
for (const sentence of sentences) {
|
|
856
|
+
if (sentence.startsWith("On OpenSearch with the security plugin")) {
|
|
857
|
+
continue;
|
|
858
|
+
}
|
|
859
|
+
expect({
|
|
860
|
+
engine,
|
|
861
|
+
sentence,
|
|
862
|
+
kept: structured.includes(sentence),
|
|
863
|
+
}).toEqual({ engine, sentence, kept: true });
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
});
|
|
867
|
+
});
|
|
868
|
+
|
|
869
|
+
describe("before a key is picked", () => {
|
|
870
|
+
test.each(SYSTEMS)(
|
|
871
|
+
"the %s install command carries neither a placeholder nor a URL, and says the script asks",
|
|
872
|
+
(system: string) => {
|
|
873
|
+
const guide: SetupGuideContent = productGuide(system, {
|
|
874
|
+
apiKey: SETUP_GUIDE_API_KEY_PLACEHOLDER,
|
|
875
|
+
hasApiKey: false,
|
|
876
|
+
});
|
|
877
|
+
const markdown: string = getSetupGuideMarkdown(guide);
|
|
878
|
+
const script: string = variantOf(guide, "Install script");
|
|
879
|
+
|
|
880
|
+
expect(installCommandOf(script)).toBe(
|
|
881
|
+
`DATABASE_SYSTEM=${system} bash install.sh`,
|
|
882
|
+
);
|
|
883
|
+
expect(script).toContain(
|
|
884
|
+
"The script asks for your OneUptime URL, the ingestion key from step 1",
|
|
885
|
+
);
|
|
886
|
+
expect(script).toContain("the endpoint to connect to");
|
|
887
|
+
// No install.sh line anywhere — the upgrade topic's included — stores a key.
|
|
888
|
+
const commands: Array<string> = installCommandsOf(markdown);
|
|
889
|
+
expect(commands.length).toBeGreaterThanOrEqual(3);
|
|
890
|
+
for (const command of commands) {
|
|
891
|
+
expect(command).not.toContain("ONEUPTIME_TELEMETRY_INGESTION_KEY");
|
|
892
|
+
expect(command).not.toContain("ONEUPTIME_URL");
|
|
893
|
+
expect(command).not.toContain(SETUP_GUIDE_API_KEY_PLACEHOLDER);
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
// The hand-written .env shows where the key goes, and says so.
|
|
897
|
+
const compose: string = variantOf(guide, "Docker Compose");
|
|
898
|
+
expect(envBlockOf(compose)).toContain(
|
|
899
|
+
`\nONEUPTIME_TELEMETRY_INGESTION_KEY=${SETUP_GUIDE_API_KEY_PLACEHOLDER}\n`,
|
|
900
|
+
);
|
|
901
|
+
expect(compose).toContain(
|
|
902
|
+
`Pick an ingestion key in step 1 to fill in \`${SETUP_GUIDE_API_KEY_PLACEHOLDER}\`.`,
|
|
903
|
+
);
|
|
904
|
+
},
|
|
905
|
+
);
|
|
906
|
+
|
|
907
|
+
test("without hasApiKey, the placeholder itself means no key", () => {
|
|
908
|
+
const guide: SetupGuideContent = getDatabaseAgentSetupGuide({
|
|
909
|
+
oneuptimeUrl: URL,
|
|
910
|
+
apiKey: SETUP_GUIDE_API_KEY_PLACEHOLDER,
|
|
911
|
+
engine: "postgresql",
|
|
912
|
+
});
|
|
913
|
+
expect(installCommandOf(variantOf(guide, "Install script"))).toBe(
|
|
914
|
+
"DATABASE_SYSTEM=postgresql bash install.sh",
|
|
915
|
+
);
|
|
916
|
+
|
|
917
|
+
const withKey: SetupGuideContent = getDatabaseAgentSetupGuide({
|
|
918
|
+
oneuptimeUrl: URL,
|
|
919
|
+
apiKey: KEY,
|
|
920
|
+
engine: "postgresql",
|
|
921
|
+
});
|
|
922
|
+
expect(installCommandOf(variantOf(withKey, "Install script"))).toBe(
|
|
923
|
+
`ONEUPTIME_URL=${URL} ONEUPTIME_TELEMETRY_INGESTION_KEY=${KEY} DATABASE_SYSTEM=postgresql bash install.sh`,
|
|
924
|
+
);
|
|
925
|
+
});
|
|
926
|
+
|
|
927
|
+
test("a placeholder never reaches the command line, whatever hasApiKey says", () => {
|
|
928
|
+
const guide: SetupGuideContent = productGuide("mysql", {
|
|
929
|
+
apiKey: SETUP_GUIDE_API_KEY_PLACEHOLDER,
|
|
930
|
+
hasApiKey: true,
|
|
931
|
+
});
|
|
932
|
+
expect(installCommandOf(variantOf(guide, "Install script"))).toBe(
|
|
933
|
+
"DATABASE_SYSTEM=mysql bash install.sh",
|
|
934
|
+
);
|
|
935
|
+
});
|
|
936
|
+
|
|
937
|
+
test("an unknown OneUptime URL is asked for, while a picked key is still passed", () => {
|
|
938
|
+
const guide: SetupGuideContent = productGuide("postgresql", {
|
|
939
|
+
oneuptimeUrl: SETUP_GUIDE_URL_PLACEHOLDER,
|
|
940
|
+
});
|
|
941
|
+
const script: string = variantOf(guide, "Install script");
|
|
942
|
+
expect(installCommandOf(script)).toBe(
|
|
943
|
+
`ONEUPTIME_TELEMETRY_INGESTION_KEY=${KEY} DATABASE_SYSTEM=postgresql bash install.sh`,
|
|
944
|
+
);
|
|
945
|
+
expect(script).toContain(
|
|
946
|
+
"The script asks for your OneUptime URL, the endpoint",
|
|
947
|
+
);
|
|
948
|
+
expect(script).not.toContain("the ingestion key from step 1");
|
|
949
|
+
});
|
|
950
|
+
|
|
951
|
+
test("a key with shell characters reaches install.sh as one quoted word", () => {
|
|
952
|
+
const guide: SetupGuideContent = productGuide("postgresql", {
|
|
953
|
+
apiKey: "it's $ecret; really",
|
|
954
|
+
});
|
|
955
|
+
const command: string = installCommandOf(
|
|
956
|
+
variantOf(guide, "Install script"),
|
|
957
|
+
);
|
|
958
|
+
expect(command).toBe(
|
|
959
|
+
`ONEUPTIME_URL=${URL} ONEUPTIME_TELEMETRY_INGESTION_KEY='it'\\''s $ecret; really' DATABASE_SYSTEM=postgresql bash install.sh`,
|
|
960
|
+
);
|
|
961
|
+
const words: Array<string> = command
|
|
962
|
+
.replace(/ bash install\.sh$/, "")
|
|
963
|
+
.match(/[A-Z_]+=(?:'(?:[^']|'\\'')*'|\S*)/g)!;
|
|
964
|
+
for (const word of words) {
|
|
965
|
+
expect(word).toMatch(
|
|
966
|
+
/^[A-Z_]+=(?:[A-Za-z0-9._:@%+,/=-]+|'(?:[^']|'\\'')*')$/,
|
|
967
|
+
);
|
|
968
|
+
}
|
|
969
|
+
});
|
|
970
|
+
});
|
|
971
|
+
|
|
972
|
+
describe("a database's own guide", () => {
|
|
973
|
+
const database: DatabaseDocumentationTarget = {
|
|
974
|
+
id: DATABASE_ID,
|
|
975
|
+
name: "PostgreSQL db.prod.internal:5432",
|
|
976
|
+
dbSystem: "postgresql",
|
|
977
|
+
serverAddress: "db.prod.internal",
|
|
978
|
+
serverPort: 5432,
|
|
979
|
+
endpoints: ["db.prod.internal:5432"],
|
|
980
|
+
};
|
|
981
|
+
const guide: SetupGuideContent = rowGuide(database);
|
|
982
|
+
const markdown: string = getSetupGuideMarkdown(guide);
|
|
983
|
+
|
|
984
|
+
test("opens with this database's identity", () => {
|
|
985
|
+
expect(guide.intro).toContain("**This database**");
|
|
986
|
+
expect(guide.intro).toContain("| `DATABASE_SYSTEM` | `postgresql` |");
|
|
987
|
+
expect(guide.intro).toContain(
|
|
988
|
+
`| \`DATABASE_SERVER_ID\` | \`${DATABASE_ID}\` |`,
|
|
989
|
+
);
|
|
990
|
+
expect(guide.intro).toContain(
|
|
991
|
+
"| `DATABASE_SERVER_ADDRESS` | `db.prod.internal` |",
|
|
992
|
+
);
|
|
993
|
+
expect(guide.intro).toContain("| `DATABASE_SERVER_PORT` | `5432` |");
|
|
994
|
+
expect(guide.intro).toContain(
|
|
995
|
+
"`DATABASE_SERVER_ID` is stamped on the agent's data as `oneuptime.database.server.id`",
|
|
996
|
+
);
|
|
997
|
+
});
|
|
998
|
+
|
|
999
|
+
test("installs for this database: its identity and id on the command line, after the URL and key", () => {
|
|
1000
|
+
expect(installCommandOf(variantOf(guide, "Install script"))).toBe(
|
|
1001
|
+
`ONEUPTIME_URL=${URL} ONEUPTIME_TELEMETRY_INGESTION_KEY=${KEY} DATABASE_SYSTEM=postgresql DATABASE_SERVER_ADDRESS=db.prod.internal DATABASE_SERVER_PORT=5432 DATABASE_SERVER_ID=${DATABASE_ID} bash install.sh`,
|
|
1002
|
+
);
|
|
1003
|
+
expect(envBlockOf(variantOf(guide, "Docker Compose"))).toContain(
|
|
1004
|
+
`\nDATABASE_SERVER_ID=${DATABASE_ID}`,
|
|
1005
|
+
);
|
|
1006
|
+
// The row is known, so the script is not said to ask for its name.
|
|
1007
|
+
expect(variantOf(guide, "Install script")).not.toContain(
|
|
1008
|
+
"it also asks for the host name",
|
|
1009
|
+
);
|
|
1010
|
+
});
|
|
1011
|
+
|
|
1012
|
+
test("says this database's Engine metrics turn Connected, and troubleshoots them", () => {
|
|
1013
|
+
expect(stepTitled(guide, "Verify the installation").markdown).toContain(
|
|
1014
|
+
"this database's **Engine metrics** status turns to Connected",
|
|
1015
|
+
);
|
|
1016
|
+
const titles: Array<string> = topicTitles(guide.troubleshooting);
|
|
1017
|
+
expect(titles[0]).toBe(
|
|
1018
|
+
'Engine metrics reads "Not connected" or "Disconnected"',
|
|
1019
|
+
);
|
|
1020
|
+
expect(titles).not.toContain(
|
|
1021
|
+
"The database does not appear under Databases",
|
|
1022
|
+
);
|
|
1023
|
+
expect(
|
|
1024
|
+
topicOf(
|
|
1025
|
+
guide.troubleshooting,
|
|
1026
|
+
'Engine metrics reads "Not connected" or "Disconnected"',
|
|
1027
|
+
).markdown,
|
|
1028
|
+
).toContain(`\`${DATABASE_ID}\``);
|
|
1029
|
+
});
|
|
1030
|
+
|
|
1031
|
+
test("alerting comes first under Advanced, with the id and the Recommendations tab", () => {
|
|
1032
|
+
expect(topicTitles(guide.advanced)[0]).toBe("Alert on this database");
|
|
1033
|
+
const alerting: string = topicOf(
|
|
1034
|
+
guide.advanced,
|
|
1035
|
+
"Alert on this database",
|
|
1036
|
+
).markdown;
|
|
1037
|
+
expect(alerting).toContain(
|
|
1038
|
+
`\`oneuptime.database.server.id\` = \`${DATABASE_ID}\``,
|
|
1039
|
+
);
|
|
1040
|
+
expect(alerting).toContain(
|
|
1041
|
+
`The [Recommendations](${RECOMMENDATIONS_URL}) tab offers ready-made PostgreSQL monitors`,
|
|
1042
|
+
);
|
|
1043
|
+
expect(alerting).toContain("`cumulativetodelta` processor");
|
|
1044
|
+
});
|
|
1045
|
+
|
|
1046
|
+
test("the Database Health monitor names this database's endpoint", () => {
|
|
1047
|
+
expect(
|
|
1048
|
+
topicOf(guide.advanced, "No agent? Use a Database Health monitor")
|
|
1049
|
+
.markdown,
|
|
1050
|
+
).toContain(
|
|
1051
|
+
`[create a Database Health monitor](${HEALTH_URL}) (PostgreSQL, MySQL and SQL Server). It uses the same monitoring user. Point it at \`db.prod.internal:5432\`, one of this database's endpoints`,
|
|
1052
|
+
);
|
|
1053
|
+
});
|
|
1054
|
+
|
|
1055
|
+
test("does not ask for the identity up front: the row has one", () => {
|
|
1056
|
+
expect((guide.prerequisites || []).join("\n")).not.toContain(
|
|
1057
|
+
"The host name your applications use",
|
|
1058
|
+
);
|
|
1059
|
+
});
|
|
1060
|
+
|
|
1061
|
+
test("is not a Kubernetes install", () => {
|
|
1062
|
+
expect(variantLabels(stepTitled(guide, "Install the agent"))).toEqual([
|
|
1063
|
+
"Install script",
|
|
1064
|
+
"Docker Compose",
|
|
1065
|
+
]);
|
|
1066
|
+
expect(markdown).not.toContain("kind: Deployment");
|
|
1067
|
+
});
|
|
1068
|
+
});
|
|
1069
|
+
|
|
1070
|
+
/*
|
|
1071
|
+
* The setup guide is built from the same pieces as the single-document
|
|
1072
|
+
* guide, whose tests pin the subtle rules — the identity a row resolves
|
|
1073
|
+
* to, a SQL Server named instance's port, the shell quoting of the command
|
|
1074
|
+
* line. Before a key is picked the two install the same way, byte for byte.
|
|
1075
|
+
*/
|
|
1076
|
+
describe("parity with the single-document guide", () => {
|
|
1077
|
+
const ROWS: Array<DatabaseDocumentationTarget> = [
|
|
1078
|
+
{
|
|
1079
|
+
id: DATABASE_ID,
|
|
1080
|
+
dbSystem: "postgresql",
|
|
1081
|
+
serverAddress: "db.prod.internal",
|
|
1082
|
+
serverPort: 5432,
|
|
1083
|
+
},
|
|
1084
|
+
{ id: DATABASE_ID, dbSystem: "postgresql" },
|
|
1085
|
+
{
|
|
1086
|
+
id: DATABASE_ID,
|
|
1087
|
+
dbSystem: "valkey",
|
|
1088
|
+
serverAddress: "cache.prod.internal",
|
|
1089
|
+
},
|
|
1090
|
+
{
|
|
1091
|
+
id: DATABASE_ID,
|
|
1092
|
+
dbSystem: "postgresql",
|
|
1093
|
+
serverAddress: "2001:db8::10",
|
|
1094
|
+
serverPort: 5432,
|
|
1095
|
+
},
|
|
1096
|
+
{
|
|
1097
|
+
id: DATABASE_ID,
|
|
1098
|
+
dbSystem: "microsoft.sql_server",
|
|
1099
|
+
serverAddress: "sql1.corp.example.com\\inst01",
|
|
1100
|
+
endpoints: ["sql1.corp.example.com\\inst01"],
|
|
1101
|
+
},
|
|
1102
|
+
{
|
|
1103
|
+
id: DATABASE_ID,
|
|
1104
|
+
dbSystem: "microsoft.sql_server",
|
|
1105
|
+
endpoints: ["sql1.corp.example.com\\inst01,14330"],
|
|
1106
|
+
},
|
|
1107
|
+
{ id: "it's; odd", dbSystem: "mysql", serverAddress: "db.example.com" },
|
|
1108
|
+
{ id: DATABASE_ID, dbSystem: "mariadb", serverAddress: "10.0.0.5" },
|
|
1109
|
+
{
|
|
1110
|
+
id: DATABASE_ID,
|
|
1111
|
+
dbSystem: "opensearch",
|
|
1112
|
+
serverAddress: "search.prod.example.com",
|
|
1113
|
+
},
|
|
1114
|
+
{
|
|
1115
|
+
id: DATABASE_ID,
|
|
1116
|
+
dbSystem: "postgresql",
|
|
1117
|
+
endpoints: ["postgres.payments.svc.cluster.local:5432@prod"],
|
|
1118
|
+
kubernetesNamespace: "payments",
|
|
1119
|
+
isKubernetes: true,
|
|
1120
|
+
},
|
|
1121
|
+
];
|
|
1122
|
+
|
|
1123
|
+
test.each(ROWS)(
|
|
1124
|
+
"installs the same way, and writes the same .env and manifest (%j)",
|
|
1125
|
+
(database: DatabaseDocumentationTarget) => {
|
|
1126
|
+
const engine: DatabaseAgentEngine = engineOf(database.dbSystem || "");
|
|
1127
|
+
const document: string = getDatabaseAgentInstallationMarkdown({
|
|
1128
|
+
oneuptimeUrl: URL,
|
|
1129
|
+
apiKey: SETUP_GUIDE_API_KEY_PLACEHOLDER,
|
|
1130
|
+
engine: engine,
|
|
1131
|
+
system: database.dbSystem,
|
|
1132
|
+
database: database,
|
|
1133
|
+
});
|
|
1134
|
+
const guide: SetupGuideContent = rowGuide(database, {
|
|
1135
|
+
apiKey: SETUP_GUIDE_API_KEY_PLACEHOLDER,
|
|
1136
|
+
hasApiKey: false,
|
|
1137
|
+
});
|
|
1138
|
+
|
|
1139
|
+
expect(installCommandOf(variantOf(guide, "Install script"))).toBe(
|
|
1140
|
+
installCommandOf(document),
|
|
1141
|
+
);
|
|
1142
|
+
expect(envBlockOf(variantOf(guide, "Docker Compose"))).toBe(
|
|
1143
|
+
envBlockOf(document),
|
|
1144
|
+
);
|
|
1145
|
+
expect(guide.intro).toContain(
|
|
1146
|
+
document.substring(
|
|
1147
|
+
document.indexOf("| Setting | Value |"),
|
|
1148
|
+
document.indexOf("\n\n## Prerequisites"),
|
|
1149
|
+
),
|
|
1150
|
+
);
|
|
1151
|
+
|
|
1152
|
+
const documentManifest: { language: string; body: string } | undefined =
|
|
1153
|
+
codeBlocks(document).find(
|
|
1154
|
+
(block: { language: string; body: string }): boolean => {
|
|
1155
|
+
return block.body.startsWith("apiVersion: apps/v1");
|
|
1156
|
+
},
|
|
1157
|
+
);
|
|
1158
|
+
if (database.isKubernetes) {
|
|
1159
|
+
expect(variantOf(guide, "Kubernetes")).toContain(
|
|
1160
|
+
documentManifest!.body,
|
|
1161
|
+
);
|
|
1162
|
+
} else {
|
|
1163
|
+
expect(documentManifest).toBeUndefined();
|
|
1164
|
+
}
|
|
1165
|
+
},
|
|
1166
|
+
);
|
|
1167
|
+
|
|
1168
|
+
test("the product page's picked engine installs the same way too", () => {
|
|
1169
|
+
for (const system of SYSTEMS) {
|
|
1170
|
+
const document: string = getDatabaseAgentInstallationMarkdown({
|
|
1171
|
+
oneuptimeUrl: URL,
|
|
1172
|
+
apiKey: KEY,
|
|
1173
|
+
engine: engineOf(system),
|
|
1174
|
+
system: system,
|
|
1175
|
+
});
|
|
1176
|
+
const guide: SetupGuideContent = productGuide(system, {
|
|
1177
|
+
hasApiKey: false,
|
|
1178
|
+
});
|
|
1179
|
+
expect(installCommandOf(variantOf(guide, "Install script"))).toBe(
|
|
1180
|
+
installCommandOf(document),
|
|
1181
|
+
);
|
|
1182
|
+
expect(envBlockOf(variantOf(guide, "Docker Compose"))).toBe(
|
|
1183
|
+
envBlockOf(document),
|
|
1184
|
+
);
|
|
1185
|
+
}
|
|
1186
|
+
});
|
|
1187
|
+
});
|
|
1188
|
+
|
|
1189
|
+
describe("a Kubernetes database's guide", () => {
|
|
1190
|
+
const database: DatabaseDocumentationTarget = {
|
|
1191
|
+
id: DATABASE_ID,
|
|
1192
|
+
dbSystem: "valkey",
|
|
1193
|
+
endpoints: ["valkey.cache.svc.cluster.local:6379@prod"],
|
|
1194
|
+
kubernetesNamespace: "cache",
|
|
1195
|
+
isKubernetes: true,
|
|
1196
|
+
};
|
|
1197
|
+
const guide: SetupGuideContent = rowGuide(database);
|
|
1198
|
+
|
|
1199
|
+
test("offers the Deployment first, then the script and Docker Compose", () => {
|
|
1200
|
+
expect(variantLabels(stepTitled(guide, "Install the agent"))).toEqual([
|
|
1201
|
+
"Kubernetes",
|
|
1202
|
+
"Install script",
|
|
1203
|
+
"Docker Compose",
|
|
1204
|
+
]);
|
|
1205
|
+
expect(stepTitled(guide, "Install the agent").description).toContain(
|
|
1206
|
+
"Run it as a Deployment next to the database",
|
|
1207
|
+
);
|
|
1208
|
+
});
|
|
1209
|
+
|
|
1210
|
+
test("the Deployment is prefilled for the row's namespace, engine and id", () => {
|
|
1211
|
+
const kubernetes: string = variantOf(guide, "Kubernetes");
|
|
1212
|
+
expect(kubernetes).toContain(
|
|
1213
|
+
`curl -fsSL ${DATABASE_AGENT_RAW_URL}/configs/redis.yaml -o config.yaml`,
|
|
1214
|
+
);
|
|
1215
|
+
expect(kubernetes).toContain(
|
|
1216
|
+
"kubectl -n cache create configmap oneuptime-database-agent --from-file=config.yaml=config.yaml",
|
|
1217
|
+
);
|
|
1218
|
+
expect(kubernetes).toContain(
|
|
1219
|
+
`--from-literal=ONEUPTIME_TELEMETRY_INGESTION_KEY='${KEY}'`,
|
|
1220
|
+
);
|
|
1221
|
+
expect(kubernetes).toContain(
|
|
1222
|
+
getDatabaseAgentKubernetesManifest({
|
|
1223
|
+
oneuptimeUrl: URL,
|
|
1224
|
+
engine: "redis",
|
|
1225
|
+
identity: resolveDatabaseAgentIdentity("valkey", database),
|
|
1226
|
+
namespace: "cache",
|
|
1227
|
+
system: "valkey",
|
|
1228
|
+
}),
|
|
1229
|
+
);
|
|
1230
|
+
expect(kubernetes).toContain('value: "valkey"');
|
|
1231
|
+
expect(kubernetes).toContain(`value: "${DATABASE_ID}"`);
|
|
1232
|
+
expect(kubernetes).toContain("write every `$` in it as `$$`");
|
|
1233
|
+
expect(kubernetes).not.toContain("Pick an ingestion key in step 1");
|
|
1234
|
+
});
|
|
1235
|
+
|
|
1236
|
+
test("the prerequisites, the check and the connection help speak Kubernetes too", () => {
|
|
1237
|
+
expect((guide.prerequisites || [])[0]).toContain(
|
|
1238
|
+
"`kubectl` access to the `cache` namespace",
|
|
1239
|
+
);
|
|
1240
|
+
expect(stepTitled(guide, "Verify the installation").markdown).toContain(
|
|
1241
|
+
"`kubectl -n cache logs deployment/oneuptime-database-agent`",
|
|
1242
|
+
);
|
|
1243
|
+
expect(
|
|
1244
|
+
topicOf(guide.troubleshooting, "The agent cannot connect to the database")
|
|
1245
|
+
.markdown,
|
|
1246
|
+
).toContain("`<service>.cache.svc.cluster.local`");
|
|
1247
|
+
expect(
|
|
1248
|
+
topicOf(guide.troubleshooting, "The agent container keeps restarting")
|
|
1249
|
+
.markdown,
|
|
1250
|
+
).toContain("`kubectl -n cache logs deployment/oneuptime-database-agent`");
|
|
1251
|
+
expect(
|
|
1252
|
+
topicOf(
|
|
1253
|
+
rowGuide({ ...database, isKubernetes: false }).troubleshooting,
|
|
1254
|
+
"The agent container keeps restarting",
|
|
1255
|
+
).markdown,
|
|
1256
|
+
).not.toContain("kubectl");
|
|
1257
|
+
expect(
|
|
1258
|
+
topicOf(guide.advanced, "What the agent collects").markdown,
|
|
1259
|
+
).toContain("The OneUptime Database Agent collects Valkey engine metrics");
|
|
1260
|
+
});
|
|
1261
|
+
|
|
1262
|
+
test("before a key is picked the Secret shows the placeholder, and says to pick one", () => {
|
|
1263
|
+
const kubernetes: string = variantOf(
|
|
1264
|
+
rowGuide(database, {
|
|
1265
|
+
apiKey: SETUP_GUIDE_API_KEY_PLACEHOLDER,
|
|
1266
|
+
hasApiKey: false,
|
|
1267
|
+
}),
|
|
1268
|
+
"Kubernetes",
|
|
1269
|
+
);
|
|
1270
|
+
expect(kubernetes).toContain(
|
|
1271
|
+
`--from-literal=ONEUPTIME_TELEMETRY_INGESTION_KEY='${SETUP_GUIDE_API_KEY_PLACEHOLDER}'`,
|
|
1272
|
+
);
|
|
1273
|
+
expect(kubernetes).toContain("Pick an ingestion key in step 1");
|
|
1274
|
+
});
|
|
1275
|
+
|
|
1276
|
+
test("a row without a namespace deploys into default", () => {
|
|
1277
|
+
const withoutNamespace: SetupGuideContent = rowGuide({
|
|
1278
|
+
...database,
|
|
1279
|
+
kubernetesNamespace: " ",
|
|
1280
|
+
});
|
|
1281
|
+
expect(variantOf(withoutNamespace, "Kubernetes")).toContain(
|
|
1282
|
+
"kubectl -n default create configmap",
|
|
1283
|
+
);
|
|
1284
|
+
expect((withoutNamespace.prerequisites || [])[0]).toContain(
|
|
1285
|
+
"`kubectl` access to the `default` namespace",
|
|
1286
|
+
);
|
|
1287
|
+
});
|
|
1288
|
+
|
|
1289
|
+
test("a database outside Kubernetes never gets the Deployment", () => {
|
|
1290
|
+
const outside: SetupGuideContent = rowGuide({
|
|
1291
|
+
...database,
|
|
1292
|
+
isKubernetes: false,
|
|
1293
|
+
});
|
|
1294
|
+
expect(variantLabels(stepTitled(outside, "Install the agent"))).toEqual([
|
|
1295
|
+
"Install script",
|
|
1296
|
+
"Docker Compose",
|
|
1297
|
+
]);
|
|
1298
|
+
expect(getSetupGuideMarkdown(outside)).not.toContain("kubectl");
|
|
1299
|
+
});
|
|
1300
|
+
});
|
|
1301
|
+
|
|
1302
|
+
describe("a row the guide cannot fully prefill", () => {
|
|
1303
|
+
test("without an address, the script asks for the name and the samples say to replace it", () => {
|
|
1304
|
+
const guide: SetupGuideContent = rowGuide({
|
|
1305
|
+
id: DATABASE_ID,
|
|
1306
|
+
dbSystem: "postgresql",
|
|
1307
|
+
});
|
|
1308
|
+
expect(installCommandOf(variantOf(guide, "Install script"))).toBe(
|
|
1309
|
+
`ONEUPTIME_URL=${URL} ONEUPTIME_TELEMETRY_INGESTION_KEY=${KEY} DATABASE_SYSTEM=postgresql DATABASE_SERVER_ID=${DATABASE_ID} bash install.sh`,
|
|
1310
|
+
);
|
|
1311
|
+
expect(guide.intro).toContain(
|
|
1312
|
+
"the install script asks for the host name your applications use to reach it, and in the samples below replace `db.example.com` with that name",
|
|
1313
|
+
);
|
|
1314
|
+
expect(envBlockOf(variantOf(guide, "Docker Compose"))).toContain(
|
|
1315
|
+
"\nDATABASE_SERVER_ADDRESS=db.example.com\n",
|
|
1316
|
+
);
|
|
1317
|
+
});
|
|
1318
|
+
|
|
1319
|
+
test("a SQL Server named instance without a port leaves the port to the reader", () => {
|
|
1320
|
+
const guide: SetupGuideContent = rowGuide({
|
|
1321
|
+
id: DATABASE_ID,
|
|
1322
|
+
dbSystem: "microsoft.sql_server",
|
|
1323
|
+
serverAddress: "sql1.corp.example.com\\inst01",
|
|
1324
|
+
});
|
|
1325
|
+
const command: string = installCommandOf(
|
|
1326
|
+
variantOf(guide, "Install script"),
|
|
1327
|
+
);
|
|
1328
|
+
expect(command).toBe(
|
|
1329
|
+
`ONEUPTIME_URL=${URL} ONEUPTIME_TELEMETRY_INGESTION_KEY=${KEY} DATABASE_SYSTEM=microsoft.sql_server DATABASE_SERVER_ADDRESS=sql1.corp.example.com DATABASE_SERVER_ID=${DATABASE_ID} bash install.sh`,
|
|
1330
|
+
);
|
|
1331
|
+
expect(command).not.toContain("\\");
|
|
1332
|
+
expect(guide.intro).toContain("named instance `inst01`");
|
|
1333
|
+
expect(guide.intro).toContain(
|
|
1334
|
+
"| `DATABASE_SERVER_PORT` | `<instance-tcp-port>` |",
|
|
1335
|
+
);
|
|
1336
|
+
expect(envBlockOf(variantOf(guide, "Docker Compose"))).toContain(
|
|
1337
|
+
"\nDATABASE_ENDPOINT_PORT=<instance-tcp-port>\n",
|
|
1338
|
+
);
|
|
1339
|
+
});
|
|
1340
|
+
});
|
|
1341
|
+
|
|
1342
|
+
describe("the troubleshooting of each engine's login", () => {
|
|
1343
|
+
test.each([...DATABASE_AGENT_ENGINES])(
|
|
1344
|
+
"%s: names the errors its own receiver logs",
|
|
1345
|
+
(engine: DatabaseAgentEngine) => {
|
|
1346
|
+
const guide: SetupGuideContent = productGuide(
|
|
1347
|
+
getDatabaseAgentSystem(engine),
|
|
1348
|
+
);
|
|
1349
|
+
const topic: SetupGuideTopic | undefined = (
|
|
1350
|
+
guide.troubleshooting || []
|
|
1351
|
+
).find((candidate: SetupGuideTopic): boolean => {
|
|
1352
|
+
return candidate.title.startsWith("Login");
|
|
1353
|
+
});
|
|
1354
|
+
|
|
1355
|
+
if (engine === "memcached") {
|
|
1356
|
+
expect(topic).toBeUndefined();
|
|
1357
|
+
return;
|
|
1358
|
+
}
|
|
1359
|
+
|
|
1360
|
+
const hasTls: boolean = engine !== "sqlserver" && engine !== "oracledb";
|
|
1361
|
+
expect(topic!.title).toBe(
|
|
1362
|
+
hasTls
|
|
1363
|
+
? "Login, permission or TLS errors in the collector log"
|
|
1364
|
+
: "Login or permission errors in the collector log",
|
|
1365
|
+
);
|
|
1366
|
+
expect(topic!.markdown.includes("TLS errors")).toBe(hasTls);
|
|
1367
|
+
expect(topic!.markdown).toContain(
|
|
1368
|
+
"the monitoring user is missing the grants from step 2",
|
|
1369
|
+
);
|
|
1370
|
+
expect(topic!.markdown).toContain("every `$` must be written as `$$`");
|
|
1371
|
+
|
|
1372
|
+
/*
|
|
1373
|
+
* Every message named is one troubleshoot.sh looks for, and each is
|
|
1374
|
+
* named only for its own engine.
|
|
1375
|
+
*/
|
|
1376
|
+
const troubleshoot: string = readAgentFile("troubleshoot.sh");
|
|
1377
|
+
const named: Array<string> = Array.from(
|
|
1378
|
+
topic!.markdown.matchAll(/^- ((?:`[^`]+`(?:, )?)+)/gm),
|
|
1379
|
+
).flatMap((match: RegExpMatchArray): Array<string> => {
|
|
1380
|
+
return Array.from(match[1]!.matchAll(/`([^`]+)`/g)).map(
|
|
1381
|
+
(inner: RegExpMatchArray): string => {
|
|
1382
|
+
return inner[1]!.split(" …")[0]!;
|
|
1383
|
+
},
|
|
1384
|
+
);
|
|
1385
|
+
});
|
|
1386
|
+
expect(named.length).toBeGreaterThanOrEqual(2);
|
|
1387
|
+
for (const message of named) {
|
|
1388
|
+
if (message.startsWith("ORA-125") || message.startsWith("ORA-2800")) {
|
|
1389
|
+
continue;
|
|
1390
|
+
}
|
|
1391
|
+
if (
|
|
1392
|
+
message === "pg_stat_statements" ||
|
|
1393
|
+
message === "failed to explain"
|
|
1394
|
+
) {
|
|
1395
|
+
expect(troubleshoot).toContain(message);
|
|
1396
|
+
continue;
|
|
1397
|
+
}
|
|
1398
|
+
expect({
|
|
1399
|
+
engine,
|
|
1400
|
+
message,
|
|
1401
|
+
checked: troubleshoot.includes(message),
|
|
1402
|
+
}).toEqual({ engine, message, checked: true });
|
|
1403
|
+
}
|
|
1404
|
+
},
|
|
1405
|
+
);
|
|
1406
|
+
|
|
1407
|
+
test("only SQL Server is told about what its connection string cannot carry", () => {
|
|
1408
|
+
for (const engine of DATABASE_AGENT_ENGINES) {
|
|
1409
|
+
expect(
|
|
1410
|
+
getSetupGuideMarkdown(
|
|
1411
|
+
productGuide(getDatabaseAgentSystem(engine)),
|
|
1412
|
+
).includes("the receiver's connection string cannot carry them"),
|
|
1413
|
+
).toBe(engine === "sqlserver");
|
|
1414
|
+
}
|
|
1415
|
+
});
|
|
1416
|
+
|
|
1417
|
+
test("only Oracle is told about its listener and locked accounts", () => {
|
|
1418
|
+
const oracle: string = getSetupGuideMarkdown(productGuide("oracle.db"));
|
|
1419
|
+
expect(oracle).toContain("`ORA-12514` or `ORA-12505`");
|
|
1420
|
+
expect(oracle).toContain("`lsnrctl services`");
|
|
1421
|
+
expect(oracle).toContain("`ORA-28000` or `ORA-28001`");
|
|
1422
|
+
expect(getSetupGuideMarkdown(productGuide("postgresql"))).not.toContain(
|
|
1423
|
+
"ORA-",
|
|
1424
|
+
);
|
|
1425
|
+
});
|
|
1426
|
+
});
|
|
1427
|
+
|
|
1428
|
+
describe("the agent's own files back what the guide says", () => {
|
|
1429
|
+
const installScript: string = readAgentFile("install.sh");
|
|
1430
|
+
const troubleshoot: string = readAgentFile("troubleshoot.sh");
|
|
1431
|
+
const compose: string = readAgentFile("docker-compose.yml");
|
|
1432
|
+
const readme: string = readAgentFile("README.md");
|
|
1433
|
+
|
|
1434
|
+
test("install.sh takes the URL and key from its environment before it prompts", () => {
|
|
1435
|
+
expect(installScript).toMatch(
|
|
1436
|
+
/if \[ -z "\$ONEUPTIME_URL" \]; then\n\s+prompt_required ONEUPTIME_URL/,
|
|
1437
|
+
);
|
|
1438
|
+
expect(installScript).toMatch(
|
|
1439
|
+
/if \[ -z "\$ONEUPTIME_TELEMETRY_INGESTION_KEY" \]; then\n\s+prompt_required ONEUPTIME_TELEMETRY_INGESTION_KEY/,
|
|
1440
|
+
);
|
|
1441
|
+
expect(installScript).toMatch(/if \[ -z "\$DATABASE_SYSTEM" \]; then/);
|
|
1442
|
+
expect(installScript).toMatch(
|
|
1443
|
+
/if \[ -z "\$DATABASE_SERVER_ADDRESS" \]; then/,
|
|
1444
|
+
);
|
|
1445
|
+
});
|
|
1446
|
+
|
|
1447
|
+
test("install.sh and troubleshoot.sh default to the directory the guide names, and take another", () => {
|
|
1448
|
+
expect(installScript).toContain(
|
|
1449
|
+
`INSTALL_DIR="\${INSTALL_DIR:-${DATABASE_AGENT_INSTALL_DIRECTORY}}"`,
|
|
1450
|
+
);
|
|
1451
|
+
expect(troubleshoot).toContain(`DIR="${DATABASE_AGENT_INSTALL_DIRECTORY}"`);
|
|
1452
|
+
expect(troubleshoot).toMatch(/-d\|--dir\)\s+DIR=/);
|
|
1453
|
+
});
|
|
1454
|
+
|
|
1455
|
+
test("every agent file a guide downloads exists", () => {
|
|
1456
|
+
const urls: Set<string> = new Set<string>();
|
|
1457
|
+
for (const system of SYSTEMS) {
|
|
1458
|
+
for (const guide of [
|
|
1459
|
+
productGuide(system),
|
|
1460
|
+
rowGuide({
|
|
1461
|
+
id: DATABASE_ID,
|
|
1462
|
+
dbSystem: system,
|
|
1463
|
+
endpoints: ["db.svc.data.svc.cluster.local:1234@prod"],
|
|
1464
|
+
kubernetesNamespace: "data",
|
|
1465
|
+
isKubernetes: true,
|
|
1466
|
+
}),
|
|
1467
|
+
]) {
|
|
1468
|
+
for (const block of getSetupGuideCodeBlocks(guide)) {
|
|
1469
|
+
for (const match of block.matchAll(
|
|
1470
|
+
new RegExp(`${DATABASE_AGENT_RAW_URL}/(\\S+)`, "g"),
|
|
1471
|
+
)) {
|
|
1472
|
+
urls.add(match[1]!);
|
|
1473
|
+
}
|
|
1474
|
+
}
|
|
1475
|
+
}
|
|
1476
|
+
}
|
|
1477
|
+
expect([...urls].sort()).toEqual(
|
|
1478
|
+
[
|
|
1479
|
+
"install.sh",
|
|
1480
|
+
"troubleshoot.sh",
|
|
1481
|
+
"docker-compose.yml",
|
|
1482
|
+
...DATABASE_AGENT_ENGINES.map((engine: DatabaseAgentEngine): string => {
|
|
1483
|
+
return `configs/${engine}.yaml`;
|
|
1484
|
+
}),
|
|
1485
|
+
].sort(),
|
|
1486
|
+
);
|
|
1487
|
+
for (const file of urls) {
|
|
1488
|
+
expect({
|
|
1489
|
+
file,
|
|
1490
|
+
exists: fs.existsSync(path.join(AGENT_DIR, file)),
|
|
1491
|
+
}).toEqual({ file, exists: true });
|
|
1492
|
+
}
|
|
1493
|
+
});
|
|
1494
|
+
|
|
1495
|
+
test("the connection help matches the compose file's own switches", () => {
|
|
1496
|
+
expect(compose).toContain('- "host.docker.internal:host-gateway"');
|
|
1497
|
+
expect(compose).toContain("# network_mode: host");
|
|
1498
|
+
});
|
|
1499
|
+
|
|
1500
|
+
test("applying an edit recreates the container, as the README says", () => {
|
|
1501
|
+
expect(readme).toContain("docker compose up -d --force-recreate");
|
|
1502
|
+
expect(
|
|
1503
|
+
topicOf(
|
|
1504
|
+
productGuide("postgresql").advanced,
|
|
1505
|
+
"Upgrade or uninstall the agent",
|
|
1506
|
+
).markdown,
|
|
1507
|
+
).toContain("`docker compose up -d --force-recreate`");
|
|
1508
|
+
});
|
|
1509
|
+
|
|
1510
|
+
test("the AI agent is described as install.sh runs it, per engine", () => {
|
|
1511
|
+
const supported: Array<string> = installScript
|
|
1512
|
+
.match(/^\s*([a-z|]+)\) AI_SUPPORTED="true" ;;$/m)![1]!
|
|
1513
|
+
.split("|");
|
|
1514
|
+
expect(compose).toContain("\n oneuptime-database-ai-agent:\n");
|
|
1515
|
+
for (const engine of DATABASE_AGENT_ENGINES) {
|
|
1516
|
+
const files: string = topicOf(
|
|
1517
|
+
productGuide(getDatabaseAgentSystem(engine)).advanced,
|
|
1518
|
+
"The files the agent runs",
|
|
1519
|
+
).markdown;
|
|
1520
|
+
expect(files).toContain("`oneuptime-database-ai-agent`");
|
|
1521
|
+
expect({
|
|
1522
|
+
engine,
|
|
1523
|
+
runsNothing: files.includes("so it runs nothing"),
|
|
1524
|
+
}).toEqual({ engine, runsNothing: !supported.includes(engine) });
|
|
1525
|
+
}
|
|
1526
|
+
});
|
|
1527
|
+
|
|
1528
|
+
test("the credentials the script asks for follow install.sh's LOGIN", () => {
|
|
1529
|
+
const required: Array<string> = installScript
|
|
1530
|
+
.match(/^\s*([a-z|]+)\) LOGIN="required" ;;$/m)![1]!
|
|
1531
|
+
.split("|");
|
|
1532
|
+
const none: Array<string> = installScript
|
|
1533
|
+
.match(/^\s*([a-z|]+)\) LOGIN="none" ;;$/m)![1]!
|
|
1534
|
+
.split("|");
|
|
1535
|
+
for (const engine of DATABASE_AGENT_ENGINES) {
|
|
1536
|
+
const script: string = variantOf(
|
|
1537
|
+
productGuide(getDatabaseAgentSystem(engine)),
|
|
1538
|
+
"Install script",
|
|
1539
|
+
);
|
|
1540
|
+
let expected: string =
|
|
1541
|
+
"the monitoring credentials, if the server has users";
|
|
1542
|
+
if (required.includes(engine)) {
|
|
1543
|
+
expected = "the monitoring credentials (the password";
|
|
1544
|
+
}
|
|
1545
|
+
if (none.includes(engine)) {
|
|
1546
|
+
expect(script).not.toContain("monitoring credentials");
|
|
1547
|
+
continue;
|
|
1548
|
+
}
|
|
1549
|
+
expect({ engine, said: script.includes(expected) }).toEqual({
|
|
1550
|
+
engine,
|
|
1551
|
+
said: true,
|
|
1552
|
+
});
|
|
1553
|
+
}
|
|
1554
|
+
// Only Oracle is asked for a service name.
|
|
1555
|
+
expect(installScript).toMatch(
|
|
1556
|
+
/if \[ "\$AGENT_CONFIG" = "oracledb" \] && \[ -z "\$DATABASE_ORACLE_SERVICE" \]/,
|
|
1557
|
+
);
|
|
1558
|
+
for (const engine of DATABASE_AGENT_ENGINES) {
|
|
1559
|
+
expect(
|
|
1560
|
+
variantOf(
|
|
1561
|
+
productGuide(getDatabaseAgentSystem(engine)),
|
|
1562
|
+
"Install script",
|
|
1563
|
+
).includes("the Oracle service name"),
|
|
1564
|
+
).toBe(engine === "oracledb");
|
|
1565
|
+
}
|
|
1566
|
+
});
|
|
1567
|
+
|
|
1568
|
+
test("query events are offered for exactly the configs install.sh asks about", () => {
|
|
1569
|
+
const withEvents: Array<string> = installScript
|
|
1570
|
+
.match(/^\s*([a-z|]+)\) HAS_QUERY_EVENTS="true" ;;$/m)![1]!
|
|
1571
|
+
.split("|");
|
|
1572
|
+
for (const engine of DATABASE_AGENT_ENGINES) {
|
|
1573
|
+
expect({
|
|
1574
|
+
engine,
|
|
1575
|
+
offered: topicTitles(
|
|
1576
|
+
productGuide(getDatabaseAgentSystem(engine)).advanced,
|
|
1577
|
+
).includes("Query samples and top queries"),
|
|
1578
|
+
}).toEqual({ engine, offered: withEvents.includes(engine) });
|
|
1579
|
+
}
|
|
1580
|
+
});
|
|
1581
|
+
|
|
1582
|
+
test("the TLS switches are offered for exactly the configs that read them", () => {
|
|
1583
|
+
const withoutTls: Array<string> = installScript
|
|
1584
|
+
.match(/^\s*([a-z|]+)\) HAS_TLS="" ;;$/m)![1]!
|
|
1585
|
+
.split("|");
|
|
1586
|
+
for (const engine of DATABASE_AGENT_ENGINES) {
|
|
1587
|
+
expect({
|
|
1588
|
+
engine,
|
|
1589
|
+
tls: getSetupGuideMarkdown(
|
|
1590
|
+
productGuide(getDatabaseAgentSystem(engine)),
|
|
1591
|
+
).includes("TLS errors"),
|
|
1592
|
+
}).toEqual({ engine, tls: !withoutTls.includes(engine) });
|
|
1593
|
+
}
|
|
1594
|
+
});
|
|
1595
|
+
});
|
|
1596
|
+
|
|
1597
|
+
/*
|
|
1598
|
+
* An engine the agent ships no config for: the guide is the collector
|
|
1599
|
+
* config that sends its engine metrics with this database's identity — or,
|
|
1600
|
+
* for an in-process engine, the application traces its page fills in from.
|
|
1601
|
+
*/
|
|
1602
|
+
describe("an engine the agent has no config for", () => {
|
|
1603
|
+
const OWN_SYSTEMS: Array<DatabaseSystemDescriptor> = DATABASE_SYSTEMS.filter(
|
|
1604
|
+
(descriptor: DatabaseSystemDescriptor): boolean => {
|
|
1605
|
+
return getDatabaseAgentEngine(descriptor.system) === null;
|
|
1606
|
+
},
|
|
1607
|
+
);
|
|
1608
|
+
|
|
1609
|
+
function ownGuide(
|
|
1610
|
+
database: DatabaseDocumentationTarget,
|
|
1611
|
+
overrides?: { apiKey?: string; hasApiKey?: boolean },
|
|
1612
|
+
): SetupGuideContent {
|
|
1613
|
+
return getDatabaseOwnCollectorSetupGuide({
|
|
1614
|
+
oneuptimeUrl: URL,
|
|
1615
|
+
apiKey: overrides?.apiKey ?? KEY,
|
|
1616
|
+
hasApiKey: overrides?.hasApiKey,
|
|
1617
|
+
database: database,
|
|
1618
|
+
databaseHealthMonitorUrl: HEALTH_URL,
|
|
1619
|
+
recommendationsUrl: RECOMMENDATIONS_URL,
|
|
1620
|
+
});
|
|
1621
|
+
}
|
|
1622
|
+
|
|
1623
|
+
function rowFor(
|
|
1624
|
+
descriptor: DatabaseSystemDescriptor,
|
|
1625
|
+
): DatabaseDocumentationTarget {
|
|
1626
|
+
return {
|
|
1627
|
+
id: DATABASE_ID,
|
|
1628
|
+
dbSystem: descriptor.system,
|
|
1629
|
+
serverAddress: "db.prod.example.com",
|
|
1630
|
+
serverPort: descriptor.defaultPort,
|
|
1631
|
+
};
|
|
1632
|
+
}
|
|
1633
|
+
|
|
1634
|
+
test("covers every catalog engine the agent does not", () => {
|
|
1635
|
+
expect(OWN_SYSTEMS.length).toBeGreaterThan(20);
|
|
1636
|
+
expect(OWN_SYSTEMS.length + SYSTEMS.length).toBe(DATABASE_SYSTEMS.length);
|
|
1637
|
+
});
|
|
1638
|
+
|
|
1639
|
+
test.each(
|
|
1640
|
+
OWN_SYSTEMS.map((descriptor: DatabaseSystemDescriptor): string => {
|
|
1641
|
+
return descriptor.system;
|
|
1642
|
+
}),
|
|
1643
|
+
)("%s gets a guide in the setup layout", (system: string) => {
|
|
1644
|
+
const descriptor: DatabaseSystemDescriptor = OWN_SYSTEMS.find(
|
|
1645
|
+
(candidate: DatabaseSystemDescriptor): boolean => {
|
|
1646
|
+
return candidate.system === system;
|
|
1647
|
+
},
|
|
1648
|
+
)!;
|
|
1649
|
+
const database: DatabaseDocumentationTarget = rowFor(descriptor);
|
|
1650
|
+
const guide: SetupGuideContent = ownGuide(database);
|
|
1651
|
+
const markdown: string = getSetupGuideMarkdown(guide);
|
|
1652
|
+
|
|
1653
|
+
// No picker, no agent install: the Documentation tab of one database.
|
|
1654
|
+
expect(markdown).not.toContain("install.sh");
|
|
1655
|
+
expect(markdown).not.toContain("docker compose");
|
|
1656
|
+
expect(guide.keyStep).toEqual({
|
|
1657
|
+
description: expect.any(String),
|
|
1658
|
+
endpointLabel: "OTLP endpoint",
|
|
1659
|
+
endpointValue: `${URL}/otlp`,
|
|
1660
|
+
});
|
|
1661
|
+
expect(guide.intro).toContain(
|
|
1662
|
+
"The OneUptime Database Agent ships configs for PostgreSQL",
|
|
1663
|
+
);
|
|
1664
|
+
for (const step of guide.steps) {
|
|
1665
|
+
expectPlainOneLine(step.description);
|
|
1666
|
+
}
|
|
1667
|
+
for (const topic of guide.advanced || []) {
|
|
1668
|
+
expectPlainOneLine(topic.summary);
|
|
1669
|
+
}
|
|
1670
|
+
for (const link of guide.links || []) {
|
|
1671
|
+
expect(
|
|
1672
|
+
fs.existsSync(
|
|
1673
|
+
path.join(
|
|
1674
|
+
REPO_ROOT,
|
|
1675
|
+
"packages/App/FeatureSet/Docs/Content/en",
|
|
1676
|
+
`${link.url.replace(/^\/docs\//, "")}.md`,
|
|
1677
|
+
),
|
|
1678
|
+
),
|
|
1679
|
+
).toBe(true);
|
|
1680
|
+
}
|
|
1681
|
+
|
|
1682
|
+
if (descriptor.engineMetrics.kind === "embedded") {
|
|
1683
|
+
expect(
|
|
1684
|
+
guide.steps.map((step: SetupGuideStep): string => {
|
|
1685
|
+
return step.title;
|
|
1686
|
+
}),
|
|
1687
|
+
).toEqual(["Instrument your application"]);
|
|
1688
|
+
expect(guide.intro).toContain("runs inside your application's process");
|
|
1689
|
+
expect(
|
|
1690
|
+
stepTitled(guide, "Instrument your application").markdown,
|
|
1691
|
+
).toContain(
|
|
1692
|
+
`export OTEL_EXPORTER_OTLP_ENDPOINT=${URL}/otlp\nexport OTEL_EXPORTER_OTLP_HEADERS=x-oneuptime-token=${KEY}`,
|
|
1693
|
+
);
|
|
1694
|
+
expect(markdown).not.toContain("resource/database");
|
|
1695
|
+
expect(markdown).toContain(`\`${DATABASE_ID}\``);
|
|
1696
|
+
return;
|
|
1697
|
+
}
|
|
1698
|
+
|
|
1699
|
+
expect(
|
|
1700
|
+
guide.steps.map((step: SetupGuideStep): string => {
|
|
1701
|
+
return step.title;
|
|
1702
|
+
}),
|
|
1703
|
+
).toEqual([guide.steps[0]!.title, "Verify the metrics arrive"]);
|
|
1704
|
+
|
|
1705
|
+
// The collector config: well-formed, wired, and carrying URL, key and id.
|
|
1706
|
+
const configs: Array<{ language: string; body: string }> = codeBlocks(
|
|
1707
|
+
guide.steps[0]!.markdown || "",
|
|
1708
|
+
).filter((block: { language: string; body: string }): boolean => {
|
|
1709
|
+
return block.language === "yaml";
|
|
1710
|
+
});
|
|
1711
|
+
expect(configs).toHaveLength(1);
|
|
1712
|
+
const config: string = configs[0]!.body;
|
|
1713
|
+
const parsed: {
|
|
1714
|
+
receivers?: Record<string, unknown>;
|
|
1715
|
+
processors?: Record<string, unknown>;
|
|
1716
|
+
exporters?: Record<string, unknown>;
|
|
1717
|
+
service?: {
|
|
1718
|
+
pipelines?: Record<
|
|
1719
|
+
string,
|
|
1720
|
+
{
|
|
1721
|
+
receivers: Array<string>;
|
|
1722
|
+
processors: Array<string>;
|
|
1723
|
+
exporters: Array<string>;
|
|
1724
|
+
}
|
|
1725
|
+
>;
|
|
1726
|
+
};
|
|
1727
|
+
} = yaml.load(config) as never;
|
|
1728
|
+
for (const pipeline of Object.values(parsed.service?.pipelines || {})) {
|
|
1729
|
+
for (const receiver of pipeline.receivers) {
|
|
1730
|
+
expect(Object.keys(parsed.receivers || {})).toContain(receiver);
|
|
1731
|
+
}
|
|
1732
|
+
for (const processor of pipeline.processors) {
|
|
1733
|
+
expect(Object.keys(parsed.processors || {})).toContain(processor);
|
|
1734
|
+
}
|
|
1735
|
+
for (const exporter of pipeline.exporters) {
|
|
1736
|
+
expect(Object.keys(parsed.exporters || {})).toContain(exporter);
|
|
1737
|
+
}
|
|
1738
|
+
}
|
|
1739
|
+
expect(config).toContain(`endpoint: "${URL}/otlp"`);
|
|
1740
|
+
expect(config).toContain(`x-oneuptime-token: "${KEY}"`);
|
|
1741
|
+
expect(config).toContain(`value: "${DATABASE_ID}"`);
|
|
1742
|
+
expect(config).toContain("key: service.name\n action: delete");
|
|
1743
|
+
|
|
1744
|
+
// The same config the single-document guide shows.
|
|
1745
|
+
expect(
|
|
1746
|
+
getDatabaseOwnCollectorMarkdown({
|
|
1747
|
+
oneuptimeUrl: URL,
|
|
1748
|
+
apiKey: KEY,
|
|
1749
|
+
database: database,
|
|
1750
|
+
}),
|
|
1751
|
+
).toContain(`\`\`\`yaml\n${config}\n\`\`\``);
|
|
1752
|
+
|
|
1753
|
+
expect(topicTitles(guide.advanced)[0]).toBe("Alert on this database");
|
|
1754
|
+
expect(
|
|
1755
|
+
topicOf(guide.advanced, "Alert on this database").markdown,
|
|
1756
|
+
).toContain(`\`oneuptime.database.server.id\` = \`${DATABASE_ID}\``);
|
|
1757
|
+
expect(topicTitles(guide.troubleshooting)).toEqual([
|
|
1758
|
+
'Engine metrics reads "Not connected"',
|
|
1759
|
+
"The metrics land on a Host, or a new Service appears",
|
|
1760
|
+
]);
|
|
1761
|
+
expect(
|
|
1762
|
+
(guide.prerequisites || []).join("\n").includes("DATABASE_PASSWORD"),
|
|
1763
|
+
).toBe(config.includes("${env:DATABASE_PASSWORD}"));
|
|
1764
|
+
expect(markdown).not.toContain(SETUP_GUIDE_API_KEY_PLACEHOLDER);
|
|
1765
|
+
});
|
|
1766
|
+
|
|
1767
|
+
test("names the step after what the reader adds to the collector", () => {
|
|
1768
|
+
const title: (dbSystem: string) => string = (dbSystem: string): string => {
|
|
1769
|
+
return ownGuide({
|
|
1770
|
+
id: DATABASE_ID,
|
|
1771
|
+
dbSystem: dbSystem,
|
|
1772
|
+
serverAddress: "db.prod.example.com",
|
|
1773
|
+
}).steps[0]!.title;
|
|
1774
|
+
};
|
|
1775
|
+
expect(title("couchdb")).toBe("Add the couchdb receiver to your collector");
|
|
1776
|
+
expect(title("gcp.spanner")).toBe(
|
|
1777
|
+
"Add the google_cloud_spanner receiver to your collector",
|
|
1778
|
+
);
|
|
1779
|
+
expect(title("clickhouse")).toBe("Scrape ClickHouse's metrics endpoint");
|
|
1780
|
+
expect(title("dynamodb")).toBe(
|
|
1781
|
+
"Stamp this database's identity on its metrics",
|
|
1782
|
+
);
|
|
1783
|
+
expect(title("ibm.db2")).toBe(
|
|
1784
|
+
"Stamp this database's identity on its metrics",
|
|
1785
|
+
);
|
|
1786
|
+
expect(title("AcmeDB")).toBe(
|
|
1787
|
+
"Stamp this database's identity on its metrics",
|
|
1788
|
+
);
|
|
1789
|
+
});
|
|
1790
|
+
|
|
1791
|
+
test("an unknown engine gets the identity stamp under its raw name", () => {
|
|
1792
|
+
const guide: SetupGuideContent = ownGuide({
|
|
1793
|
+
id: DATABASE_ID,
|
|
1794
|
+
dbSystem: "AcmeDB",
|
|
1795
|
+
serverAddress: "acme.prod.example.com",
|
|
1796
|
+
});
|
|
1797
|
+
const step: string = guide.steps[0]!.markdown || "";
|
|
1798
|
+
expect(step).toContain("OneUptime does not know AcmeDB's engine yet");
|
|
1799
|
+
expect(step).toContain("value: acmedb");
|
|
1800
|
+
expect(step).toContain('value: "acme.prod.example.com"');
|
|
1801
|
+
});
|
|
1802
|
+
|
|
1803
|
+
test("before a key is picked the config shows the placeholder, and says to pick one", () => {
|
|
1804
|
+
const guide: SetupGuideContent = ownGuide(
|
|
1805
|
+
{
|
|
1806
|
+
id: DATABASE_ID,
|
|
1807
|
+
dbSystem: "couchdb",
|
|
1808
|
+
serverAddress: "couch.example.com",
|
|
1809
|
+
},
|
|
1810
|
+
{ apiKey: SETUP_GUIDE_API_KEY_PLACEHOLDER },
|
|
1811
|
+
);
|
|
1812
|
+
const step: string = guide.steps[0]!.markdown || "";
|
|
1813
|
+
expect(step).toContain(
|
|
1814
|
+
`x-oneuptime-token: "${SETUP_GUIDE_API_KEY_PLACEHOLDER}"`,
|
|
1815
|
+
);
|
|
1816
|
+
expect(step).toContain("Pick an ingestion key in step 1");
|
|
1817
|
+
|
|
1818
|
+
const embedded: string =
|
|
1819
|
+
ownGuide(
|
|
1820
|
+
{ id: DATABASE_ID, dbSystem: "sqlite" },
|
|
1821
|
+
{ apiKey: SETUP_GUIDE_API_KEY_PLACEHOLDER },
|
|
1822
|
+
).steps[0]!.markdown || "";
|
|
1823
|
+
// Quoted, so the shell does not read `<` and `>` as redirections.
|
|
1824
|
+
expect(embedded).toContain(
|
|
1825
|
+
`export OTEL_EXPORTER_OTLP_HEADERS='x-oneuptime-token=${SETUP_GUIDE_API_KEY_PLACEHOLDER}'`,
|
|
1826
|
+
);
|
|
1827
|
+
expect(embedded).toContain("Pick an ingestion key in step 1");
|
|
1828
|
+
});
|
|
1829
|
+
|
|
1830
|
+
test("a row without an address says to replace the placeholder name", () => {
|
|
1831
|
+
const step: string =
|
|
1832
|
+
ownGuide({ id: DATABASE_ID, dbSystem: "couchdb" }).steps[0]!.markdown ||
|
|
1833
|
+
"";
|
|
1834
|
+
expect(step).toContain(
|
|
1835
|
+
"This database has no address yet, so replace `db.example.com`",
|
|
1836
|
+
);
|
|
1837
|
+
});
|
|
1838
|
+
});
|
|
1839
|
+
|
|
1840
|
+
describe("the Documentation tab's heading", () => {
|
|
1841
|
+
test("an engine the agent monitors is told to install it", () => {
|
|
1842
|
+
expect(
|
|
1843
|
+
getDatabaseDocumentationHeading({ id: DATABASE_ID, dbSystem: "mariadb" }),
|
|
1844
|
+
).toEqual({
|
|
1845
|
+
title: "Connect MariaDB engine metrics",
|
|
1846
|
+
description:
|
|
1847
|
+
"Install the OneUptime Database Agent next to this database to add its engine metrics. Every value below is prefilled for this database, including its id.",
|
|
1848
|
+
});
|
|
1849
|
+
});
|
|
1850
|
+
|
|
1851
|
+
test("another engine is pointed at its own collector, not the agent", () => {
|
|
1852
|
+
const heading: { title: string; description: string } =
|
|
1853
|
+
getDatabaseDocumentationHeading({ id: DATABASE_ID, dbSystem: "couchdb" });
|
|
1854
|
+
expect(heading.title).toBe("Connect CouchDB engine metrics");
|
|
1855
|
+
expect(heading.description).toContain("your own OpenTelemetry Collector");
|
|
1856
|
+
expect(heading.description).not.toContain(
|
|
1857
|
+
"Install the OneUptime Database Agent",
|
|
1858
|
+
);
|
|
1859
|
+
});
|
|
1860
|
+
|
|
1861
|
+
test("an in-process engine is told there is no server to monitor", () => {
|
|
1862
|
+
const heading: { title: string; description: string } =
|
|
1863
|
+
getDatabaseDocumentationHeading({ id: DATABASE_ID, dbSystem: "sqlite" });
|
|
1864
|
+
expect(heading.title).toBe("Monitor SQLite");
|
|
1865
|
+
expect(heading.description).toContain(
|
|
1866
|
+
"runs inside your application's process",
|
|
1867
|
+
);
|
|
1868
|
+
});
|
|
1869
|
+
});
|