Skip to content

Commit

Permalink
Adding migration utility tests and some clean up
Browse files Browse the repository at this point in the history
  • Loading branch information
jonathan-buttner committed Jul 30, 2021
1 parent 3be7768 commit d418f91
Show file tree
Hide file tree
Showing 6 changed files with 215 additions and 37 deletions.
4 changes: 0 additions & 4 deletions x-pack/plugins/cases/common/api/cases/case.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,6 @@ const CaseBasicRt = rt.type({
owner: rt.string,
});

/**
* The external service fields. Exporting here for use in the service transformation code so I can define
* a type without the connector_id field.
*/
export const CaseExternalServiceBasicRt = rt.type({
connector_id: rt.union([rt.string, rt.null]),
connector_name: rt.string,
Expand Down
5 changes: 3 additions & 2 deletions x-pack/plugins/cases/server/client/configure/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ async function update(
let error = null;
const updateDate = new Date().toISOString();
let mappings: ConnectorMappingsAttributes[] = [];
const { connector } = queryWithoutVersion;
const { connector, ...queryWithoutVersionAndConnector } = queryWithoutVersion;

try {
const resMappings = await casesClientInternal.configuration.getMappings({
Expand Down Expand Up @@ -318,7 +318,8 @@ async function update(
unsecuredSavedObjectsClient,
configurationId: configuration.id,
updatedAttributes: {
...queryWithoutVersion,
...queryWithoutVersionAndConnector,
...(connector && { connector }),
updated_at: updateDate,
updated_by: user,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,12 @@ import { SavedObjectSanitizedDoc } from 'kibana/server';
import {
CaseAttributes,
CaseFullExternalService,
CaseStatuses,
CaseType,
CASE_SAVED_OBJECT,
ConnectorTypes,
SECURITY_SOLUTION_OWNER,
noneConnectorId,
} from '../../../common';
import { getNoneCaseConnector } from '../../common';
import { ESCaseConnectorWithId } from '../../services/test_utils';
import { createExternalService, ESCaseConnectorWithId } from '../../services/test_utils';
import { caseConnectorIdMigration } from './cases';

// eslint-disable-next-line @typescript-eslint/naming-convention
Expand All @@ -29,29 +27,6 @@ const create_7_14_0_case = ({
attributes: {
connector,
external_service: externalService,
closed_at: null,
closed_by: null,
created_at: '2019-11-25T21:54:48.952Z',
created_by: {
full_name: 'elastic',
email: 'testemail@elastic.co',
username: 'elastic',
},
description: 'This is a brand new case of a bad meanie defacing data',
title: 'Super Bad Security Issue',
status: CaseStatuses.open,
tags: ['defacement'],
type: CaseType.individual,
updated_at: '2019-11-25T21:54:48.952Z',
updated_by: {
full_name: 'elastic',
email: 'testemail@elastic.co',
username: 'elastic',
},
settings: {
syncAlerts: true,
},
owner: SECURITY_SOLUTION_OWNER,
},
});

Expand Down Expand Up @@ -138,6 +113,32 @@ describe('7.15.0 connector ID migration', () => {
expect(migratedConnector.attributes).not.toHaveProperty('external_service');
});

it('does not create a reference when the external_service.connector_id is none', () => {
const caseSavedObject = create_7_14_0_case({
externalService: createExternalService({ connector_id: noneConnectorId }),
});

const migratedConnector = caseConnectorIdMigration(
caseSavedObject
) as SavedObjectSanitizedDoc<CaseAttributes>;

expect(migratedConnector.references.length).toBe(0);
expect(migratedConnector.attributes.external_service).toMatchInlineSnapshot(`
Object {
"connector_name": ".jira",
"external_id": "100",
"external_title": "awesome",
"external_url": "http://www.google.com",
"pushed_at": "2019-11-25T21:54:48.952Z",
"pushed_by": Object {
"email": "testemail@elastic.co",
"full_name": "elastic",
"username": "elastic",
},
}
`);
});

it('preserves the existing references when migrating', () => {
const caseSavedObject = {
...create_7_14_0_case(),
Expand Down Expand Up @@ -280,4 +281,71 @@ describe('7.15.0 connector ID migration', () => {
}
`);
});

it('migrates both connector and external_service when provided', () => {
const caseSavedObject = create_7_14_0_case({
externalService: {
connector_id: '100',
connector_name: '.jira',
external_id: '100',
external_title: 'awesome',
external_url: 'http://www.google.com',
pushed_at: '2019-11-25T21:54:48.952Z',
pushed_by: {
full_name: 'elastic',
email: 'testemail@elastic.co',
username: 'elastic',
},
},
connector: {
id: '123',
fields: null,
name: 'connector',
type: ConnectorTypes.jira,
},
});

const migratedConnector = caseConnectorIdMigration(
caseSavedObject
) as SavedObjectSanitizedDoc<CaseAttributes>;

expect(migratedConnector.references.length).toBe(2);
expect(migratedConnector.attributes.external_service).not.toHaveProperty('connector_id');
expect(migratedConnector.attributes.external_service).toMatchInlineSnapshot(`
Object {
"connector_name": ".jira",
"external_id": "100",
"external_title": "awesome",
"external_url": "http://www.google.com",
"pushed_at": "2019-11-25T21:54:48.952Z",
"pushed_by": Object {
"email": "testemail@elastic.co",
"full_name": "elastic",
"username": "elastic",
},
}
`);
expect(migratedConnector.attributes.connector).not.toHaveProperty('id');
expect(migratedConnector.attributes.connector).toMatchInlineSnapshot(`
Object {
"fields": null,
"name": "connector",
"type": ".jira",
}
`);
expect(migratedConnector.references).toMatchInlineSnapshot(`
Array [
Object {
"id": "123",
"name": "connectorId",
"type": "action",
},
Object {
"id": "100",
"name": "pushConnectorId",
"type": "action",
},
]
`);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
} from '../../../../../../src/core/server';
import { ACTION_SAVED_OBJECT_TYPE } from '../../../../actions/server';
import { ESConnectorFields, pushConnectorIdReferenceName } from '../../services';
import { ConnectorTypes, CaseType } from '../../../common';
import { ConnectorTypes, CaseType, noneConnectorId } from '../../../common';
import { transformConnectorIdToReference } from './utils';

interface UnsanitizedCaseConnector {
Expand Down Expand Up @@ -52,7 +52,7 @@ const transformPushConnectorIdToReference = (
const { connector_id: pushConnectorId, ...restExternalService } = external_service ?? {};

const references =
pushConnectorId && pushConnectorId !== 'none'
pushConnectorId && pushConnectorId !== noneConnectorId
? [
{
id: pushConnectorId,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/*
* 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 { noneConnectorId } from '../../../common';
import { createJiraConnector } from '../../services/test_utils';
import { transformConnectorIdToReference } from './utils';

describe('migration utils', () => {
describe('transformConnectorIdToReference', () => {
it('returns the default none connector when the connector is undefined', () => {
expect(transformConnectorIdToReference().transformedConnector).toMatchInlineSnapshot(`
Object {
"connector": Object {
"fields": null,
"name": "none",
"type": ".none",
},
}
`);
});

it('returns the default none connector when the id is undefined', () => {
expect(transformConnectorIdToReference({ id: undefined }).transformedConnector)
.toMatchInlineSnapshot(`
Object {
"connector": Object {
"fields": null,
"name": "none",
"type": ".none",
},
}
`);
});

it('returns the default none connector when the id is none', () => {
expect(transformConnectorIdToReference({ id: noneConnectorId }).transformedConnector)
.toMatchInlineSnapshot(`
Object {
"connector": Object {
"fields": null,
"name": "none",
"type": ".none",
},
}
`);
});

it('returns the default none connector when the id is none and other fields are defined', () => {
expect(
transformConnectorIdToReference({ ...createJiraConnector(), id: noneConnectorId })
.transformedConnector
).toMatchInlineSnapshot(`
Object {
"connector": Object {
"fields": null,
"name": "none",
"type": ".none",
},
}
`);
});

it('returns an empty array of references when the connector is undefined', () => {
expect(transformConnectorIdToReference().references.length).toBe(0);
});

it('returns an empty array of references when the id is undefined', () => {
expect(transformConnectorIdToReference({ id: undefined }).references.length).toBe(0);
});

it('returns an empty array of references when the id is the none connector', () => {
expect(transformConnectorIdToReference({ id: noneConnectorId }).references.length).toBe(0);
});

it('returns an empty array of references when the id is the none connector and other fields are defined', () => {
expect(
transformConnectorIdToReference({ ...createJiraConnector(), id: noneConnectorId })
.references.length
).toBe(0);
});

it('returns a jira connector', () => {
const transformedFields = transformConnectorIdToReference(createJiraConnector());
expect(transformedFields.transformedConnector).toMatchInlineSnapshot(`
Object {
"connector": Object {
"fields": Object {
"issueType": "bug",
"parent": "2",
"priority": "high",
},
"name": ".jira",
"type": ".jira",
},
}
`);
expect(transformedFields.references).toMatchInlineSnapshot(`
Array [
Object {
"id": "1",
"name": "connectorId",
"type": "action",
},
]
`);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* 2.0.
*/

import { noneConnectorId } from '../../../common';
import { SavedObjectReference } from '../../../../../../src/core/server';
import { ACTION_SAVED_OBJECT_TYPE } from '../../../../actions/server';
import { getNoneCaseConnector } from '../../common';
Expand All @@ -16,7 +17,7 @@ export const transformConnectorIdToReference = (connector?: {
const { id: connectorId, ...restConnector } = connector ?? {};

const references =
connectorId && connectorId !== 'none'
connectorId && connectorId !== noneConnectorId
? [
{
id: connectorId,
Expand All @@ -29,7 +30,7 @@ export const transformConnectorIdToReference = (connector?: {

const { id: ignoreNoneId, ...restNoneConnector } = getNoneCaseConnector();
let transformedConnector: object = { connector: restNoneConnector };
if (connector && connectorId) {
if (connector && connectorId && references.length > 0) {
transformedConnector = { connector: { ...restConnector } };
}

Expand Down

0 comments on commit d418f91

Please sign in to comment.