From ba09fc558e58a03b259133be6cbce07967f724b1 Mon Sep 17 00:00:00 2001 From: Marshall Main Date: Tue, 20 Jul 2021 21:40:32 -0700 Subject: [PATCH 1/4] Add namespacing to index templates in support of secondary aliases and ILM policies --- x-pack/plugins/apm/server/plugin.ts | 26 +++++------ .../server/services/rules/rule_data_client.ts | 23 +++++----- x-pack/plugins/observability/server/plugin.ts | 6 ++- .../server/rule_data_client/index.ts | 43 ++++++++++++++++++- .../server/rule_data_client/types.ts | 2 + .../server/rule_data_plugin_service/index.ts | 15 +++++-- .../rule_data_plugin_service.mock.ts | 2 +- .../security_solution/server/plugin.ts | 23 +++++----- x-pack/plugins/uptime/server/plugin.ts | 20 +++++---- 9 files changed, 110 insertions(+), 50 deletions(-) diff --git a/x-pack/plugins/apm/server/plugin.ts b/x-pack/plugins/apm/server/plugin.ts index d28e43d9cb976..8871c5b5a518b 100644 --- a/x-pack/plugins/apm/server/plugin.ts +++ b/x-pack/plugins/apm/server/plugin.ts @@ -113,15 +113,11 @@ export class APMPlugin const getCoreStart = () => core.getStartServices().then(([coreStart]) => coreStart); - const alertsIndexPattern = ruleDataService.getFullAssetName( - 'observability-apm*' + const assetName = 'observability-apm'; + const componentTemplateName = ruleDataService.getFullAssetName( + 'apm-mappings' ); - const initializeRuleDataTemplates = once(async () => { - const componentTemplateName = ruleDataService.getFullAssetName( - 'apm-mappings' - ); - if (!ruleDataService.isWriteEnabled()) { return; } @@ -151,7 +147,7 @@ export class APMPlugin }, }); - await ruleDataService.createOrUpdateIndexTemplate({ + /*await ruleDataService.createOrUpdateIndexTemplate({ name: ruleDataService.getFullAssetName('apm-index-template'), body: { index_patterns: [alertsIndexPattern], @@ -160,9 +156,9 @@ export class APMPlugin componentTemplateName, ], }, - }); - await ruleDataService.updateIndexMappingsMatchingPattern( - alertsIndexPattern + });*/ + await ruleDataService.updateIndexMappingsForAsset( + assetName ); }); @@ -175,8 +171,12 @@ export class APMPlugin const ruleDataClient = ruleDataService.getRuleDataClient( APM_SERVER_FEATURE_ID, - ruleDataService.getFullAssetName('observability-apm'), - () => initializeRuleDataTemplatesPromise + assetName, + () => initializeRuleDataTemplatesPromise, + [ + ruleDataService.getFullAssetName(TECHNICAL_COMPONENT_TEMPLATE_NAME), + componentTemplateName, + ] ); const resourcePlugins = mapValues(plugins, (value, key) => { diff --git a/x-pack/plugins/infra/server/services/rules/rule_data_client.ts b/x-pack/plugins/infra/server/services/rules/rule_data_client.ts index d693be40f10d0..077614b4231bb 100644 --- a/x-pack/plugins/infra/server/services/rules/rule_data_client.ts +++ b/x-pack/plugins/infra/server/services/rules/rule_data_client.ts @@ -26,13 +26,10 @@ export const createRuleDataClient = ({ logger: Logger; ruleDataService: RuleRegistryPluginSetupContract['ruleDataService']; }) => { + const componentTemplateName = ruleDataService.getFullAssetName( + `${registrationContext}-mappings` + ); const initializeRuleDataTemplates = once(async () => { - const componentTemplateName = ruleDataService.getFullAssetName( - `${registrationContext}-mappings` - ); - - const indexNamePattern = ruleDataService.getFullAssetName(`${registrationContext}*`); - if (!ruleDataService.isWriteEnabled()) { return; } @@ -60,7 +57,7 @@ export const createRuleDataClient = ({ }, }); - await ruleDataService.createOrUpdateIndexTemplate({ + /*await ruleDataService.createOrUpdateIndexTemplate({ name: ruleDataService.getFullAssetName(registrationContext), body: { index_patterns: [indexNamePattern], @@ -69,9 +66,9 @@ export const createRuleDataClient = ({ componentTemplateName, ], }, - }); + });*/ - await ruleDataService.updateIndexMappingsMatchingPattern(indexNamePattern); + await ruleDataService.updateIndexMappingsForAsset(registrationContext); }); // initialize eagerly @@ -81,7 +78,11 @@ export const createRuleDataClient = ({ return ruleDataService.getRuleDataClient( ownerFeatureId, - ruleDataService.getFullAssetName(registrationContext), - () => initializeRuleDataTemplatesPromise + registrationContext, + () => initializeRuleDataTemplatesPromise, + [ + ruleDataService.getFullAssetName(TECHNICAL_COMPONENT_TEMPLATE_NAME), + componentTemplateName, + ] ); }; diff --git a/x-pack/plugins/observability/server/plugin.ts b/x-pack/plugins/observability/server/plugin.ts index 868e234fcb2a1..8fdc63041add8 100644 --- a/x-pack/plugins/observability/server/plugin.ts +++ b/x-pack/plugins/observability/server/plugin.ts @@ -100,10 +100,12 @@ export class ObservabilityPlugin implements Plugin { const start = () => core.getStartServices().then(([coreStart]) => coreStart); + // ???? This appears to be a stub const ruleDataClient = plugins.ruleRegistry.ruleDataService.getRuleDataClient( 'observability', - plugins.ruleRegistry.ruleDataService.getFullAssetName(), - () => Promise.resolve() + '', + () => Promise.resolve(), + [], ); registerRoutes({ diff --git a/x-pack/plugins/rule_registry/server/rule_data_client/index.ts b/x-pack/plugins/rule_registry/server/rule_data_client/index.ts index a9e559a6b1932..f6a77948c2f72 100644 --- a/x-pack/plugins/rule_registry/server/rule_data_client/index.ts +++ b/x-pack/plugins/rule_registry/server/rule_data_client/index.ts @@ -5,8 +5,10 @@ * 2.0. */ +import { IndicesPutIndexTemplateRequest } from '@elastic/elasticsearch/api/types'; import { ResponseError } from '@elastic/elasticsearch/lib/errors'; import { IndexPatternsFetcher } from '../../../../../src/plugins/data/server'; +import { DEFAULT_ILM_POLICY_ID } from '../../common/assets'; import { RuleDataWriteDisabledError } from '../rule_data_plugin_service/errors'; import { IRuleDataClient, @@ -111,11 +113,50 @@ export class RuleDataClient implements IRuleDataClient { }; } + createNamespacedIndexTemplate(namespace?: string): IndicesPutIndexTemplateRequest { + const namespacedAlias = getNamespacedAlias({ alias: this.options.alias, namespace }); + return { + name: namespacedAlias, + body: { + index_patterns: [`${namespacedAlias}*`], + composed_of: [ + ...this.options.componentTemplateNames, + ], + template: { + aliases: this.options.secondaryAlias != null ? { + [getNamespacedAlias({ alias: this.options.secondaryAlias, namespace})]: { + is_write_index: false, + } + } : undefined, + settings: { + 'index.lifecycle': { + name: DEFAULT_ILM_POLICY_ID, + // TODO: fix the types in the ES package, they don't include rollover_alias??? + // @ts-expect-error + rollover_alias: namespacedAlias, + }, + }, + }, + } + }; + } + async createWriteTargetIfNeeded({ namespace }: { namespace?: string }) { const alias = getNamespacedAlias({ alias: this.options.alias, namespace }); const clusterClient = await this.getClusterClient(); - + const template = this.createNamespacedIndexTemplate(namespace); + // TODO: need a way to update this template if/when we decide to make changes to the + // built in index template. Probably do it as part of updateIndexMappingsForAsset? + // (Before upgrading any indices, find and upgrade all namespaced index templates - component templates + // will already have been upgraded by solutions or rule registry, in the case of technical/ECS templates) + // With the current structure, it's tricky because the index template creation + // depends on both the namespace and secondary alias, both of which are not currently available + // to updateIndexMappingsForAsset. We can make the secondary alias available since + // it's known at plugin startup time, but + // the namespace values can really only come from the existing templates that we're trying to update + // - maybe we want to store the namespace as a _meta field on the index template for easy retrieval + await clusterClient.indices.putIndexTemplate(template); const { body: aliasExists } = await clusterClient.indices.existsAlias({ name: alias, }); diff --git a/x-pack/plugins/rule_registry/server/rule_data_client/types.ts b/x-pack/plugins/rule_registry/server/rule_data_client/types.ts index 92ba5c7060ebb..f6b1c04db2176 100644 --- a/x-pack/plugins/rule_registry/server/rule_data_client/types.ts +++ b/x-pack/plugins/rule_registry/server/rule_data_client/types.ts @@ -50,6 +50,8 @@ export interface RuleDataClientConstructorOptions { getClusterClient: () => Promise; isWriteEnabled: boolean; ready: () => Promise; + componentTemplateNames: string[]; alias: string; feature: ValidFeatureId; + secondaryAlias?: string; } diff --git a/x-pack/plugins/rule_registry/server/rule_data_plugin_service/index.ts b/x-pack/plugins/rule_registry/server/rule_data_plugin_service/index.ts index d84f85dbc99b7..cad1e2b118d5d 100644 --- a/x-pack/plugins/rule_registry/server/rule_data_plugin_service/index.ts +++ b/x-pack/plugins/rule_registry/server/rule_data_plugin_service/index.ts @@ -184,9 +184,10 @@ export class RuleDataPluginService { return this._createOrUpdateLifecyclePolicy(policy); } - async updateIndexMappingsMatchingPattern(pattern: string) { + async updateIndexMappingsForAsset(assetName: string) { await this.wait(); const clusterClient = await this.getClusterClient(); + const pattern = this.getFullAssetName(assetName); const { body: aliasesResponse } = await clusterClient.indices.getAlias({ index: pattern }); const writeIndicesAndAliases: Array<{ index: string; alias: string }> = []; Object.entries(aliasesResponse).forEach(([index, aliases]) => { @@ -224,13 +225,21 @@ export class RuleDataPluginService { return [this.options.index, assetName].filter(Boolean).join('-'); } - getRuleDataClient(feature: ValidFeatureId, alias: string, initialize: () => Promise) { + getRuleDataClient( + feature: ValidFeatureId, + assetName: string, + initialize: () => Promise, + componentTemplateNames: string[], + secondaryAlias?: string, + ) { return new RuleDataClient({ - alias, + alias: this.getFullAssetName(assetName), feature, getClusterClient: () => this.getClusterClient(), isWriteEnabled: this.isWriteEnabled(), ready: initialize, + componentTemplateNames, + secondaryAlias, }); } } diff --git a/x-pack/plugins/rule_registry/server/rule_data_plugin_service/rule_data_plugin_service.mock.ts b/x-pack/plugins/rule_registry/server/rule_data_plugin_service/rule_data_plugin_service.mock.ts index 275d68621864f..20f6b1a3238c8 100644 --- a/x-pack/plugins/rule_registry/server/rule_data_plugin_service/rule_data_plugin_service.mock.ts +++ b/x-pack/plugins/rule_registry/server/rule_data_plugin_service/rule_data_plugin_service.mock.ts @@ -21,7 +21,7 @@ const createRuleDataPluginServiceMock = (_: RuleDataPluginServiceConstructorOpti createOrUpdateIndexTemplate: jest.fn(), createOrUpdateLifecyclePolicy: jest.fn(), getRuleDataClient: jest.fn(), - updateIndexMappingsMatchingPattern: jest.fn(), + updateIndexMappingsForAsset: jest.fn(), }; return mocked; }; diff --git a/x-pack/plugins/security_solution/server/plugin.ts b/x-pack/plugins/security_solution/server/plugin.ts index 07b0e2ed4b9dd..4e33e70051470 100644 --- a/x-pack/plugins/security_solution/server/plugin.ts +++ b/x-pack/plugins/security_solution/server/plugin.ts @@ -195,12 +195,9 @@ export class Plugin implements IPlugin { - const componentTemplateName = ruleDataService.getFullAssetName('security.alerts-mappings'); - if (!ruleDataService.isWriteEnabled()) { return; } @@ -217,7 +214,7 @@ export class Plugin implements IPlugin initializeRuleDataTemplatesPromise + assetName, + () => initializeRuleDataTemplatesPromise, + [ + ruleDataService.getFullAssetName(TECHNICAL_COMPONENT_TEMPLATE_NAME), + ruleDataService.getFullAssetName(ECS_COMPONENT_TEMPLATE_NAME), + componentTemplateName, + ], + config.signalsIndex, ); // sec diff --git a/x-pack/plugins/uptime/server/plugin.ts b/x-pack/plugins/uptime/server/plugin.ts index 5ef5e17d4e33a..fc3fff62740da 100644 --- a/x-pack/plugins/uptime/server/plugin.ts +++ b/x-pack/plugins/uptime/server/plugin.ts @@ -34,11 +34,9 @@ export class Plugin implements PluginType { public setup(core: CoreSetup, plugins: UptimeCorePlugins) { this.logger = this.initContext.logger.get(); const { ruleDataService } = plugins.ruleRegistry; - + const assetName = 'observability.synthetics'; + const componentTemplateName = ruleDataService.getFullAssetName('synthetics-mappings'); const ready = once(async () => { - const componentTemplateName = ruleDataService.getFullAssetName('synthetics-mappings'); - const alertsIndexPattern = ruleDataService.getFullAssetName('observability.synthetics*'); - if (!ruleDataService.isWriteEnabled()) { return; } @@ -55,7 +53,7 @@ export class Plugin implements PluginType { }, }); - await ruleDataService.createOrUpdateIndexTemplate({ + /*await ruleDataService.createOrUpdateIndexTemplate({ name: ruleDataService.getFullAssetName('synthetics-index-template'), body: { index_patterns: [alertsIndexPattern], @@ -64,9 +62,9 @@ export class Plugin implements PluginType { componentTemplateName, ], }, - }); + });*/ - await ruleDataService.updateIndexMappingsMatchingPattern(alertsIndexPattern); + await ruleDataService.updateIndexMappingsForAsset(assetName); }); // initialize eagerly @@ -76,8 +74,12 @@ export class Plugin implements PluginType { const ruleDataClient = ruleDataService.getRuleDataClient( 'synthetics', - ruleDataService.getFullAssetName('observability.synthetics'), - () => initializeRuleDataTemplatesPromise + assetName, + () => initializeRuleDataTemplatesPromise, + [ + ruleDataService.getFullAssetName(TECHNICAL_COMPONENT_TEMPLATE_NAME), + componentTemplateName, + ] ); initServerWithKibana( From 4f16ccc91e02f94c29e2dc012fc18b05a9b57718 Mon Sep 17 00:00:00 2001 From: Marshall Main Date: Tue, 20 Jul 2021 21:55:53 -0700 Subject: [PATCH 2/4] Compute namespaced alias in one place to ensure consistency --- .../server/rule_data_client/index.ts | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/x-pack/plugins/rule_registry/server/rule_data_client/index.ts b/x-pack/plugins/rule_registry/server/rule_data_client/index.ts index f6a77948c2f72..d52fb3da73f0d 100644 --- a/x-pack/plugins/rule_registry/server/rule_data_client/index.ts +++ b/x-pack/plugins/rule_registry/server/rule_data_client/index.ts @@ -113,18 +113,17 @@ export class RuleDataClient implements IRuleDataClient { }; } - createNamespacedIndexTemplate(namespace?: string): IndicesPutIndexTemplateRequest { - const namespacedAlias = getNamespacedAlias({ alias: this.options.alias, namespace }); + createNamespacedIndexTemplate(primaryNamespacedAlias: string, secondaryNamespacedAlias?: string): IndicesPutIndexTemplateRequest { return { - name: namespacedAlias, + name: primaryNamespacedAlias, body: { - index_patterns: [`${namespacedAlias}*`], + index_patterns: [`${primaryNamespacedAlias}*`], composed_of: [ ...this.options.componentTemplateNames, ], template: { - aliases: this.options.secondaryAlias != null ? { - [getNamespacedAlias({ alias: this.options.secondaryAlias, namespace})]: { + aliases: secondaryNamespacedAlias != null ? { + [secondaryNamespacedAlias]: { is_write_index: false, } } : undefined, @@ -133,7 +132,7 @@ export class RuleDataClient implements IRuleDataClient { name: DEFAULT_ILM_POLICY_ID, // TODO: fix the types in the ES package, they don't include rollover_alias??? // @ts-expect-error - rollover_alias: namespacedAlias, + rollover_alias: primaryNamespacedAlias, }, }, }, @@ -142,10 +141,13 @@ export class RuleDataClient implements IRuleDataClient { } async createWriteTargetIfNeeded({ namespace }: { namespace?: string }) { - const alias = getNamespacedAlias({ alias: this.options.alias, namespace }); + const namespacedAlias = getNamespacedAlias({ alias: this.options.alias, namespace }); const clusterClient = await this.getClusterClient(); - const template = this.createNamespacedIndexTemplate(namespace); + const secondaryNamespacedAlias = this.options.secondaryAlias != null ? + getNamespacedAlias({ alias: this.options.secondaryAlias, namespace }) + : undefined; + const template = this.createNamespacedIndexTemplate(namespacedAlias, secondaryNamespacedAlias); // TODO: need a way to update this template if/when we decide to make changes to the // built in index template. Probably do it as part of updateIndexMappingsForAsset? // (Before upgrading any indices, find and upgrade all namespaced index templates - component templates @@ -158,10 +160,10 @@ export class RuleDataClient implements IRuleDataClient { // - maybe we want to store the namespace as a _meta field on the index template for easy retrieval await clusterClient.indices.putIndexTemplate(template); const { body: aliasExists } = await clusterClient.indices.existsAlias({ - name: alias, + name: namespacedAlias, }); - const concreteIndexName = `${alias}-000001`; + const concreteIndexName = `${namespacedAlias}-000001`; if (!aliasExists) { try { @@ -169,7 +171,7 @@ export class RuleDataClient implements IRuleDataClient { index: concreteIndexName, body: { aliases: { - [alias]: { + [namespacedAlias]: { is_write_index: true, }, }, From bcbd9524422b0479414efe8a181981e8c28cc336 Mon Sep 17 00:00:00 2001 From: Marshall Main Date: Thu, 29 Jul 2021 12:57:37 -0700 Subject: [PATCH 3/4] Formatting files --- .../server/rule_data_client/index.ts | 76 ++++++++++++------- .../server/rule_data_plugin_service/index.ts | 4 +- .../security_solution/server/plugin.ts | 4 +- 3 files changed, 51 insertions(+), 33 deletions(-) diff --git a/x-pack/plugins/rule_registry/server/rule_data_client/index.ts b/x-pack/plugins/rule_registry/server/rule_data_client/index.ts index d52fb3da73f0d..376b582dcd14f 100644 --- a/x-pack/plugins/rule_registry/server/rule_data_client/index.ts +++ b/x-pack/plugins/rule_registry/server/rule_data_client/index.ts @@ -113,20 +113,29 @@ export class RuleDataClient implements IRuleDataClient { }; } - createNamespacedIndexTemplate(primaryNamespacedAlias: string, secondaryNamespacedAlias?: string): IndicesPutIndexTemplateRequest { + createNamespacedIndexTemplate({ + primaryNamespacedAlias, + secondaryNamespacedAlias, + namespace, + }: { + primaryNamespacedAlias: string; + secondaryNamespacedAlias?: string; + namespace?: string; + }): IndicesPutIndexTemplateRequest { return { name: primaryNamespacedAlias, body: { index_patterns: [`${primaryNamespacedAlias}*`], - composed_of: [ - ...this.options.componentTemplateNames, - ], + composed_of: [...this.options.componentTemplateNames], template: { - aliases: secondaryNamespacedAlias != null ? { - [secondaryNamespacedAlias]: { - is_write_index: false, - } - } : undefined, + aliases: + secondaryNamespacedAlias != null + ? { + [secondaryNamespacedAlias]: { + is_write_index: false, + }, + } + : undefined, settings: { 'index.lifecycle': { name: DEFAULT_ILM_POLICY_ID, @@ -136,42 +145,51 @@ export class RuleDataClient implements IRuleDataClient { }, }, }, - } + _meta: { + namespace, + }, + }, }; } async createWriteTargetIfNeeded({ namespace }: { namespace?: string }) { - const namespacedAlias = getNamespacedAlias({ alias: this.options.alias, namespace }); + const primaryNamespacedAlias = getNamespacedAlias({ alias: this.options.alias, namespace }); const clusterClient = await this.getClusterClient(); - const secondaryNamespacedAlias = this.options.secondaryAlias != null ? - getNamespacedAlias({ alias: this.options.secondaryAlias, namespace }) - : undefined; - const template = this.createNamespacedIndexTemplate(namespacedAlias, secondaryNamespacedAlias); - // TODO: need a way to update this template if/when we decide to make changes to the - // built in index template. Probably do it as part of updateIndexMappingsForAsset? - // (Before upgrading any indices, find and upgrade all namespaced index templates - component templates - // will already have been upgraded by solutions or rule registry, in the case of technical/ECS templates) - // With the current structure, it's tricky because the index template creation - // depends on both the namespace and secondary alias, both of which are not currently available - // to updateIndexMappingsForAsset. We can make the secondary alias available since - // it's known at plugin startup time, but - // the namespace values can really only come from the existing templates that we're trying to update - // - maybe we want to store the namespace as a _meta field on the index template for easy retrieval - await clusterClient.indices.putIndexTemplate(template); + const { body: aliasExists } = await clusterClient.indices.existsAlias({ - name: namespacedAlias, + name: primaryNamespacedAlias, }); - const concreteIndexName = `${namespacedAlias}-000001`; + const concreteIndexName = `${primaryNamespacedAlias}-000001`; if (!aliasExists) { + const secondaryNamespacedAlias = + this.options.secondaryAlias != null + ? getNamespacedAlias({ alias: this.options.secondaryAlias, namespace }) + : undefined; + const template = this.createNamespacedIndexTemplate({ + primaryNamespacedAlias, + secondaryNamespacedAlias, + namespace, + }); + // TODO: need a way to update this template if/when we decide to make changes to the + // built in index template. Probably do it as part of updateIndexMappingsForAsset? + // (Before upgrading any indices, find and upgrade all namespaced index templates - component templates + // will already have been upgraded by solutions or rule registry, in the case of technical/ECS templates) + // With the current structure, it's tricky because the index template creation + // depends on both the namespace and secondary alias, both of which are not currently available + // to updateIndexMappingsForAsset. We can make the secondary alias available since + // it's known at plugin startup time, but + // the namespace values can really only come from the existing templates that we're trying to update + // - maybe we want to store the namespace as a _meta field on the index template for easy retrieval + await clusterClient.indices.putIndexTemplate(template); try { await clusterClient.indices.create({ index: concreteIndexName, body: { aliases: { - [namespacedAlias]: { + [primaryNamespacedAlias]: { is_write_index: true, }, }, diff --git a/x-pack/plugins/rule_registry/server/rule_data_plugin_service/index.ts b/x-pack/plugins/rule_registry/server/rule_data_plugin_service/index.ts index c6894247845cd..e1c900aa5d05a 100644 --- a/x-pack/plugins/rule_registry/server/rule_data_plugin_service/index.ts +++ b/x-pack/plugins/rule_registry/server/rule_data_plugin_service/index.ts @@ -230,8 +230,8 @@ export class RuleDataPluginService { feature: ValidFeatureId, assetName: string, initialize: () => Promise, - componentTemplateNames: string[], - secondaryAlias?: string, + componentTemplateNames: string[], + secondaryAlias?: string ) { return new RuleDataClient({ alias: this.getFullAssetName(assetName), diff --git a/x-pack/plugins/security_solution/server/plugin.ts b/x-pack/plugins/security_solution/server/plugin.ts index c94e0ee8d1c25..cf4a9f907e549 100644 --- a/x-pack/plugins/security_solution/server/plugin.ts +++ b/x-pack/plugins/security_solution/server/plugin.ts @@ -217,7 +217,7 @@ export class Plugin implements IPlugin Date: Thu, 5 Aug 2021 09:37:27 -0700 Subject: [PATCH 4/4] Add template priority --- .../plugins/rule_registry/server/rule_data_client/index.ts | 5 ++++- .../rule_registry/server/rule_data_plugin_service/index.ts | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/rule_registry/server/rule_data_client/index.ts b/x-pack/plugins/rule_registry/server/rule_data_client/index.ts index 376b582dcd14f..e5a2e1ee53cc0 100644 --- a/x-pack/plugins/rule_registry/server/rule_data_client/index.ts +++ b/x-pack/plugins/rule_registry/server/rule_data_client/index.ts @@ -125,7 +125,7 @@ export class RuleDataClient implements IRuleDataClient { return { name: primaryNamespacedAlias, body: { - index_patterns: [`${primaryNamespacedAlias}*`], + index_patterns: [`${primaryNamespacedAlias}-*`], composed_of: [...this.options.componentTemplateNames], template: { aliases: @@ -148,6 +148,9 @@ export class RuleDataClient implements IRuleDataClient { _meta: { namespace, }, + // By setting the priority to namespace.length, we ensure that if one namespace is a prefix of another namespace + // then newly created indices will use the matching template with the *longest* namespace + priority: namespace?.length, }, }; } diff --git a/x-pack/plugins/rule_registry/server/rule_data_plugin_service/index.ts b/x-pack/plugins/rule_registry/server/rule_data_plugin_service/index.ts index 4689442ef155e..a8fcd79eab51b 100644 --- a/x-pack/plugins/rule_registry/server/rule_data_plugin_service/index.ts +++ b/x-pack/plugins/rule_registry/server/rule_data_plugin_service/index.ts @@ -198,8 +198,8 @@ export class RuleDataPluginService { async updateIndexMappingsForAsset(assetName: string) { await this.wait(); const clusterClient = await this.getClusterClient(); - const pattern = this.getFullAssetName(assetName); - const { body: aliasesResponse } = await clusterClient.indices.getAlias({ index: pattern }); + const pattern = `${this.getFullAssetName(assetName)}-*`; + const { body: aliasesResponse } = await clusterClient.indices.getAlias({ name: pattern }); const writeIndicesAndAliases: Array<{ index: string; alias: string }> = []; Object.entries(aliasesResponse).forEach(([index, aliases]) => { Object.entries(aliases.aliases).forEach(([aliasName, aliasProperties]) => {