[Actions] Migrate cases configuration object (#77998)

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
Co-authored-by: Gidi Meir Morris <github@gidi.io>
This commit is contained in:
Christos Nasikas 2020-09-29 21:10:57 +03:00 committed by GitHub
parent 0329f9252e
commit 4f6df624e9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 2780 additions and 21 deletions

View file

@ -5,8 +5,9 @@
*/
import { SavedObjectsServiceSetup } from 'kibana/server';
import mappings from './mappings.json';
import { EncryptedSavedObjectsPluginSetup } from '../../../encrypted_saved_objects/server';
import mappings from './mappings.json';
import { getMigrations } from './migrations';
export const ACTION_SAVED_OBJECT_TYPE = 'action';
export const ALERT_SAVED_OBJECT_TYPE = 'alert';
@ -21,6 +22,7 @@ export function setupSavedObjects(
hidden: true,
namespaceType: 'single',
mappings: mappings.action,
migrations: getMigrations(encryptedSavedObjects),
});
// Encrypted attributes

View file

@ -0,0 +1,53 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import uuid from 'uuid';
import { getMigrations } from './migrations';
import { RawAction } from '../types';
import { SavedObjectUnsanitizedDoc } from 'kibana/server';
import { encryptedSavedObjectsMock } from '../../../encrypted_saved_objects/server/mocks';
import { migrationMocks } from 'src/core/server/mocks';
const context = migrationMocks.createContext();
const encryptedSavedObjectsSetup = encryptedSavedObjectsMock.createSetup();
describe('7.10.0', () => {
beforeEach(() => {
jest.resetAllMocks();
encryptedSavedObjectsSetup.createMigration.mockImplementation(
(shouldMigrateWhenPredicate, migration) => migration
);
});
test('rename cases configuration object', () => {
const migration710 = getMigrations(encryptedSavedObjectsSetup)['7.10.0'];
const action = getMockData({});
expect(migration710(action, context)).toMatchObject({
...action,
attributes: {
...action.attributes,
config: {
incidentConfiguration: { mapping: [] },
},
},
});
});
});
function getMockData(
overwrites: Record<string, unknown> = {}
): SavedObjectUnsanitizedDoc<RawAction> {
return {
attributes: {
name: 'abc',
actionTypeId: '123',
config: { casesConfiguration: { mapping: [] } },
secrets: {},
...overwrites,
},
id: uuid.v4(),
type: 'action',
};
}

View file

@ -0,0 +1,42 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import {
SavedObjectMigrationMap,
SavedObjectUnsanitizedDoc,
SavedObjectMigrationFn,
} from '../../../../../src/core/server';
import { RawAction } from '../types';
import { EncryptedSavedObjectsPluginSetup } from '../../../encrypted_saved_objects/server';
export function getMigrations(
encryptedSavedObjects: EncryptedSavedObjectsPluginSetup
): SavedObjectMigrationMap {
return { '7.10.0': renameCasesConfigurationObject(encryptedSavedObjects) };
}
const renameCasesConfigurationObject = (
encryptedSavedObjects: EncryptedSavedObjectsPluginSetup
): SavedObjectMigrationFn<RawAction, RawAction> => {
return encryptedSavedObjects.createMigration<RawAction, RawAction>(
(doc): doc is SavedObjectUnsanitizedDoc<RawAction> =>
!!doc.attributes.config?.casesConfiguration,
(doc: SavedObjectUnsanitizedDoc<RawAction>): SavedObjectUnsanitizedDoc<RawAction> => {
const { casesConfiguration, ...restConfiguration } = doc.attributes.config;
return {
...doc,
attributes: {
...doc.attributes,
config: {
...restConfiguration,
incidentConfiguration: casesConfiguration,
},
},
};
}
);
};

View file

@ -5,10 +5,14 @@
*/
import { FtrProviderContext } from '../../../common/ftr_provider_context';
import { buildUp, tearDown } from '..';
// eslint-disable-next-line import/no-default-export
export default function actionsTests({ loadTestFile }: FtrProviderContext) {
export default function actionsTests({ loadTestFile, getService }: FtrProviderContext) {
describe('Actions', () => {
before(async () => buildUp(getService));
after(async () => tearDown(getService));
loadTestFile(require.resolve('./create'));
loadTestFile(require.resolve('./delete'));
loadTestFile(require.resolve('./get_all'));
@ -19,5 +23,8 @@ export default function actionsTests({ loadTestFile }: FtrProviderContext) {
loadTestFile(require.resolve('./builtin_action_types/es_index'));
loadTestFile(require.resolve('./builtin_action_types/webhook'));
loadTestFile(require.resolve('./type_not_enabled'));
// note that this test will destroy existing spaces
loadTestFile(require.resolve('./migrations'));
});
}

View file

@ -0,0 +1,54 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import expect from '@kbn/expect';
import { getUrlPrefix } from '../../../common/lib';
import { FtrProviderContext } from '../../../common/ftr_provider_context';
// eslint-disable-next-line import/no-default-export
export default function createGetTests({ getService }: FtrProviderContext) {
const supertest = getService('supertest');
const esArchiver = getService('esArchiver');
describe('migrations', () => {
before(async () => {
await esArchiver.load('actions');
});
after(async () => {
await esArchiver.unload('actions');
});
it('7.10.0 migrates the `casesConfiguration` to be the `incidentConfiguration` in `config`', async () => {
const response = await supertest.get(
`${getUrlPrefix(``)}/api/actions/action/791a2ab1-784a-46ea-aa68-04c837e5da2d`
);
expect(response.status).to.eql(200);
expect(response.body.config).key('incidentConfiguration');
expect(response.body.config).not.key('casesConfiguration');
expect(response.body.config.incidentConfiguration).to.eql({
mapping: [
{
actionType: 'overwrite',
source: 'title',
target: 'summary',
},
{
actionType: 'overwrite',
source: 'description',
target: 'description',
},
{
actionType: 'append',
source: 'comments',
target: 'comments',
},
],
});
});
});
}

View file

@ -5,10 +5,14 @@
*/
import { FtrProviderContext } from '../../../common/ftr_provider_context';
import { buildUp, tearDown } from '..';
// eslint-disable-next-line import/no-default-export
export default function alertingTests({ loadTestFile }: FtrProviderContext) {
export default function alertingTests({ loadTestFile, getService }: FtrProviderContext) {
describe('Alerting', () => {
before(async () => buildUp(getService));
after(async () => tearDown(getService));
loadTestFile(require.resolve('./create'));
loadTestFile(require.resolve('./delete'));
loadTestFile(require.resolve('./disable'));

View file

@ -8,28 +8,26 @@ import { FtrProviderContext } from '../../common/ftr_provider_context';
import { Spaces } from '../scenarios';
// eslint-disable-next-line import/no-default-export
export default function alertingApiIntegrationTests({
loadTestFile,
getService,
}: FtrProviderContext) {
const spacesService = getService('spaces');
const esArchiver = getService('esArchiver');
export default function alertingApiIntegrationTests({ loadTestFile }: FtrProviderContext) {
describe('alerting api integration spaces only', function () {
this.tags('ciGroup9');
before(async () => {
for (const space of Object.values(Spaces)) {
if (space.id === 'default') continue;
const { id, name, disabledFeatures } = space;
await spacesService.create({ id, name, disabledFeatures });
}
});
after(async () => await esArchiver.unload('empty_kibana'));
loadTestFile(require.resolve('./actions'));
loadTestFile(require.resolve('./alerting'));
});
}
export async function buildUp(getService: FtrProviderContext['getService']) {
const spacesService = getService('spaces');
for (const space of Object.values(Spaces)) {
if (space.id === 'default') continue;
const { id, name, disabledFeatures } = space;
await spacesService.create({ id, name, disabledFeatures });
}
}
export async function tearDown(getService: FtrProviderContext['getService']) {
const esArchiver = getService('esArchiver');
await esArchiver.unload('empty_kibana');
}

View file

@ -13,3 +13,46 @@
}
}
}
{
"type": "doc",
"value": {
"id": "action:791a2ab1-784a-46ea-aa68-04c837e5da2d",
"index": ".kibana_1",
"source": {
"action": {
"actionTypeId": ".jira",
"config": {
"apiUrl": "http://elastic:changeme@localhost:5620/api/_actions-FTS-external-service-simulators/jira",
"casesConfiguration": {
"mapping": [
{
"actionType": "overwrite",
"source": "title",
"target": "summary"
},
{
"actionType": "overwrite",
"source": "description",
"target": "description"
},
{
"actionType": "append",
"source": "comments",
"target": "comments"
}
]
},
"projectKey": "CK"
},
"name": "A jira action",
"secrets": "gUYVHxyvkY6I6rZrST16PzSBjwuPLzWYIm9Ow6qjJXiCimA1wHGgH1BR5nO/xZJjv9QqIGO3eKDSYsn7K9m39UJv83+oi5P4ZgtFktsFq0Jv6XEFQPFkuVY5sWno7w89CxgxlsTQFpYAJb0Hl0qf/6p6bKKaje48YRqNS5roebNAAribh9AWu80uxIJFWNo="
},
"references": [
],
"type": "action",
"updated_at": "2020-09-24T08:08:23.715Z"
},
"type": "_doc"
}
}

File diff suppressed because it is too large Load diff