Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Response Ops][Alerting] Update alerts-as-data ILM policy name to be consistent between framework & rule registry #150334

Merged
merged 11 commits into from
Feb 13, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ const IlmPutBody = {
},
},
},
name: 'alerts-default-ilm-policy',
name: '.alerts-ilm-policy',
};

const getIndexTemplatePutBody = (context?: string) => ({
Expand All @@ -88,7 +88,7 @@ const getIndexTemplatePutBody = (context?: string) => ({
auto_expand_replicas: '0-1',
hidden: true,
'index.lifecycle': {
name: 'alerts-default-ilm-policy',
name: '.alerts-ilm-policy',
rollover_alias: `.alerts-${context ? context : 'test'}-default`,
},
'index.mapping.total_fields.limit': 2500,
Expand Down Expand Up @@ -165,7 +165,7 @@ describe('Alerts Service', () => {
expect(alertsService.isInitialized()).toEqual(false);

expect(logger.error).toHaveBeenCalledWith(
`Error installing ILM policy alerts-default-ilm-policy - fail`
`Error installing ILM policy .alerts-ilm-policy - fail`
);

expect(clusterClient.ilm.putLifecycle).toHaveBeenCalled();
Expand Down Expand Up @@ -342,7 +342,7 @@ describe('Alerts Service', () => {
auto_expand_replicas: '0-1',
hidden: true,
'index.lifecycle': {
name: 'alerts-default-ilm-policy',
name: '.alerts-ilm-policy',
rollover_alias: `.alerts-empty-default`,
},
'index.mapping.total_fields.limit': 2500,
Expand Down
17 changes: 11 additions & 6 deletions x-pack/plugins/alerting/server/alerts_service/alerts_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ import { Logger, ElasticsearchClient } from '@kbn/core/server';
import { firstValueFrom, Observable } from 'rxjs';
import { FieldMap } from '../../common/alert_schema/field_maps/types';
import { alertFieldMap } from '../../common/alert_schema';
import { ILM_POLICY_NAME, DEFAULT_ILM_POLICY } from './default_lifecycle_policy';
import {
DEFAULT_ALERTS_ILM_POLICY_NAME,
DEFAULT_ALERTS_ILM_POLICY,
} from './default_lifecycle_policy';
import {
getComponentTemplate,
getComponentTemplateName,
Expand Down Expand Up @@ -178,19 +181,21 @@ export class AlertsService implements IAlertsService {
* Creates ILM policy if it doesn't already exist, updates it if it does
*/
private async createOrUpdateIlmPolicy(esClient: ElasticsearchClient) {
this.options.logger.info(`Installing ILM policy ${ILM_POLICY_NAME}`);
this.options.logger.info(`Installing ILM policy ${DEFAULT_ALERTS_ILM_POLICY_NAME}`);

try {
await retryTransientEsErrors(
() =>
esClient.ilm.putLifecycle({
name: ILM_POLICY_NAME,
body: DEFAULT_ILM_POLICY,
name: DEFAULT_ALERTS_ILM_POLICY_NAME,
body: DEFAULT_ALERTS_ILM_POLICY,
}),
{ logger: this.options.logger }
);
} catch (err) {
this.options.logger.error(`Error installing ILM policy ${ILM_POLICY_NAME} - ${err.message}`);
this.options.logger.error(
`Error installing ILM policy ${DEFAULT_ALERTS_ILM_POLICY_NAME} - ${err.message}`
);
throw err;
}
}
Expand Down Expand Up @@ -236,7 +241,7 @@ export class AlertsService implements IAlertsService {
auto_expand_replicas: '0-1',
hidden: true,
'index.lifecycle': {
name: ILM_POLICY_NAME,
name: DEFAULT_ALERTS_ILM_POLICY_NAME,
rollover_alias: indexPatterns.alias,
},
'index.mapping.total_fields.limit': TOTAL_FIELDS_LIMIT,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
* This should be used by all alerts-as-data indices
*/

export const ILM_POLICY_NAME = 'alerts-default-ilm-policy';
export const DEFAULT_ILM_POLICY = {
export const DEFAULT_ALERTS_ILM_POLICY_NAME = '.alerts-ilm-policy';
export const DEFAULT_ALERTS_ILM_POLICY = {
policy: {
_meta: {
managed: true,
Expand Down
4 changes: 4 additions & 0 deletions x-pack/plugins/alerting/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ export {
WriteOperations,
AlertingAuthorizationEntity,
} from './authorization';
export {
DEFAULT_ALERTS_ILM_POLICY,
DEFAULT_ALERTS_ILM_POLICY_NAME,
} from './alerts_service/default_lifecycle_policy';

export const plugin = (initContext: PluginInitializerContext) => new AlertingPlugin(initContext);

Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/alerting/server/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const createSetupMock = () => {
registerType: jest.fn(),
getSecurityHealth: jest.fn(),
getConfig: jest.fn(),
getFrameworkAlertsEnabled: jest.fn(),
};
return mock;
};
Expand Down
6 changes: 5 additions & 1 deletion x-pack/plugins/alerting/server/plugin.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,10 +132,12 @@ describe('Alerting Plugin', () => {
plugin = new AlertingPlugin(context);

// need await to test number of calls of setupMocks.status.set, because it is under async function which awaiting core.getStartServices()
await plugin.setup(setupMocks, mockPlugins);
const setupContract = await plugin.setup(setupMocks, mockPlugins);

expect(AlertsService).toHaveBeenCalled();
expect(mockAlertService.initialize).toHaveBeenCalled();

expect(setupContract.getFrameworkAlertsEnabled()).toEqual(true);
});

it(`exposes configured minimumScheduleInterval()`, async () => {
Expand All @@ -150,6 +152,8 @@ describe('Alerting Plugin', () => {
isUsingSecurity: false,
minimumScheduleInterval: { value: '1m', enforce: false },
});

expect(setupContract.getFrameworkAlertsEnabled()).toEqual(false);
});

describe('registerType()', () => {
Expand Down
2 changes: 2 additions & 0 deletions x-pack/plugins/alerting/server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ export interface PluginSetupContract {
): void;
getSecurityHealth: () => Promise<SecurityHealth>;
getConfig: () => AlertingRulesConfig;
getFrameworkAlertsEnabled: () => boolean;
}

export interface PluginStartContract {
Expand Down Expand Up @@ -385,6 +386,7 @@ export class AlertingPlugin {
isUsingSecurity: this.licenseState ? !!this.licenseState.getIsSecurityEnabled() : false,
};
},
getFrameworkAlertsEnabled: () => this.config.enableFrameworkAlerts,
};
}

Expand Down
1 change: 0 additions & 1 deletion x-pack/plugins/rule_registry/common/assets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,3 @@

export const TECHNICAL_COMPONENT_TEMPLATE_NAME = `technical-mappings`;
export const ECS_COMPONENT_TEMPLATE_NAME = `ecs-mappings`;
export const DEFAULT_ILM_POLICY_ID = 'ilm-policy';

This file was deleted.

7 changes: 6 additions & 1 deletion x-pack/plugins/rule_registry/server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ import type {
IContextProvider,
} from '@kbn/core/server';

import type { PluginStartContract as AlertingStart } from '@kbn/alerting-plugin/server';
import type {
PluginSetupContract as AlertingSetup,
PluginStartContract as AlertingStart,
} from '@kbn/alerting-plugin/server';
import type { SecurityPluginSetup } from '@kbn/security-plugin/server';
import type { SpacesPluginStart } from '@kbn/spaces-plugin/server';
import type {
Expand All @@ -36,6 +39,7 @@ import { ruleRegistrySearchStrategyProvider, RULE_SEARCH_STRATEGY_NAME } from '.
export interface RuleRegistryPluginSetupDependencies {
security?: SecurityPluginSetup;
data: DataPluginSetup;
alerting: AlertingSetup;
}

export interface RuleRegistryPluginStartDependencies {
Expand Down Expand Up @@ -106,6 +110,7 @@ export class RuleRegistryPlugin
const deps = await startDependencies;
return deps.core.elasticsearch.client.asInternalUser;
},
areFrameworkAlertsEnabled: plugins.alerting.getFrameworkAlertsEnabled(),
pluginStop$: this.pluginStop$,
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import { Dataset } from './index_options';
import { IndexInfo } from './index_info';
import { elasticsearchServiceMock, ElasticsearchClientMock } from '@kbn/core/server/mocks';
import {
DEFAULT_ILM_POLICY_ID,
ECS_COMPONENT_TEMPLATE_NAME,
TECHNICAL_COMPONENT_TEMPLATE_NAME,
} from '../../common/assets';
Expand All @@ -41,6 +40,7 @@ describe('resourceInstaller', () => {
disabledRegistrationContexts: [],
getResourceName: jest.fn(),
getClusterClient,
areFrameworkAlertsEnabled: false,
pluginStop$,
});
installer.installCommonResources();
Expand All @@ -57,6 +57,7 @@ describe('resourceInstaller', () => {
disabledRegistrationContexts: [],
getResourceName: jest.fn(),
getClusterClient,
areFrameworkAlertsEnabled: false,
pluginStop$,
});
const indexOptions = {
Expand All @@ -83,7 +84,6 @@ describe('resourceInstaller', () => {
const getClusterClient = jest.fn(() => Promise.resolve(mockClusterClient));
const getResourceNameMock = jest
.fn()
.mockReturnValueOnce(DEFAULT_ILM_POLICY_ID)
.mockReturnValueOnce(TECHNICAL_COMPONENT_TEMPLATE_NAME)
.mockReturnValueOnce(ECS_COMPONENT_TEMPLATE_NAME);
const installer = new ResourceInstaller({
Expand All @@ -92,6 +92,7 @@ describe('resourceInstaller', () => {
disabledRegistrationContexts: [],
getResourceName: getResourceNameMock,
getClusterClient,
areFrameworkAlertsEnabled: false,
pluginStop$,
});

Expand All @@ -108,6 +109,38 @@ describe('resourceInstaller', () => {
expect.objectContaining({ name: ECS_COMPONENT_TEMPLATE_NAME })
);
});

it('should install common resources when framework alerts are enabled', async () => {
const mockClusterClient = elasticsearchServiceMock.createElasticsearchClient();
const getClusterClient = jest.fn(() => Promise.resolve(mockClusterClient));
const getResourceNameMock = jest
.fn()
.mockReturnValueOnce(TECHNICAL_COMPONENT_TEMPLATE_NAME)
.mockReturnValueOnce(ECS_COMPONENT_TEMPLATE_NAME);
const installer = new ResourceInstaller({
logger: loggerMock.create(),
isWriteEnabled: true,
disabledRegistrationContexts: [],
getResourceName: getResourceNameMock,
getClusterClient,
areFrameworkAlertsEnabled: true,
pluginStop$,
});

await installer.installCommonResources();

// ILM policy should be handled by framework
expect(mockClusterClient.ilm.putLifecycle).not.toHaveBeenCalled();
expect(mockClusterClient.cluster.putComponentTemplate).toHaveBeenCalledTimes(2);
expect(mockClusterClient.cluster.putComponentTemplate).toHaveBeenNthCalledWith(
1,
expect.objectContaining({ name: TECHNICAL_COMPONENT_TEMPLATE_NAME })
);
expect(mockClusterClient.cluster.putComponentTemplate).toHaveBeenNthCalledWith(
2,
expect.objectContaining({ name: ECS_COMPONENT_TEMPLATE_NAME })
);
});
it('should install index level resources', async () => {
const mockClusterClient = elasticsearchServiceMock.createElasticsearchClient();
const getClusterClient = jest.fn(() => Promise.resolve(mockClusterClient));
Expand All @@ -117,6 +150,7 @@ describe('resourceInstaller', () => {
disabledRegistrationContexts: [],
getResourceName: jest.fn(),
getClusterClient,
areFrameworkAlertsEnabled: false,
pluginStop$,
});

Expand Down Expand Up @@ -188,6 +222,7 @@ describe('resourceInstaller', () => {
disabledRegistrationContexts: [],
getResourceName: jest.fn(),
getClusterClient: async () => mockClusterClient,
areFrameworkAlertsEnabled: false,
pluginStop$,
};
const indexOptions = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,15 @@ import type { ElasticsearchClient, Logger } from '@kbn/core/server';

import type { PublicMethodsOf } from '@kbn/utility-types';
import {
DEFAULT_ILM_POLICY_ID,
DEFAULT_ALERTS_ILM_POLICY,
DEFAULT_ALERTS_ILM_POLICY_NAME,
} from '@kbn/alerting-plugin/server';
import {
ECS_COMPONENT_TEMPLATE_NAME,
TECHNICAL_COMPONENT_TEMPLATE_NAME,
} from '../../common/assets';
import { technicalComponentTemplate } from '../../common/assets/component_templates/technical_component_template';
import { ecsComponentTemplate } from '../../common/assets/component_templates/ecs_component_template';
import { defaultLifecyclePolicy } from '../../common/assets/lifecycle_policies/default_lifecycle_policy';

import type { IndexInfo } from './index_info';

Expand All @@ -31,6 +33,7 @@ interface ConstructorOptions {
logger: Logger;
isWriteEnabled: boolean;
disabledRegistrationContexts: string[];
areFrameworkAlertsEnabled: boolean;
pluginStop$: Observable<void>;
}

Expand Down Expand Up @@ -95,16 +98,21 @@ export class ResourceInstaller {
*/
public async installCommonResources(): Promise<void> {
await this.installWithTimeout('common resources shared between all indices', async () => {
const { getResourceName, logger } = this.options;
const { getResourceName, logger, areFrameworkAlertsEnabled } = this.options;

try {
// We can install them in parallel
await Promise.all([
this.createOrUpdateLifecyclePolicy({
name: getResourceName(DEFAULT_ILM_POLICY_ID),
body: defaultLifecyclePolicy,
}),

// Install ILM policy only if framework alerts are not enabled
// If framework alerts are enabled, the alerting framework will install this ILM policy
...(areFrameworkAlertsEnabled
? []
: [
this.createOrUpdateLifecyclePolicy({
name: DEFAULT_ALERTS_ILM_POLICY_NAME,
body: DEFAULT_ALERTS_ILM_POLICY,
}),
]),
this.createOrUpdateComponentTemplate({
name: getResourceName(TECHNICAL_COMPONENT_TEMPLATE_NAME),
body: technicalComponentTemplate,
Expand Down Expand Up @@ -326,9 +334,7 @@ export class ResourceInstaller {
const ownComponentNames = componentTemplates.map((template) =>
indexInfo.getComponentTemplateName(template.name)
);
const ilmPolicyName = ilmPolicy
? indexInfo.getIlmPolicyName()
: getResourceName(DEFAULT_ILM_POLICY_ID);
const ilmPolicyName = ilmPolicy ? indexInfo.getIlmPolicyName() : DEFAULT_ALERTS_ILM_POLICY_NAME;

const indexMetadata: estypes.Metadata = {
...indexTemplate._meta,
Expand Down
Loading