Skip to content

Commit

Permalink
[Alerting] Enable rule import/export and allow rule types to exclude …
Browse files Browse the repository at this point in the history
…themselves from export (#102999)

* Removing feature flag changes

* Adding isExportable flag to rule type definition

* Adding isExportable flag to rule type definition

* Adding isExportable flag to rule type definition

* Filtering rule on export by rule type isExportable flag

* Fixing types

* Adding docs

* Fix condition when exportCount is 0

* Unit test for fix condition when exportCount is 0

Co-authored-by: Kibana Machine <[email protected]>
  • Loading branch information
ymao1 and kibanamachine authored Jun 29, 2021
1 parent 6336494 commit c05588f
Show file tree
Hide file tree
Showing 68 changed files with 489 additions and 139 deletions.
4 changes: 4 additions & 0 deletions docs/api/alerting/legacy/list.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ The API returns the following:
},
"producer":"stackAlerts",
"minimumLicenseRequired":"basic",
"isExportable":true,
"enabledInLicense":true,
"authorizedConsumers":{
"alerts":{
Expand Down Expand Up @@ -113,6 +114,9 @@ Each alert type contains the following properties:
| `minimumLicenseRequired`
| The license required to use the alert type.

| `isExportable`
| Whether the rule type is exportable through the Saved Objects Management UI.

| `enabledInLicense`
| Whether the alert type is enabled or disabled based on the license.

Expand Down
4 changes: 4 additions & 0 deletions docs/api/alerting/list_rule_types.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ The API returns the following:
},
"producer":"stackAlerts",
"minimum_license_required":"basic",
"is_exportable":true,
"enabled_in_license":true,
"authorized_consumers":{
"alerts":{
Expand Down Expand Up @@ -115,6 +116,9 @@ Each rule type contains the following properties:
| `minimum_license_required`
| The license required to use the rule type.

| `is_exportable`
| Whether the rule type is exportable through the Saved Objects Management UI.

| `enabled_in_license`
| Whether the rule type is enabled or disabled based on the license.

Expand Down
19 changes: 19 additions & 0 deletions docs/user/alerting/create-and-manage-rules.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,25 @@ You can perform these operations in bulk by multi-selecting rules, and then clic
[role="screenshot"]
image:images/bulk-mute-disable.png[The Manage rules button lets you mute/unmute, enable/disable, and delete in bulk,width=75%]

[float]
[[importing-and-exporting-rules]]
=== Import and export rules

To import and export rules, use the <<managing-saved-objects, Saved Objects Management UI>>.

[NOTE]
==============================================
Some rule types cannot be exported through this interface:
**Security rules** can be imported and exported using the {security-guide}/rules-ui-management.html#import-export-rules-ui[Security UI].
**Stack monitoring rules** are <<kibana-alerts, automatically created>> for you and therefore cannot be managed via the Saved Objects Management UI.
==============================================

Rules are disabled on export. You are prompted to re-enable rule on successful import.
[role="screenshot"]
image::images/rules-imported-banner.png[Rules import banner, width=50%]

[float]
[[rule-details]]
=== Drilldown to rule details
Expand Down
16 changes: 16 additions & 0 deletions src/core/server/saved_objects/routes/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,22 @@ describe('createSavedObjectsStreamFromNdJson', () => {
},
]);
});

it('handles an ndjson stream that only contains excluded saved objects', async () => {
const savedObjectsStream = await createSavedObjectsStreamFromNdJson(
new Readable({
read() {
this.push(
'{"excludedObjects":[{"id":"foo","reason":"excluded","type":"foo-type"}],"excludedObjectsCount":1,"exportedCount":0,"missingRefCount":0,"missingReferences":[]}\n'
);
this.push(null);
},
})
);

const result = await readStreamToCompletion(savedObjectsStream);
expect(result).toEqual([]);
});
});

describe('validateTypes', () => {
Expand Down
2 changes: 1 addition & 1 deletion src/core/server/saved_objects/routes/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ export async function createSavedObjectsStreamFromNdJson(ndJsonStream: Readable)
}
}),
createFilterStream<SavedObject | SavedObjectsExportResultDetails>(
(obj) => !!obj && !(obj as SavedObjectsExportResultDetails).exportedCount
(obj) => !!obj && (obj as SavedObjectsExportResultDetails).exportedCount === undefined
),
createConcatStream([]),
]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export const alertType: AlertType<
],
defaultActionGroupId: DEFAULT_ACTION_GROUP,
minimumLicenseRequired: 'basic',
isExportable: true,
async executor({
services,
params: { instances = DEFAULT_INSTANCES_TO_GENERATE, thresholds },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export const alertType: AlertType<
name: 'People In Space Right Now',
actionGroups: [{ id: 'default', name: 'default' }],
minimumLicenseRequired: 'basic',
isExportable: true,
defaultActionGroupId: 'default',
recoveryActionGroup: {
id: 'hasLandedBackOnEarth',
Expand Down
2 changes: 2 additions & 0 deletions x-pack/plugins/alerting/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ The following table describes the properties of the `options` object.
|executor|This is where the code for the rule type lives. This is a function to be called when executing a rule on an interval basis. For full details, see the executor section below.|Function|
|producer|The id of the application producing this rule type.|string|
|minimumLicenseRequired|The value of a minimum license. Most of the rules are licensed as "basic".|string|
|isExportable|Whether the rule type is exportable from the Saved Objects Management UI.|boolean|

### Executor

Expand Down Expand Up @@ -262,6 +263,7 @@ const myRuleType: AlertType<
],
},
minimumLicenseRequired: 'basic',
isExportable: true,
async executor({
alertId,
startedAt,
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/alerting/common/alert_type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export interface AlertType<
defaultActionGroupId: ActionGroupIds;
producer: string;
minimumLicenseRequired: LicenseType;
isExportable: boolean;
}

export interface ActionGroup<ActionGroupIds extends string> {
Expand Down
3 changes: 3 additions & 0 deletions x-pack/plugins/alerting/public/alert_api.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ describe('loadAlertTypes', () => {
actionGroups: [{ id: 'default', name: 'Default' }],
defaultActionGroupId: 'default',
minimumLicenseRequired: 'basic',
isExportable: true,
recoveryActionGroup: RecoveredActionGroup,
producer: 'alerts',
},
Expand All @@ -49,6 +50,7 @@ describe('loadAlertType', () => {
actionGroups: [{ id: 'default', name: 'Default' }],
defaultActionGroupId: 'default',
minimumLicenseRequired: 'basic',
isExportable: true,
recoveryActionGroup: RecoveredActionGroup,
producer: 'alerts',
};
Expand All @@ -71,6 +73,7 @@ describe('loadAlertType', () => {
actionGroups: [{ id: 'default', name: 'Default' }],
defaultActionGroupId: 'default',
minimumLicenseRequired: 'basic',
isExportable: true,
recoveryActionGroup: RecoveredActionGroup,
producer: 'alerts',
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const mockAlertType = (id: string): AlertType => ({
defaultActionGroupId: 'default',
producer: 'alerts',
minimumLicenseRequired: 'basic',
isExportable: true,
});

describe('AlertNavigationRegistry', () => {
Expand Down
16 changes: 16 additions & 0 deletions x-pack/plugins/alerting/server/alert_type_registry.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ describe('has()', () => {
],
defaultActionGroupId: 'default',
minimumLicenseRequired: 'basic',
isExportable: true,
executor: jest.fn(),
producer: 'alerts',
});
Expand All @@ -67,6 +68,7 @@ describe('register()', () => {
],
defaultActionGroupId: 'default',
minimumLicenseRequired: 'basic',
isExportable: true,
executor: jest.fn(),
producer: 'alerts',
};
Expand Down Expand Up @@ -99,6 +101,7 @@ describe('register()', () => {
],
defaultActionGroupId: 'default',
minimumLicenseRequired: 'basic',
isExportable: true,
executor: jest.fn(),
producer: 'alerts',
};
Expand Down Expand Up @@ -129,6 +132,7 @@ describe('register()', () => {
],
defaultActionGroupId: 'default',
minimumLicenseRequired: 'basic',
isExportable: true,
executor: jest.fn(),
producer: 'alerts',
};
Expand Down Expand Up @@ -159,6 +163,7 @@ describe('register()', () => {
executor: jest.fn(),
producer: 'alerts',
minimumLicenseRequired: 'basic',
isExportable: true,
};
const registry = new AlertTypeRegistry(alertTypeRegistryParams);
registry.register(alertType);
Expand Down Expand Up @@ -203,6 +208,7 @@ describe('register()', () => {
},
defaultActionGroupId: 'default',
minimumLicenseRequired: 'basic',
isExportable: true,
executor: jest.fn(),
producer: 'alerts',
};
Expand All @@ -227,6 +233,7 @@ describe('register()', () => {
],
defaultActionGroupId: 'default',
minimumLicenseRequired: 'basic',
isExportable: true,
executor: jest.fn(),
producer: 'alerts',
};
Expand Down Expand Up @@ -257,6 +264,7 @@ describe('register()', () => {
],
defaultActionGroupId: 'default',
minimumLicenseRequired: 'basic',
isExportable: true,
executor: jest.fn(),
producer: 'alerts',
};
Expand All @@ -279,6 +287,7 @@ describe('register()', () => {
],
defaultActionGroupId: 'default',
minimumLicenseRequired: 'basic',
isExportable: true,
executor: jest.fn(),
producer: 'alerts',
});
Expand All @@ -294,6 +303,7 @@ describe('register()', () => {
],
defaultActionGroupId: 'default',
minimumLicenseRequired: 'basic',
isExportable: true,
executor: jest.fn(),
producer: 'alerts',
})
Expand All @@ -315,6 +325,7 @@ describe('get()', () => {
],
defaultActionGroupId: 'default',
minimumLicenseRequired: 'basic',
isExportable: true,
executor: jest.fn(),
producer: 'alerts',
});
Expand All @@ -339,6 +350,7 @@ describe('get()', () => {
"defaultActionGroupId": "default",
"executor": [MockFunction],
"id": "test",
"isExportable": true,
"minimumLicenseRequired": "basic",
"name": "Test",
"producer": "alerts",
Expand Down Expand Up @@ -377,6 +389,7 @@ describe('list()', () => {
},
],
defaultActionGroupId: 'testActionGroup',
isExportable: true,
minimumLicenseRequired: 'basic',
executor: jest.fn(),
producer: 'alerts',
Expand All @@ -403,6 +416,7 @@ describe('list()', () => {
"defaultActionGroupId": "testActionGroup",
"enabledInLicense": false,
"id": "test",
"isExportable": true,
"minimumLicenseRequired": "basic",
"name": "Test",
"producer": "alerts",
Expand Down Expand Up @@ -467,6 +481,7 @@ describe('ensureAlertTypeEnabled', () => {
defaultActionGroupId: 'default',
executor: jest.fn(),
producer: 'alerts',
isExportable: true,
minimumLicenseRequired: 'basic',
recoveryActionGroup: { id: 'recovered', name: 'Recovered' },
});
Expand Down Expand Up @@ -497,6 +512,7 @@ function alertTypeWithVariables<ActionGroupIds extends string>(
name: `${id}-name`,
actionGroups: [],
defaultActionGroupId: id,
isExportable: true,
minimumLicenseRequired: 'basic',
async executor() {},
producer: 'alerts',
Expand Down
3 changes: 3 additions & 0 deletions x-pack/plugins/alerting/server/alert_type_registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export interface RegistryAlertType
| 'actionVariables'
| 'producer'
| 'minimumLicenseRequired'
| 'isExportable'
> {
id: string;
enabledInLicense: boolean;
Expand Down Expand Up @@ -250,6 +251,7 @@ export class AlertTypeRegistry {
actionVariables,
producer,
minimumLicenseRequired,
isExportable,
},
]: [string, UntypedNormalizedAlertType]) => ({
id,
Expand All @@ -260,6 +262,7 @@ export class AlertTypeRegistry {
actionVariables,
producer,
minimumLicenseRequired,
isExportable,
enabledInLicense: !!this.licenseState.getLicenseCheckForAlertType(
id,
name,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ describe('aggregate()', () => {
actionVariables: undefined,
defaultActionGroupId: 'default',
minimumLicenseRequired: 'basic',
isExportable: true,
recoveryActionGroup: RecoveredActionGroup,
id: 'myType',
name: 'myType',
Expand Down Expand Up @@ -110,6 +111,7 @@ describe('aggregate()', () => {
actionGroups: [{ id: 'default', name: 'Default' }],
defaultActionGroupId: 'default',
minimumLicenseRequired: 'basic',
isExportable: true,
recoveryActionGroup: RecoveredActionGroup,
producer: 'alerts',
authorizedConsumers: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1293,6 +1293,7 @@ describe('create()', () => {
}),
},
minimumLicenseRequired: 'basic',
isExportable: true,
async executor() {},
producer: 'alerts',
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ describe('find()', () => {
actionVariables: undefined,
defaultActionGroupId: 'default',
minimumLicenseRequired: 'basic',
isExportable: true,
id: 'myType',
name: 'myType',
producer: 'myApp',
Expand Down Expand Up @@ -126,6 +127,7 @@ describe('find()', () => {
recoveryActionGroup: RecoveredActionGroup,
defaultActionGroupId: 'default',
minimumLicenseRequired: 'basic',
isExportable: true,
producer: 'alerts',
authorizedConsumers: {
myApp: { read: true, all: true },
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/alerting/server/alerts_client/tests/lib.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ export function getBeforeSetup(
recoveryActionGroup: RecoveredActionGroup,
defaultActionGroupId: 'default',
minimumLicenseRequired: 'basic',
isExportable: true,
async executor() {},
producer: 'alerts',
}));
Expand Down
Loading

0 comments on commit c05588f

Please sign in to comment.