Skip to content

Commit 60dfef8

Browse files
committed
Merge remote-tracking branch upstream/master
2 parents d03cf87 + 93614af commit 60dfef8

67 files changed

Lines changed: 1129 additions & 183 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

x-pack/plugins/actions/server/action_type_registry.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ export class ActionTypeRegistry {
177177
minimumLicenseRequired: actionType.minimumLicenseRequired,
178178
enabled: this.isActionTypeEnabled(actionTypeId),
179179
enabledInConfig: this.actionsConfigUtils.isActionTypeEnabled(actionTypeId),
180-
enabledInLicense: this.licenseState.isLicenseValidForActionType(actionType).isValid === true,
180+
enabledInLicense: !!this.licenseState.isLicenseValidForActionType(actionType).isValid,
181181
}));
182182
}
183183
}

x-pack/plugins/alerts/common/alert.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ export enum AlertExecutionStatusErrorReasons {
2525
Decrypt = 'decrypt',
2626
Execute = 'execute',
2727
Unknown = 'unknown',
28+
License = 'license',
2829
}
2930

3031
export interface AlertExecutionStatus {

x-pack/plugins/alerts/server/alert_type_registry.mock.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ const createAlertTypeRegistryMock = () => {
1414
register: jest.fn(),
1515
get: jest.fn(),
1616
list: jest.fn(),
17+
ensureAlertTypeEnabled: jest.fn(),
1718
};
1819
return mocked;
1920
};

x-pack/plugins/alerts/server/alert_type_registry.test.ts

Lines changed: 54 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,27 @@
55
*/
66

77
import { TaskRunnerFactory } from './task_runner';
8-
import { AlertTypeRegistry } from './alert_type_registry';
8+
import { AlertTypeRegistry, ConstructorOptions } from './alert_type_registry';
99
import { AlertType } from './types';
1010
import { taskManagerMock } from '../../task_manager/server/mocks';
11+
import { ILicenseState } from './lib/license_state';
12+
import { licenseStateMock } from './lib/license_state.mock';
13+
import { licensingMock } from '../../licensing/server/mocks';
14+
let mockedLicenseState: jest.Mocked<ILicenseState>;
15+
let alertTypeRegistryParams: ConstructorOptions;
1116

1217
const taskManager = taskManagerMock.createSetup();
13-
const alertTypeRegistryParams = {
14-
taskManager,
15-
taskRunnerFactory: new TaskRunnerFactory(),
16-
};
1718

18-
beforeEach(() => jest.resetAllMocks());
19+
beforeEach(() => {
20+
jest.resetAllMocks();
21+
mockedLicenseState = licenseStateMock.create();
22+
alertTypeRegistryParams = {
23+
taskManager,
24+
taskRunnerFactory: new TaskRunnerFactory(),
25+
licenseState: mockedLicenseState,
26+
licensing: licensingMock.createSetup(),
27+
};
28+
});
1929

2030
describe('has()', () => {
2131
test('returns false for unregistered alert types', () => {
@@ -379,6 +389,7 @@ describe('list()', () => {
379389
"state": Array [],
380390
},
381391
"defaultActionGroupId": "testActionGroup",
392+
"enabledInLicense": false,
382393
"id": "test",
383394
"minimumLicenseRequired": "basic",
384395
"name": "Test",
@@ -427,6 +438,43 @@ describe('list()', () => {
427438
});
428439
});
429440

441+
describe('ensureAlertTypeEnabled', () => {
442+
let alertTypeRegistry: AlertTypeRegistry;
443+
444+
beforeEach(() => {
445+
alertTypeRegistry = new AlertTypeRegistry(alertTypeRegistryParams);
446+
alertTypeRegistry.register({
447+
id: 'test',
448+
name: 'Test',
449+
actionGroups: [
450+
{
451+
id: 'default',
452+
name: 'Default',
453+
},
454+
],
455+
defaultActionGroupId: 'default',
456+
executor: jest.fn(),
457+
producer: 'alerts',
458+
minimumLicenseRequired: 'basic',
459+
recoveryActionGroup: { id: 'recovered', name: 'Recovered' },
460+
});
461+
});
462+
463+
test('should call ensureLicenseForAlertType on the license state', async () => {
464+
alertTypeRegistry.ensureAlertTypeEnabled('test');
465+
expect(mockedLicenseState.ensureLicenseForAlertType).toHaveBeenCalled();
466+
});
467+
468+
test('should throw when ensureLicenseForAlertType throws', async () => {
469+
mockedLicenseState.ensureLicenseForAlertType.mockImplementation(() => {
470+
throw new Error('Fail');
471+
});
472+
expect(() =>
473+
alertTypeRegistry.ensureAlertTypeEnabled('test')
474+
).toThrowErrorMatchingInlineSnapshot(`"Fail"`);
475+
});
476+
});
477+
430478
function alertTypeWithVariables(id: string, context: string, state: string): AlertType {
431479
const baseAlert: AlertType = {
432480
id,

x-pack/plugins/alerts/server/alert_type_registry.ts

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { i18n } from '@kbn/i18n';
99
import { schema } from '@kbn/config-schema';
1010
import typeDetect from 'type-detect';
1111
import { intersection } from 'lodash';
12+
import { LicensingPluginSetup } from '../../licensing/server';
1213
import { RunContext, TaskManagerSetupContract } from '../../task_manager/server';
1314
import { TaskRunnerFactory } from './task_runner';
1415
import {
@@ -19,10 +20,14 @@ import {
1920
AlertInstanceContext,
2021
} from './types';
2122
import { RecoveredActionGroup, getBuiltinActionGroups } from '../common';
23+
import { ILicenseState } from './lib/license_state';
24+
import { getAlertTypeFeatureUsageName } from './lib/get_alert_type_feature_usage_name';
2225

23-
interface ConstructorOptions {
26+
export interface ConstructorOptions {
2427
taskManager: TaskManagerSetupContract;
2528
taskRunnerFactory: TaskRunnerFactory;
29+
licenseState: ILicenseState;
30+
licensing: LicensingPluginSetup;
2631
}
2732

2833
export interface RegistryAlertType
@@ -34,8 +39,10 @@ export interface RegistryAlertType
3439
| 'defaultActionGroupId'
3540
| 'actionVariables'
3641
| 'producer'
42+
| 'minimumLicenseRequired'
3743
> {
3844
id: string;
45+
enabledInLicense: boolean;
3946
}
4047

4148
/**
@@ -70,16 +77,24 @@ export class AlertTypeRegistry {
7077
private readonly taskManager: TaskManagerSetupContract;
7178
private readonly alertTypes: Map<string, NormalizedAlertType> = new Map();
7279
private readonly taskRunnerFactory: TaskRunnerFactory;
80+
private readonly licenseState: ILicenseState;
81+
private readonly licensing: LicensingPluginSetup;
7382

74-
constructor({ taskManager, taskRunnerFactory }: ConstructorOptions) {
83+
constructor({ taskManager, taskRunnerFactory, licenseState, licensing }: ConstructorOptions) {
7584
this.taskManager = taskManager;
7685
this.taskRunnerFactory = taskRunnerFactory;
86+
this.licenseState = licenseState;
87+
this.licensing = licensing;
7788
}
7889

7990
public has(id: string) {
8091
return this.alertTypes.has(id);
8192
}
8293

94+
public ensureAlertTypeEnabled(id: string) {
95+
this.licenseState.ensureLicenseForAlertType(this.get(id));
96+
}
97+
8398
public register<
8499
Params extends AlertTypeParams = AlertTypeParams,
85100
State extends AlertTypeState = AlertTypeState,
@@ -108,6 +123,13 @@ export class AlertTypeRegistry {
108123
this.taskRunnerFactory.create(normalizedAlertType, context),
109124
},
110125
});
126+
// No need to notify usage on basic alert types
127+
if (alertType.minimumLicenseRequired !== 'basic') {
128+
this.licensing.featureUsage.register(
129+
getAlertTypeFeatureUsageName(alertType.name),
130+
alertType.minimumLicenseRequired
131+
);
132+
}
111133
}
112134

113135
public get<
@@ -157,6 +179,11 @@ export class AlertTypeRegistry {
157179
actionVariables,
158180
producer,
159181
minimumLicenseRequired,
182+
enabledInLicense: !!this.licenseState.getLicenseCheckForAlertType(
183+
id,
184+
name,
185+
minimumLicenseRequired
186+
).isValid,
160187
})
161188
)
162189
);

x-pack/plugins/alerts/server/alerts_client/alerts_client.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,8 @@ export class AlertsClient {
236236
throw error;
237237
}
238238

239+
this.alertTypeRegistry.ensureAlertTypeEnabled(data.alertTypeId);
240+
239241
// Throws an error if alert type isn't registered
240242
const alertType = this.alertTypeRegistry.get(data.alertTypeId);
241243

@@ -644,6 +646,8 @@ export class AlertsClient {
644646
})
645647
);
646648

649+
this.alertTypeRegistry.ensureAlertTypeEnabled(alertSavedObject.attributes.alertTypeId);
650+
647651
const updateResult = await this.updateAlert({ id, data }, alertSavedObject);
648652

649653
await Promise.all([
@@ -819,6 +823,8 @@ export class AlertsClient {
819823
})
820824
);
821825

826+
this.alertTypeRegistry.ensureAlertTypeEnabled(attributes.alertTypeId);
827+
822828
try {
823829
await this.unsecuredSavedObjectsClient.update('alert', id, updateAttributes, { version });
824830
} catch (e) {
@@ -902,6 +908,8 @@ export class AlertsClient {
902908
})
903909
);
904910

911+
this.alertTypeRegistry.ensureAlertTypeEnabled(attributes.alertTypeId);
912+
905913
if (attributes.enabled === false) {
906914
const username = await this.getUserName();
907915
const updateAttributes = this.updateMeta({
@@ -1001,6 +1009,8 @@ export class AlertsClient {
10011009
})
10021010
);
10031011

1012+
this.alertTypeRegistry.ensureAlertTypeEnabled(attributes.alertTypeId);
1013+
10041014
if (attributes.enabled === true) {
10051015
await this.unsecuredSavedObjectsClient.update(
10061016
'alert',
@@ -1075,6 +1085,8 @@ export class AlertsClient {
10751085
})
10761086
);
10771087

1088+
this.alertTypeRegistry.ensureAlertTypeEnabled(attributes.alertTypeId);
1089+
10781090
const updateAttributes = this.updateMeta({
10791091
muteAll: true,
10801092
mutedInstanceIds: [],
@@ -1134,6 +1146,8 @@ export class AlertsClient {
11341146
})
11351147
);
11361148

1149+
this.alertTypeRegistry.ensureAlertTypeEnabled(attributes.alertTypeId);
1150+
11371151
const updateAttributes = this.updateMeta({
11381152
muteAll: false,
11391153
mutedInstanceIds: [],
@@ -1193,6 +1207,8 @@ export class AlertsClient {
11931207
})
11941208
);
11951209

1210+
this.alertTypeRegistry.ensureAlertTypeEnabled(attributes.alertTypeId);
1211+
11961212
const mutedInstanceIds = attributes.mutedInstanceIds || [];
11971213
if (!attributes.muteAll && !mutedInstanceIds.includes(alertInstanceId)) {
11981214
mutedInstanceIds.push(alertInstanceId);
@@ -1257,6 +1273,8 @@ export class AlertsClient {
12571273
})
12581274
);
12591275

1276+
this.alertTypeRegistry.ensureAlertTypeEnabled(attributes.alertTypeId);
1277+
12601278
const mutedInstanceIds = attributes.mutedInstanceIds || [];
12611279
if (!attributes.muteAll && mutedInstanceIds.includes(alertInstanceId)) {
12621280
await this.unsecuredSavedObjectsClient.update<RawAlert>(

x-pack/plugins/alerts/server/alerts_client/tests/aggregate.test.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { ActionsAuthorization } from '../../../../actions/server';
1515
import { getBeforeSetup, setGlobalDate } from './lib';
1616
import { AlertExecutionStatusValues } from '../../types';
1717
import { RecoveredActionGroup } from '../../../common';
18+
import { RegistryAlertType } from '../../alert_type_registry';
1819

1920
const taskManager = taskManagerMock.createStart();
2021
const alertTypeRegistry = alertTypeRegistryMock.create();
@@ -49,7 +50,7 @@ beforeEach(() => {
4950
setGlobalDate();
5051

5152
describe('aggregate()', () => {
52-
const listedTypes = new Set([
53+
const listedTypes = new Set<RegistryAlertType>([
5354
{
5455
actionGroups: [],
5556
actionVariables: undefined,
@@ -59,6 +60,7 @@ describe('aggregate()', () => {
5960
id: 'myType',
6061
name: 'myType',
6162
producer: 'myApp',
63+
enabledInLicense: true,
6264
},
6365
]);
6466
beforeEach(() => {
@@ -111,6 +113,7 @@ describe('aggregate()', () => {
111113
authorizedConsumers: {
112114
myApp: { read: true, all: true },
113115
},
116+
enabledInLicense: true,
114117
},
115118
])
116119
);

x-pack/plugins/alerts/server/alerts_client/tests/create.test.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1194,4 +1194,14 @@ describe('create()', () => {
11941194
}
11951195
);
11961196
});
1197+
1198+
test('throws error when ensureActionTypeEnabled throws', async () => {
1199+
const data = getMockData();
1200+
alertTypeRegistry.ensureAlertTypeEnabled.mockImplementation(() => {
1201+
throw new Error('Fail');
1202+
});
1203+
await expect(alertsClient.create({ data })).rejects.toThrowErrorMatchingInlineSnapshot(
1204+
`"Fail"`
1205+
);
1206+
});
11971207
});

x-pack/plugins/alerts/server/alerts_client/tests/find.test.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { httpServerMock } from '../../../../../../src/core/server/mocks';
1818
import { auditServiceMock } from '../../../../security/server/audit/index.mock';
1919
import { getBeforeSetup, setGlobalDate } from './lib';
2020
import { RecoveredActionGroup } from '../../../common';
21+
import { RegistryAlertType } from '../../alert_type_registry';
2122

2223
const taskManager = taskManagerMock.createStart();
2324
const alertTypeRegistry = alertTypeRegistryMock.create();
@@ -53,7 +54,7 @@ beforeEach(() => {
5354
setGlobalDate();
5455

5556
describe('find()', () => {
56-
const listedTypes = new Set([
57+
const listedTypes = new Set<RegistryAlertType>([
5758
{
5859
actionGroups: [],
5960
recoveryActionGroup: RecoveredActionGroup,
@@ -63,6 +64,7 @@ describe('find()', () => {
6364
id: 'myType',
6465
name: 'myType',
6566
producer: 'myApp',
67+
enabledInLicense: true,
6668
},
6769
]);
6870
beforeEach(() => {
@@ -121,6 +123,7 @@ describe('find()', () => {
121123
authorizedConsumers: {
122124
myApp: { read: true, all: true },
123125
},
126+
enabledInLicense: true,
124127
},
125128
])
126129
);

0 commit comments

Comments
 (0)