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 <42973632+kibanamachine@users.noreply.github.com>

* [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 <42973632+kibanamachine@users.noreply.github.com>

* fixed merge

* fixed legacy tests

* fixed tests

* fixed eslint

* Update migrations.ts

fixed action task

* fixed due to comments

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
  • Loading branch information
YulNaumenko and kibanamachine committed Aug 31, 2021
1 parent 40b91c9 commit 3e15695
Show file tree
Hide file tree
Showing 17 changed files with 736 additions and 20 deletions.
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
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
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
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
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
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
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
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
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
@@ -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',
};
}

0 comments on commit 3e15695

Please sign in to comment.