[Connectors][ServiceNow] Rename isLegacy configuration property (#115028)

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Christos Nasikas 2021-10-25 20:13:47 +03:00 committed by GitHub
parent 59815a0681
commit 62e203818f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
34 changed files with 168 additions and 154 deletions

View file

@ -132,7 +132,7 @@ describe('api_sir', () => {
});
describe('prepareParams', () => {
test('it prepares the params correctly when the connector is legacy', async () => {
test('it prepares the params correctly when the connector uses the old API', async () => {
expect(prepareParams(true, sirParams)).toEqual({
...sirParams,
incident: {
@ -145,7 +145,7 @@ describe('api_sir', () => {
});
});
test('it prepares the params correctly when the connector is not legacy', async () => {
test('it prepares the params correctly when the connector does not uses the old API', async () => {
expect(prepareParams(false, sirParams)).toEqual({
...sirParams,
incident: {
@ -158,7 +158,7 @@ describe('api_sir', () => {
});
});
test('it prepares the params correctly when the connector is legacy and the observables are undefined', async () => {
test('it prepares the params correctly when the connector uses the old API and the observables are undefined', async () => {
const {
dest_ip: destIp,
source_ip: sourceIp,
@ -192,7 +192,7 @@ describe('api_sir', () => {
const res = await apiSIR.pushToService({
externalService,
params,
config: { isLegacy: false },
config: { usesTableApi: false },
secrets: {},
logger: mockedLogger,
commentFieldKey: 'work_notes',
@ -221,7 +221,7 @@ describe('api_sir', () => {
await apiSIR.pushToService({
externalService,
params,
config: { isLegacy: false },
config: { usesTableApi: false },
secrets: {},
logger: mockedLogger,
commentFieldKey: 'work_notes',
@ -244,12 +244,12 @@ describe('api_sir', () => {
);
});
test('it does not call bulkAddObservableToIncident if it a legacy connector', async () => {
test('it does not call bulkAddObservableToIncident if the connector uses the old API', async () => {
const params = { ...sirParams, incident: { ...sirParams.incident, externalId: null } };
await apiSIR.pushToService({
externalService,
params,
config: { isLegacy: true },
config: { usesTableApi: true },
secrets: {},
logger: mockedLogger,
commentFieldKey: 'work_notes',
@ -274,7 +274,7 @@ describe('api_sir', () => {
await apiSIR.pushToService({
externalService,
params,
config: { isLegacy: false },
config: { usesTableApi: false },
secrets: {},
logger: mockedLogger,
commentFieldKey: 'work_notes',

View file

@ -59,13 +59,13 @@ const observablesToString = (obs: string | string[] | null | undefined): string
};
export const prepareParams = (
isLegacy: boolean,
usesTableApi: boolean,
params: PushToServiceApiParamsSIR
): PushToServiceApiParamsSIR => {
if (isLegacy) {
if (usesTableApi) {
/**
* The schema has change to accept an array of observables
* or a string. In the case of a legacy connector we need to
* or a string. In the case of connector that uses the old API we need to
* convert the observables to a string
*/
return {
@ -81,8 +81,8 @@ export const prepareParams = (
}
/**
* For non legacy connectors the observables
* will be added in a different call.
* For connectors that do not use the old API
* the observables will be added in a different call.
* They need to be set to null when sending the fields
* to ServiceNow
*/
@ -108,7 +108,7 @@ const pushToServiceHandler = async ({
}: PushToServiceApiHandlerArgs): Promise<PushToServiceResponse> => {
const res = await api.pushToService({
externalService,
params: prepareParams(!!config.isLegacy, params as PushToServiceApiParamsSIR),
params: prepareParams(!!config.usesTableApi, params as PushToServiceApiParamsSIR),
config,
secrets,
commentFieldKey,
@ -130,7 +130,7 @@ const pushToServiceHandler = async ({
* through the pushToService call.
*/
if (!config.isLegacy) {
if (!config.usesTableApi) {
const sirExternalService = externalService as ExternalServiceSIR;
const obsWithType: Array<[string[], ObservableTypes]> = [

View file

@ -14,7 +14,7 @@ export const ExternalIncidentServiceConfigurationBase = {
export const ExternalIncidentServiceConfiguration = {
...ExternalIncidentServiceConfigurationBase,
isLegacy: schema.boolean({ defaultValue: true }),
usesTableApi: schema.boolean({ defaultValue: true }),
};
export const ExternalIncidentServiceConfigurationBaseSchema = schema.object(
@ -49,7 +49,7 @@ const CommonAttributes = {
externalId: schema.nullable(schema.string()),
category: schema.nullable(schema.string()),
subcategory: schema.nullable(schema.string()),
correlation_id: schema.nullable(schema.string()),
correlation_id: schema.nullable(schema.string({ defaultValue: DEFAULT_ALERTS_GROUPING_KEY })),
correlation_display: schema.nullable(schema.string()),
};

View file

@ -35,7 +35,8 @@ export const createExternalService: ServiceFactory = (
configurationUtilities: ActionsConfigurationUtilities,
{ table, importSetTable, useImportAPI, appScope }: SNProductsConfigValue
): ExternalService => {
const { apiUrl: url, isLegacy } = config as ServiceNowPublicConfigurationType;
const { apiUrl: url, usesTableApi: usesTableApiConfigValue } =
config as ServiceNowPublicConfigurationType;
const { username, password } = secrets as ServiceNowSecretConfigurationType;
if (!url || !username || !password) {
@ -57,11 +58,11 @@ export const createExternalService: ServiceFactory = (
auth: { username, password },
});
const useOldApi = !useImportAPI || isLegacy;
const useTableApi = !useImportAPI || usesTableApiConfigValue;
const getCreateIncidentUrl = () => (useOldApi ? tableApiIncidentUrl : importSetTableUrl);
const getCreateIncidentUrl = () => (useTableApi ? tableApiIncidentUrl : importSetTableUrl);
const getUpdateIncidentUrl = (incidentId: string) =>
useOldApi ? `${tableApiIncidentUrl}/${incidentId}` : importSetTableUrl;
useTableApi ? `${tableApiIncidentUrl}/${incidentId}` : importSetTableUrl;
const getIncidentViewURL = (id: string) => {
// Based on: https://docs.servicenow.com/bundle/orlando-platform-user-interface/page/use/navigation/reference/r_NavigatingByURLExamples.html
@ -105,7 +106,7 @@ export const createExternalService: ServiceFactory = (
/**
* Gets the Elastic SN Application information including the current version.
* It should not be used on legacy connectors.
* It should not be used on connectors that use the old API.
*/
const getApplicationInformation = async (): Promise<GetApplicationInfoResponse> => {
try {
@ -129,7 +130,7 @@ export const createExternalService: ServiceFactory = (
logger.debug(`Create incident: Application scope: ${scope}: Application version${version}`);
const checkIfApplicationIsInstalled = async () => {
if (!useOldApi) {
if (!useTableApi) {
const { version, scope } = await getApplicationInformation();
logApplicationInfo(scope, version);
}
@ -180,17 +181,17 @@ export const createExternalService: ServiceFactory = (
url: getCreateIncidentUrl(),
logger,
method: 'post',
data: prepareIncident(useOldApi, incident),
data: prepareIncident(useTableApi, incident),
configurationUtilities,
});
checkInstance(res);
if (!useOldApi) {
if (!useTableApi) {
throwIfImportSetApiResponseIsAnError(res.data);
}
const incidentId = useOldApi ? res.data.result.sys_id : res.data.result[0].sys_id;
const incidentId = useTableApi ? res.data.result.sys_id : res.data.result[0].sys_id;
const insertedIncident = await getIncident(incidentId);
return {
@ -212,23 +213,23 @@ export const createExternalService: ServiceFactory = (
axios: axiosInstance,
url: getUpdateIncidentUrl(incidentId),
// Import Set API supports only POST.
method: useOldApi ? 'patch' : 'post',
method: useTableApi ? 'patch' : 'post',
logger,
data: {
...prepareIncident(useOldApi, incident),
...prepareIncident(useTableApi, incident),
// elastic_incident_id is used to update the incident when using the Import Set API.
...(useOldApi ? {} : { elastic_incident_id: incidentId }),
...(useTableApi ? {} : { elastic_incident_id: incidentId }),
},
configurationUtilities,
});
checkInstance(res);
if (!useOldApi) {
if (!useTableApi) {
throwIfImportSetApiResponseIsAnError(res.data);
}
const id = useOldApi ? res.data.result.sys_id : res.data.result[0].sys_id;
const id = useTableApi ? res.data.result.sys_id : res.data.result[0].sys_id;
const updatedIncident = await getIncident(id);
return {

View file

@ -166,7 +166,7 @@ describe('successful migrations', () => {
expect(migratedAction).toEqual(action);
});
test('set isLegacy config property for .servicenow', () => {
test('set usesTableApi config property for .servicenow', () => {
const migration716 = getActionsMigrations(encryptedSavedObjectsSetup)['7.16.0'];
const action = getMockDataForServiceNow();
const migratedAction = migration716(action, context);
@ -177,13 +177,13 @@ describe('successful migrations', () => {
...action.attributes,
config: {
apiUrl: 'https://example.com',
isLegacy: true,
usesTableApi: true,
},
},
});
});
test('set isLegacy config property for .servicenow-sir', () => {
test('set usesTableApi config property for .servicenow-sir', () => {
const migration716 = getActionsMigrations(encryptedSavedObjectsSetup)['7.16.0'];
const action = getMockDataForServiceNow({ actionTypeId: '.servicenow-sir' });
const migratedAction = migration716(action, context);
@ -194,13 +194,13 @@ describe('successful migrations', () => {
...action.attributes,
config: {
apiUrl: 'https://example.com',
isLegacy: true,
usesTableApi: true,
},
},
});
});
test('it does not set isLegacy config for other connectors', () => {
test('it does not set usesTableApi config for other connectors', () => {
const migration716 = getActionsMigrations(encryptedSavedObjectsSetup)['7.16.0'];
const action = getMockData();
const migratedAction = migration716(action, context);

View file

@ -68,7 +68,7 @@ export function getActionsMigrations(
doc.attributes.actionTypeId === '.servicenow' ||
doc.attributes.actionTypeId === '.servicenow-sir' ||
doc.attributes.actionTypeId === '.email',
pipeMigrations(markOldServiceNowITSMConnectorAsLegacy, setServiceConfigIfNotSet)
pipeMigrations(addUsesTableApiToServiceNowConnectors, setServiceConfigIfNotSet)
);
const migrationActions800 = createEsoMigration(
@ -197,7 +197,7 @@ const addIsMissingSecretsField = (
};
};
const markOldServiceNowITSMConnectorAsLegacy = (
const addUsesTableApiToServiceNowConnectors = (
doc: SavedObjectUnsanitizedDoc<RawAction>
): SavedObjectUnsanitizedDoc<RawAction> => {
if (
@ -213,7 +213,7 @@ const markOldServiceNowITSMConnectorAsLegacy = (
...doc.attributes,
config: {
...doc.attributes.config,
isLegacy: true,
usesTableApi: true,
},
},
};

View file

@ -123,11 +123,11 @@ describe('Connectors', () => {
).toBe('Update My Connector');
});
test('it shows the deprecated callout when the connector is legacy', async () => {
test('it shows the deprecated callout when the connector is deprecated', async () => {
render(
<Connectors
{...props}
selectedConnector={{ id: 'servicenow-legacy', type: ConnectorTypes.serviceNowITSM }}
selectedConnector={{ id: 'servicenow-uses-table-api', type: ConnectorTypes.serviceNowITSM }}
/>,
{
// wrapper: TestProviders produces a TS error

View file

@ -23,7 +23,7 @@ import { ActionConnector, CaseConnectorMapping } from '../../containers/configur
import { Mapping } from './mapping';
import { ActionTypeConnector, ConnectorTypes } from '../../../common';
import { DeprecatedCallout } from '../connectors/deprecated_callout';
import { isLegacyConnector } from '../utils';
import { isDeprecatedConnector } from '../utils';
const EuiFormRowExtended = styled(EuiFormRow)`
.euiFormRow__labelWrapper {
@ -111,7 +111,7 @@ const ConnectorsComponent: React.FC<Props> = ({
appendAddConnectorButton={true}
/>
</EuiFlexItem>
{selectedConnector.type !== ConnectorTypes.none && isLegacyConnector(connector) && (
{selectedConnector.type !== ConnectorTypes.none && isDeprecatedConnector(connector) && (
<EuiFlexItem grow={false}>
<DeprecatedCallout />
</EuiFlexItem>

View file

@ -171,7 +171,7 @@ describe('ConnectorsDropdown', () => {
"value": "servicenow-sir",
},
Object {
"data-test-subj": "dropdown-connector-servicenow-legacy",
"data-test-subj": "dropdown-connector-servicenow-uses-table-api",
"inputDisplay": <EuiFlexGroup
alignItems="center"
gutterSize="s"
@ -205,7 +205,7 @@ describe('ConnectorsDropdown', () => {
/>
</EuiFlexItem>
</EuiFlexGroup>,
"value": "servicenow-legacy",
"value": "servicenow-uses-table-api",
},
]
`);
@ -288,8 +288,8 @@ describe('ConnectorsDropdown', () => {
).not.toThrowError();
});
test('it shows the deprecated tooltip when the connector is legacy', () => {
render(<ConnectorsDropdown {...props} selectedConnector="servicenow-legacy" />, {
test('it shows the deprecated tooltip when the connector is deprecated', () => {
render(<ConnectorsDropdown {...props} selectedConnector="servicenow-uses-table-api" />, {
wrapper: ({ children }) => <TestProviders>{children}</TestProviders>,
});

View file

@ -13,7 +13,7 @@ import { ConnectorTypes } from '../../../common';
import { ActionConnector } from '../../containers/configure/types';
import * as i18n from './translations';
import { useKibana } from '../../common/lib/kibana';
import { getConnectorIcon, isLegacyConnector } from '../utils';
import { getConnectorIcon, isDeprecatedConnector } from '../utils';
import { euiStyled } from '../../../../../../src/plugins/kibana_react/common';
export interface Props {
@ -95,10 +95,10 @@ const ConnectorsDropdownComponent: React.FC<Props> = ({
<EuiFlexItem grow={false}>
<span>
{connector.name}
{isLegacyConnector(connector) && ` (${i18n.DEPRECATED_TOOLTIP_TEXT})`}
{isDeprecatedConnector(connector) && ` (${i18n.DEPRECATED_TOOLTIP_TEXT})`}
</span>
</EuiFlexItem>
{isLegacyConnector(connector) && (
{isDeprecatedConnector(connector) && (
<EuiFlexItem grow={false}>
<StyledEuiIconTip
aria-label={i18n.DEPRECATED_TOOLTIP_CONTENT}

View file

@ -14,14 +14,14 @@ describe('DeprecatedCallout', () => {
render(<DeprecatedCallout />);
expect(screen.getByText('This connector type is deprecated')).toBeInTheDocument();
expect(screen.getByText('Update this connector, or create a new one.')).toBeInTheDocument();
expect(screen.getByTestId('legacy-connector-warning-callout')).toHaveClass(
expect(screen.getByTestId('deprecated-connector-warning-callout')).toHaveClass(
'euiCallOut euiCallOut--warning'
);
});
test('it renders a danger flyout correctly', () => {
render(<DeprecatedCallout type="danger" />);
expect(screen.getByTestId('legacy-connector-warning-callout')).toHaveClass(
expect(screen.getByTestId('deprecated-connector-warning-callout')).toHaveClass(
'euiCallOut euiCallOut--danger'
);
});

View file

@ -9,15 +9,15 @@ import React from 'react';
import { EuiCallOut, EuiCallOutProps } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
const LEGACY_CONNECTOR_WARNING_TITLE = i18n.translate(
'xpack.cases.connectors.serviceNow.legacyConnectorWarningTitle',
const DEPRECATED_CONNECTOR_WARNING_TITLE = i18n.translate(
'xpack.cases.connectors.serviceNow.deprecatedConnectorWarningTitle',
{
defaultMessage: 'This connector type is deprecated',
}
);
const LEGACY_CONNECTOR_WARNING_DESC = i18n.translate(
'xpack.cases.connectors.serviceNow.legacyConnectorWarningDesc',
const DEPRECATED_CONNECTOR_WARNING_DESC = i18n.translate(
'xpack.cases.connectors.serviceNow.deprecatedConnectorWarningDesc',
{
defaultMessage: 'Update this connector, or create a new one.',
}
@ -29,12 +29,12 @@ interface Props {
const DeprecatedCalloutComponent: React.FC<Props> = ({ type = 'warning' }) => (
<EuiCallOut
title={LEGACY_CONNECTOR_WARNING_TITLE}
title={DEPRECATED_CONNECTOR_WARNING_TITLE}
color={type}
iconType="alert"
data-test-subj="legacy-connector-warning-callout"
data-test-subj="deprecated-connector-warning-callout"
>
{LEGACY_CONNECTOR_WARNING_DESC}
{DEPRECATED_CONNECTOR_WARNING_DESC}
</EuiCallOut>
);

View file

@ -127,15 +127,15 @@ describe('ServiceNowITSM Fields', () => {
);
});
test('it shows the deprecated callout when the connector is legacy', async () => {
const legacyConnector = { ...connector, config: { isLegacy: true } };
render(<Fields fields={fields} onChange={onChange} connector={legacyConnector} />);
expect(screen.getByTestId('legacy-connector-warning-callout')).toBeInTheDocument();
test('it shows the deprecated callout when the connector uses the table API', async () => {
const tableApiConnector = { ...connector, config: { usesTableApi: true } };
render(<Fields fields={fields} onChange={onChange} connector={tableApiConnector} />);
expect(screen.getByTestId('deprecated-connector-warning-callout')).toBeInTheDocument();
});
test('it does not show the deprecated callout when the connector is not legacy', async () => {
test('it does not show the deprecated callout when the connector does not uses the table API', async () => {
render(<Fields fields={fields} onChange={onChange} connector={connector} />);
expect(screen.queryByTestId('legacy-connector-warning-callout')).not.toBeInTheDocument();
expect(screen.queryByTestId('deprecated-connector-warning-callout')).not.toBeInTheDocument();
});
describe('onChange calls', () => {

View file

@ -161,15 +161,15 @@ describe('ServiceNowSIR Fields', () => {
]);
});
test('it shows the deprecated callout when the connector is legacy', async () => {
const legacyConnector = { ...connector, config: { isLegacy: true } };
render(<Fields fields={fields} onChange={onChange} connector={legacyConnector} />);
expect(screen.getByTestId('legacy-connector-warning-callout')).toBeInTheDocument();
test('it shows the deprecated callout when the connector uses the table API', async () => {
const tableApiConnector = { ...connector, config: { usesTableApi: true } };
render(<Fields fields={fields} onChange={onChange} connector={tableApiConnector} />);
expect(screen.getByTestId('deprecated-connector-warning-callout')).toBeInTheDocument();
});
test('it does not show the deprecated callout when the connector is not legacy', async () => {
test('it does not show the deprecated callout when the connector does not uses the table API', async () => {
render(<Fields fields={fields} onChange={onChange} connector={connector} />);
expect(screen.queryByTestId('legacy-connector-warning-callout')).not.toBeInTheDocument();
expect(screen.queryByTestId('deprecated-connector-warning-callout')).not.toBeInTheDocument();
});
describe('onChange calls', () => {

View file

@ -10,24 +10,24 @@ import { connectorValidator } from './validator';
describe('ServiceNow validator', () => {
describe('connectorValidator', () => {
test('it returns an error message if the connector is legacy', () => {
test('it returns an error message if the connector uses the table API', () => {
const invalidConnector = {
...connector,
config: {
...connector.config,
isLegacy: true,
usesTableApi: true,
},
};
expect(connectorValidator(invalidConnector)).toEqual({ message: 'Deprecated connector' });
});
test('it does not returns an error message if the connector is not legacy', () => {
test('it does not returns an error message if the connector does not uses the table API', () => {
const invalidConnector = {
...connector,
config: {
...connector.config,
isLegacy: false,
usesTableApi: false,
},
};

View file

@ -9,16 +9,16 @@ import { ValidationConfig } from '../../../common/shared_imports';
import { CaseActionConnector } from '../../types';
/**
* The user can not use a legacy connector
* The user can not create cases with connectors that use the table API
*/
export const connectorValidator = (
connector: CaseActionConnector
): ReturnType<ValidationConfig['validator']> => {
const {
config: { isLegacy },
config: { usesTableApi },
} = connector;
if (isLegacy) {
if (usesTableApi) {
return {
message: 'Deprecated connector',
};

View file

@ -78,7 +78,7 @@ export const getConnectorIcon = (
};
// TODO: Remove when the applications are certified
export const isLegacyConnector = (connector?: CaseActionConnector) => {
export const isDeprecatedConnector = (connector?: CaseActionConnector): boolean => {
if (connector == null) {
return true;
}
@ -91,5 +91,16 @@ export const isLegacyConnector = (connector?: CaseActionConnector) => {
return true;
}
return connector.config.isLegacy;
/**
* Connector's prior to the Elastic ServiceNow application
* use the Table API (https://developer.servicenow.com/dev.do#!/reference/api/rome/rest/c_TableAPI)
* Connectors after the Elastic ServiceNow application use the
* Import Set API (https://developer.servicenow.com/dev.do#!/reference/api/rome/rest/c_ImportSetAPI)
* A ServiceNow connector is considered deprecated if it uses the Table API.
*
* All other connectors do not have the usesTableApi config property
* so the function will always return false for them.
*/
return !!connector.config.usesTableApi;
};

View file

@ -72,12 +72,12 @@ export const connectorsMock: ActionConnector[] = [
isPreconfigured: false,
},
{
id: 'servicenow-legacy',
id: 'servicenow-uses-table-api',
actionTypeId: '.servicenow',
name: 'My Connector',
config: {
apiUrl: 'https://instance1.service-now.com',
isLegacy: true,
usesTableApi: true,
},
isPreconfigured: false,
},

View file

@ -28,7 +28,7 @@ export const isFieldInvalid = (
): boolean => error !== undefined && error.length > 0 && field != null;
// TODO: Remove when the applications are certified
export const isLegacyConnector = (connector: ServiceNowActionConnector) => {
export const isDeprecatedConnector = (connector: ServiceNowActionConnector): boolean => {
if (connector == null) {
return true;
}
@ -41,5 +41,14 @@ export const isLegacyConnector = (connector: ServiceNowActionConnector) => {
return true;
}
return connector.config.isLegacy;
/**
* Connectors after the Elastic ServiceNow application use the
* Import Set API (https://developer.servicenow.com/dev.do#!/reference/api/rome/rest/c_ImportSetAPI)
* A ServiceNow connector is considered deprecated if it uses the Table API.
*
* All other connectors do not have the usesTableApi config property
* so the function will always return false for them.
*/
return !!connector.config.usesTableApi;
};

View file

@ -52,7 +52,7 @@ describe('servicenow connector validation', () => {
isPreconfigured: false,
config: {
apiUrl: 'https://dev94428.service-now.com/',
isLegacy: false,
usesTableApi: false,
},
} as ServiceNowActionConnector;
@ -60,7 +60,7 @@ describe('servicenow connector validation', () => {
config: {
errors: {
apiUrl: [],
isLegacy: [],
usesTableApi: [],
},
},
secrets: {
@ -88,7 +88,7 @@ describe('servicenow connector validation', () => {
config: {
errors: {
apiUrl: ['URL is required.'],
isLegacy: [],
usesTableApi: [],
},
},
secrets: {

View file

@ -28,7 +28,7 @@ const validateConnector = async (
const translations = await import('./translations');
const configErrors = {
apiUrl: new Array<string>(),
isLegacy: new Array<string>(),
usesTableApi: new Array<string>(),
};
const secretsErrors = {
username: new Array<string>(),

View file

@ -36,7 +36,7 @@ describe('ServiceNowActionConnectorFields renders', () => {
name: 'SN',
config: {
apiUrl: 'https://test/',
isLegacy: true,
usesTableApi: true,
},
} as ServiceNowActionConnector;
@ -44,7 +44,7 @@ describe('ServiceNowActionConnectorFields renders', () => {
...usesTableApiConnector,
config: {
...usesTableApiConnector.config,
isLegacy: false,
usesTableApi: false,
},
} as ServiceNowActionConnector;
@ -350,7 +350,7 @@ describe('ServiceNowActionConnectorFields renders', () => {
id: usesTableApiConnector.id,
connector: {
name: usesTableApiConnector.name,
config: { ...usesTableApiConnector.config, isLegacy: false },
config: { ...usesTableApiConnector.config, usesTableApi: false },
secrets: usesTableApiConnector.secrets,
},
})
@ -415,7 +415,7 @@ describe('ServiceNowActionConnectorFields renders', () => {
).toBeTruthy();
});
test('should set the isLegacy to false when creating a connector', async () => {
test('should set the usesTableApi to false when creating a connector', async () => {
const newConnector = { ...usesTableApiConnector, config: {}, secrets: {} };
const editActionConfig = jest.fn();
@ -432,7 +432,7 @@ describe('ServiceNowActionConnectorFields renders', () => {
/>
);
expect(editActionConfig).toHaveBeenCalledWith('isLegacy', false);
expect(editActionConfig).toHaveBeenCalledWith('usesTableApi', false);
});
test('it should set the legacy attribute if it is not undefined', async () => {

View file

@ -15,7 +15,7 @@ import { useKibana } from '../../../../common/lib/kibana';
import { DeprecatedCallout } from './deprecated_callout';
import { useGetAppInfo } from './use_get_app_info';
import { ApplicationRequiredCallout } from './application_required_callout';
import { isRESTApiError, isLegacyConnector } from './helpers';
import { isRESTApiError, isDeprecatedConnector } from './helpers';
import { InstallationCallout } from './installation_callout';
import { UpdateConnector } from './update_connector';
import { updateActionConnector } from '../../../lib/action_connector_api';
@ -36,9 +36,9 @@ const ServiceNowConnectorFields: React.FC<ActionConnectorFieldsProps<ServiceNowA
http,
notifications: { toasts },
} = useKibana().services;
const { apiUrl, isLegacy } = action.config;
const { apiUrl, usesTableApi } = action.config;
const { username, password } = action.secrets;
const isOldConnector = isLegacyConnector(action);
const requiresNewApplication = !isDeprecatedConnector(action);
const [showUpdateConnector, setShowUpdateConnector] = useState(false);
@ -46,11 +46,12 @@ const ServiceNowConnectorFields: React.FC<ActionConnectorFieldsProps<ServiceNowA
actionTypeId: action.actionTypeId,
});
const [applicationRequired, setApplicationRequired] = useState<boolean>(false);
const [showApplicationRequiredCallout, setShowApplicationRequiredCallout] =
useState<boolean>(false);
const [applicationInfoErrorMsg, setApplicationInfoErrorMsg] = useState<string | null>(null);
const getApplicationInfo = useCallback(async () => {
setApplicationRequired(false);
setShowApplicationRequiredCallout(false);
setApplicationInfoErrorMsg(null);
try {
@ -61,7 +62,7 @@ const ServiceNowConnectorFields: React.FC<ActionConnectorFieldsProps<ServiceNowA
return res;
} catch (e) {
setApplicationRequired(true);
setShowApplicationRequiredCallout(true);
setApplicationInfoErrorMsg(e.message);
// We need to throw here so the connector will be not be saved.
throw e;
@ -69,10 +70,10 @@ const ServiceNowConnectorFields: React.FC<ActionConnectorFieldsProps<ServiceNowA
}, [action, fetchAppInfo]);
const beforeActionConnectorSave = useCallback(async () => {
if (!isOldConnector) {
if (requiresNewApplication) {
await getApplicationInfo();
}
}, [getApplicationInfo, isOldConnector]);
}, [getApplicationInfo, requiresNewApplication]);
useEffect(
() => setCallbacks({ beforeActionConnectorSave }),
@ -90,13 +91,13 @@ const ServiceNowConnectorFields: React.FC<ActionConnectorFieldsProps<ServiceNowA
http,
connector: {
name: action.name,
config: { apiUrl, isLegacy: false },
config: { apiUrl, usesTableApi: false },
secrets: { username, password },
},
id: action.id,
});
editActionConfig('isLegacy', false);
editActionConfig('usesTableApi', false);
setShowUpdateConnector(false);
toasts.addSuccess({
@ -124,14 +125,14 @@ const ServiceNowConnectorFields: React.FC<ActionConnectorFieldsProps<ServiceNowA
]);
/**
* Defaults the isLegacy attribute to false
* if it is not defined. The isLegacy attribute
* Defaults the usesTableApi attribute to false
* if it is not defined. The usesTableApi attribute
* will be undefined only at the creation of
* the connector.
*/
useEffect(() => {
if (isLegacy == null) {
editActionConfig('isLegacy', false);
if (usesTableApi == null) {
editActionConfig('usesTableApi', false);
}
});
@ -150,8 +151,8 @@ const ServiceNowConnectorFields: React.FC<ActionConnectorFieldsProps<ServiceNowA
onCancel={onModalCancel}
/>
)}
{!isOldConnector && <InstallationCallout />}
{isOldConnector && <DeprecatedCallout onMigrate={onMigrateClick} />}
{requiresNewApplication && <InstallationCallout />}
{!requiresNewApplication && <DeprecatedCallout onMigrate={onMigrateClick} />}
<Credentials
action={action}
errors={errors}
@ -160,7 +161,7 @@ const ServiceNowConnectorFields: React.FC<ActionConnectorFieldsProps<ServiceNowA
editActionSecrets={editActionSecrets}
editActionConfig={editActionConfig}
/>
{applicationRequired && !isOldConnector && (
{showApplicationRequiredCallout && requiresNewApplication && (
<ApplicationRequiredCallout message={applicationInfoErrorMsg} />
)}
</>

View file

@ -23,7 +23,7 @@ import { ServiceNowITSMActionParams, Choice, Fields, ServiceNowActionConnector }
import { TextAreaWithMessageVariables } from '../../text_area_with_message_variables';
import { TextFieldWithMessageVariables } from '../../text_field_with_message_variables';
import { useGetChoices } from './use_get_choices';
import { choicesToEuiOptions, DEFAULT_CORRELATION_ID, isLegacyConnector } from './helpers';
import { choicesToEuiOptions, DEFAULT_CORRELATION_ID, isDeprecatedConnector } from './helpers';
import * as i18n from './translations';
@ -46,10 +46,6 @@ const ServiceNowParamsFields: React.FunctionComponent<
notifications: { toasts },
} = useKibana().services;
const isDeprecatedConnector = isLegacyConnector(
actionConnector as unknown as ServiceNowActionConnector
);
const actionConnectorRef = useRef(actionConnector?.id ?? '');
const { incident, comments } = useMemo(
() =>
@ -244,7 +240,7 @@ const ServiceNowParamsFields: React.FunctionComponent<
</EuiFlexItem>
</EuiFlexGroup>
<EuiSpacer size="m" />
{!isDeprecatedConnector && (
{!isDeprecatedConnector(actionConnector as unknown as ServiceNowActionConnector) && (
<>
<EuiFlexGroup>
<EuiFlexItem>

View file

@ -25,7 +25,7 @@ import { TextFieldWithMessageVariables } from '../../text_field_with_message_var
import * as i18n from './translations';
import { useGetChoices } from './use_get_choices';
import { ServiceNowSIRActionParams, Fields, Choice, ServiceNowActionConnector } from './types';
import { choicesToEuiOptions, isLegacyConnector, DEFAULT_CORRELATION_ID } from './helpers';
import { choicesToEuiOptions, isDeprecatedConnector, DEFAULT_CORRELATION_ID } from './helpers';
const useGetChoicesFields = ['category', 'subcategory', 'priority'];
const defaultFields: Fields = {
@ -43,10 +43,6 @@ const ServiceNowSIRParamsFields: React.FunctionComponent<
notifications: { toasts },
} = useKibana().services;
const isDeprecatedConnector = isLegacyConnector(
actionConnector as unknown as ServiceNowActionConnector
);
const actionConnectorRef = useRef(actionConnector?.id ?? '');
const { incident, comments } = useMemo(
() =>
@ -229,7 +225,7 @@ const ServiceNowSIRParamsFields: React.FunctionComponent<
</EuiFlexItem>
</EuiFlexGroup>
<EuiSpacer size="m" />
{!isDeprecatedConnector && (
{!isDeprecatedConnector(actionConnector as unknown as ServiceNowActionConnector) && (
<>
<EuiFlexGroup>
<EuiFlexItem>

View file

@ -35,7 +35,7 @@ export interface ServiceNowITOMActionParams {
export interface ServiceNowConfig {
apiUrl: string;
isLegacy: boolean;
usesTableApi: boolean;
}
export interface ServiceNowSecrets {

View file

@ -22,7 +22,7 @@ const actionConnector: ServiceNowActionConnector = {
name: 'servicenow',
config: {
apiUrl: 'https://test/',
isLegacy: true,
usesTableApi: true,
},
};

View file

@ -34,7 +34,7 @@ const actionConnector = {
isPreconfigured: false,
config: {
apiUrl: 'https://test.service-now.com/',
isLegacy: false,
usesTableApi: false,
},
} as ServiceNowActionConnector;

View file

@ -205,8 +205,8 @@ const ActionsConnectorsList: React.FunctionComponent = () => {
const itemConfig = (
item as UserConfiguredActionConnector<Record<string, unknown>, Record<string, unknown>>
).config;
const showLegacyTooltip =
itemConfig?.isLegacy &&
const showDeprecatedTooltip =
itemConfig?.usesTableApi &&
// TODO: Remove when applications are certified
((ENABLE_NEW_SN_ITSM_CONNECTOR && item.actionTypeId === '.servicenow') ||
(ENABLE_NEW_SN_SIR_CONNECTOR && item.actionTypeId === '.servicenow-sir'));
@ -233,7 +233,7 @@ const ActionsConnectorsList: React.FunctionComponent = () => {
position="right"
/>
) : null}
{showLegacyTooltip && <ConnectorIconTipWithSpacing />}
{showDeprecatedTooltip && <ConnectorIconTipWithSpacing />}
</>
);

View file

@ -22,7 +22,7 @@ export default function serviceNowITSMTest({ getService }: FtrProviderContext) {
const mockServiceNow = {
config: {
apiUrl: 'www.servicenowisinkibanaactions.com',
isLegacy: false,
usesTableApi: false,
},
secrets: {
password: 'elastic',
@ -91,7 +91,7 @@ export default function serviceNowITSMTest({ getService }: FtrProviderContext) {
connector_type_id: '.servicenow',
config: {
apiUrl: serviceNowSimulatorURL,
isLegacy: false,
usesTableApi: false,
},
secrets: mockServiceNow.secrets,
})
@ -105,7 +105,7 @@ export default function serviceNowITSMTest({ getService }: FtrProviderContext) {
is_missing_secrets: false,
config: {
apiUrl: serviceNowSimulatorURL,
isLegacy: false,
usesTableApi: false,
},
});
@ -121,12 +121,12 @@ export default function serviceNowITSMTest({ getService }: FtrProviderContext) {
is_missing_secrets: false,
config: {
apiUrl: serviceNowSimulatorURL,
isLegacy: false,
usesTableApi: false,
},
});
});
it('should set the isLegacy to true when not provided', async () => {
it('should set the usesTableApi to true when not provided', async () => {
const { body: createdAction } = await supertest
.post('/api/actions/connector')
.set('kbn-xsrf', 'foo')
@ -144,7 +144,7 @@ export default function serviceNowITSMTest({ getService }: FtrProviderContext) {
.get(`/api/actions/connector/${createdAction.id}`)
.expect(200);
expect(fetchedAction.config.isLegacy).to.be(true);
expect(fetchedAction.config.usesTableApi).to.be(true);
});
it('should respond with a 400 Bad Request when creating a servicenow action with no apiUrl', async () => {
@ -223,7 +223,7 @@ export default function serviceNowITSMTest({ getService }: FtrProviderContext) {
connector_type_id: '.servicenow',
config: {
apiUrl: serviceNowSimulatorURL,
isLegacy: false,
usesTableApi: false,
},
secrets: mockServiceNow.secrets,
});
@ -383,7 +383,7 @@ export default function serviceNowITSMTest({ getService }: FtrProviderContext) {
});
describe('Execution', () => {
// New connectors
// Connectors that use the Import set API
describe('Import set API', () => {
it('should handle creating an incident without comments', async () => {
const { body: result } = await supertest
@ -414,7 +414,7 @@ export default function serviceNowITSMTest({ getService }: FtrProviderContext) {
});
});
// Legacy connectors
// Connectors that use the Table API
describe('Table API', () => {
before(async () => {
const { body } = await supertest
@ -425,7 +425,7 @@ export default function serviceNowITSMTest({ getService }: FtrProviderContext) {
connector_type_id: '.servicenow',
config: {
apiUrl: serviceNowSimulatorURL,
isLegacy: true,
usesTableApi: true,
},
secrets: mockServiceNow.secrets,
});

View file

@ -22,7 +22,7 @@ export default function serviceNowSIRTest({ getService }: FtrProviderContext) {
const mockServiceNow = {
config: {
apiUrl: 'www.servicenowisinkibanaactions.com',
isLegacy: false,
usesTableApi: false,
},
secrets: {
password: 'elastic',
@ -95,7 +95,7 @@ export default function serviceNowSIRTest({ getService }: FtrProviderContext) {
connector_type_id: '.servicenow-sir',
config: {
apiUrl: serviceNowSimulatorURL,
isLegacy: false,
usesTableApi: false,
},
secrets: mockServiceNow.secrets,
})
@ -109,7 +109,7 @@ export default function serviceNowSIRTest({ getService }: FtrProviderContext) {
is_missing_secrets: false,
config: {
apiUrl: serviceNowSimulatorURL,
isLegacy: false,
usesTableApi: false,
},
});
@ -125,12 +125,12 @@ export default function serviceNowSIRTest({ getService }: FtrProviderContext) {
is_missing_secrets: false,
config: {
apiUrl: serviceNowSimulatorURL,
isLegacy: false,
usesTableApi: false,
},
});
});
it('should set the isLegacy to true when not provided', async () => {
it('should set the usesTableApi to true when not provided', async () => {
const { body: createdAction } = await supertest
.post('/api/actions/connector')
.set('kbn-xsrf', 'foo')
@ -148,7 +148,7 @@ export default function serviceNowSIRTest({ getService }: FtrProviderContext) {
.get(`/api/actions/connector/${createdAction.id}`)
.expect(200);
expect(fetchedAction.config.isLegacy).to.be(true);
expect(fetchedAction.config.usesTableApi).to.be(true);
});
it('should respond with a 400 Bad Request when creating a servicenow action with no apiUrl', async () => {
@ -227,7 +227,7 @@ export default function serviceNowSIRTest({ getService }: FtrProviderContext) {
connector_type_id: '.servicenow-sir',
config: {
apiUrl: serviceNowSimulatorURL,
isLegacy: false,
usesTableApi: false,
},
secrets: mockServiceNow.secrets,
});
@ -387,7 +387,7 @@ export default function serviceNowSIRTest({ getService }: FtrProviderContext) {
});
describe('Execution', () => {
// New connectors
// Connectors that use the Import set API
describe('Import set API', () => {
it('should handle creating an incident without comments', async () => {
const { body: result } = await supertest
@ -418,7 +418,7 @@ export default function serviceNowSIRTest({ getService }: FtrProviderContext) {
});
});
// Legacy connectors
// Connectors that use the Table API
describe('Table API', () => {
before(async () => {
const { body } = await supertest
@ -429,7 +429,7 @@ export default function serviceNowSIRTest({ getService }: FtrProviderContext) {
connector_type_id: '.servicenow-sir',
config: {
apiUrl: serviceNowSimulatorURL,
isLegacy: true,
usesTableApi: true,
},
secrets: mockServiceNow.secrets,
});

View file

@ -329,7 +329,7 @@ export const getServiceNowConnector = () => ({
},
config: {
apiUrl: 'http://some.non.existent.com',
isLegacy: false,
usesTableApi: false,
},
});
@ -386,7 +386,7 @@ export const getServiceNowSIRConnector = () => ({
},
config: {
apiUrl: 'http://some.non.existent.com',
isLegacy: false,
usesTableApi: false,
},
});

View file

@ -109,7 +109,7 @@ export default ({ getService }: FtrProviderContext): void => {
name: 'ServiceNow Connector',
config: {
apiUrl: 'http://some.non.existent.com',
isLegacy: false,
usesTableApi: false,
},
isPreconfigured: false,
isMissingSecrets: false,
@ -121,7 +121,7 @@ export default ({ getService }: FtrProviderContext): void => {
name: 'ServiceNow Connector',
config: {
apiUrl: 'http://some.non.existent.com',
isLegacy: false,
usesTableApi: false,
},
isPreconfigured: false,
isMissingSecrets: false,

View file

@ -109,7 +109,7 @@ export default ({ getService }: FtrProviderContext): void => {
name: 'ServiceNow Connector',
config: {
apiUrl: 'http://some.non.existent.com',
isLegacy: false,
usesTableApi: false,
},
isPreconfigured: false,
isMissingSecrets: false,
@ -121,7 +121,7 @@ export default ({ getService }: FtrProviderContext): void => {
name: 'ServiceNow Connector',
config: {
apiUrl: 'http://some.non.existent.com',
isLegacy: false,
usesTableApi: false,
},
isPreconfigured: false,
isMissingSecrets: false,