diff --git a/x-pack/platform/plugins/shared/cases/server/cases_analytics/index.ts b/x-pack/platform/plugins/shared/cases/server/cases_analytics/index.ts index e55a7ad8de29b..4b54bac8f72ae 100644 --- a/x-pack/platform/plugins/shared/cases/server/cases_analytics/index.ts +++ b/x-pack/platform/plugins/shared/cases/server/cases_analytics/index.ts @@ -20,6 +20,7 @@ import { import { createCasesAnalyticsIndex, scheduleCasesAnalyticsSyncTask } from './cases_index'; import { createCommentsAnalyticsIndex, scheduleCommentsAnalyticsSyncTask } from './comments_index'; import { createActivityAnalyticsIndex, scheduleActivityAnalyticsSyncTask } from './activity_index'; +import type { ConfigType } from '../config'; export const createCasesAnalyticsIndexes = ({ esClient, @@ -69,13 +70,15 @@ export const registerCasesAnalyticsIndexesTasks = ({ taskManager, logger, core, + analyticsConfig, }: { taskManager: TaskManagerSetupContract; logger: Logger; core: CoreSetup; + analyticsConfig: ConfigType['analytics']; }) => { - registerCAIBackfillTask({ taskManager, logger, core }); - registerCAISynchronizationTask({ taskManager, logger, core }); + registerCAIBackfillTask({ taskManager, logger, core, analyticsConfig }); + registerCAISynchronizationTask({ taskManager, logger, core, analyticsConfig }); }; export const scheduleCasesAnalyticsSyncTasks = ({ diff --git a/x-pack/platform/plugins/shared/cases/server/cases_analytics/tasks/backfill_task/backfill_task_factory.ts b/x-pack/platform/plugins/shared/cases/server/cases_analytics/tasks/backfill_task/backfill_task_factory.ts index 79ba1a0b14f5e..acf9571b89d61 100644 --- a/x-pack/platform/plugins/shared/cases/server/cases_analytics/tasks/backfill_task/backfill_task_factory.ts +++ b/x-pack/platform/plugins/shared/cases/server/cases_analytics/tasks/backfill_task/backfill_task_factory.ts @@ -7,20 +7,28 @@ import type { Logger } from '@kbn/logging'; import type { ElasticsearchClient } from '@kbn/core/server'; import type { RunContext } from '@kbn/task-manager-plugin/server'; +import type { ConfigType } from '../../../config'; import { BackfillTaskRunner } from './backfill_task_runner'; interface CaseAnalyticsIndexBackfillTaskFactoryParams { logger: Logger; getESClient: () => Promise; + analyticsConfig: ConfigType['analytics']; } export class CaseAnalyticsIndexBackfillTaskFactory { private readonly logger: Logger; private readonly getESClient: () => Promise; + private readonly analyticsConfig: ConfigType['analytics']; - constructor({ logger, getESClient }: CaseAnalyticsIndexBackfillTaskFactoryParams) { + constructor({ + logger, + getESClient, + analyticsConfig, + }: CaseAnalyticsIndexBackfillTaskFactoryParams) { this.logger = logger; this.getESClient = getESClient; + this.analyticsConfig = analyticsConfig; } public create(context: RunContext) { @@ -28,6 +36,7 @@ export class CaseAnalyticsIndexBackfillTaskFactory { taskInstance: context.taskInstance, logger: this.logger, getESClient: this.getESClient, + analyticsConfig: this.analyticsConfig, }); } } diff --git a/x-pack/platform/plugins/shared/cases/server/cases_analytics/tasks/backfill_task/backfill_task_runner.test.ts b/x-pack/platform/plugins/shared/cases/server/cases_analytics/tasks/backfill_task/backfill_task_runner.test.ts index 72310cd63703d..5b4bf1ddc0407 100644 --- a/x-pack/platform/plugins/shared/cases/server/cases_analytics/tasks/backfill_task/backfill_task_runner.test.ts +++ b/x-pack/platform/plugins/shared/cases/server/cases_analytics/tasks/backfill_task/backfill_task_runner.test.ts @@ -27,6 +27,12 @@ describe('BackfillTaskRunner', () => { let taskRunner: BackfillTaskRunner; + const analyticsConfig = { + index: { + enabled: true, + }, + }; + beforeEach(() => { jest.clearAllMocks(); }); @@ -61,6 +67,7 @@ describe('BackfillTaskRunner', () => { logger, getESClient, taskInstance, + analyticsConfig, }); const result = await taskRunner.run(); @@ -101,6 +108,7 @@ describe('BackfillTaskRunner', () => { logger, getESClient, taskInstance, + analyticsConfig, }); try { @@ -132,6 +140,7 @@ describe('BackfillTaskRunner', () => { logger, getESClient, taskInstance, + analyticsConfig, }); try { @@ -146,4 +155,29 @@ describe('BackfillTaskRunner', () => { ); }); }); + + describe('Analytics index disabled', () => { + const analyticsConfigDisabled = { + index: { + enabled: false, + }, + }; + + it('does not call the reindex API if analytics is disabled', async () => { + const esClient = elasticsearchServiceMock.createElasticsearchClient(); + const getESClient = async () => esClient; + + taskRunner = new BackfillTaskRunner({ + logger, + getESClient, + taskInstance, + analyticsConfig: analyticsConfigDisabled, + }); + + await taskRunner.run(); + + expect(esClient.cluster.health).not.toBeCalled(); + expect(esClient.reindex).not.toBeCalled(); + }); + }); }); diff --git a/x-pack/platform/plugins/shared/cases/server/cases_analytics/tasks/backfill_task/backfill_task_runner.ts b/x-pack/platform/plugins/shared/cases/server/cases_analytics/tasks/backfill_task/backfill_task_runner.ts index 8dd67e466a06c..2318589f9443a 100644 --- a/x-pack/platform/plugins/shared/cases/server/cases_analytics/tasks/backfill_task/backfill_task_runner.ts +++ b/x-pack/platform/plugins/shared/cases/server/cases_analytics/tasks/backfill_task/backfill_task_runner.ts @@ -19,12 +19,14 @@ import type { IndicesGetMappingResponse, QueryDslQueryContainer, } from '@elastic/elasticsearch/lib/api/types'; +import type { ConfigType } from '../../../config'; import { isRetryableEsClientError } from '../../utils'; interface BackfillTaskRunnerFactoryConstructorParams { taskInstance: ConcreteTaskInstance; getESClient: () => Promise; logger: Logger; + analyticsConfig: ConfigType['analytics']; } export class BackfillTaskRunner implements CancellableTask { @@ -34,16 +36,28 @@ export class BackfillTaskRunner implements CancellableTask { private readonly getESClient: () => Promise; private readonly logger: Logger; private readonly errorSource = TaskErrorSource.FRAMEWORK; - - constructor({ taskInstance, getESClient, logger }: BackfillTaskRunnerFactoryConstructorParams) { + private readonly analyticsConfig: ConfigType['analytics']; + + constructor({ + taskInstance, + getESClient, + logger, + analyticsConfig, + }: BackfillTaskRunnerFactoryConstructorParams) { this.sourceIndex = taskInstance.params.sourceIndex; this.destIndex = taskInstance.params.destIndex; this.sourceQuery = taskInstance.params.sourceQuery; this.getESClient = getESClient; this.logger = logger; + this.analyticsConfig = analyticsConfig; } public async run() { + if (!this.analyticsConfig.index.enabled) { + this.logDebug('Analytics index is disabled, skipping backfill task.'); + return; + } + const esClient = await this.getESClient(); try { await this.waitForDestIndex(esClient); diff --git a/x-pack/platform/plugins/shared/cases/server/cases_analytics/tasks/backfill_task/index.ts b/x-pack/platform/plugins/shared/cases/server/cases_analytics/tasks/backfill_task/index.ts index 72f4ec66e765a..108671c090eab 100644 --- a/x-pack/platform/plugins/shared/cases/server/cases_analytics/tasks/backfill_task/index.ts +++ b/x-pack/platform/plugins/shared/cases/server/cases_analytics/tasks/backfill_task/index.ts @@ -13,6 +13,7 @@ import type { } from '@kbn/task-manager-plugin/server'; import type { CoreSetup, ElasticsearchClient } from '@kbn/core/server'; import type { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/types'; +import type { ConfigType } from '../../../config'; import { ANALYTICS_BACKFILL_TASK_TYPE } from '../../../../common/constants'; import type { CasesServerStartDependencies } from '../../../types'; import { CaseAnalyticsIndexBackfillTaskFactory } from './backfill_task_factory'; @@ -22,10 +23,12 @@ export function registerCAIBackfillTask({ taskManager, logger, core, + analyticsConfig, }: { taskManager: TaskManagerSetupContract; logger: Logger; core: CoreSetup; + analyticsConfig: ConfigType['analytics']; }) { const getESClient = async (): Promise => { const [{ elasticsearch }] = await core.getStartServices(); @@ -37,7 +40,11 @@ export function registerCAIBackfillTask({ title: 'Backfill cases analytics indexes.', maxAttempts: 3, createTaskRunner: (context: RunContext) => { - return new CaseAnalyticsIndexBackfillTaskFactory({ getESClient, logger }).create(context); + return new CaseAnalyticsIndexBackfillTaskFactory({ + getESClient, + logger, + analyticsConfig, + }).create(context); }, }, }); diff --git a/x-pack/platform/plugins/shared/cases/server/cases_analytics/tasks/synchronization_task/index.ts b/x-pack/platform/plugins/shared/cases/server/cases_analytics/tasks/synchronization_task/index.ts index a7743f980255b..f00722a0329d8 100644 --- a/x-pack/platform/plugins/shared/cases/server/cases_analytics/tasks/synchronization_task/index.ts +++ b/x-pack/platform/plugins/shared/cases/server/cases_analytics/tasks/synchronization_task/index.ts @@ -13,6 +13,7 @@ import type { TaskManagerStartContract, } from '@kbn/task-manager-plugin/server'; import type { CoreSetup, ElasticsearchClient } from '@kbn/core/server'; +import type { ConfigType } from '../../../config'; import { ANALYTICS_SYNCHRONIZATION_TASK_TYPE } from '../../../../common/constants'; import type { CasesServerStartDependencies } from '../../../types'; import { AnalyticsIndexSynchronizationTaskFactory } from './synchronization_task_factory'; @@ -23,10 +24,12 @@ export function registerCAISynchronizationTask({ taskManager, logger, core, + analyticsConfig, }: { taskManager: TaskManagerSetupContract; logger: Logger; core: CoreSetup; + analyticsConfig: ConfigType['analytics']; }) { const getESClient = async (): Promise => { const [{ elasticsearch }] = await core.getStartServices(); @@ -37,9 +40,11 @@ export function registerCAISynchronizationTask({ [ANALYTICS_SYNCHRONIZATION_TASK_TYPE]: { title: 'Synchronization for the cases analytics index', createTaskRunner: (context: RunContext) => { - return new AnalyticsIndexSynchronizationTaskFactory({ getESClient, logger }).create( - context - ); + return new AnalyticsIndexSynchronizationTaskFactory({ + getESClient, + logger, + analyticsConfig, + }).create(context); }, }, }); diff --git a/x-pack/platform/plugins/shared/cases/server/cases_analytics/tasks/synchronization_task/synchronization_task_factory.ts b/x-pack/platform/plugins/shared/cases/server/cases_analytics/tasks/synchronization_task/synchronization_task_factory.ts index 1bb04ab7d3034..c2233ea6dbb17 100644 --- a/x-pack/platform/plugins/shared/cases/server/cases_analytics/tasks/synchronization_task/synchronization_task_factory.ts +++ b/x-pack/platform/plugins/shared/cases/server/cases_analytics/tasks/synchronization_task/synchronization_task_factory.ts @@ -7,20 +7,28 @@ import type { Logger } from '@kbn/logging'; import type { ElasticsearchClient } from '@kbn/core/server'; import type { RunContext } from '@kbn/task-manager-plugin/server'; +import type { ConfigType } from '../../../config'; import { SynchronizationTaskRunner } from './synchronization_task_runner'; interface AnalyticsIndexSynchronizationTaskFactoryParams { logger: Logger; getESClient: () => Promise; + analyticsConfig: ConfigType['analytics']; } export class AnalyticsIndexSynchronizationTaskFactory { private readonly logger: Logger; private readonly getESClient: () => Promise; + private readonly analyticsConfig: ConfigType['analytics']; - constructor({ logger, getESClient }: AnalyticsIndexSynchronizationTaskFactoryParams) { + constructor({ + logger, + getESClient, + analyticsConfig, + }: AnalyticsIndexSynchronizationTaskFactoryParams) { this.logger = logger; this.getESClient = getESClient; + this.analyticsConfig = analyticsConfig; } public create(context: RunContext) { @@ -28,6 +36,7 @@ export class AnalyticsIndexSynchronizationTaskFactory { taskInstance: context.taskInstance, logger: this.logger, getESClient: this.getESClient, + analyticsConfig: this.analyticsConfig, }); } } diff --git a/x-pack/platform/plugins/shared/cases/server/cases_analytics/tasks/synchronization_task/synchronization_task_runner.test.ts b/x-pack/platform/plugins/shared/cases/server/cases_analytics/tasks/synchronization_task/synchronization_task_runner.test.ts index 1114641365105..56c25ed08c65b 100644 --- a/x-pack/platform/plugins/shared/cases/server/cases_analytics/tasks/synchronization_task/synchronization_task_runner.test.ts +++ b/x-pack/platform/plugins/shared/cases/server/cases_analytics/tasks/synchronization_task/synchronization_task_runner.test.ts @@ -47,6 +47,12 @@ describe('SynchronizationTaskRunner', () => { let taskRunner: SynchronizationTaskRunner; + const analyticsConfig = { + index: { + enabled: true, + }, + }; + beforeEach(() => { jest.clearAllMocks(); jest.useFakeTimers().setSystemTime(newAttemptTime); @@ -87,6 +93,7 @@ describe('SynchronizationTaskRunner', () => { logger, getESClient, taskInstance, + analyticsConfig, }); const result = await taskRunner.run(); @@ -176,6 +183,7 @@ describe('SynchronizationTaskRunner', () => { ...taskInstance, state: {}, }, + analyticsConfig, }); const result = await taskRunner.run(); @@ -250,6 +258,7 @@ describe('SynchronizationTaskRunner', () => { logger, getESClient, taskInstance, + analyticsConfig, }); const result = await taskRunner.run(); @@ -273,6 +282,7 @@ describe('SynchronizationTaskRunner', () => { logger, getESClient, taskInstance, + analyticsConfig, }); const result = await taskRunner.run(); @@ -347,6 +357,7 @@ describe('SynchronizationTaskRunner', () => { logger, getESClient, taskInstance, + analyticsConfig, }); try { @@ -370,6 +381,7 @@ describe('SynchronizationTaskRunner', () => { logger, getESClient, taskInstance, + analyticsConfig, }); try { @@ -384,4 +396,29 @@ describe('SynchronizationTaskRunner', () => { ); }); }); + + describe('Analytics index disabled', () => { + const analyticsConfigDisabled = { + index: { + enabled: false, + }, + }; + + it('does not call the reindex API if analytics is disabled', async () => { + const getESClient = async () => esClient; + + taskRunner = new SynchronizationTaskRunner({ + logger, + getESClient, + taskInstance, + analyticsConfig: analyticsConfigDisabled, + }); + + await taskRunner.run(); + + expect(esClient.tasks.get).not.toBeCalled(); + expect(esClient.cluster.health).not.toBeCalled(); + expect(esClient.reindex).not.toBeCalled(); + }); + }); }); diff --git a/x-pack/platform/plugins/shared/cases/server/cases_analytics/tasks/synchronization_task/synchronization_task_runner.ts b/x-pack/platform/plugins/shared/cases/server/cases_analytics/tasks/synchronization_task/synchronization_task_runner.ts index 62fcfcf21ca19..018f5e2a8dfca 100644 --- a/x-pack/platform/plugins/shared/cases/server/cases_analytics/tasks/synchronization_task/synchronization_task_runner.ts +++ b/x-pack/platform/plugins/shared/cases/server/cases_analytics/tasks/synchronization_task/synchronization_task_runner.ts @@ -19,6 +19,7 @@ import type { IndicesGetMappingResponse, QueryDslQueryContainer, } from '@elastic/elasticsearch/lib/api/types'; +import type { ConfigType } from '../../../config'; import { isRetryableEsClientError } from '../../utils'; import { SYNCHRONIZATION_QUERIES_DICTIONARY } from '../../constants'; @@ -26,6 +27,7 @@ interface SynchronizationTaskRunnerFactoryConstructorParams { taskInstance: ConcreteTaskInstance; getESClient: () => Promise; logger: Logger; + analyticsConfig: ConfigType['analytics']; } interface SynchronizationTaskState { @@ -50,6 +52,7 @@ export class SynchronizationTaskRunner implements CancellableTask { private readonly logger: Logger; private readonly errorSource = TaskErrorSource.FRAMEWORK; private readonly esReindexTaskId: TaskId | undefined; + private readonly analyticsConfig: ConfigType['analytics']; private lastSyncSuccess: Date | undefined; private lastSyncAttempt: Date | undefined; @@ -57,6 +60,7 @@ export class SynchronizationTaskRunner implements CancellableTask { taskInstance, getESClient, logger, + analyticsConfig, }: SynchronizationTaskRunnerFactoryConstructorParams) { if (taskInstance.state.lastSyncSuccess) this.lastSyncSuccess = new Date(taskInstance.state.lastSyncSuccess); @@ -67,9 +71,15 @@ export class SynchronizationTaskRunner implements CancellableTask { this.destIndex = taskInstance.params.destIndex; this.getESClient = getESClient; this.logger = logger; + this.analyticsConfig = analyticsConfig; } public async run() { + if (!this.analyticsConfig.index.enabled) { + this.logDebug('Analytics index is disabled, skipping synchronization task.'); + return; + } + const esClient = await this.getESClient(); try { diff --git a/x-pack/platform/plugins/shared/cases/server/config.ts b/x-pack/platform/plugins/shared/cases/server/config.ts index 0e198c5e81779..255af5f8013ee 100644 --- a/x-pack/platform/plugins/shared/cases/server/config.ts +++ b/x-pack/platform/plugins/shared/cases/server/config.ts @@ -6,7 +6,7 @@ */ import type { TypeOf } from '@kbn/config-schema'; -import { schema } from '@kbn/config-schema'; +import { schema, offeringBasedSchema } from '@kbn/config-schema'; import { ALLOWED_MIME_TYPES } from '../common/constants/mime_types'; import { DEFAULT_TASK_INTERVAL_MINUTES, @@ -49,7 +49,10 @@ export const ConfigSchema = schema.object({ }), analytics: schema.object({ index: schema.object({ - enabled: schema.boolean({ defaultValue: true }), + enabled: offeringBasedSchema({ + serverless: schema.boolean({ defaultValue: false }), + traditional: schema.boolean({ defaultValue: true }), + }), }), }), enabled: schema.boolean({ defaultValue: true }), diff --git a/x-pack/platform/plugins/shared/cases/server/plugin.ts b/x-pack/platform/plugins/shared/cases/server/plugin.ts index f7afdd26a4b1d..dc4ba481f6c03 100644 --- a/x-pack/platform/plugins/shared/cases/server/plugin.ts +++ b/x-pack/platform/plugins/shared/cases/server/plugin.ts @@ -108,6 +108,7 @@ export class CasePlugin taskManager: plugins.taskManager, logger: this.logger, core, + analyticsConfig: this.caseConfig.analytics, }); this.securityPluginSetup = plugins.security; diff --git a/x-pack/platform/test/cases_api_integration/common/config.ts b/x-pack/platform/test/cases_api_integration/common/config.ts index 5ecf335b6eb7e..21edf311faeea 100644 --- a/x-pack/platform/test/cases_api_integration/common/config.ts +++ b/x-pack/platform/test/cases_api_integration/common/config.ts @@ -118,6 +118,7 @@ export function createTestConfig(name: string, options: CreateTestConfigOptions) : []), '--xpack.ruleRegistry.write.enabled=true', '--xpack.ruleRegistry.write.cache.enabled=false', + '--xpack.cases.analytics.index.enabled=true', ], }, };