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

[Alerting][8.0] Prepare alerting SOs to sharecapable #110386

Merged
merged 12 commits into from
Aug 31, 2021
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 Expand Up @@ -402,7 +410,8 @@ describe('isPreconfiguredAction()', () => {

function getMockData(
overwrites: Record<string, unknown> = {},
referencesOverwrites: SavedObjectReference[] = []
referencesOverwrites: SavedObjectReference[] = [],
namespaces: string[] = ['default']
YulNaumenko marked this conversation as resolved.
Show resolved Hide resolved
): SavedObjectUnsanitizedDoc<ActionTaskParams> {
return {
attributes: {
Expand All @@ -412,6 +421,7 @@ function getMockData(
},
references: [...referencesOverwrites],
id: uuid.v4(),
namespaces,
type: 'action_task_param',
};
}
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',
};
}