From 02b9415e28fcbd62861a383c3e68e5803168e926 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Louv-Jansen?= Date: Wed, 23 Apr 2025 00:28:28 +0200 Subject: [PATCH 1/5] [LockManager] Ensure index template are created --- .../lock_manager_client.ts | 24 +++---- .../distributed_lock_manager.spec.ts | 62 +++++++++++++++++-- 2 files changed, 69 insertions(+), 17 deletions(-) diff --git a/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/distributed_lock_manager/lock_manager_client.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/distributed_lock_manager/lock_manager_client.ts index 4d19684ee2f7c..9cfce5936e079 100644 --- a/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/distributed_lock_manager/lock_manager_client.ts +++ b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/distributed_lock_manager/lock_manager_client.ts @@ -14,8 +14,10 @@ import { once } from 'lodash'; import { duration } from 'moment'; import { ElasticsearchClient } from '@kbn/core/server'; -export const LOCKS_INDEX_ALIAS = '.kibana_locks'; +const LOCKS_INDEX_ALIAS = '.kibana_locks'; export const LOCKS_CONCRETE_INDEX_NAME = `${LOCKS_INDEX_ALIAS}-000001`; +export const LOCKS_COMPONENT_TEMPLATE_NAME = `${LOCKS_INDEX_ALIAS}-component`; +export const LOCKS_INDEX_TEMPLATE_NAME = `${LOCKS_INDEX_ALIAS}-index-template`; export type LockId = string; export interface LockDocument { @@ -38,7 +40,7 @@ export interface AcquireOptions { ttl?: number; } -const createLocksWriteIndexOnce = once(createLocksWriteIndex); +const createLockIndexAssetOnce = once(ensureTemplatesAndIndexCreated); export class LockManager { private token = uuid(); @@ -58,7 +60,7 @@ export class LockManager { ttl = duration(30, 'seconds').asMilliseconds(), }: AcquireOptions = {}): Promise { let response: Awaited>; - await createLocksWriteIndexOnce(this.esClient); + await createLockIndexAssetOnce(this.esClient, this.logger); this.token = uuid(); try { @@ -303,13 +305,15 @@ export async function withLock( } } -export async function ensureTemplatesAndIndexCreated(esClient: ElasticsearchClient): Promise { - const COMPONENT_TEMPLATE_NAME = `${LOCKS_INDEX_ALIAS}-component`; - const INDEX_TEMPLATE_NAME = `${LOCKS_INDEX_ALIAS}-index-template`; +export async function ensureTemplatesAndIndexCreated( + esClient: ElasticsearchClient, + logger: Logger +): Promise { + logger.info('Creating index template and component template for locks'); const INDEX_PATTERN = `${LOCKS_INDEX_ALIAS}*`; await esClient.cluster.putComponentTemplate({ - name: COMPONENT_TEMPLATE_NAME, + name: LOCKS_COMPONENT_TEMPLATE_NAME, template: { mappings: { dynamic: false, @@ -324,9 +328,9 @@ export async function ensureTemplatesAndIndexCreated(esClient: ElasticsearchClie }); await esClient.indices.putIndexTemplate({ - name: INDEX_TEMPLATE_NAME, + name: LOCKS_INDEX_TEMPLATE_NAME, index_patterns: [INDEX_PATTERN], - composed_of: [COMPONENT_TEMPLATE_NAME], + composed_of: [LOCKS_COMPONENT_TEMPLATE_NAME], priority: 500, template: { settings: { @@ -336,9 +340,7 @@ export async function ensureTemplatesAndIndexCreated(esClient: ElasticsearchClie }, }, }); -} -export async function createLocksWriteIndex(esClient: ElasticsearchClient): Promise { await esClient.indices.create({ index: LOCKS_CONCRETE_INDEX_NAME }, { ignore: [400] }); } diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/distributed_lock_manager/distributed_lock_manager.spec.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/distributed_lock_manager/distributed_lock_manager.spec.ts index dbc5fb9e656da..7742d429f8b6c 100644 --- a/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/distributed_lock_manager/distributed_lock_manager.spec.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/distributed_lock_manager/distributed_lock_manager.spec.ts @@ -10,12 +10,12 @@ import { v4 as uuid } from 'uuid'; import prettyMilliseconds from 'pretty-ms'; import { LockId, - ensureTemplatesAndIndexCreated, LockManager, LockDocument, LOCKS_CONCRETE_INDEX_NAME, - createLocksWriteIndex, withLock, + LOCKS_INDEX_TEMPLATE_NAME, + LOCKS_COMPONENT_TEMPLATE_NAME, } from '@kbn/observability-ai-assistant-plugin/server/service/distributed_lock_manager/lock_manager_client'; import nock from 'nock'; import { Client } from '@elastic/elasticsearch'; @@ -32,11 +32,14 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon const logger = getLoggerMock(log); describe('LockManager', function () { + before(async () => { + // delete existing index mappings to ensure we start from a clean state + await deleteLockIndexAssets(es, log); + }); + describe('Manual locking API', function () { this.tags(['failsOnMKI']); before(async () => { - await ensureTemplatesAndIndexCreated(es); - await createLocksWriteIndex(es); await clearAllLocks(es, log); }); @@ -439,8 +442,6 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon describe('withLock API', function () { this.tags(['failsOnMKI']); before(async () => { - await ensureTemplatesAndIndexCreated(es); - await createLocksWriteIndex(es); await clearAllLocks(es, log); }); @@ -642,9 +643,58 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon }); }); }); + + describe('index assets', () => { + before(async () => { + const LOCK_ID = 'my_lock_with_mappings'; + + // create a lock to trigger the creation of the index mappings + await withLock({ esClient: es, lockId: LOCK_ID, logger }, async () => {}); + + // wait for the index to be created + await es.indices.refresh({ index: LOCKS_CONCRETE_INDEX_NAME }); + }); + + describe('Index mappings', () => { + it('should have the correct mappings for the lock index', async () => { + const res = await es.indices.getMapping({ index: LOCKS_CONCRETE_INDEX_NAME }); + const { mappings } = res[LOCKS_CONCRETE_INDEX_NAME]; + + const expectedMapping = { + dynamic: 'false', + properties: { + token: { type: 'keyword' }, + expiresAt: { type: 'date' }, + createdAt: { type: 'date' }, + metadata: { enabled: false, type: 'object' }, + }, + }; + + expect(mappings).to.eql(expectedMapping); + }); + }); + + describe('Index settings', () => { + it('has the right number_of_replicas', async () => { + const res = await es.indices.getSettings({ index: LOCKS_CONCRETE_INDEX_NAME }); + const { settings } = res[LOCKS_CONCRETE_INDEX_NAME]; + expect(settings?.index?.auto_expand_replicas).to.eql('0-1'); + }); + }); + }); }); } +async function deleteLockIndexAssets(es: Client, log: ToolingLog) { + log.debug(`Deleting index assets`); + await es.indices.delete({ index: LOCKS_CONCRETE_INDEX_NAME }, { ignore: [404] }); + await es.indices.deleteIndexTemplate({ name: LOCKS_INDEX_TEMPLATE_NAME }, { ignore: [404] }); + await es.cluster.deleteComponentTemplate( + { name: LOCKS_COMPONENT_TEMPLATE_NAME }, + { ignore: [404] } + ); +} + function clearAllLocks(es: Client, log: ToolingLog) { try { return es.deleteByQuery( From 2769d21440235d016750c06becafb80462e738a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Louv-Jansen?= Date: Wed, 23 Apr 2025 14:35:21 +0200 Subject: [PATCH 2/5] Add migration that deletes the index if the mappings are incorrect --- .../lock_manager_client.ts | 55 ++--------- .../setup_lock_manager_index.ts | 93 +++++++++++++++++++ .../distributed_lock_manager.spec.ts | 57 +++++++++++- 3 files changed, 156 insertions(+), 49 deletions(-) create mode 100644 x-pack/platform/plugins/shared/observability_ai_assistant/server/service/distributed_lock_manager/setup_lock_manager_index.ts diff --git a/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/distributed_lock_manager/lock_manager_client.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/distributed_lock_manager/lock_manager_client.ts index 9cfce5936e079..95f69c9c02358 100644 --- a/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/distributed_lock_manager/lock_manager_client.ts +++ b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/distributed_lock_manager/lock_manager_client.ts @@ -13,11 +13,7 @@ import prettyMilliseconds from 'pretty-ms'; import { once } from 'lodash'; import { duration } from 'moment'; import { ElasticsearchClient } from '@kbn/core/server'; - -const LOCKS_INDEX_ALIAS = '.kibana_locks'; -export const LOCKS_CONCRETE_INDEX_NAME = `${LOCKS_INDEX_ALIAS}-000001`; -export const LOCKS_COMPONENT_TEMPLATE_NAME = `${LOCKS_INDEX_ALIAS}-component`; -export const LOCKS_INDEX_TEMPLATE_NAME = `${LOCKS_INDEX_ALIAS}-index-template`; +import { LOCKS_CONCRETE_INDEX_NAME, setuplockManagerIndex } from './setup_lock_manager_index'; export type LockId = string; export interface LockDocument { @@ -40,7 +36,12 @@ export interface AcquireOptions { ttl?: number; } -const createLockIndexAssetOnce = once(ensureTemplatesAndIndexCreated); +// The index assets should only be set up once +// For testing purposes, we need to be able to set it up every time +let runSetupIndexAssetOnce = once(setuplockManagerIndex); +export function runSetupIndexAssetEveryTime() { + runSetupIndexAssetOnce = setuplockManagerIndex; +} export class LockManager { private token = uuid(); @@ -60,7 +61,8 @@ export class LockManager { ttl = duration(30, 'seconds').asMilliseconds(), }: AcquireOptions = {}): Promise { let response: Awaited>; - await createLockIndexAssetOnce(this.esClient, this.logger); + + await runSetupIndexAssetOnce(this.esClient, this.logger); this.token = uuid(); try { @@ -305,45 +307,6 @@ export async function withLock( } } -export async function ensureTemplatesAndIndexCreated( - esClient: ElasticsearchClient, - logger: Logger -): Promise { - logger.info('Creating index template and component template for locks'); - const INDEX_PATTERN = `${LOCKS_INDEX_ALIAS}*`; - - await esClient.cluster.putComponentTemplate({ - name: LOCKS_COMPONENT_TEMPLATE_NAME, - template: { - mappings: { - dynamic: false, - properties: { - token: { type: 'keyword' }, - metadata: { enabled: false }, - createdAt: { type: 'date' }, - expiresAt: { type: 'date' }, - }, - }, - }, - }); - - await esClient.indices.putIndexTemplate({ - name: LOCKS_INDEX_TEMPLATE_NAME, - index_patterns: [INDEX_PATTERN], - composed_of: [LOCKS_COMPONENT_TEMPLATE_NAME], - priority: 500, - template: { - settings: { - number_of_shards: 1, - auto_expand_replicas: '0-1', - hidden: true, - }, - }, - }); - - await esClient.indices.create({ index: LOCKS_CONCRETE_INDEX_NAME }, { ignore: [400] }); -} - function isVersionConflictException(e: Error): boolean { return ( e instanceof errors.ResponseError && e.body?.error?.type === 'version_conflict_engine_exception' diff --git a/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/distributed_lock_manager/setup_lock_manager_index.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/distributed_lock_manager/setup_lock_manager_index.ts new file mode 100644 index 0000000000000..1fe0d4b1f708a --- /dev/null +++ b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/distributed_lock_manager/setup_lock_manager_index.ts @@ -0,0 +1,93 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { errors } from '@elastic/elasticsearch'; +import { ElasticsearchClient, Logger } from '@kbn/core/server'; +import { IndicesGetMappingResponse } from '@elastic/elasticsearch/lib/api/types'; + +const LOCKS_INDEX_ALIAS = '.kibana_locks'; +export const LOCKS_CONCRETE_INDEX_NAME = `${LOCKS_INDEX_ALIAS}-000001`; +export const LOCKS_COMPONENT_TEMPLATE_NAME = `${LOCKS_INDEX_ALIAS}-component`; +export const LOCKS_INDEX_TEMPLATE_NAME = `${LOCKS_INDEX_ALIAS}-index-template`; + +export async function removeLockIndexWithIncorrectMappings( + esClient: ElasticsearchClient, + logger: Logger +) { + let res: IndicesGetMappingResponse; + try { + res = await esClient.indices.getMapping({ index: LOCKS_CONCRETE_INDEX_NAME }); + } catch (error) { + const isNotFoundError = error instanceof errors.ResponseError && error.statusCode === 404; + if (!isNotFoundError) { + logger.error( + `Failed to get mapping for lock index "${LOCKS_CONCRETE_INDEX_NAME}": ${error.message}` + ); + } + + return; + } + + const { mappings } = res[LOCKS_CONCRETE_INDEX_NAME]; + const hasIncorrectMappings = + mappings.properties?.token?.type !== 'keyword' || + mappings.properties?.expiresAt?.type !== 'date'; + + if (hasIncorrectMappings) { + logger.warn(`Lock index "${LOCKS_CONCRETE_INDEX_NAME}" has incorrect mappings. Removing it...`); + try { + await esClient.indices.delete({ index: LOCKS_CONCRETE_INDEX_NAME }); + logger.info(`Lock index "${LOCKS_CONCRETE_INDEX_NAME}" removed successfully.`); + } catch (error) { + logger.error(`Failed to remove lock index "${LOCKS_CONCRETE_INDEX_NAME}": ${error.message}`); + } + } +} + +export async function ensureTemplatesAndIndexCreated( + esClient: ElasticsearchClient, + logger: Logger +): Promise { + logger.info('Creating index template and component template for locks'); + const INDEX_PATTERN = `${LOCKS_INDEX_ALIAS}*`; + + await esClient.cluster.putComponentTemplate({ + name: LOCKS_COMPONENT_TEMPLATE_NAME, + template: { + mappings: { + dynamic: false, + properties: { + token: { type: 'keyword' }, + metadata: { enabled: false }, + createdAt: { type: 'date' }, + expiresAt: { type: 'date' }, + }, + }, + }, + }); + + await esClient.indices.putIndexTemplate({ + name: LOCKS_INDEX_TEMPLATE_NAME, + index_patterns: [INDEX_PATTERN], + composed_of: [LOCKS_COMPONENT_TEMPLATE_NAME], + priority: 500, + template: { + settings: { + number_of_shards: 1, + auto_expand_replicas: '0-1', + hidden: true, + }, + }, + }); + + await esClient.indices.create({ index: LOCKS_CONCRETE_INDEX_NAME }, { ignore: [400] }); +} + +export async function setuplockManagerIndex(esClient: ElasticsearchClient, logger: Logger) { + await removeLockIndexWithIncorrectMappings(esClient, logger); // TODO: should be remove in the future (after 9.1). See https://github.com/elastic/kibana/issues/218944 + await ensureTemplatesAndIndexCreated(esClient, logger); +} diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/distributed_lock_manager/distributed_lock_manager.spec.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/distributed_lock_manager/distributed_lock_manager.spec.ts index 7742d429f8b6c..3db283cdb4785 100644 --- a/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/distributed_lock_manager/distributed_lock_manager.spec.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/distributed_lock_manager/distributed_lock_manager.spec.ts @@ -12,16 +12,19 @@ import { LockId, LockManager, LockDocument, - LOCKS_CONCRETE_INDEX_NAME, withLock, - LOCKS_INDEX_TEMPLATE_NAME, - LOCKS_COMPONENT_TEMPLATE_NAME, + runSetupIndexAssetEveryTime, } from '@kbn/observability-ai-assistant-plugin/server/service/distributed_lock_manager/lock_manager_client'; import nock from 'nock'; import { Client } from '@elastic/elasticsearch'; import { times } from 'lodash'; import { ToolingLog } from '@kbn/tooling-log'; import pRetry from 'p-retry'; +import { + LOCKS_COMPONENT_TEMPLATE_NAME, + LOCKS_CONCRETE_INDEX_NAME, + LOCKS_INDEX_TEMPLATE_NAME, +} from '@kbn/observability-ai-assistant-plugin/server/service/distributed_lock_manager/setup_lock_manager_index'; import type { DeploymentAgnosticFtrProviderContext } from '../../../../ftr_provider_context'; import { getLoggerMock } from '../utils/logger'; import { dateAsTimestamp, durationAsMs, sleep } from '../utils/time'; @@ -35,6 +38,13 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon before(async () => { // delete existing index mappings to ensure we start from a clean state await deleteLockIndexAssets(es, log); + + // ensure that the index and templates are created + runSetupIndexAssetEveryTime(); + }); + + after(async () => { + await deleteLockIndexAssets(es, log); }); describe('Manual locking API', function () { @@ -682,6 +692,47 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon }); }); }); + + describe('when lock index is created with incorrect mappings', () => { + async function getMappings() { + const res = await es.indices.getMapping({ index: LOCKS_CONCRETE_INDEX_NAME }); + const { mappings } = res[LOCKS_CONCRETE_INDEX_NAME]; + return mappings; + } + + before(async () => { + await deleteLockIndexAssets(es, log); + + await es.index({ + refresh: true, + index: LOCKS_CONCRETE_INDEX_NAME, + id: 'my_lock_with_incorrect_mappings', + document: { + token: 'my token', + expiresAt: new Date(Date.now() + 100000), + createdAt: new Date(), + metadata: { foo: 'bar' }, + }, + }); + }); + + it('should delete the index and re-create it', async () => { + const mappingsBefore = await getMappings(); + log.debug(`Mappings before: ${JSON.stringify(mappingsBefore)}`); + expect(mappingsBefore.properties?.token.type).to.eql('text'); + + // Simulate a scenario where the index mappings are incorrect + // await setuplockManagerIndex(es, logger); + await withLock( + { esClient: es, lockId: 'my_lock_with_correct_mappings', logger }, + async () => {} + ); + + const mappingsAfter = await getMappings(); + log.debug(`Mappings after: ${JSON.stringify(mappingsAfter)}`); + expect(mappingsAfter.properties?.token.type).to.be('keyword'); + }); + }); }); } From 98aec204aeaf92b568b2c47fa9b5caa7146baf93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Louv-Jansen?= Date: Wed, 23 Apr 2025 14:59:40 +0200 Subject: [PATCH 3/5] Add test to verify that index is not deleted if it has the right mappings --- .../distributed_lock_manager.spec.ts | 106 +++++++++--------- 1 file changed, 55 insertions(+), 51 deletions(-) diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/distributed_lock_manager/distributed_lock_manager.spec.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/distributed_lock_manager/distributed_lock_manager.spec.ts index 3db283cdb4785..980fee21879c6 100644 --- a/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/distributed_lock_manager/distributed_lock_manager.spec.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/ai_assistant/distributed_lock_manager/distributed_lock_manager.spec.ts @@ -655,20 +655,47 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon }); describe('index assets', () => { - before(async () => { - const LOCK_ID = 'my_lock_with_mappings'; + describe('when lock index is created with incorrect mappings', () => { + before(async () => { + await deleteLockIndexAssets(es, log); + await es.index({ + refresh: true, + index: LOCKS_CONCRETE_INDEX_NAME, + id: 'my_lock_with_incorrect_mappings', + document: { + token: 'my token', + expiresAt: new Date(Date.now() + 100000), + createdAt: new Date(), + metadata: { foo: 'bar' }, + }, + }); + }); + + it('should delete the index and re-create it', async () => { + const mappingsBefore = await getMappings(es); + log.debug(`Mappings before: ${JSON.stringify(mappingsBefore)}`); + expect(mappingsBefore.properties?.token.type).to.eql('text'); - // create a lock to trigger the creation of the index mappings - await withLock({ esClient: es, lockId: LOCK_ID, logger }, async () => {}); + // Simulate a scenario where the index mappings are incorrect and a lock is added + // it should delete the index and re-create it with the correct mappings + await withLock({ esClient: es, lockId: uuid(), logger }, async () => {}); - // wait for the index to be created - await es.indices.refresh({ index: LOCKS_CONCRETE_INDEX_NAME }); + const mappingsAfter = await getMappings(es); + log.debug(`Mappings after: ${JSON.stringify(mappingsAfter)}`); + expect(mappingsAfter.properties?.token.type).to.be('keyword'); + }); }); - describe('Index mappings', () => { + describe('when lock index is created with correct mappings', () => { + before(async () => { + await withLock({ esClient: es, lockId: uuid(), logger }, async () => {}); + + // wait for the index to be created + await es.indices.refresh({ index: LOCKS_CONCRETE_INDEX_NAME }); + }); + it('should have the correct mappings for the lock index', async () => { - const res = await es.indices.getMapping({ index: LOCKS_CONCRETE_INDEX_NAME }); - const { mappings } = res[LOCKS_CONCRETE_INDEX_NAME]; + const mappings = await getMappings(es); const expectedMapping = { dynamic: 'false', @@ -682,55 +709,20 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon expect(mappings).to.eql(expectedMapping); }); - }); - describe('Index settings', () => { it('has the right number_of_replicas', async () => { - const res = await es.indices.getSettings({ index: LOCKS_CONCRETE_INDEX_NAME }); - const { settings } = res[LOCKS_CONCRETE_INDEX_NAME]; + const settings = await getSettings(es); expect(settings?.index?.auto_expand_replicas).to.eql('0-1'); }); - }); - }); - describe('when lock index is created with incorrect mappings', () => { - async function getMappings() { - const res = await es.indices.getMapping({ index: LOCKS_CONCRETE_INDEX_NAME }); - const { mappings } = res[LOCKS_CONCRETE_INDEX_NAME]; - return mappings; - } + it('does not delete the index when adding a new lock', async () => { + const settingsBefore = await getSettings(es); - before(async () => { - await deleteLockIndexAssets(es, log); - - await es.index({ - refresh: true, - index: LOCKS_CONCRETE_INDEX_NAME, - id: 'my_lock_with_incorrect_mappings', - document: { - token: 'my token', - expiresAt: new Date(Date.now() + 100000), - createdAt: new Date(), - metadata: { foo: 'bar' }, - }, - }); - }); + await withLock({ esClient: es, lockId: uuid(), logger }, async () => {}); - it('should delete the index and re-create it', async () => { - const mappingsBefore = await getMappings(); - log.debug(`Mappings before: ${JSON.stringify(mappingsBefore)}`); - expect(mappingsBefore.properties?.token.type).to.eql('text'); - - // Simulate a scenario where the index mappings are incorrect - // await setuplockManagerIndex(es, logger); - await withLock( - { esClient: es, lockId: 'my_lock_with_correct_mappings', logger }, - async () => {} - ); - - const mappingsAfter = await getMappings(); - log.debug(`Mappings after: ${JSON.stringify(mappingsAfter)}`); - expect(mappingsAfter.properties?.token.type).to.be('keyword'); + const settingsAfter = await getSettings(es); + expect(settingsAfter?.uuid).to.be(settingsBefore?.uuid); + }); }); }); }); @@ -797,3 +789,15 @@ async function getLockById(esClient: Client, lockId: LockId): Promise Date: Wed, 23 Apr 2025 21:15:44 +0200 Subject: [PATCH 4/5] Improve log messages --- .../distributed_lock_manager/setup_lock_manager_index.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/distributed_lock_manager/setup_lock_manager_index.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/distributed_lock_manager/setup_lock_manager_index.ts index 1fe0d4b1f708a..7ae92981dbeef 100644 --- a/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/distributed_lock_manager/setup_lock_manager_index.ts +++ b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/distributed_lock_manager/setup_lock_manager_index.ts @@ -38,7 +38,7 @@ export async function removeLockIndexWithIncorrectMappings( mappings.properties?.expiresAt?.type !== 'date'; if (hasIncorrectMappings) { - logger.warn(`Lock index "${LOCKS_CONCRETE_INDEX_NAME}" has incorrect mappings. Removing it...`); + logger.warn(`Lock index "${LOCKS_CONCRETE_INDEX_NAME}" has incorrect mappings.`); try { await esClient.indices.delete({ index: LOCKS_CONCRETE_INDEX_NAME }); logger.info(`Lock index "${LOCKS_CONCRETE_INDEX_NAME}" removed successfully.`); @@ -52,7 +52,6 @@ export async function ensureTemplatesAndIndexCreated( esClient: ElasticsearchClient, logger: Logger ): Promise { - logger.info('Creating index template and component template for locks'); const INDEX_PATTERN = `${LOCKS_INDEX_ALIAS}*`; await esClient.cluster.putComponentTemplate({ @@ -69,6 +68,9 @@ export async function ensureTemplatesAndIndexCreated( }, }, }); + logger.info( + `Component template ${LOCKS_COMPONENT_TEMPLATE_NAME} created or updated successfully.` + ); await esClient.indices.putIndexTemplate({ name: LOCKS_INDEX_TEMPLATE_NAME, @@ -83,8 +85,10 @@ export async function ensureTemplatesAndIndexCreated( }, }, }); + logger.info(`Index template ${LOCKS_INDEX_TEMPLATE_NAME} created or updated successfully.`); await esClient.indices.create({ index: LOCKS_CONCRETE_INDEX_NAME }, { ignore: [400] }); + logger.info(`Index ${LOCKS_CONCRETE_INDEX_NAME} created or updated successfully.`); } export async function setuplockManagerIndex(esClient: ElasticsearchClient, logger: Logger) { From 7879f173e3945b799939374c663ae138358218fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B8ren=20Louv-Jansen?= Date: Wed, 23 Apr 2025 23:52:56 +0200 Subject: [PATCH 5/5] Update x-pack/platform/plugins/shared/observability_ai_assistant/server/service/distributed_lock_manager/setup_lock_manager_index.ts Co-authored-by: Viduni Wickramarachchi --- .../distributed_lock_manager/setup_lock_manager_index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/distributed_lock_manager/setup_lock_manager_index.ts b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/distributed_lock_manager/setup_lock_manager_index.ts index 7ae92981dbeef..e02ed86b7ef3a 100644 --- a/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/distributed_lock_manager/setup_lock_manager_index.ts +++ b/x-pack/platform/plugins/shared/observability_ai_assistant/server/service/distributed_lock_manager/setup_lock_manager_index.ts @@ -92,6 +92,6 @@ export async function ensureTemplatesAndIndexCreated( } export async function setuplockManagerIndex(esClient: ElasticsearchClient, logger: Logger) { - await removeLockIndexWithIncorrectMappings(esClient, logger); // TODO: should be remove in the future (after 9.1). See https://github.com/elastic/kibana/issues/218944 + await removeLockIndexWithIncorrectMappings(esClient, logger); // TODO: should be removed in the future (after 9.1). See https://github.com/elastic/kibana/issues/218944 await ensureTemplatesAndIndexCreated(esClient, logger); }