Skip to content

Commit

Permalink
[Alerting][8.0] Prepare alerting SOs to sharecapable (#110386)
Browse files Browse the repository at this point in the history
* [Alerting] [8.0] Prepare for making alerting saved objects sharecapable (#109990)

* [Alerting] [8.0] Prepare for making alerting saved objects sharecapable

* removed v8 check

* removed link

* added no op migration

* fixed name

Co-authored-by: Kibana Machine <[email protected]>

* [Actions] [8.0] Prepare for making action saved objects sharecapable. (#109756)

* [Actions] [8.0] Prepare for making action saved objects sharecapable.

* added more tests

* made it compatible to merge to 7.x

* fixed due to comments

* fixed tests

* added tests

* fixed tests

* fixed due to comments

* added no-opactions migration

* fixed test

* [Task Manager][8.0] Added migrations to savedObject Ids for "actions:* and "alerting:*" task types (#109180)

* [Task Manager][8.0] Added migrations to savedObject Ids for "actions:* and "alerting:*" task types

* fixed due to comments

* fixed typo

* added more tests

* added unit test

* added func test

* added func tests

* fixed test

Co-authored-by: Kibana Machine <[email protected]>

* fixed merge

* fixed legacy tests

* fixed tests

* fixed eslint

* Update migrations.ts

fixed action task

* fixed due to comments

Co-authored-by: Kibana Machine <[email protected]>
  • Loading branch information
YulNaumenko and kibanamachine authored Aug 31, 2021
1 parent 40b91c9 commit 3e15695
Show file tree
Hide file tree
Showing 17 changed files with 736 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,14 @@ describe('successful migrations', () => {
});
});
});

describe('8.0.0', () => {
test('no op migration for rules SO', () => {
const migration800 = getActionTaskParamsMigrations(encryptedSavedObjectsSetup, [])['8.0.0'];
const actionTaskParam = getMockData();
expect(migration800(actionTaskParam, context)).toEqual(actionTaskParam);
});
});
});

describe('handles errors during migrations', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,17 @@ export function getActionTaskParamsMigrations(
pipeMigrations(getUseSavedObjectReferencesFn(preconfiguredActions))
);

const migrationActionsTaskParams800 = createEsoMigration(
encryptedSavedObjects,
(
doc: SavedObjectUnsanitizedDoc<ActionTaskParams>
): doc is SavedObjectUnsanitizedDoc<ActionTaskParams> => true,
(doc) => doc // no-op
);

return {
'7.16.0': executeMigrationWithErrorHandling(migrationActionTaskParamsSixteen, '7.16.0'),
'8.0.0': executeMigrationWithErrorHandling(migrationActionsTaskParams800, '8.0.0'),
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,14 @@ describe('successful migrations', () => {
});
});
});

describe('8.0.0', () => {
test('no op migration for rules SO', () => {
const migration800 = getActionsMigrations(encryptedSavedObjectsSetup)['8.0.0'];
const action = getMockData({});
expect(migration800(action, context)).toEqual(action);
});
});
});

describe('handles errors during migrations', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,18 @@ export function getActionsMigrations(
pipeMigrations(addisMissingSecretsField)
);

const migrationActions800 = createEsoMigration(
encryptedSavedObjects,
(doc: SavedObjectUnsanitizedDoc<RawAction>): doc is SavedObjectUnsanitizedDoc<RawAction> =>
true,
(doc) => doc // no-op
);

return {
'7.10.0': executeMigrationWithErrorHandling(migrationActionsTen, '7.10.0'),
'7.11.0': executeMigrationWithErrorHandling(migrationActionsEleven, '7.11.0'),
'7.14.0': executeMigrationWithErrorHandling(migrationActionsFourteen, '7.14.0'),
'8.0.0': executeMigrationWithErrorHandling(migrationActions800, '8.0.0'),
};
}

Expand Down
6 changes: 4 additions & 2 deletions x-pack/plugins/actions/server/saved_objects/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ export function setupSavedObjects(
savedObjects.registerType({
name: ACTION_SAVED_OBJECT_TYPE,
hidden: true,
namespaceType: 'single',
namespaceType: 'multiple-isolated',
convertToMultiNamespaceTypeVersion: '8.0.0',
mappings: mappings.action as SavedObjectsTypeMappingDefinition,
migrations: getActionsMigrations(encryptedSavedObjects),
management: {
Expand Down Expand Up @@ -71,7 +72,8 @@ export function setupSavedObjects(
savedObjects.registerType({
name: ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE,
hidden: true,
namespaceType: 'single',
namespaceType: 'multiple-isolated',
convertToMultiNamespaceTypeVersion: '8.0.0',
mappings: mappings.action_task_params as SavedObjectsTypeMappingDefinition,
migrations: getActionTaskParamsMigrations(encryptedSavedObjects, preconfiguredActions),
excludeOnUpgrade: async ({ readonlyEsClient }) => {
Expand Down
3 changes: 2 additions & 1 deletion x-pack/plugins/alerting/server/saved_objects/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,8 @@ export function setupSavedObjects(
savedObjects.registerType({
name: 'alert',
hidden: true,
namespaceType: 'single',
namespaceType: 'multiple-isolated',
convertToMultiNamespaceTypeVersion: '8.0.0',
migrations: getMigrations(encryptedSavedObjects, isPreconfigured),
mappings: mappings.alert as SavedObjectsTypeMappingDefinition,
management: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1700,6 +1700,14 @@ describe('successful migrations', () => {
});
});
});

describe('8.0.0', () => {
test('no op migration for rules SO', () => {
const migration800 = getMigrations(encryptedSavedObjectsSetup, isPreconfigured)['8.0.0'];
const alert = getMockData({}, true);
expect(migration800(alert, migrationContext)).toEqual(alert);
});
});
});

describe('handles errors during migrations', () => {
Expand Down
7 changes: 7 additions & 0 deletions x-pack/plugins/alerting/server/saved_objects/migrations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,12 @@ export function getMigrations(
pipeMigrations(setLegacyId, getRemovePreconfiguredConnectorsFromReferencesFn(isPreconfigured))
);

const migrationRules800 = createEsoMigration(
encryptedSavedObjects,
(doc: SavedObjectUnsanitizedDoc<RawAlert>): doc is SavedObjectUnsanitizedDoc<RawAlert> => true,
(doc) => doc // no-op
);

return {
'7.10.0': executeMigrationWithErrorHandling(migrationWhenRBACWasIntroduced, '7.10.0'),
'7.11.0': executeMigrationWithErrorHandling(migrationAlertUpdatedAtAndNotifyWhen, '7.11.0'),
Expand All @@ -114,6 +120,7 @@ export function getMigrations(
'7.14.1': executeMigrationWithErrorHandling(migrationSecurityRules714, '7.14.1'),
'7.15.0': executeMigrationWithErrorHandling(migrationSecurityRules715, '7.15.0'),
'7.16.0': executeMigrationWithErrorHandling(migrateRules716, '7.16.0'),
'8.0.0': executeMigrationWithErrorHandling(migrationRules800, '8.0.0'),
};
}

Expand Down
4 changes: 2 additions & 2 deletions x-pack/plugins/task_manager/server/saved_objects/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import type { SavedObjectsServiceSetup, SavedObjectsTypeMappingDefinition } from 'kibana/server';
import { estypes } from '@elastic/elasticsearch';
import mappings from './mappings.json';
import { migrations } from './migrations';
import { getMigrations } from './migrations';
import { TaskManagerConfig } from '../config.js';
import { getOldestIdleActionTask } from '../queries/oldest_idle_action_task';

Expand All @@ -22,7 +22,7 @@ export function setupSavedObjects(
hidden: true,
convertToAliasScript: `ctx._id = ctx._source.type + ':' + ctx._id; ctx._source.remove("kibana")`,
mappings: mappings.task as SavedObjectsTypeMappingDefinition,
migrations,
migrations: getMigrations(),
indexPattern: config.index,
excludeOnUpgrade: async ({ readonlyEsClient }) => {
const oldestNeededActionParams = await getOldestIdleActionTask(
Expand Down
169 changes: 169 additions & 0 deletions x-pack/plugins/task_manager/server/saved_objects/migrations.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
/*
* 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 uuid from 'uuid';
import { getMigrations } from './migrations';
import { SavedObjectUnsanitizedDoc } from 'kibana/server';
import { migrationMocks } from 'src/core/server/mocks';
import { TaskInstanceWithDeprecatedFields } from '../task';

const migrationContext = migrationMocks.createContext();

describe('successful migrations', () => {
beforeEach(() => {
jest.resetAllMocks();
});
describe('7.4.0', () => {
test('extend task instance with updated_at', () => {
const migration740 = getMigrations()['7.4.0'];
const taskInstance = getMockData({});
expect(migration740(taskInstance, migrationContext).attributes.updated_at).not.toBeNull();
});
});

describe('7.6.0', () => {
test('rename property Internal to Schedule', () => {
const migration760 = getMigrations()['7.6.0'];
const taskInstance = getMockData({});
expect(migration760(taskInstance, migrationContext)).toEqual({
...taskInstance,
attributes: {
...taskInstance.attributes,
schedule: taskInstance.attributes.schedule,
},
});
});
});

describe('8.0.0', () => {
test('transforms actionsTasksLegacyIdToSavedObjectIds', () => {
const migration800 = getMigrations()['8.0.0'];
const taskInstance = getMockData({
taskType: 'actions:123456',
params: JSON.stringify({ spaceId: 'user1', actionTaskParamsId: '123456' }),
});

expect(migration800(taskInstance, migrationContext)).toEqual({
...taskInstance,
attributes: {
...taskInstance.attributes,
params: '{"spaceId":"user1","actionTaskParamsId":"800f81f8-980e-58ca-b710-d1b0644adea2"}',
},
});
});

test('it is only applicable for saved objects that live in a custom space', () => {
const migration800 = getMigrations()['8.0.0'];
const taskInstance = getMockData({
taskType: 'actions:123456',
params: JSON.stringify({ spaceId: 'default', actionTaskParamsId: '123456' }),
});

expect(migration800(taskInstance, migrationContext)).toEqual(taskInstance);
});

test('it is only applicable for saved objects that live in a custom space even if spaces are disabled', () => {
const migration800 = getMigrations()['8.0.0'];
const taskInstance = getMockData({
taskType: 'actions:123456',
params: JSON.stringify({ actionTaskParamsId: '123456' }),
});

expect(migration800(taskInstance, migrationContext)).toEqual(taskInstance);
});

test('transforms alertingTaskLegacyIdToSavedObjectIds', () => {
const migration800 = getMigrations()['8.0.0'];
const taskInstance = getMockData({
taskType: 'alerting:123456',
params: JSON.stringify({ spaceId: 'user1', alertId: '123456' }),
});

expect(migration800(taskInstance, migrationContext)).toEqual({
...taskInstance,
attributes: {
...taskInstance.attributes,
params: '{"spaceId":"user1","alertId":"1a4f9206-e25f-58e6-bad5-3ff21e90648e"}',
},
});
});

test('skip transformation for defult space scenario', () => {
const migration800 = getMigrations()['8.0.0'];
const taskInstance = getMockData({
taskType: 'alerting:123456',
params: JSON.stringify({ spaceId: 'default', alertId: '123456' }),
});

expect(migration800(taskInstance, migrationContext)).toEqual({
...taskInstance,
attributes: {
...taskInstance.attributes,
params: '{"spaceId":"default","alertId":"123456"}',
},
});
});
});
});

describe('handles errors during migrations', () => {
describe('8.0.0 throws if migration fails', () => {
test('should throw the exception if task instance params format is wrong', () => {
const migration800 = getMigrations()['8.0.0'];
const taskInstance = getMockData({
taskType: 'alerting:123456',
params: `{ spaceId: 'user1', customId: '123456' }`,
});
expect(() => {
migration800(taskInstance, migrationContext);
}).toThrowError();
expect(migrationContext.log.error).toHaveBeenCalledWith(
`savedObject 8.0.0 migration failed for task instance ${taskInstance.id} with error: Unexpected token s in JSON at position 2`,
{
migrations: {
taskInstanceDocument: {
...taskInstance,
attributes: {
...taskInstance.attributes,
},
},
},
}
);
});
});
});

function getUpdatedAt(): string {
const updatedAt = new Date();
updatedAt.setHours(updatedAt.getHours() + 2);
return updatedAt.toISOString();
}

function getMockData(
overwrites: Record<string, unknown> = {}
): SavedObjectUnsanitizedDoc<Partial<TaskInstanceWithDeprecatedFields>> {
return {
attributes: {
scheduledAt: new Date(),
state: { runs: 0, total_cleaned_up: 0 },
runAt: new Date(),
startedAt: new Date(),
retryAt: new Date(),
ownerId: '234',
taskType: 'foo',
schedule: { interval: '10s' },
params: {
bar: true,
},
...overwrites,
},
updated_at: getUpdatedAt(),
id: uuid.v4(),
type: 'task',
};
}
Loading

0 comments on commit 3e15695

Please sign in to comment.