Skip to content

Commit 473141f

Browse files
academocnasikas
andauthored
[Cases] Show deprecated icon in connectors with isDeprecated true (#132237)
Co-authored-by: Christos Nasikas <christos.nasikas@elastic.co>
1 parent f88b140 commit 473141f

25 files changed

Lines changed: 285 additions & 178 deletions

File tree

x-pack/plugins/actions/server/lib/is_conector_deprecated.test.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ describe('isConnectorDeprecated', () => {
1717
isPreconfigured: false as const,
1818
};
1919

20+
it('returns false if the config is not defined', () => {
21+
// @ts-expect-error
22+
expect(isConnectorDeprecated({})).toBe(false);
23+
});
24+
2025
it('returns false if the connector is not ITSM or SecOps', () => {
2126
expect(isConnectorDeprecated(connector)).toBe(false);
2227
});
@@ -48,4 +53,24 @@ describe('isConnectorDeprecated', () => {
4853
})
4954
).toBe(true);
5055
});
56+
57+
it('returns true if the connector is .servicenow and the usesTableApi is omitted', () => {
58+
expect(
59+
isConnectorDeprecated({
60+
...connector,
61+
actionTypeId: '.servicenow',
62+
config: { apiUrl: 'http://example.com' },
63+
})
64+
).toBe(true);
65+
});
66+
67+
it('returns true if the connector is .servicenow-sir and the usesTableApi is omitted', () => {
68+
expect(
69+
isConnectorDeprecated({
70+
...connector,
71+
actionTypeId: '.servicenow-sir',
72+
config: { apiUrl: 'http://example.com' },
73+
})
74+
).toBe(true);
75+
});
5176
});

x-pack/plugins/actions/server/lib/is_conector_deprecated.ts

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,14 @@
55
* 2.0.
66
*/
77

8+
import { isPlainObject } from 'lodash';
89
import { PreConfiguredAction, RawAction } from '../types';
910

1011
export type ConnectorWithOptionalDeprecation = Omit<PreConfiguredAction, 'isDeprecated'> &
1112
Pick<Partial<PreConfiguredAction>, 'isDeprecated'>;
1213

14+
const isObject = (obj: unknown): obj is Record<string, unknown> => isPlainObject(obj);
15+
1316
export const isConnectorDeprecated = (
1417
connector: RawAction | ConnectorWithOptionalDeprecation
1518
): boolean => {
@@ -18,11 +21,40 @@ export const isConnectorDeprecated = (
1821
* Connectors after the Elastic ServiceNow application use the
1922
* Import Set API (https://developer.servicenow.com/dev.do#!/reference/api/rome/rest/c_ImportSetAPI)
2023
* A ServiceNow connector is considered deprecated if it uses the Table API.
21-
*
22-
* All other connectors do not have the usesTableApi config property
23-
* so the function will always return false for them.
2424
*/
25-
return !!connector.config?.usesTableApi;
25+
26+
/**
27+
* We cannot deduct if the connector is
28+
* deprecated without config. In this case
29+
* we always return false.
30+
*/
31+
if (!isObject(connector.config)) {
32+
return false;
33+
}
34+
35+
/**
36+
* If the usesTableApi is not defined it means that the connector is created
37+
* before the introduction of the usesTableApi property. In that case, the connector is assumed
38+
* to be deprecated because all connectors prior 7.16 where using the Table API.
39+
* Migrations x-pack/plugins/actions/server/saved_objects/actions_migrations.ts set
40+
* the usesTableApi property to true to all connectors prior 7.16. Pre configured connectors
41+
* cannot be migrated. This check ensures that pre configured connectors without the
42+
* usesTableApi property explicitly in the kibana.yml file are considered deprecated.
43+
* According to the schema defined here x-pack/plugins/actions/server/builtin_action_types/servicenow/schema.ts
44+
* if the property is not defined it will be set to true at the execution of the connector.
45+
*/
46+
if (!Object.hasOwn(connector.config, 'usesTableApi')) {
47+
return true;
48+
}
49+
50+
/**
51+
* Connector created prior to 7.16 will be migrated to have the usesTableApi property set to true.
52+
* Connectors created after 7.16 should have the usesTableApi property set to true or false.
53+
* If the usesTableApi is omitted on an API call it will be defaulted to true. Check the schema
54+
* here x-pack/plugins/actions/server/builtin_action_types/servicenow/schema.ts.
55+
* The !! is to make TS happy.
56+
*/
57+
return !!connector.config.usesTableApi;
2658
}
2759

2860
return false;

x-pack/plugins/cases/common/api/connectors/index.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,15 @@
77

88
import * as rt from 'io-ts';
99

10-
import { ActionResult, ActionType } from '@kbn/actions-plugin/common';
10+
import type { ActionType } from '@kbn/actions-plugin/common';
11+
/**
12+
* ActionResult type from the common folder is outdated.
13+
* The type from server is not exported properly so we
14+
* disable the linting for the moment
15+
*/
16+
17+
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
18+
import type { ActionResult } from '@kbn/actions-plugin/server/types';
1119
import { JiraFieldsRT } from './jira';
1220
import { ResilientFieldsRT } from './resilient';
1321
import { ServiceNowITSMFieldsRT } from './servicenow_itsm';

x-pack/plugins/cases/public/common/mock/connectors.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export const connectorsMock: ActionConnector[] = [
1616
apiUrl: 'https://instance1.service-now.com',
1717
},
1818
isPreconfigured: false,
19+
isDeprecated: false,
1920
},
2021
{
2122
id: 'resilient-2',
@@ -26,6 +27,7 @@ export const connectorsMock: ActionConnector[] = [
2627
orgId: '201',
2728
},
2829
isPreconfigured: false,
30+
isDeprecated: false,
2931
},
3032
{
3133
id: 'jira-1',
@@ -35,6 +37,7 @@ export const connectorsMock: ActionConnector[] = [
3537
apiUrl: 'https://instance.atlassian.ne',
3638
},
3739
isPreconfigured: false,
40+
isDeprecated: false,
3841
},
3942
{
4043
id: 'servicenow-sir',
@@ -44,6 +47,7 @@ export const connectorsMock: ActionConnector[] = [
4447
apiUrl: 'https://instance1.service-now.com',
4548
},
4649
isPreconfigured: false,
50+
isDeprecated: false,
4751
},
4852
{
4953
id: 'servicenow-uses-table-api',
@@ -54,6 +58,7 @@ export const connectorsMock: ActionConnector[] = [
5458
usesTableApi: true,
5559
},
5660
isPreconfigured: false,
61+
isDeprecated: true,
5762
},
5863
];
5964

x-pack/plugins/cases/public/components/all_cases/columns.test.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ describe('ExternalServiceColumn ', () => {
7777
name: 'None',
7878
config: {},
7979
isPreconfigured: false,
80+
isDeprecated: false,
8081
},
8182
]}
8283
/>

x-pack/plugins/cases/public/components/configure_cases/connectors_dropdown.test.tsx

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ describe('ConnectorsDropdown', () => {
249249
name: 'None',
250250
config: {},
251251
isPreconfigured: false,
252+
isDeprecated: false,
252253
},
253254
]}
254255
/>,
@@ -269,4 +270,26 @@ describe('ConnectorsDropdown', () => {
269270
);
270271
expect(tooltips[0]).toBeInTheDocument();
271272
});
273+
274+
test('it shows the deprecated tooltip when the connector is deprecated by configuration', () => {
275+
const connector = connectors[0];
276+
render(
277+
<ConnectorsDropdown
278+
{...props}
279+
connectors={[
280+
{
281+
...connector,
282+
isDeprecated: true,
283+
},
284+
]}
285+
selectedConnector={connector.id}
286+
/>,
287+
{ wrapper: ({ children }) => <TestProviders>{children}</TestProviders> }
288+
);
289+
290+
const tooltips = screen.getAllByText(
291+
'This connector is deprecated. Update it, or create a new one.'
292+
);
293+
expect(tooltips[0]).toBeInTheDocument();
294+
});
272295
});

x-pack/plugins/cases/public/components/connectors/mock.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ export const connector = {
1313
actionTypeId: '.jira',
1414
config: {},
1515
isPreconfigured: false,
16+
isDeprecated: false,
1617
};
1718

1819
export const swimlaneConnector = {
@@ -29,6 +30,7 @@ export const swimlaneConnector = {
2930
},
3031
},
3132
isPreconfigured: false,
33+
isDeprecated: false,
3234
};
3335

3436
export const issues = [

x-pack/plugins/cases/public/components/connectors/servicenow/servicenow_itsm_case_fields.test.tsx

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -135,18 +135,18 @@ describe('ServiceNowITSM Fields', () => {
135135
);
136136
});
137137

138-
it('shows the deprecated callout when the connector uses the table API', async () => {
139-
const tableApiConnector = { ...connector, config: { usesTableApi: true } };
138+
it('shows the deprecated callout if the connector is deprecated', async () => {
139+
const tableApiConnector = { ...connector, isDeprecated: true };
140140
render(<Fields fields={fields} onChange={onChange} connector={tableApiConnector} />);
141141
expect(screen.getByTestId('deprecated-connector-warning-callout')).toBeInTheDocument();
142142
});
143143

144-
it('does not show the deprecated callout when the connector does not uses the table API', async () => {
144+
it('does not show the deprecated callout when the connector is not deprecated', async () => {
145145
render(<Fields fields={fields} onChange={onChange} connector={connector} />);
146146
expect(screen.queryByTestId('deprecated-connector-warning-callout')).not.toBeInTheDocument();
147147
});
148148

149-
it('does not show the deprecated callout when the connector is preconfigured', async () => {
149+
it('does not show the deprecated callout when the connector is preconfigured and not deprecated', async () => {
150150
render(
151151
<Fields
152152
fields={fields}
@@ -157,12 +157,15 @@ describe('ServiceNowITSM Fields', () => {
157157
expect(screen.queryByTestId('deprecated-connector-warning-callout')).not.toBeInTheDocument();
158158
});
159159

160-
it('does not show the deprecated callout when the config of the connector is undefined', async () => {
160+
it('shows the deprecated callout when the connector is preconfigured and deprecated', async () => {
161161
render(
162-
// @ts-expect-error
163-
<Fields fields={fields} onChange={onChange} connector={{ ...connector, config: undefined }} />
162+
<Fields
163+
fields={fields}
164+
onChange={onChange}
165+
connector={{ ...connector, isPreconfigured: true, isDeprecated: true }}
166+
/>
164167
);
165-
expect(screen.queryByTestId('deprecated-connector-warning-callout')).not.toBeInTheDocument();
168+
expect(screen.queryByTestId('deprecated-connector-warning-callout')).toBeInTheDocument();
166169
});
167170

168171
it('should hide subcategory if selecting a category without subcategories', async () => {

x-pack/plugins/cases/public/components/connectors/servicenow/servicenow_itsm_case_fields.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import { ConnectorCard } from '../card';
1616
import { useGetChoices } from './use_get_choices';
1717
import { Fields, Choice } from './types';
1818
import { choicesToEuiOptions } from './helpers';
19-
import { connectorValidator } from './validator';
2019
import { DeprecatedCallout } from '../deprecated_callout';
2120

2221
const useGetChoicesFields = ['urgency', 'severity', 'impact', 'category', 'subcategory'];
@@ -44,7 +43,7 @@ const ServiceNowITSMFieldsComponent: React.FunctionComponent<
4443
} = fields ?? {};
4544
const { http, notifications } = useKibana().services;
4645
const [choices, setChoices] = useState<Fields>(defaultFields);
47-
const showConnectorWarning = useMemo(() => connectorValidator(connector) != null, [connector]);
46+
const showConnectorWarning = connector.isDeprecated;
4847

4948
const categoryOptions = useMemo(
5049
() => choicesToEuiOptions(choices.category),

x-pack/plugins/cases/public/components/connectors/servicenow/servicenow_sir_case_fields.test.tsx

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -169,18 +169,18 @@ describe('ServiceNowSIR Fields', () => {
169169
]);
170170
});
171171

172-
test('it shows the deprecated callout when the connector uses the table API', async () => {
173-
const tableApiConnector = { ...connector, config: { usesTableApi: true } };
172+
test('shows the deprecated callout if the connector is deprecated', async () => {
173+
const tableApiConnector = { ...connector, isDeprecated: true };
174174
render(<Fields fields={fields} onChange={onChange} connector={tableApiConnector} />);
175175
expect(screen.getByTestId('deprecated-connector-warning-callout')).toBeInTheDocument();
176176
});
177177

178-
test('it does not show the deprecated callout when the connector does not uses the table API', async () => {
178+
test('does not show the deprecated callout when the connector is not deprecated', async () => {
179179
render(<Fields fields={fields} onChange={onChange} connector={connector} />);
180180
expect(screen.queryByTestId('deprecated-connector-warning-callout')).not.toBeInTheDocument();
181181
});
182182

183-
it('does not show the deprecated callout when the connector is preconfigured', async () => {
183+
it('does not show the deprecated callout when the connector is preconfigured and not deprecated', async () => {
184184
render(
185185
<Fields
186186
fields={fields}
@@ -191,12 +191,15 @@ describe('ServiceNowSIR Fields', () => {
191191
expect(screen.queryByTestId('deprecated-connector-warning-callout')).not.toBeInTheDocument();
192192
});
193193

194-
it('does not show the deprecated callout when the config of the connector is undefined', async () => {
194+
it('shows the deprecated callout when the connector is preconfigured and deprecated', async () => {
195195
render(
196-
// @ts-expect-error
197-
<Fields fields={fields} onChange={onChange} connector={{ ...connector, config: undefined }} />
196+
<Fields
197+
fields={fields}
198+
onChange={onChange}
199+
connector={{ ...connector, isPreconfigured: true, isDeprecated: true }}
200+
/>
198201
);
199-
expect(screen.queryByTestId('deprecated-connector-warning-callout')).not.toBeInTheDocument();
202+
expect(screen.queryByTestId('deprecated-connector-warning-callout')).toBeInTheDocument();
200203
});
201204

202205
test('it should hide subcategory if selecting a category without subcategories', async () => {

0 commit comments

Comments
 (0)