From e22974a85f60e0a10d9138ccab6b582958217de5 Mon Sep 17 00:00:00 2001 From: Kyle Pollich Date: Thu, 14 Oct 2021 15:16:58 -0400 Subject: [PATCH 01/24] Validate package policy immediately after dry run data is available (#115060) --- .../edit_package_policy_page/index.tsx | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/index.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/index.tsx index 4d940534c4a7b..840a5a71a63c7 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/index.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/index.tsx @@ -200,10 +200,19 @@ export const EditPackagePolicyForm = memo<{ if (packageData?.response) { setPackageInfo(packageData.response); - setValidationResults( - validatePackagePolicy(newPackagePolicy, packageData.response, safeLoad) + + const newValidationResults = validatePackagePolicy( + newPackagePolicy, + packageData.response, + safeLoad ); - setFormState('VALID'); + setValidationResults(newValidationResults); + + if (validationHasErrors(newValidationResults)) { + setFormState('INVALID'); + } else { + setFormState('VALID'); + } } } } From 065b42b6617a199138897eec92c6d2e6a6888a9f Mon Sep 17 00:00:00 2001 From: Nicolas Chaulet Date: Thu, 14 Oct 2021 15:28:43 -0400 Subject: [PATCH 02/24] [Fleet] Remove escaping numeric value in agent template (#114123) --- .../server/services/epm/agent/agent.test.ts | 14 ++++++++------ .../fleet/server/services/epm/agent/agent.ts | 18 ------------------ 2 files changed, 8 insertions(+), 24 deletions(-) diff --git a/x-pack/plugins/fleet/server/services/epm/agent/agent.test.ts b/x-pack/plugins/fleet/server/services/epm/agent/agent.test.ts index 1be0f73a347e9..ed5d6473760ff 100644 --- a/x-pack/plugins/fleet/server/services/epm/agent/agent.test.ts +++ b/x-pack/plugins/fleet/server/services/epm/agent/agent.test.ts @@ -29,7 +29,7 @@ foo: {{bar}} some_text_field: {{should_be_text}} multi_text_field: {{#each multi_text}} - - {{this}} + - !!str {{this}} {{/each}} `; const vars = { @@ -37,7 +37,7 @@ multi_text_field: password: { type: 'password', value: '' }, optional_field: { type: 'text', value: undefined }, bar: { type: 'text', value: 'bar' }, - should_be_text: { type: 'text', value: '1234' }, + should_be_text: { type: 'text', value: 'textvalue' }, multi_text: { type: 'text', value: ['1234', 'foo', 'bar'] }, }; @@ -49,7 +49,7 @@ multi_text_field: processors: [{ add_locale: null }], password: '', foo: 'bar', - some_text_field: '1234', + some_text_field: 'textvalue', multi_text_field: ['1234', 'foo', 'bar'], }); }); @@ -217,12 +217,13 @@ input: logs }); }); - it('should escape string values when necessary', () => { + it('should suport !!str for string values', () => { const stringTemplate = ` my-package: asteriskOnly: {{asteriskOnly}} startsWithAsterisk: {{startsWithAsterisk}} - numeric: {{numeric}} + numeric_with_str: !!str {{numeric}} + numeric_without_str: {{numeric}} mixed: {{mixed}} concatenatedEnd: {{a}}{{b}} concatenatedMiddle: {{c}}{{d}} @@ -245,7 +246,8 @@ my-package: 'my-package': { asteriskOnly: '*', startsWithAsterisk: '*lala', - numeric: '100', + numeric_with_str: '100', + numeric_without_str: 100, mixed: '1s', concatenatedEnd: '/opt/package/*/logs/my.log*', concatenatedMiddle: '/opt/*/package/logs/*my.log', diff --git a/x-pack/plugins/fleet/server/services/epm/agent/agent.ts b/x-pack/plugins/fleet/server/services/epm/agent/agent.ts index a0d14e6962a8d..a01643b22cf9d 100644 --- a/x-pack/plugins/fleet/server/services/epm/agent/agent.ts +++ b/x-pack/plugins/fleet/server/services/epm/agent/agent.ts @@ -58,14 +58,6 @@ function replaceVariablesInYaml(yamlVariables: { [k: string]: any }, yaml: any) return yaml; } -const maybeEscapeString = (value: string) => { - // Numeric strings need to be quoted to stay strings. - if (value.length && !isNaN(+value)) { - return `"${value}"`; - } - return value; -}; - function buildTemplateVariables(variables: PackagePolicyConfigRecord, templateStr: string) { const yamlValues: { [k: string]: any } = {}; const vars = Object.entries(variables).reduce((acc, [key, recordEntry]) => { @@ -92,16 +84,6 @@ function buildTemplateVariables(variables: PackagePolicyConfigRecord, templateSt const yamlKeyPlaceholder = `##${key}##`; varPart[lastKeyPart] = recordEntry.value ? `"${yamlKeyPlaceholder}"` : null; yamlValues[yamlKeyPlaceholder] = recordEntry.value ? safeLoad(recordEntry.value) : null; - } else if ( - recordEntry.type && - (recordEntry.type === 'text' || recordEntry.type === 'string') && - recordEntry.value?.length - ) { - if (Array.isArray(recordEntry.value)) { - varPart[lastKeyPart] = recordEntry.value.map((value: string) => maybeEscapeString(value)); - } else { - varPart[lastKeyPart] = maybeEscapeString(recordEntry.value); - } } else { varPart[lastKeyPart] = recordEntry.value; } From 5657f80feb8401d81dad704b1ab2f25850344d61 Mon Sep 17 00:00:00 2001 From: ymao1 Date: Thu, 14 Oct 2021 15:52:23 -0400 Subject: [PATCH 03/24] [Alerting] Show execution duration on Rule Details view (#114719) * Adding execution duration to get alert instance summary * Showing execution duration on rule details view * Fixing unit tests * Updating to match new mockup * Fixing types * Fixing functional test * Removing unneeded max and min and adding tests * Removing unneeded max and min and adding tests * Fixing functional test * Adding left axis * PR feedback * Reducing chart height * PR feedback * PR feedback * PR feedback --- .../alerting/common/alert_instance_summary.ts | 4 + ...rt_instance_summary_from_event_log.test.ts | 70 +++++++-- .../alert_instance_summary_from_event_log.ts | 19 +++ .../routes/get_rule_alert_summary.test.ts | 4 + .../server/routes/get_rule_alert_summary.ts | 2 + .../legacy/get_alert_instance_summary.test.ts | 4 + .../tests/get_alert_instance_summary.test.ts | 11 +- .../lib/alert_api/alert_summary.test.ts | 8 ++ .../lib/alert_api/alert_summary.ts | 2 + .../lib/execution_duration_utils.test.ts | 68 +++++++++ .../lib/execution_duration_utils.ts | 38 +++++ .../components/alert_instances.scss | 5 + .../components/alert_instances.test.tsx | 120 ++++++++++++++++ .../components/alert_instances.tsx | 112 ++++++++++++++- .../components/alert_instances_route.test.tsx | 4 + .../alerts_list/components/alerts_list.tsx | 28 ++-- .../execution_duration_chart.test.tsx | 72 ++++++++++ .../components/execution_duration_chart.tsx | 133 ++++++++++++++++++ .../alerting/get_alert_instance_summary.ts | 1 + .../alerting/get_alert_instance_summary.ts | 14 +- 20 files changed, 685 insertions(+), 34 deletions(-) create mode 100644 x-pack/plugins/triggers_actions_ui/public/application/lib/execution_duration_utils.test.ts create mode 100644 x-pack/plugins/triggers_actions_ui/public/application/lib/execution_duration_utils.ts create mode 100644 x-pack/plugins/triggers_actions_ui/public/application/sections/common/components/execution_duration_chart.test.tsx create mode 100644 x-pack/plugins/triggers_actions_ui/public/application/sections/common/components/execution_duration_chart.tsx diff --git a/x-pack/plugins/alerting/common/alert_instance_summary.ts b/x-pack/plugins/alerting/common/alert_instance_summary.ts index 7ae37d6ddf53a..462d20b8fb2ea 100644 --- a/x-pack/plugins/alerting/common/alert_instance_summary.ts +++ b/x-pack/plugins/alerting/common/alert_instance_summary.ts @@ -23,6 +23,10 @@ export interface AlertInstanceSummary { lastRun?: string; errorMessages: Array<{ date: string; message: string }>; instances: Record; + executionDuration: { + average: number; + values: number[]; + }; } export interface AlertInstanceStatus { diff --git a/x-pack/plugins/alerting/server/lib/alert_instance_summary_from_event_log.test.ts b/x-pack/plugins/alerting/server/lib/alert_instance_summary_from_event_log.test.ts index 22122b22fd3bb..a6529f4c30a7b 100644 --- a/x-pack/plugins/alerting/server/lib/alert_instance_summary_from_event_log.test.ts +++ b/x-pack/plugins/alerting/server/lib/alert_instance_summary_from_event_log.test.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { random, mean } from 'lodash'; import { SanitizedAlert, AlertInstanceSummary } from '../types'; import { IValidatedEvent } from '../../../event_log/server'; import { EVENT_LOG_ACTIONS, EVENT_LOG_PROVIDER, LEGACY_EVENT_LOG_ACTIONS } from '../plugin'; @@ -31,6 +32,10 @@ describe('alertInstanceSummaryFromEventLog', () => { "consumer": "alert-consumer", "enabled": false, "errorMessages": Array [], + "executionDuration": Object { + "average": 0, + "values": Array [], + }, "id": "alert-123", "instances": Object {}, "lastRun": undefined, @@ -71,6 +76,10 @@ describe('alertInstanceSummaryFromEventLog', () => { "consumer": "alert-consumer-2", "enabled": true, "errorMessages": Array [], + "executionDuration": Object { + "average": 0, + "values": Array [], + }, "id": "alert-456", "instances": Object {}, "lastRun": undefined, @@ -137,7 +146,7 @@ describe('alertInstanceSummaryFromEventLog', () => { dateEnd, }); - const { lastRun, status, instances } = summary; + const { lastRun, status, instances, executionDuration } = summary; expect({ lastRun, status, instances }).toMatchInlineSnapshot(` Object { "instances": Object {}, @@ -145,6 +154,8 @@ describe('alertInstanceSummaryFromEventLog', () => { "status": "OK", } `); + + testExecutionDurations(eventsFactory.getExecutionDurations(), executionDuration); }); test('active alert with no instances but has errors', async () => { @@ -163,7 +174,7 @@ describe('alertInstanceSummaryFromEventLog', () => { dateEnd, }); - const { lastRun, status, errorMessages, instances } = summary; + const { lastRun, status, errorMessages, instances, executionDuration } = summary; expect({ lastRun, status, errorMessages, instances }).toMatchInlineSnapshot(` Object { "errorMessages": Array [ @@ -181,6 +192,8 @@ describe('alertInstanceSummaryFromEventLog', () => { "status": "Error", } `); + + testExecutionDurations(eventsFactory.getExecutionDurations(), executionDuration); }); test('alert with currently inactive instance', async () => { @@ -202,7 +215,7 @@ describe('alertInstanceSummaryFromEventLog', () => { dateEnd, }); - const { lastRun, status, instances } = summary; + const { lastRun, status, instances, executionDuration } = summary; expect({ lastRun, status, instances }).toMatchInlineSnapshot(` Object { "instances": Object { @@ -218,6 +231,8 @@ describe('alertInstanceSummaryFromEventLog', () => { "status": "OK", } `); + + testExecutionDurations(eventsFactory.getExecutionDurations(), executionDuration); }); test('legacy alert with currently inactive instance', async () => { @@ -239,7 +254,7 @@ describe('alertInstanceSummaryFromEventLog', () => { dateEnd, }); - const { lastRun, status, instances } = summary; + const { lastRun, status, instances, executionDuration } = summary; expect({ lastRun, status, instances }).toMatchInlineSnapshot(` Object { "instances": Object { @@ -255,6 +270,8 @@ describe('alertInstanceSummaryFromEventLog', () => { "status": "OK", } `); + + testExecutionDurations(eventsFactory.getExecutionDurations(), executionDuration); }); test('alert with currently inactive instance, no new-instance', async () => { @@ -275,7 +292,7 @@ describe('alertInstanceSummaryFromEventLog', () => { dateEnd, }); - const { lastRun, status, instances } = summary; + const { lastRun, status, instances, executionDuration } = summary; expect({ lastRun, status, instances }).toMatchInlineSnapshot(` Object { "instances": Object { @@ -291,6 +308,8 @@ describe('alertInstanceSummaryFromEventLog', () => { "status": "OK", } `); + + testExecutionDurations(eventsFactory.getExecutionDurations(), executionDuration); }); test('alert with currently active instance', async () => { @@ -312,7 +331,7 @@ describe('alertInstanceSummaryFromEventLog', () => { dateEnd, }); - const { lastRun, status, instances } = summary; + const { lastRun, status, instances, executionDuration } = summary; expect({ lastRun, status, instances }).toMatchInlineSnapshot(` Object { "instances": Object { @@ -328,6 +347,8 @@ describe('alertInstanceSummaryFromEventLog', () => { "status": "Active", } `); + + testExecutionDurations(eventsFactory.getExecutionDurations(), executionDuration); }); test('alert with currently active instance with no action group in event log', async () => { @@ -349,7 +370,7 @@ describe('alertInstanceSummaryFromEventLog', () => { dateEnd, }); - const { lastRun, status, instances } = summary; + const { lastRun, status, instances, executionDuration } = summary; expect({ lastRun, status, instances }).toMatchInlineSnapshot(` Object { "instances": Object { @@ -365,6 +386,8 @@ describe('alertInstanceSummaryFromEventLog', () => { "status": "Active", } `); + + testExecutionDurations(eventsFactory.getExecutionDurations(), executionDuration); }); test('alert with currently active instance that switched action groups', async () => { @@ -386,7 +409,7 @@ describe('alertInstanceSummaryFromEventLog', () => { dateEnd, }); - const { lastRun, status, instances } = summary; + const { lastRun, status, instances, executionDuration } = summary; expect({ lastRun, status, instances }).toMatchInlineSnapshot(` Object { "instances": Object { @@ -402,6 +425,8 @@ describe('alertInstanceSummaryFromEventLog', () => { "status": "Active", } `); + + testExecutionDurations(eventsFactory.getExecutionDurations(), executionDuration); }); test('alert with currently active instance, no new-instance', async () => { @@ -422,7 +447,7 @@ describe('alertInstanceSummaryFromEventLog', () => { dateEnd, }); - const { lastRun, status, instances } = summary; + const { lastRun, status, instances, executionDuration } = summary; expect({ lastRun, status, instances }).toMatchInlineSnapshot(` Object { "instances": Object { @@ -438,6 +463,8 @@ describe('alertInstanceSummaryFromEventLog', () => { "status": "Active", } `); + + testExecutionDurations(eventsFactory.getExecutionDurations(), executionDuration); }); test('alert with active and inactive muted alerts', async () => { @@ -462,7 +489,7 @@ describe('alertInstanceSummaryFromEventLog', () => { dateEnd, }); - const { lastRun, status, instances } = summary; + const { lastRun, status, instances, executionDuration } = summary; expect({ lastRun, status, instances }).toMatchInlineSnapshot(` Object { "instances": Object { @@ -485,6 +512,8 @@ describe('alertInstanceSummaryFromEventLog', () => { "status": "Active", } `); + + testExecutionDurations(eventsFactory.getExecutionDurations(), executionDuration); }); test('alert with active and inactive alerts over many executes', async () => { @@ -515,7 +544,7 @@ describe('alertInstanceSummaryFromEventLog', () => { dateEnd, }); - const { lastRun, status, instances } = summary; + const { lastRun, status, instances, executionDuration } = summary; expect({ lastRun, status, instances }).toMatchInlineSnapshot(` Object { "instances": Object { @@ -538,7 +567,19 @@ describe('alertInstanceSummaryFromEventLog', () => { "status": "Active", } `); + + testExecutionDurations(eventsFactory.getExecutionDurations(), executionDuration); }); + + const testExecutionDurations = ( + actualDurations: number[], + executionDuration?: { average?: number; values?: number[] } + ) => { + expect(executionDuration).toEqual({ + average: Math.round(mean(actualDurations)), + values: actualDurations, + }); + }; }); function dateString(isoBaseDate: string, offsetMillis = 0): string { @@ -573,6 +614,7 @@ export class EventsFactory { event: { provider: EVENT_LOG_PROVIDER, action: EVENT_LOG_ACTIONS.execute, + duration: random(2000, 180000) * 1000 * 1000, }, }; @@ -634,6 +676,12 @@ export class EventsFactory { }); return this; } + + getExecutionDurations(): number[] { + return this.events + .filter((ev) => ev?.event?.action === 'execute' && ev?.event?.duration !== undefined) + .map((ev) => ev?.event?.duration! / (1000 * 1000)); + } } function createAlert(overrides: Partial): SanitizedAlert<{ bar: boolean }> { diff --git a/x-pack/plugins/alerting/server/lib/alert_instance_summary_from_event_log.ts b/x-pack/plugins/alerting/server/lib/alert_instance_summary_from_event_log.ts index 8a6c55dfac619..40fae121df51d 100644 --- a/x-pack/plugins/alerting/server/lib/alert_instance_summary_from_event_log.ts +++ b/x-pack/plugins/alerting/server/lib/alert_instance_summary_from_event_log.ts @@ -5,10 +5,13 @@ * 2.0. */ +import { mean } from 'lodash'; import { SanitizedAlert, AlertInstanceSummary, AlertInstanceStatus } from '../types'; import { IEvent } from '../../../event_log/server'; import { EVENT_LOG_ACTIONS, EVENT_LOG_PROVIDER, LEGACY_EVENT_LOG_ACTIONS } from '../plugin'; +const Millis2Nanos = 1000 * 1000; + export interface AlertInstanceSummaryFromEventLogParams { alert: SanitizedAlert<{ bar: boolean }>; events: IEvent[]; @@ -36,9 +39,14 @@ export function alertInstanceSummaryFromEventLog( lastRun: undefined, errorMessages: [], instances: {}, + executionDuration: { + average: 0, + values: [], + }, }; const instances = new Map(); + const eventDurations: number[] = []; // loop through the events // should be sorted newest to oldest, we want oldest to newest, so reverse @@ -66,6 +74,10 @@ export function alertInstanceSummaryFromEventLog( alertInstanceSummary.status = 'OK'; } + if (event?.event?.duration) { + eventDurations.push(event?.event?.duration / Millis2Nanos); + } + continue; } @@ -111,6 +123,13 @@ export function alertInstanceSummaryFromEventLog( alertInstanceSummary.errorMessages.sort((a, b) => a.date.localeCompare(b.date)); + if (eventDurations.length > 0) { + alertInstanceSummary.executionDuration = { + average: Math.round(mean(eventDurations)), + values: eventDurations, + }; + } + return alertInstanceSummary; } diff --git a/x-pack/plugins/alerting/server/routes/get_rule_alert_summary.test.ts b/x-pack/plugins/alerting/server/routes/get_rule_alert_summary.test.ts index f0f34ae5756b4..5044c5c8617a0 100644 --- a/x-pack/plugins/alerting/server/routes/get_rule_alert_summary.test.ts +++ b/x-pack/plugins/alerting/server/routes/get_rule_alert_summary.test.ts @@ -38,6 +38,10 @@ describe('getRuleAlertSummaryRoute', () => { status: 'OK', errorMessages: [], instances: {}, + executionDuration: { + average: 1, + values: [3, 5, 5], + }, }; it('gets rule alert summary', async () => { diff --git a/x-pack/plugins/alerting/server/routes/get_rule_alert_summary.ts b/x-pack/plugins/alerting/server/routes/get_rule_alert_summary.ts index 5bb8c5efd0d79..131bddcce049d 100644 --- a/x-pack/plugins/alerting/server/routes/get_rule_alert_summary.ts +++ b/x-pack/plugins/alerting/server/routes/get_rule_alert_summary.ts @@ -39,6 +39,7 @@ const rewriteBodyRes: RewriteResponseCase = ({ errorMessages, lastRun, instances: alerts, + executionDuration, ...rest }) => ({ ...rest, @@ -49,6 +50,7 @@ const rewriteBodyRes: RewriteResponseCase = ({ status_end_date: statusEndDate, error_messages: errorMessages, last_run: lastRun, + execution_duration: executionDuration, }); export const getRuleAlertSummaryRoute = ( diff --git a/x-pack/plugins/alerting/server/routes/legacy/get_alert_instance_summary.test.ts b/x-pack/plugins/alerting/server/routes/legacy/get_alert_instance_summary.test.ts index d529aec4162d6..ed2b3056da45e 100644 --- a/x-pack/plugins/alerting/server/routes/legacy/get_alert_instance_summary.test.ts +++ b/x-pack/plugins/alerting/server/routes/legacy/get_alert_instance_summary.test.ts @@ -43,6 +43,10 @@ describe('getAlertInstanceSummaryRoute', () => { status: 'OK', errorMessages: [], instances: {}, + executionDuration: { + average: 0, + values: [], + }, }; it('gets alert instance summary', async () => { diff --git a/x-pack/plugins/alerting/server/rules_client/tests/get_alert_instance_summary.test.ts b/x-pack/plugins/alerting/server/rules_client/tests/get_alert_instance_summary.test.ts index e116f18d779ea..bd88b0f53ab07 100644 --- a/x-pack/plugins/alerting/server/rules_client/tests/get_alert_instance_summary.test.ts +++ b/x-pack/plugins/alerting/server/rules_client/tests/get_alert_instance_summary.test.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { omit, mean } from 'lodash'; import { RulesClient, ConstructorOptions } from '../rules_client'; import { savedObjectsClientMock, loggingSystemMock } from '../../../../../../src/core/server/mocks'; import { taskManagerMock } from '../../../../task_manager/server/mocks'; @@ -138,8 +139,11 @@ describe('getAlertInstanceSummary()', () => { const dateStart = new Date(Date.now() - 60 * 1000).toISOString(); + const durations: number[] = eventsFactory.getExecutionDurations(); + const result = await rulesClient.getAlertInstanceSummary({ id: '1', dateStart }); - expect(result).toMatchInlineSnapshot(` + const resultWithoutExecutionDuration = omit(result, 'executionDuration'); + expect(resultWithoutExecutionDuration).toMatchInlineSnapshot(` Object { "alertTypeId": "123", "consumer": "alert-consumer", @@ -182,6 +186,11 @@ describe('getAlertInstanceSummary()', () => { "throttle": null, } `); + + expect(result.executionDuration).toEqual({ + average: Math.round(mean(durations)), + values: durations, + }); }); // Further tests don't check the result of `getAlertInstanceSummary()`, as the result diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api/alert_summary.test.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api/alert_summary.test.ts index c7b987f2b04bd..9f62e0ed0d50e 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api/alert_summary.test.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api/alert_summary.test.ts @@ -28,6 +28,10 @@ describe('loadAlertInstanceSummary', () => { statusStartDate: '2021-04-01T21:19:25.174Z', tags: [], throttle: null, + executionDuration: { + average: 0, + values: [], + }, }; http.get.mockResolvedValueOnce({ @@ -45,6 +49,10 @@ describe('loadAlertInstanceSummary', () => { status_start_date: '2021-04-01T21:19:25.174Z', tags: [], throttle: null, + execution_duration: { + average: 0, + values: [], + }, }); const result = await loadAlertInstanceSummary({ http, alertId: 'te/st' }); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api/alert_summary.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api/alert_summary.ts index cb924db74cea5..701c8f3a7beec 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api/alert_summary.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/alert_api/alert_summary.ts @@ -17,6 +17,7 @@ const rewriteBodyRes: RewriteRequestCase = ({ status_end_date: statusEndDate, error_messages: errorMessages, last_run: lastRun, + execution_duration: executionDuration, ...rest }: any) => ({ ...rest, @@ -27,6 +28,7 @@ const rewriteBodyRes: RewriteRequestCase = ({ errorMessages, lastRun, instances: alerts, + executionDuration, }); export async function loadAlertInstanceSummary({ diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/execution_duration_utils.test.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/execution_duration_utils.test.ts new file mode 100644 index 0000000000000..da102405c179d --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/execution_duration_utils.test.ts @@ -0,0 +1,68 @@ +/* + * 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 { formatMillisForDisplay, shouldShowDurationWarning } from './execution_duration_utils'; +import { AlertType as RuleType } from '../../types'; + +describe('formatMillisForDisplay', () => { + it('should return 0 for undefined', () => { + expect(formatMillisForDisplay(undefined)).toEqual('00:00:00.000'); + }); + + it('should correctly format millisecond duration in milliseconds', () => { + expect(formatMillisForDisplay(845)).toEqual('00:00:00.845'); + }); + + it('should correctly format second duration in milliseconds', () => { + expect(formatMillisForDisplay(45200)).toEqual('00:00:45.200'); + }); + + it('should correctly format minute duration in milliseconds', () => { + expect(formatMillisForDisplay(122450)).toEqual('00:02:02.450'); + }); + + it('should correctly format hour duration in milliseconds', () => { + expect(formatMillisForDisplay(3634601)).toEqual('01:00:34.601'); + }); +}); + +describe('shouldShowDurationWarning', () => { + it('should return false if rule type or ruleTaskTimeout is undefined', () => { + expect(shouldShowDurationWarning(undefined, 1000)).toEqual(false); + expect(shouldShowDurationWarning(mockRuleType(), 1000)).toEqual(false); + }); + + it('should return false if average duration is less than rule task timeout', () => { + expect(shouldShowDurationWarning(mockRuleType({ ruleTaskTimeout: '1m' }), 1000)).toEqual(false); + }); + + it('should return true if average duration is greater than rule task timeout', () => { + expect(shouldShowDurationWarning(mockRuleType({ ruleTaskTimeout: '1m' }), 120000)).toEqual( + true + ); + }); +}); + +function mockRuleType(overwrites: Partial = {}): RuleType { + return { + id: 'test.testRuleType', + name: 'My Test Rule Type', + actionGroups: [{ id: 'default', name: 'Default Action Group' }], + actionVariables: { + context: [], + state: [], + params: [], + }, + defaultActionGroupId: 'default', + recoveryActionGroup: { id: 'recovered', name: 'Recovered' }, + authorizedConsumers: {}, + producer: 'alerts', + minimumLicenseRequired: 'basic', + enabledInLicense: true, + ...overwrites, + }; +} diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/execution_duration_utils.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/execution_duration_utils.ts new file mode 100644 index 0000000000000..ecad5475274ce --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/execution_duration_utils.ts @@ -0,0 +1,38 @@ +/* + * 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 moment from 'moment'; +import { padStart } from 'lodash'; +import { AlertType as RuleType } from '../../types'; +import { parseDuration } from '../../../../alerting/common'; + +export function formatMillisForDisplay(value: number | undefined) { + if (!value) { + return '00:00:00.000'; + } + + const duration = moment.duration(value); + const durationString = [duration.hours(), duration.minutes(), duration.seconds()] + .map((v: number) => padStart(`${v}`, 2, '0')) + .join(':'); + + // add millis + const millisString = padStart(`${duration.milliseconds()}`, 3, '0'); + return `${durationString}.${millisString}`; +} + +export function shouldShowDurationWarning( + ruleType: RuleType | undefined, + avgDurationMillis: number +) { + if (!ruleType || !ruleType.ruleTaskTimeout) { + return false; + } + const ruleTypeTimeout: string = ruleType.ruleTaskTimeout; + const ruleTypeTimeoutMillis: number = parseDuration(ruleTypeTimeout); + return avgDurationMillis > ruleTypeTimeoutMillis; +} diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_instances.scss b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_instances.scss index 76fd94fd4044b..454d6e20d9323 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_instances.scss +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_instances.scss @@ -9,3 +9,8 @@ width: 85%; } } + +.ruleDurationWarningIcon { + bottom: $euiSizeXS; + position: relative; +} \ No newline at end of file diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_instances.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_instances.test.tsx index cada7748062f1..a790427e36483 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_instances.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_instances.test.tsx @@ -8,9 +8,13 @@ import * as React from 'react'; import uuid from 'uuid'; import { shallow } from 'enzyme'; +import { mountWithIntl, nextTick } from '@kbn/test/jest'; +import { act } from 'react-dom/test-utils'; import { AlertInstances, AlertInstanceListItem, alertInstanceToListItem } from './alert_instances'; import { Alert, AlertInstanceSummary, AlertInstanceStatus, AlertType } from '../../../../types'; import { EuiBasicTable } from '@elastic/eui'; +import { ExecutionDurationChart } from '../../common/components/execution_duration_chart'; + jest.mock('../../../../common/lib/kibana'); const fakeNow = new Date('2020-02-09T23:15:41.941Z'); @@ -271,6 +275,118 @@ describe('alertInstanceToListItem', () => { }); }); +describe('execution duration overview', () => { + it('render last execution status', async () => { + const rule = mockAlert({ + executionStatus: { status: 'ok', lastExecutionDate: new Date('2020-08-20T19:23:38Z') }, + }); + const ruleType = mockAlertType(); + const alertSummary = mockAlertInstanceSummary(); + + const wrapper = mountWithIntl( + + ); + + await act(async () => { + await nextTick(); + wrapper.update(); + }); + + const ruleExecutionStatusStat = wrapper.find('[data-test-subj="ruleStatus-ok"]'); + expect(ruleExecutionStatusStat.exists()).toBeTruthy(); + expect(ruleExecutionStatusStat.first().prop('description')).toEqual('Last response'); + expect(wrapper.find('EuiHealth[data-test-subj="ruleStatus-ok"]').text()).toEqual('Ok'); + }); + + it('renders average execution duration', async () => { + const rule = mockAlert(); + const ruleType = mockAlertType({ ruleTaskTimeout: '10m' }); + const alertSummary = mockAlertInstanceSummary({ + executionDuration: { average: 60284, values: [] }, + }); + + const wrapper = mountWithIntl( + + ); + + await act(async () => { + await nextTick(); + wrapper.update(); + }); + + const avgExecutionDurationPanel = wrapper.find('[data-test-subj="avgExecutionDurationPanel"]'); + expect(avgExecutionDurationPanel.exists()).toBeTruthy(); + expect(avgExecutionDurationPanel.first().prop('color')).toEqual('subdued'); + expect(wrapper.find('EuiStat[data-test-subj="avgExecutionDurationStat"]').text()).toEqual( + 'Average duration00:01:00.284' + ); + expect(wrapper.find('[data-test-subj="ruleDurationWarning"]').exists()).toBeFalsy(); + }); + + it('renders warning when average execution duration exceeds rule timeout', async () => { + const rule = mockAlert(); + const ruleType = mockAlertType({ ruleTaskTimeout: '10m' }); + const alertSummary = mockAlertInstanceSummary({ + executionDuration: { average: 60284345, values: [] }, + }); + + const wrapper = mountWithIntl( + + ); + + await act(async () => { + await nextTick(); + wrapper.update(); + }); + + const avgExecutionDurationPanel = wrapper.find('[data-test-subj="avgExecutionDurationPanel"]'); + expect(avgExecutionDurationPanel.exists()).toBeTruthy(); + expect(avgExecutionDurationPanel.first().prop('color')).toEqual('warning'); + expect(wrapper.find('EuiStat[data-test-subj="avgExecutionDurationStat"]').text()).toEqual( + 'Average duration16:44:44.345' + ); + expect(wrapper.find('[data-test-subj="ruleDurationWarning"]').exists()).toBeTruthy(); + }); + + it('renders execution duration chart', () => { + const rule = mockAlert(); + const ruleType = mockAlertType(); + const alertSummary = mockAlertInstanceSummary(); + + expect( + shallow( + + ) + .find(ExecutionDurationChart) + .exists() + ).toBeTruthy(); + }); +}); + function mockAlert(overloads: Partial = {}): Alert { return { id: uuid.v4(), @@ -342,6 +458,10 @@ function mockAlertInstanceSummary( actionGroupId: 'testActionGroup', }, }, + executionDuration: { + average: 0, + values: [], + }, }; return { ...summary, ...overloads }; } diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_instances.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_instances.tsx index 1583cb188f1c1..9de70699edbdb 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_instances.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alert_details/components/alert_instances.tsx @@ -8,11 +8,26 @@ import React, { useState } from 'react'; import moment, { Duration } from 'moment'; import { i18n } from '@kbn/i18n'; -import { EuiBasicTable, EuiHealth, EuiSpacer, EuiToolTip } from '@elastic/eui'; +import { + EuiBasicTable, + EuiHealth, + EuiSpacer, + EuiToolTip, + EuiFlexGroup, + EuiFlexItem, + EuiHorizontalRule, + EuiPanel, + EuiStat, + EuiIconTip, +} from '@elastic/eui'; // @ts-ignore import { RIGHT_ALIGNMENT, CENTER_ALIGNMENT } from '@elastic/eui/lib/services'; import { padStart, chunk } from 'lodash'; -import { ActionGroup, AlertInstanceStatusValues } from '../../../../../../alerting/common'; +import { + ActionGroup, + AlertExecutionStatusErrorReasons, + AlertInstanceStatusValues, +} from '../../../../../../alerting/common'; import { Alert, AlertInstanceSummary, @@ -27,6 +42,16 @@ import { import { DEFAULT_SEARCH_PAGE_SIZE } from '../../../constants'; import './alert_instances.scss'; import { RuleMutedSwitch } from './rule_muted_switch'; +import { getHealthColor } from '../../alerts_list/components/alert_status_filter'; +import { + alertsStatusesTranslationsMapping, + ALERT_STATUS_LICENSE_ERROR, +} from '../../alerts_list/translations'; +import { + formatMillisForDisplay, + shouldShowDurationWarning, +} from '../../../lib/execution_duration_utils'; +import { ExecutionDurationChart } from '../../common/components/execution_duration_chart'; type AlertInstancesProps = { alert: Alert; @@ -161,8 +186,91 @@ export function AlertInstances({ requestRefresh(); }; + const showDurationWarning = shouldShowDurationWarning( + alertType, + alertInstanceSummary.executionDuration.average + ); + + const healthColor = getHealthColor(alert.executionStatus.status); + const isLicenseError = + alert.executionStatus.error?.reason === AlertExecutionStatusErrorReasons.License; + const statusMessage = isLicenseError + ? ALERT_STATUS_LICENSE_ERROR + : alertsStatusesTranslationsMapping[alert.executionStatus.status]; + return ( <> + + + + + + {statusMessage} + + } + description={i18n.translate( + 'xpack.triggersActionsUI.sections.alertDetails.alertInstancesList.ruleLastExecutionDescription', + { + defaultMessage: `Last response`, + } + )} + /> + + + + + + {showDurationWarning && ( + + + + )} + + {formatMillisForDisplay(alertInstanceSummary.executionDuration.average)} + + + } + description={i18n.translate( + 'xpack.triggersActionsUI.sections.alertDetails.alertInstancesList.avgDurationDescription', + { + defaultMessage: `Average duration`, + } + )} + /> + + + + + + = {}): any { muted: false, }, }, + executionDuration: { + average: 0, + values: [], + }, }; return summary; } diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_list/components/alerts_list.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_list/components/alerts_list.tsx index 91b1b14083ed2..a7d54a896d7ef 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_list/components/alerts_list.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/alerts_list/components/alerts_list.tsx @@ -8,7 +8,7 @@ /* eslint-disable react-hooks/exhaustive-deps */ import { i18n } from '@kbn/i18n'; -import { capitalize, padStart, sortBy } from 'lodash'; +import { capitalize, sortBy } from 'lodash'; import moment from 'moment'; import { FormattedMessage } from '@kbn/i18n/react'; import React, { useEffect, useState } from 'react'; @@ -72,7 +72,6 @@ import { ALERTS_FEATURE_ID, AlertExecutionStatusErrorReasons, formatDuration, - parseDuration, } from '../../../../../../alerting/common'; import { alertsStatusesTranslationsMapping, ALERT_STATUS_LICENSE_ERROR } from '../translations'; import { useKibana } from '../../../../common/lib/kibana'; @@ -82,6 +81,10 @@ import { CenterJustifiedSpinner } from '../../../components/center_justified_spi import { ManageLicenseModal } from './manage_license_modal'; import { checkAlertTypeEnabled } from '../../../lib/check_alert_type_enabled'; import { RuleEnabledSwitch } from './rule_enabled_switch'; +import { + formatMillisForDisplay, + shouldShowDurationWarning, +} from '../../../lib/execution_duration_utils'; const ENTER_KEY = 13; @@ -523,25 +526,14 @@ export const AlertsList: React.FunctionComponent = () => { truncateText: false, 'data-test-subj': 'alertsTableCell-duration', render: (value: number, item: AlertTableItem) => { - const ruleTypeTimeout: string | undefined = alertTypesState.data.get( - item.alertTypeId - )?.ruleTaskTimeout; - const ruleTypeTimeoutMillis: number | undefined = ruleTypeTimeout - ? parseDuration(ruleTypeTimeout) - : undefined; - const showDurationWarning: boolean = ruleTypeTimeoutMillis - ? value > ruleTypeTimeoutMillis - : false; - const duration = moment.duration(value); - const durationString = [duration.hours(), duration.minutes(), duration.seconds()] - .map((v: number) => padStart(`${v}`, 2, '0')) - .join(':'); + const showDurationWarning = shouldShowDurationWarning( + alertTypesState.data.get(item.alertTypeId), + value + ); - // add millis - const millisString = padStart(`${duration.milliseconds()}`, 3, '0'); return ( <> - {`${durationString}.${millisString}`} + {`${formatMillisForDisplay(value)}`} {showDurationWarning && ( { + it('renders empty state when no execution duration values are available', async () => { + const executionDuration = mockExecutionDuration(); + + const wrapper = mountWithIntl(); + + await act(async () => { + await nextTick(); + wrapper.update(); + }); + + expect(wrapper.find('[data-test-subj="executionDurationChartPanel"]').exists()).toBeTruthy(); + expect(wrapper.find('[data-test-subj="executionDurationChartEmpty"]').exists()).toBeTruthy(); + expect(wrapper.find('[data-test-subj="executionDurationChart"]').exists()).toBeFalsy(); + }); + + it('renders chart when execution duration values are available', async () => { + const executionDuration = mockExecutionDuration({ average: 10, values: [1, 2] }); + + const wrapper = mountWithIntl(); + + await act(async () => { + await nextTick(); + wrapper.update(); + }); + + expect(wrapper.find('[data-test-subj="executionDurationChartPanel"]').exists()).toBeTruthy(); + expect(wrapper.find('[data-test-subj="executionDurationChartEmpty"]').exists()).toBeFalsy(); + expect(wrapper.find('[data-test-subj="executionDurationChart"]').exists()).toBeTruthy(); + }); +}); + +describe('padOrTruncateDurations', () => { + it('does nothing when array is the correct length', () => { + expect(padOrTruncateDurations([1, 2, 3], 3)).toEqual([1, 2, 3]); + }); + + it('pads execution duration values when there are fewer than display desires', () => { + expect(padOrTruncateDurations([1, 2, 3], 10)).toEqual([1, 2, 3, 0, 0, 0, 0, 0, 0, 0]); + }); + + it('truncates execution duration values when there are more than display desires', () => { + expect(padOrTruncateDurations([1, 2, 3, 5, 6, 7, 8, 9, 10, 11, 12, 13], 10)).toEqual([ + 3, 5, 6, 7, 8, 9, 10, 11, 12, 13, + ]); + }); +}); + +function mockExecutionDuration( + overwrites: { + average?: number; + values?: number[]; + } = {} +) { + return { + average: 0, + values: [], + ...overwrites, + }; +} diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/common/components/execution_duration_chart.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/common/components/execution_duration_chart.tsx new file mode 100644 index 0000000000000..ca20af9cea0fd --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/common/components/execution_duration_chart.tsx @@ -0,0 +1,133 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import React from 'react'; +import { FormattedMessage } from '@kbn/i18n/react'; +import { + EuiFlexGroup, + EuiFlexItem, + EuiPanel, + EuiEmptyPrompt, + EuiIconTip, + EuiTitle, +} from '@elastic/eui'; +import lightEuiTheme from '@elastic/eui/dist/eui_theme_light.json'; +import { Axis, BarSeries, Chart, CurveType, LineSeries, Settings } from '@elastic/charts'; +import { assign, fill } from 'lodash'; +import { formatMillisForDisplay } from '../../../lib/execution_duration_utils'; + +export interface ComponentOpts { + executionDuration: { + average: number; + values: number[]; + }; +} + +const DESIRED_NUM_EXECUTION_DURATIONS = 30; + +export const ExecutionDurationChart: React.FunctionComponent = ({ + executionDuration, +}: ComponentOpts) => { + const paddedExecutionDurations = padOrTruncateDurations( + executionDuration.values, + DESIRED_NUM_EXECUTION_DURATIONS + ); + + return ( + + + + +

+ +

+
+
+ + + +
+ + {executionDuration.values && executionDuration.values.length > 0 ? ( + <> + + + [ndx, val])} + /> + [ndx, executionDuration.average])} + curve={CurveType.CURVE_NATURAL} + /> + formatMillisForDisplay(d)} /> + + + ) : ( + <> + +

+ +

+ + } + /> + + )} +
+ ); +}; + +export function padOrTruncateDurations(values: number[], desiredSize: number) { + if (values.length === desiredSize) { + return values; + } else if (values.length < desiredSize) { + return assign(fill(new Array(desiredSize), 0), values); + } else { + // oldest durations are at the start of the array, so take the last {desiredSize} values + return values.slice(-desiredSize); + } +} diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/get_alert_instance_summary.ts b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/get_alert_instance_summary.ts index d4ca6c2aa9cd8..181e6cc940c38 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/get_alert_instance_summary.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/tests/alerting/get_alert_instance_summary.ts @@ -73,6 +73,7 @@ export default function createGetAlertInstanceSummaryTests({ getService }: FtrPr 'status_start_date', 'status_end_date', 'last_run', + 'execution_duration', ]); expect(stableBody).to.eql({ name: 'abc', diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/get_alert_instance_summary.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/get_alert_instance_summary.ts index 099502e375faa..ff55c376c04b2 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/get_alert_instance_summary.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/get_alert_instance_summary.ts @@ -58,7 +58,12 @@ export default function createGetAlertInstanceSummaryTests({ getService }: FtrPr const { status_start_date: statusStartDate, status_end_date: statusEndDate } = response.body; expect(Date.parse(statusStartDate)).to.be.lessThan(Date.parse(statusEndDate)); - const stableBody = omit(response.body, ['status_start_date', 'status_end_date', 'last_run']); + const stableBody = omit(response.body, [ + 'status_start_date', + 'status_end_date', + 'last_run', + 'execution_duration', + ]); expect(stableBody).to.eql({ id: createdAlert.id, name: 'abc', @@ -91,7 +96,12 @@ export default function createGetAlertInstanceSummaryTests({ getService }: FtrPr const { status_start_date: statusStartDate, status_end_date: statusEndDate } = response.body; expect(Date.parse(statusStartDate)).to.be.lessThan(Date.parse(statusEndDate)); - const stableBody = omit(response.body, ['status_start_date', 'status_end_date', 'last_run']); + const stableBody = omit(response.body, [ + 'status_start_date', + 'status_end_date', + 'last_run', + 'execution_duration', + ]); expect(stableBody).to.eql({ id: createdAlert.id, name: 'abc', From 91d48ff475075691c833ed401cfaf4013c0786d1 Mon Sep 17 00:00:00 2001 From: Scotty Bollinger Date: Thu, 14 Oct 2021 15:01:42 -0500 Subject: [PATCH 04/24] [Workplace Search] Fix loading state bug and update button (#115068) * Change source deletion to set entire page loading Do this instead of having the button loading * Replace text button with icon button for blocked windows --- .../synchronization/blocked_window_item.test.tsx | 4 ++-- .../synchronization/blocked_window_item.tsx | 13 +++++++++---- .../views/content_sources/source_logic.ts | 2 +- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/blocked_window_item.test.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/blocked_window_item.test.tsx index f3c01b8d94d37..183d336ea62da 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/blocked_window_item.test.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/blocked_window_item.test.tsx @@ -16,7 +16,7 @@ import { shallow } from 'enzyme'; import moment from 'moment'; import { - EuiButton, + EuiButtonIcon, EuiDatePicker, EuiDatePickerRange, EuiSelect, @@ -53,7 +53,7 @@ describe('BlockedWindowItem', () => { it('handles remove button click', () => { const wrapper = shallow(); - wrapper.find(EuiButton).simulate('click'); + wrapper.find(EuiButtonIcon).simulate('click'); expect(removeBlockedWindow).toHaveBeenCalledWith(0); }); diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/blocked_window_item.tsx b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/blocked_window_item.tsx index 272efc6fc3c50..3399f41254004 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/blocked_window_item.tsx +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/components/synchronization/blocked_window_item.tsx @@ -11,7 +11,7 @@ import { useActions, useValues } from 'kea'; import moment from 'moment'; import { - EuiButton, + EuiButtonIcon, EuiDatePicker, EuiDatePickerRange, EuiFlexGroup, @@ -179,9 +179,14 @@ export const BlockedWindowItem: React.FC = ({ blockedWindow, index }) => /> - removeBlockedWindow(index)}> - {REMOVE_BUTTON} - + removeBlockedWindow(index)} + aria-label={REMOVE_BUTTON} + title={REMOVE_BUTTON} + /> diff --git a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_logic.ts b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_logic.ts index 9dcd0824cad11..0b67e3f2da79b 100644 --- a/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_logic.ts +++ b/x-pack/plugins/enterprise_search/public/applications/workplace_search/views/content_sources/source_logic.ts @@ -112,6 +112,7 @@ export const SourceLogic = kea>({ { setContentSource: () => false, resetSourceState: () => true, + removeContentSource: () => true, }, ], buttonLoading: [ @@ -119,7 +120,6 @@ export const SourceLogic = kea>({ { setButtonNotLoading: () => false, resetSourceState: () => false, - removeContentSource: () => true, }, ], sectionLoading: [ From e49ec25fae79ed83245d23cf33edcdaaaf912fcd Mon Sep 17 00:00:00 2001 From: Kevin Lacabane Date: Thu, 14 Oct 2021 22:47:57 +0200 Subject: [PATCH 05/24] [Stack Monitoring] Fix monitoring func test (#115013) * add noDataContainer test-subj * remove unnecessary test step * Fix test subjects for overview page * remove unused service * update NoData component snapshots Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../no_data/__snapshots__/no_data.test.js.snap | 2 ++ .../public/components/no_data/no_data.js | 16 ++++++++++------ .../apps/monitoring/enable_monitoring/index.js | 3 --- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/x-pack/plugins/monitoring/public/components/no_data/__snapshots__/no_data.test.js.snap b/x-pack/plugins/monitoring/public/components/no_data/__snapshots__/no_data.test.js.snap index 34a4c049dddcc..8852d104fe00a 100644 --- a/x-pack/plugins/monitoring/public/components/no_data/__snapshots__/no_data.test.js.snap +++ b/x-pack/plugins/monitoring/public/components/no_data/__snapshots__/no_data.test.js.snap @@ -3,6 +3,7 @@ exports[`NoData should show a default message if reason is unknown 1`] = `

{ + return {children}; + }; + if (isCloudEnabled) { return ( - +

- + ); } if (useInternalCollection) { return ( - +

- + ); } return ( - +

- + ); } diff --git a/x-pack/test/functional/apps/monitoring/enable_monitoring/index.js b/x-pack/test/functional/apps/monitoring/enable_monitoring/index.js index 79bd479c45a17..cce6401453d21 100644 --- a/x-pack/test/functional/apps/monitoring/enable_monitoring/index.js +++ b/x-pack/test/functional/apps/monitoring/enable_monitoring/index.js @@ -11,7 +11,6 @@ export default function ({ getService, getPageObjects }) { const PageObjects = getPageObjects(['monitoring', 'common', 'header']); const esSupertest = getService('esSupertest'); const noData = getService('monitoringNoData'); - const testSubjects = getService('testSubjects'); const clusterOverview = getService('monitoringClusterOverview'); const retry = getService('retry'); const esDeleteAllIndices = getService('esDeleteAllIndices'); @@ -53,8 +52,6 @@ export default function ({ getService, getPageObjects }) { // Here we are checking that once Monitoring is enabled, // it moves on to the cluster overview page. await retry.tryForTime(20000, async () => { - // Click the refresh button - await testSubjects.click('querySubmitButton'); await clusterOverview.closeAlertsModal(); expect(await clusterOverview.isOnClusterOverview()).to.be(true); }); From 8db36d9f4a93b89e1c3fba166e90f646290958ce Mon Sep 17 00:00:00 2001 From: Vadim Yakhin Date: Thu, 14 Oct 2021 15:36:56 -0700 Subject: [PATCH 06/24] [Fleet, Workplace Search] Add Workplace Search connectors as non-Fleet integrations (#114919) * Add icons * Add new categories * Add Workplace Search connectors to the unified integrations view * Add a new enterprise_search shipper * Update number of custom integrations in test * Change customIntegrations type to optional * Revert "Update number of custom integrations in test" This reverts commit 30214b2c7c2ba290176b44a80a72a5392918d9dc. The reason is that while this test passes with 2 separate commands for functional test runner, it fails when it is run with a single command. Reverting to make the CI pass. We will look into this test separately. I will link the investigation issue in the PR. --- .../custom_integrations/common/index.ts | 10 +- x-pack/plugins/enterprise_search/kibana.json | 2 +- .../public/assets/source_icons/box.svg | 1 + .../assets/source_icons/confluence_cloud.svg | 1 + .../assets/source_icons/confluence_server.svg | 1 + .../assets/source_icons/custom_api_source.svg | 1 + .../public/assets/source_icons/dropbox.svg | 1 + .../public/assets/source_icons/github.svg | 1 + .../source_icons/github_enterprise_server.svg | 1 + .../public/assets/source_icons/gmail.svg | 1 + .../assets/source_icons/google_drive.svg | 1 + .../public/assets/source_icons/jira_cloud.svg | 1 + .../assets/source_icons/jira_server.svg | 1 + .../public/assets/source_icons/onedrive.svg | 1 + .../public/assets/source_icons/salesforce.svg | 1 + .../source_icons/salesforce_sandbox.svg | 1 + .../public/assets/source_icons/servicenow.svg | 1 + .../assets/source_icons/sharepoint_online.svg | 1 + .../public/assets/source_icons/slack.svg | 1 + .../public/assets/source_icons/zendesk.svg | 1 + .../enterprise_search/server/integrations.ts | 304 ++++++++++++++++++ .../enterprise_search/server/plugin.ts | 9 +- 22 files changed, 340 insertions(+), 3 deletions(-) create mode 100644 x-pack/plugins/enterprise_search/public/assets/source_icons/box.svg create mode 100644 x-pack/plugins/enterprise_search/public/assets/source_icons/confluence_cloud.svg create mode 100644 x-pack/plugins/enterprise_search/public/assets/source_icons/confluence_server.svg create mode 100644 x-pack/plugins/enterprise_search/public/assets/source_icons/custom_api_source.svg create mode 100644 x-pack/plugins/enterprise_search/public/assets/source_icons/dropbox.svg create mode 100644 x-pack/plugins/enterprise_search/public/assets/source_icons/github.svg create mode 100644 x-pack/plugins/enterprise_search/public/assets/source_icons/github_enterprise_server.svg create mode 100644 x-pack/plugins/enterprise_search/public/assets/source_icons/gmail.svg create mode 100644 x-pack/plugins/enterprise_search/public/assets/source_icons/google_drive.svg create mode 100644 x-pack/plugins/enterprise_search/public/assets/source_icons/jira_cloud.svg create mode 100644 x-pack/plugins/enterprise_search/public/assets/source_icons/jira_server.svg create mode 100644 x-pack/plugins/enterprise_search/public/assets/source_icons/onedrive.svg create mode 100644 x-pack/plugins/enterprise_search/public/assets/source_icons/salesforce.svg create mode 100644 x-pack/plugins/enterprise_search/public/assets/source_icons/salesforce_sandbox.svg create mode 100644 x-pack/plugins/enterprise_search/public/assets/source_icons/servicenow.svg create mode 100644 x-pack/plugins/enterprise_search/public/assets/source_icons/sharepoint_online.svg create mode 100644 x-pack/plugins/enterprise_search/public/assets/source_icons/slack.svg create mode 100644 x-pack/plugins/enterprise_search/public/assets/source_icons/zendesk.svg create mode 100644 x-pack/plugins/enterprise_search/server/integrations.ts diff --git a/src/plugins/custom_integrations/common/index.ts b/src/plugins/custom_integrations/common/index.ts index de2a6592465a2..944ac6ba3e6ee 100755 --- a/src/plugins/custom_integrations/common/index.ts +++ b/src/plugins/custom_integrations/common/index.ts @@ -40,8 +40,15 @@ export const INTEGRATION_CATEGORY_DISPLAY = { web: 'Web', // Kibana added - upload_file: 'Upload a file', + communication: 'Communication', + customer_support: 'Customer Support', + document_storage: 'Document Storage', + enterprise_management: 'Enterprise Management', + knowledge_platform: 'Knowledge Platform', language_client: 'Language client', + project_management: 'Project Management', + software_development: 'Software Development', + upload_file: 'Upload a file', }; /** @@ -70,6 +77,7 @@ export interface IntegrationCategoryCount { // TODO: consider i18n export const SHIPPER_DISPLAY = { beats: 'Beats', + enterprise_search: 'Enterprise Search', language_clients: 'Language clients', other: 'Other', sample_data: 'Sample data', diff --git a/x-pack/plugins/enterprise_search/kibana.json b/x-pack/plugins/enterprise_search/kibana.json index 9df01988fbd89..76b53766b1f0e 100644 --- a/x-pack/plugins/enterprise_search/kibana.json +++ b/x-pack/plugins/enterprise_search/kibana.json @@ -4,7 +4,7 @@ "kibanaVersion": "kibana", "requiredPlugins": ["features", "spaces", "security", "licensing", "data", "charts", "infra"], "configPath": ["enterpriseSearch"], - "optionalPlugins": ["usageCollection", "home", "cloud"], + "optionalPlugins": ["usageCollection", "home", "cloud", "customIntegrations"], "server": true, "ui": true, "requiredBundles": ["home", "kibanaReact"], diff --git a/x-pack/plugins/enterprise_search/public/assets/source_icons/box.svg b/x-pack/plugins/enterprise_search/public/assets/source_icons/box.svg new file mode 100644 index 0000000000000..b1b542eadd59c --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/assets/source_icons/box.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/x-pack/plugins/enterprise_search/public/assets/source_icons/confluence_cloud.svg b/x-pack/plugins/enterprise_search/public/assets/source_icons/confluence_cloud.svg new file mode 100644 index 0000000000000..7aac36a6fe3c5 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/assets/source_icons/confluence_cloud.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/x-pack/plugins/enterprise_search/public/assets/source_icons/confluence_server.svg b/x-pack/plugins/enterprise_search/public/assets/source_icons/confluence_server.svg new file mode 100644 index 0000000000000..7aac36a6fe3c5 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/assets/source_icons/confluence_server.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/x-pack/plugins/enterprise_search/public/assets/source_icons/custom_api_source.svg b/x-pack/plugins/enterprise_search/public/assets/source_icons/custom_api_source.svg new file mode 100644 index 0000000000000..cc07fbbc50877 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/assets/source_icons/custom_api_source.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/x-pack/plugins/enterprise_search/public/assets/source_icons/dropbox.svg b/x-pack/plugins/enterprise_search/public/assets/source_icons/dropbox.svg new file mode 100644 index 0000000000000..01e5a7735de12 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/assets/source_icons/dropbox.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/x-pack/plugins/enterprise_search/public/assets/source_icons/github.svg b/x-pack/plugins/enterprise_search/public/assets/source_icons/github.svg new file mode 100644 index 0000000000000..aa9c3e5b45146 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/assets/source_icons/github.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/x-pack/plugins/enterprise_search/public/assets/source_icons/github_enterprise_server.svg b/x-pack/plugins/enterprise_search/public/assets/source_icons/github_enterprise_server.svg new file mode 100644 index 0000000000000..aa9c3e5b45146 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/assets/source_icons/github_enterprise_server.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/x-pack/plugins/enterprise_search/public/assets/source_icons/gmail.svg b/x-pack/plugins/enterprise_search/public/assets/source_icons/gmail.svg new file mode 100644 index 0000000000000..31fe60c6a63f9 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/assets/source_icons/gmail.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/x-pack/plugins/enterprise_search/public/assets/source_icons/google_drive.svg b/x-pack/plugins/enterprise_search/public/assets/source_icons/google_drive.svg new file mode 100644 index 0000000000000..f3fe82cd3cd98 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/assets/source_icons/google_drive.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/x-pack/plugins/enterprise_search/public/assets/source_icons/jira_cloud.svg b/x-pack/plugins/enterprise_search/public/assets/source_icons/jira_cloud.svg new file mode 100644 index 0000000000000..c12e55798d889 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/assets/source_icons/jira_cloud.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/x-pack/plugins/enterprise_search/public/assets/source_icons/jira_server.svg b/x-pack/plugins/enterprise_search/public/assets/source_icons/jira_server.svg new file mode 100644 index 0000000000000..4dfd0fd910079 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/assets/source_icons/jira_server.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/x-pack/plugins/enterprise_search/public/assets/source_icons/onedrive.svg b/x-pack/plugins/enterprise_search/public/assets/source_icons/onedrive.svg new file mode 100644 index 0000000000000..c390dff1e418f --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/assets/source_icons/onedrive.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/x-pack/plugins/enterprise_search/public/assets/source_icons/salesforce.svg b/x-pack/plugins/enterprise_search/public/assets/source_icons/salesforce.svg new file mode 100644 index 0000000000000..ef6d552949424 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/assets/source_icons/salesforce.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/x-pack/plugins/enterprise_search/public/assets/source_icons/salesforce_sandbox.svg b/x-pack/plugins/enterprise_search/public/assets/source_icons/salesforce_sandbox.svg new file mode 100644 index 0000000000000..ef6d552949424 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/assets/source_icons/salesforce_sandbox.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/x-pack/plugins/enterprise_search/public/assets/source_icons/servicenow.svg b/x-pack/plugins/enterprise_search/public/assets/source_icons/servicenow.svg new file mode 100644 index 0000000000000..6388ec44d21d7 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/assets/source_icons/servicenow.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/x-pack/plugins/enterprise_search/public/assets/source_icons/sharepoint_online.svg b/x-pack/plugins/enterprise_search/public/assets/source_icons/sharepoint_online.svg new file mode 100644 index 0000000000000..aebfd7a8e49c0 --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/assets/source_icons/sharepoint_online.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/x-pack/plugins/enterprise_search/public/assets/source_icons/slack.svg b/x-pack/plugins/enterprise_search/public/assets/source_icons/slack.svg new file mode 100644 index 0000000000000..8f6fc0c987eaa --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/assets/source_icons/slack.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/x-pack/plugins/enterprise_search/public/assets/source_icons/zendesk.svg b/x-pack/plugins/enterprise_search/public/assets/source_icons/zendesk.svg new file mode 100644 index 0000000000000..8afd143dd9a7c --- /dev/null +++ b/x-pack/plugins/enterprise_search/public/assets/source_icons/zendesk.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/x-pack/plugins/enterprise_search/server/integrations.ts b/x-pack/plugins/enterprise_search/server/integrations.ts new file mode 100644 index 0000000000000..48909261243e8 --- /dev/null +++ b/x-pack/plugins/enterprise_search/server/integrations.ts @@ -0,0 +1,304 @@ +/* + * 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 { i18n } from '@kbn/i18n'; +import type { HttpServiceSetup } from 'src/core/server'; + +import type { IntegrationCategory } from '../../../../src/plugins/custom_integrations/common'; +import type { CustomIntegrationsPluginSetup } from '../../../../src/plugins/custom_integrations/server'; + +interface WorkplaceSearchIntegration { + id: string; + title: string; + description: string; + categories: IntegrationCategory[]; + uiInternalPath?: string; +} + +const workplaceSearchIntegrations: WorkplaceSearchIntegration[] = [ + { + id: 'box', + title: i18n.translate('xpack.enterpriseSearch.workplaceSearch.integrations.boxName', { + defaultMessage: 'Box', + }), + description: i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.integrations.boxDescription', + { + defaultMessage: 'Search over your files and folders stored on Box with Workplace Search.', + } + ), + categories: ['document_storage'], + }, + { + id: 'confluence_cloud', + title: i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.integrations.confluenceCloudName', + { + defaultMessage: 'Confluence Cloud', + } + ), + description: i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.integrations.confluenceCloudDescription', + { + defaultMessage: + 'Search over your organizational content on Confluence Cloud with Workplace Search.', + } + ), + categories: ['knowledge_platform'], + }, + { + id: 'confluence_server', + title: i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.integrations.confluenceServerName', + { + defaultMessage: 'Confluence Server', + } + ), + description: i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.integrations.confluenceServerDescription', + { + defaultMessage: + 'Search over your organizational content on Confluence Server with Workplace Search.', + } + ), + categories: ['knowledge_platform'], + }, + { + id: 'dropbox', + title: i18n.translate('xpack.enterpriseSearch.workplaceSearch.integrations.dropboxName', { + defaultMessage: 'Dropbox', + }), + description: i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.integrations.dropboxDescription', + { + defaultMessage: + 'Search over your files and folders stored on Dropbox with Workplace Search.', + } + ), + categories: ['document_storage'], + }, + { + id: 'github', + title: i18n.translate('xpack.enterpriseSearch.workplaceSearch.integrations.githubName', { + defaultMessage: 'GitHub', + }), + description: i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.integrations.githubDescription', + { + defaultMessage: 'Search over your projects and repos on GitHub with Workplace Search.', + } + ), + categories: ['software_development'], + }, + { + id: 'github_enterprise_server', + title: i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.integrations.githubEnterpriseServerName', + { + defaultMessage: 'GitHub Enterprise Server', + } + ), + description: i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.integrations.githubEnterpriseServerDescription', + { + defaultMessage: + 'Search over your projects and repos on GitHub Enterprise Server with Workplace Search.', + } + ), + categories: ['software_development'], + }, + { + id: 'gmail', + title: i18n.translate('xpack.enterpriseSearch.workplaceSearch.integrations.gmailName', { + defaultMessage: 'Gmail', + }), + description: i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.integrations.gmailDescription', + { + defaultMessage: 'Search over your emails managed by Gmail with Workplace Search.', + } + ), + categories: ['communication'], + }, + { + id: 'google_drive', + title: i18n.translate('xpack.enterpriseSearch.workplaceSearch.integrations.googleDriveName', { + defaultMessage: 'Google Drive', + }), + description: i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.integrations.googleDriveDescription', + { + defaultMessage: 'Search over your documents on Google Drive with Workplace Search.', + } + ), + categories: ['document_storage'], + }, + { + id: 'jira_cloud', + title: i18n.translate('xpack.enterpriseSearch.workplaceSearch.integrations.jiraCloudName', { + defaultMessage: 'Jira Cloud', + }), + description: i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.integrations.jiraCloudDescription', + { + defaultMessage: 'Search over your project workflow on Jira Cloud with Workplace Search.', + } + ), + categories: ['project_management'], + }, + { + id: 'jira_server', + title: i18n.translate('xpack.enterpriseSearch.workplaceSearch.integrations.jiraServerName', { + defaultMessage: 'Jira Server', + }), + description: i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.integrations.jiraServerDescription', + { + defaultMessage: 'Search over your project workflow on Jira Server with Workplace Search.', + } + ), + categories: ['project_management'], + }, + { + id: 'onedrive', + title: i18n.translate('xpack.enterpriseSearch.workplaceSearch.integrations.onedriveName', { + defaultMessage: 'OneDrive', + }), + description: i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.integrations.onedriveDescription', + { + defaultMessage: 'Search over your files stored on OneDrive with Workplace Search.', + } + ), + categories: ['document_storage'], + uiInternalPath: '/app/enterprise_search/workplace_search/sources/add/one_drive', + }, + { + id: 'salesforce', + title: i18n.translate('xpack.enterpriseSearch.workplaceSearch.integrations.salesforceName', { + defaultMessage: 'Salesforce', + }), + description: i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.integrations.salesforceDescription', + { + defaultMessage: 'Search over your content on Salesforce with Workplace Search.', + } + ), + categories: ['crm'], + }, + { + id: 'salesforce_sandbox', + title: i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.integrations.salesforceSandboxName', + { + defaultMessage: 'Salesforce Sandbox', + } + ), + description: i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.integrations.salesforceSandboxDescription', + { + defaultMessage: 'Search over your content on Salesforce Sandbox with Workplace Search.', + } + ), + categories: ['crm'], + }, + { + id: 'servicenow', + title: i18n.translate('xpack.enterpriseSearch.workplaceSearch.integrations.servicenowName', { + defaultMessage: 'ServiceNow', + }), + description: i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.integrations.servicenowDescription', + { + defaultMessage: 'Search over your content on ServiceNow with Workplace Search.', + } + ), + categories: ['enterprise_management'], + }, + { + id: 'sharepoint_online', + title: i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.integrations.sharepointOnlineName', + { + defaultMessage: 'SharePoint Online', + } + ), + description: i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.integrations.sharepointOnlineDescription', + { + defaultMessage: 'Search over your files stored on SharePoint Online with Workplace Search.', + } + ), + categories: ['document_storage'], + uiInternalPath: '/app/enterprise_search/workplace_search/sources/add/share_point', + }, + { + id: 'slack', + title: i18n.translate('xpack.enterpriseSearch.workplaceSearch.integrations.slackName', { + defaultMessage: 'Slack', + }), + description: i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.integrations.slackDescription', + { + defaultMessage: 'Search over your messages on Slack with Workplace Search.', + } + ), + categories: ['communication'], + }, + { + id: 'zendesk', + title: i18n.translate('xpack.enterpriseSearch.workplaceSearch.integrations.zendeskName', { + defaultMessage: 'Zendesk', + }), + description: i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.integrations.zendeskDescription', + { + defaultMessage: 'Search over your tickets on Zendesk with Workplace Search.', + } + ), + categories: ['customer_support'], + }, + { + id: 'custom_api_source', + title: i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.integrations.customApiSourceName', + { + defaultMessage: 'Custom API Source', + } + ), + description: i18n.translate( + 'xpack.enterpriseSearch.workplaceSearch.integrations.customApiSourceDescription', + { + defaultMessage: + 'Search over anything by building your own integration with Workplace Search.', + } + ), + categories: ['custom'], + uiInternalPath: '/app/enterprise_search/workplace_search/sources/add/custom', + }, +]; + +export const registerEnterpriseSearchIntegrations = ( + http: HttpServiceSetup, + customIntegrations: CustomIntegrationsPluginSetup +) => { + workplaceSearchIntegrations.forEach((integration) => { + customIntegrations.registerCustomIntegration({ + uiInternalPath: `/app/enterprise_search/workplace_search/sources/add/${integration.id}`, + icons: [ + { + type: 'svg', + src: http.basePath.prepend( + `/plugins/enterpriseSearch/assets/source_icons/${integration.id}.svg` + ), + }, + ], + isBeta: false, + shipper: 'enterprise_search', + ...integration, + }); + }); +}; diff --git a/x-pack/plugins/enterprise_search/server/plugin.ts b/x-pack/plugins/enterprise_search/server/plugin.ts index 63ac8ed02afbe..f40046c22b419 100644 --- a/x-pack/plugins/enterprise_search/server/plugin.ts +++ b/x-pack/plugins/enterprise_search/server/plugin.ts @@ -15,6 +15,7 @@ import { KibanaRequest, DEFAULT_APP_CATEGORIES, } from '../../../../src/core/server'; +import { CustomIntegrationsPluginSetup } from '../../../../src/plugins/custom_integrations/server'; import { UsageCollectionSetup } from '../../../../src/plugins/usage_collection/server'; import { PluginSetupContract as FeaturesPluginSetup } from '../../features/server'; import { InfraPluginSetup } from '../../infra/server'; @@ -31,6 +32,7 @@ import { import { registerTelemetryUsageCollector as registerASTelemetryUsageCollector } from './collectors/app_search/telemetry'; import { registerTelemetryUsageCollector as registerESTelemetryUsageCollector } from './collectors/enterprise_search/telemetry'; import { registerTelemetryUsageCollector as registerWSTelemetryUsageCollector } from './collectors/workplace_search/telemetry'; +import { registerEnterpriseSearchIntegrations } from './integrations'; import { checkAccess } from './lib/check_access'; import { entSearchHttpAgent } from './lib/enterprise_search_http_agent'; @@ -55,6 +57,7 @@ interface PluginsSetup { security: SecurityPluginSetup; features: FeaturesPluginSetup; infra: InfraPluginSetup; + customIntegrations?: CustomIntegrationsPluginSetup; } interface PluginsStart { @@ -80,11 +83,15 @@ export class EnterpriseSearchPlugin implements Plugin { public setup( { capabilities, http, savedObjects, getStartServices }: CoreSetup, - { usageCollection, security, features, infra }: PluginsSetup + { usageCollection, security, features, infra, customIntegrations }: PluginsSetup ) { const config = this.config; const log = this.logger; + if (customIntegrations) { + registerEnterpriseSearchIntegrations(http, customIntegrations); + } + /* * Initialize config.ssl.certificateAuthorities file(s) - required for all API calls (+ access checks) */ From 0a3ede8fd105c66081f8ef186c11f3ba64e7eb32 Mon Sep 17 00:00:00 2001 From: Tyler Smalley Date: Thu, 14 Oct 2021 15:59:02 -0700 Subject: [PATCH 07/24] [ci] Explicitly define tasks for ES snapshot build (#115074) Signed-off-by: Tyler Smalley --- .buildkite/scripts/steps/es_snapshots/build.sh | 9 ++++++++- packages/kbn-es/src/utils/build_snapshot.js | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/.buildkite/scripts/steps/es_snapshots/build.sh b/.buildkite/scripts/steps/es_snapshots/build.sh index 91b5004594a6d..975d5944da883 100755 --- a/.buildkite/scripts/steps/es_snapshots/build.sh +++ b/.buildkite/scripts/steps/es_snapshots/build.sh @@ -61,7 +61,14 @@ export DOCKER_TLS_CERTDIR="$CERTS_DIR" export DOCKER_HOST=localhost:2377 echo "--- Build Elasticsearch" -./gradlew -Dbuild.docker=true assemble --parallel +./gradlew \ + :distribution:archives:darwin-aarch64-tar:assemble \ + :distribution:archives:darwin-tar:assemble \ + :distribution:docker:docker-export:assemble \ + :distribution:archives:linux-aarch64-tar:assemble \ + :distribution:archives:linux-tar:assemble \ + :distribution:archives:windows-zip:assemble \ + --parallel echo "--- Create distribution archives" find distribution -type f \( -name 'elasticsearch-*-*-*-*.tar.gz' -o -name 'elasticsearch-*-*-*-*.zip' \) -not -path '*no-jdk*' -not -path '*build-context*' -exec cp {} "$destination" \; diff --git a/packages/kbn-es/src/utils/build_snapshot.js b/packages/kbn-es/src/utils/build_snapshot.js index c60ef61e98538..ec26ba69e658b 100644 --- a/packages/kbn-es/src/utils/build_snapshot.js +++ b/packages/kbn-es/src/utils/build_snapshot.js @@ -26,6 +26,7 @@ const onceEvent = (emitter, event) => new Promise((resolve) => emitter.once(even * @returns {Object} containing archive and optional plugins * * Gradle tasks: + * $ ./gradlew tasks --all | grep 'distribution.*assemble\s' * :distribution:archives:darwin-tar:assemble * :distribution:archives:linux-tar:assemble * :distribution:archives:windows-zip:assemble From 45f02d3c9bfe7708ebd609b8f321c93dbe1a6e1f Mon Sep 17 00:00:00 2001 From: Mat Schaffer Date: Fri, 15 Oct 2021 08:46:06 +0900 Subject: [PATCH 08/24] [Stack Monitoring] Enable react stack monitoring by default (#114436) * Enable react stack monitoring by default * Also update test snapshot Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- x-pack/plugins/monitoring/server/config.test.ts | 2 +- x-pack/plugins/monitoring/server/config.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/monitoring/server/config.test.ts b/x-pack/plugins/monitoring/server/config.test.ts index 76880d8f83d34..f4604903e0068 100644 --- a/x-pack/plugins/monitoring/server/config.test.ts +++ b/x-pack/plugins/monitoring/server/config.test.ts @@ -107,7 +107,7 @@ describe('config schema', () => { "index": "metricbeat-*", }, "min_interval_seconds": 10, - "render_react_app": false, + "render_react_app": true, "show_license_expiration": true, }, } diff --git a/x-pack/plugins/monitoring/server/config.ts b/x-pack/plugins/monitoring/server/config.ts index 5c2bdc1424f93..ddbfd480a9f4e 100644 --- a/x-pack/plugins/monitoring/server/config.ts +++ b/x-pack/plugins/monitoring/server/config.ts @@ -51,7 +51,7 @@ export const configSchema = schema.object({ }), min_interval_seconds: schema.number({ defaultValue: 10 }), show_license_expiration: schema.boolean({ defaultValue: true }), - render_react_app: schema.boolean({ defaultValue: false }), + render_react_app: schema.boolean({ defaultValue: true }), }), kibana: schema.object({ collection: schema.object({ From ed9859ac147bfeb597f03b30514afc10190f05bf Mon Sep 17 00:00:00 2001 From: Frank Hassanabad Date: Thu, 14 Oct 2021 20:24:01 -0600 Subject: [PATCH 09/24] [Security solutions] Adds linter rule to forbid usage of no-non-null-assertion (TypeScript ! bang operator) (#114375) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Fixes: https://github.com/elastic/kibana/issues/114535 **What this linter rule does:** * Sets the [@typescript-eslint/no-non-null-assertion](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-non-null-assertion.md) linter rule to become an error if seen. If you try to use the `!` operator you get an error and nice helper message that tries to encourage better practices such as this one: Screen Shot 2021-10-07 at 11 26 14 AM **Why are we deciding to set this linter rule?** * Recommended from Kibana [styleguide](https://github.com/elastic/kibana/blob/master/STYLEGUIDE.mdx#avoid-non-null-assertions) for ~2 years now and still recommended. * A lot of TypeScript has evolved and has operators such as `?` which can replace the `!` in most cases. Other cases can use a throw explicitly or other ways to manage this. * Some types can change instead of using this operator and we should just change the types. * TypeScript flows have improved and when we upgrade the linter will cause errors where we can remove the `!` operator which is 👍 better than leaving them when they're not needed anymore. * Newer programmers and team members sometimes mistake it for the `?` when it is not the same thing. * We have had past bugs and bugs recently because of these. * It's easier to use the linter to find bugs than to rely on manual tests. **How did Frank fix all the 403 areas in which the linter goes off?** * Anywhere I could remove the `!` operator without side effects or type script errors I just removed the `!` operator. * Anywhere in test code where I could replace the code with a `?` or a `throw` I went through that route. * Within the code areas (non test code) where I saw what looks like a simple bug that I could fix using a `?? []` or `?` operator or `String(value)` or fixing a simple type I would choose that route first. These areas I marked in the code review with the words `NOTE:` for anyone to look at. * Within all other areas of the code and tests where anything looked more involved I just disabled the linter for that particular line. When in doubt I chose this route. ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --- .eslintrc.js | 38 +++++++++++++++++-- .../common/detection_engine/utils.ts | 3 +- .../data_loaders/index_endpoint_hosts.ts | 2 +- .../data_loaders/index_fleet_agent.ts | 2 +- .../integration/cases/connectors.spec.ts | 4 +- .../detection_rules/custom_query_rule.spec.ts | 10 ++--- .../detection_rules/export_rule.spec.ts | 2 +- .../timeline_templates/creation.spec.ts | 2 +- .../timeline_templates/export.spec.ts | 4 +- .../integration/timelines/export.spec.ts | 4 +- .../timelines/search_or_filter.spec.ts | 8 ++-- .../cypress/integration/urls/state.spec.ts | 4 +- .../value_lists/value_lists.spec.ts | 14 +++---- .../cypress/screens/timelines.ts | 5 ++- .../cypress/tasks/create_new_rule.ts | 11 ++++-- .../security_solution/cypress/tasks/login.ts | 4 +- .../cypress/tasks/rule_details.ts | 2 +- .../common/components/charts/barchart.tsx | 2 +- .../components/event_details/helpers.test.tsx | 2 +- .../components/event_details/helpers.tsx | 2 +- .../events_viewer/events_viewer.tsx | 4 +- .../common/components/events_viewer/index.tsx | 10 ++--- .../navigation/breadcrumbs/index.ts | 1 + .../public/common/components/utils.ts | 1 + .../mock/endpoint/app_context_render.tsx | 2 +- .../components/alerts_table/actions.test.tsx | 8 ++-- .../components/alerts_table/actions.tsx | 2 + .../components/alerts_table/index.tsx | 6 +-- .../components/rules/ml_job_select/index.tsx | 2 + .../components/rules/rule_switch/index.tsx | 4 +- .../detection_engine/detection_engine.tsx | 4 +- .../detection_engine/rules/details/index.tsx | 7 ++-- .../pages/detection_engine/rules/helpers.tsx | 1 + .../authentications_table/index.tsx | 8 ++-- .../artifact_card_grid/artifact_card_grid.tsx | 1 + .../back_to_external_app_button.tsx | 4 +- .../context_menu_with_router_support.tsx | 1 + .../paginated_content/paginated_content.tsx | 1 + .../pages/endpoint_hosts/store/reducer.ts | 9 +++-- .../event_filter_delete_modal.test.tsx | 4 +- .../view/components/flyout/index.test.tsx | 8 ++-- .../view/components/form/index.test.tsx | 4 +- .../view/components/modal/index.test.tsx | 12 +++--- .../use_event_filters_notification.test.tsx | 20 +++++----- .../view/components/delete_modal.test.tsx | 10 ++--- .../view/components/form_flyout.tsx | 2 +- .../pages/mocks/trusted_apps_http_mocks.ts | 1 + .../policy/store/policy_details/index.test.ts | 6 +-- .../exception_items_summary.test.tsx | 2 +- .../components/policy_form_layout.tsx | 1 + .../pages/policy/view/policy_hooks.ts | 2 +- .../flyout/policy_trusted_apps_flyout.tsx | 1 + .../list/policy_trusted_apps_list.tsx | 1 + .../pages/trusted_apps/store/middleware.ts | 2 + .../components/create_trusted_app_form.tsx | 2 + .../effected_policy_select.tsx | 2 +- .../network/components/details/index.tsx | 2 +- .../network_dns_table/index.test.tsx | 4 +- .../network_http_table/index.test.tsx | 4 +- .../components/tls_table/index.test.tsx | 4 +- .../components/users_table/index.test.tsx | 4 +- .../security_solution/public/plugin.tsx | 9 ++++- .../public/resolver/mocks/resolver_tree.ts | 1 + .../models/indexed_process_tree/index.ts | 1 + .../public/resolver/store/selectors.test.ts | 6 +-- .../resolver/test_utilities/extend_jest.ts | 4 +- .../resolver/view/graph_controls.test.tsx | 30 +++++++-------- .../public/resolver/view/panel.test.tsx | 10 ++--- .../view/side_effect_simulator_factory.ts | 1 + .../field_renderers/field_renderers.test.tsx | 6 +-- .../flyout/header/active_timelines.tsx | 1 + .../components/flyout/header/index.tsx | 3 ++ .../components/open_timeline/helpers.ts | 2 + .../components/open_timeline/index.test.tsx | 2 +- .../note_previews/index.test.tsx | 4 +- .../timelines_table/actions_columns.tsx | 2 + .../event_details/expandable_event.tsx | 2 +- .../header_tooltip_content/index.tsx | 2 +- .../timeline/body/events/stateful_event.tsx | 1 + .../components/timeline/body/index.tsx | 6 +-- .../suricata/suricata_row_renderer.test.tsx | 2 +- .../body/renderers/zeek/zeek_signature.tsx | 6 +-- .../add_data_provider_popover.tsx | 6 +-- .../timeline/notes_tab_content/index.tsx | 7 +++- .../timeline/query_tab_content/index.tsx | 2 +- .../timeline/search_or_filter/index.tsx | 8 +++- .../selectable_timeline/index.test.tsx | 4 +- .../timeline/selectable_timeline/index.tsx | 4 +- .../timelines/components/timeline/styles.tsx | 4 +- .../public/timelines/containers/api.ts | 3 +- .../public/timelines/store/timeline/epic.ts | 2 +- .../timelines/store/timeline/reducer.test.ts | 8 ++-- .../server/endpoint/lib/artifacts/task.ts | 1 + .../endpoint/lib/policy/license_watch.test.ts | 2 +- .../endpoint/routes/actions/isolation.ts | 1 + .../routes/metadata/enrichment.test.ts | 12 +++--- .../endpoint/routes/metadata/handlers.ts | 8 ++++ .../endpoint/routes/metadata/metadata.test.ts | 6 +-- .../routes/metadata/query_builders.ts | 4 +- .../server/endpoint/routes/policy/service.ts | 2 + .../endpoint/routes/trusted_apps/service.ts | 2 + .../server/endpoint/services/actions.ts | 2 + .../services/artifacts/artifact_client.ts | 3 +- .../manifest_manager/manifest_manager.mock.ts | 8 ++-- .../metadata/endpoint_metadata_service.ts | 4 +- .../migrations/create_migration.ts | 2 +- .../routes/index/create_index_route.ts | 2 +- .../rules/add_prepackaged_rules_route.test.ts | 2 +- .../rules/create_rules_bulk_route.test.ts | 2 +- .../routes/rules/create_rules_route.test.ts | 2 +- .../rules/delete_rules_bulk_route.test.ts | 2 +- .../routes/rules/delete_rules_route.test.ts | 2 +- .../routes/rules/find_rules_route.test.ts | 2 +- .../rules/find_rules_status_route.test.ts | 2 +- ...get_prepackaged_rules_status_route.test.ts | 2 +- .../routes/rules/import_rules_route.test.ts | 2 +- .../rules/patch_rules_bulk_route.test.ts | 2 +- .../routes/rules/patch_rules_route.test.ts | 2 +- .../rules/perform_bulk_action_route.test.ts | 2 +- .../routes/rules/read_rules_route.test.ts | 2 +- .../rules/update_rules_bulk_route.test.ts | 2 +- .../routes/rules/update_rules_route.test.ts | 2 +- .../routes/signals/query_signals_route.ts | 2 +- .../signals/build_event_type_signal.ts | 4 +- .../signals/build_rule.test.ts | 4 +- .../enrich_signal_threat_matches.ts | 2 +- .../bulk_create_threshold_signals.ts | 2 + .../threshold/get_threshold_bucket_filters.ts | 1 + .../detection_engine/signals/utils.test.ts | 2 +- .../lib/detection_engine/signals/utils.ts | 1 + .../timeline/utils/check_timelines_status.ts | 1 + .../lib/timeline/utils/failure_cases.ts | 2 +- .../security_solution/server/plugin.ts | 10 ++++- .../cti/event_enrichment/response.test.ts | 2 +- .../factory/hosts/details/helpers.ts | 1 + .../public/components/hover_actions/index.tsx | 1 + .../timelines/public/components/index.tsx | 1 + .../header_tooltip_content/index.tsx | 2 +- .../t_grid/body/events/stateful_event.tsx | 1 + .../public/components/t_grid/helpers.tsx | 1 + .../components/t_grid/integrated/index.tsx | 2 +- .../components/t_grid/standalone/index.tsx | 2 +- .../public/components/t_grid/styles.tsx | 4 +- .../fields_browser/field_browser.test.tsx | 4 +- .../t_grid/toolbar/fields_browser/helpers.tsx | 1 + .../t_grid/toolbar/fields_browser/index.tsx | 2 + .../public/components/utils/helpers.ts | 2 +- .../public/container/use_update_alerts.ts | 4 +- x-pack/plugins/timelines/public/plugin.ts | 7 +++- 149 files changed, 367 insertions(+), 238 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index c12cc7c1eb496..0c2c78cd1dd7f 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -899,7 +899,12 @@ module.exports = { }, /** - * Security Solution overrides + * Security Solution overrides. These rules below are maintained and owned by + * the people within the security-solution-platform team. Please see ping them + * or check with them if you are encountering issues, have suggestions, or would + * like to add, change, or remove any particular rule. Linters, Typescript, and rules + * evolve and change over time just like coding styles, so please do not hesitate to + * reach out. */ { // front end and common typescript and javascript files only @@ -922,6 +927,22 @@ module.exports = { ], }, }, + { + // typescript only for front and back end, but excludes the test files. + // We use this section to add rules in which we do not want to apply to test files. + // This should be a very small set as most linter rules are useful for tests as well. + files: [ + 'x-pack/plugins/security_solution/**/*.{ts,tsx}', + 'x-pack/plugins/timelines/**/*.{ts,tsx}', + ], + excludedFiles: [ + 'x-pack/plugins/security_solution/**/*.{test,mock,test_helper}.{ts,tsx}', + 'x-pack/plugins/timelines/**/*.{test,mock,test_helper}.{ts,tsx}', + ], + rules: { + '@typescript-eslint/no-non-null-assertion': 'error', + }, + }, { // typescript only for front and back end files: [ @@ -1040,7 +1061,12 @@ module.exports = { }, /** - * Lists overrides + * Lists overrides. These rules below are maintained and owned by + * the people within the security-solution-platform team. Please see ping them + * or check with them if you are encountering issues, have suggestions, or would + * like to add, change, or remove any particular rule. Linters, Typescript, and rules + * evolve and change over time just like coding styles, so please do not hesitate to + * reach out. */ { // front end and common typescript and javascript files only @@ -1215,8 +1241,14 @@ module.exports = { ], }, }, + /** - * Metrics entities overrides + * Metrics entities overrides. These rules below are maintained and owned by + * the people within the security-solution-platform team. Please see ping them + * or check with them if you are encountering issues, have suggestions, or would + * like to add, change, or remove any particular rule. Linters, Typescript, and rules + * evolve and change over time just like coding styles, so please do not hesitate to + * reach out. */ { // front end and common typescript and javascript files only diff --git a/x-pack/plugins/security_solution/common/detection_engine/utils.ts b/x-pack/plugins/security_solution/common/detection_engine/utils.ts index 28749e0400bbb..7d4badcd3507c 100644 --- a/x-pack/plugins/security_solution/common/detection_engine/utils.ts +++ b/x-pack/plugins/security_solution/common/detection_engine/utils.ts @@ -51,7 +51,8 @@ export const normalizeThresholdField = ( ? thresholdField : isEmpty(thresholdField) ? [] - : [thresholdField!]; + : // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + [thresholdField!]; }; export const normalizeThresholdObject = (threshold: Threshold): ThresholdNormalized => { diff --git a/x-pack/plugins/security_solution/common/endpoint/data_loaders/index_endpoint_hosts.ts b/x-pack/plugins/security_solution/common/endpoint/data_loaders/index_endpoint_hosts.ts index d7ab014c3b445..fdb8416de2ed8 100644 --- a/x-pack/plugins/security_solution/common/endpoint/data_loaders/index_endpoint_hosts.ts +++ b/x-pack/plugins/security_solution/common/endpoint/data_loaders/index_endpoint_hosts.ts @@ -161,7 +161,7 @@ export async function indexEndpointHostDocs({ const indexedAgentResponse = await indexFleetAgentForHost( client, kbnClient, - hostMetadata!, + hostMetadata, realPolicies[appliedPolicyId].policy_id, kibanaVersion ); diff --git a/x-pack/plugins/security_solution/common/endpoint/data_loaders/index_fleet_agent.ts b/x-pack/plugins/security_solution/common/endpoint/data_loaders/index_fleet_agent.ts index b792b34dd510f..67a261d088f86 100644 --- a/x-pack/plugins/security_solution/common/endpoint/data_loaders/index_fleet_agent.ts +++ b/x-pack/plugins/security_solution/common/endpoint/data_loaders/index_fleet_agent.ts @@ -73,7 +73,7 @@ export const indexFleetAgentForHost = async ( .index({ index: agentDoc._index, id: agentDoc._id, - body: agentDoc._source!, + body: agentDoc._source, op_type: 'create', }) .catch(wrapErrorAndRejectPromise); diff --git a/x-pack/plugins/security_solution/cypress/integration/cases/connectors.spec.ts b/x-pack/plugins/security_solution/cypress/integration/cases/connectors.spec.ts index a53e37f363d05..287d86c6fba9e 100644 --- a/x-pack/plugins/security_solution/cypress/integration/cases/connectors.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/cases/connectors.spec.ts @@ -89,11 +89,11 @@ describe('Cases connectors', () => { addServiceNowConnector(snConnector); cy.wait('@createConnector').then(({ response }) => { - cy.wrap(response!.statusCode).should('eql', 200); + cy.wrap(response?.statusCode).should('eql', 200); cy.get(TOASTER).should('have.text', "Created 'New connector'"); cy.get(TOASTER).should('not.exist'); - selectLastConnectorCreated(response!.body.id); + selectLastConnectorCreated(response?.body.id); cy.wait('@saveConnector', { timeout: 10000 }).its('response.statusCode').should('eql', 200); cy.get(SERVICE_NOW_MAPPING).first().should('have.text', 'short_description'); diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_rules/custom_query_rule.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_rules/custom_query_rule.spec.ts index 028ef36138bbd..3af966b4ba2b2 100644 --- a/x-pack/plugins/security_solution/cypress/integration/detection_rules/custom_query_rule.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/detection_rules/custom_query_rule.spec.ts @@ -351,10 +351,10 @@ describe('Custom detection rules deletion and edition', () => { goToRuleDetails(); cy.wait('@fetchRuleDetails').then(({ response }) => { - cy.wrap(response!.statusCode).should('eql', 200); + cy.wrap(response?.statusCode).should('eql', 200); - cy.wrap(response!.body.max_signals).should('eql', getExistingRule().maxSignals); - cy.wrap(response!.body.enabled).should('eql', false); + cy.wrap(response?.body.max_signals).should('eql', getExistingRule().maxSignals); + cy.wrap(response?.body.enabled).should('eql', false); }); }); @@ -414,9 +414,9 @@ describe('Custom detection rules deletion and edition', () => { saveEditedRule(); cy.wait('@getRule').then(({ response }) => { - cy.wrap(response!.statusCode).should('eql', 200); + cy.wrap(response?.statusCode).should('eql', 200); // ensure that editing rule does not modify max_signals - cy.wrap(response!.body.max_signals).should('eql', getExistingRule().maxSignals); + cy.wrap(response?.body.max_signals).should('eql', getExistingRule().maxSignals); }); cy.get(RULE_NAME_HEADER).should('contain', `${getEditedRule().name}`); diff --git a/x-pack/plugins/security_solution/cypress/integration/detection_rules/export_rule.spec.ts b/x-pack/plugins/security_solution/cypress/integration/detection_rules/export_rule.spec.ts index 03086810a8435..18b7b122f0967 100644 --- a/x-pack/plugins/security_solution/cypress/integration/detection_rules/export_rule.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/detection_rules/export_rule.spec.ts @@ -35,7 +35,7 @@ describe('Export rules', () => { goToManageAlertsDetectionRules(); exportFirstRule(); cy.wait('@export').then(({ response }) => { - cy.wrap(response!.body).should('eql', expectedExportedRule(this.ruleResponse)); + cy.wrap(response?.body).should('eql', expectedExportedRule(this.ruleResponse)); }); }); }); diff --git a/x-pack/plugins/security_solution/cypress/integration/timeline_templates/creation.spec.ts b/x-pack/plugins/security_solution/cypress/integration/timeline_templates/creation.spec.ts index 48269677466b6..71bbea673e5c8 100644 --- a/x-pack/plugins/security_solution/cypress/integration/timeline_templates/creation.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/timeline_templates/creation.spec.ts @@ -70,7 +70,7 @@ describe('Timeline Templates', () => { addNameToTimeline(getTimeline().title); cy.wait('@timeline').then(({ response }) => { - const timelineId = response!.body.data.persistTimeline.timeline.savedObjectId; + const timelineId = response?.body.data.persistTimeline.timeline.savedObjectId; addDescriptionToTimeline(getTimeline().description); addNotesToTimeline(getTimeline().notes); diff --git a/x-pack/plugins/security_solution/cypress/integration/timeline_templates/export.spec.ts b/x-pack/plugins/security_solution/cypress/integration/timeline_templates/export.spec.ts index a20baffeadc7e..638a70df35850 100644 --- a/x-pack/plugins/security_solution/cypress/integration/timeline_templates/export.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/timeline_templates/export.spec.ts @@ -35,9 +35,9 @@ describe('Export timelines', () => { exportTimeline(this.templateId); cy.wait('@export').then(({ response }) => { - cy.wrap(response!.statusCode).should('eql', 200); + cy.wrap(response?.statusCode).should('eql', 200); - cy.wrap(response!.body).should( + cy.wrap(response?.body).should( 'eql', expectedExportedTimelineTemplate(this.templateResponse) ); diff --git a/x-pack/plugins/security_solution/cypress/integration/timelines/export.spec.ts b/x-pack/plugins/security_solution/cypress/integration/timelines/export.spec.ts index 029216f701ae0..29d1cb588f1a2 100644 --- a/x-pack/plugins/security_solution/cypress/integration/timelines/export.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/timelines/export.spec.ts @@ -33,9 +33,9 @@ describe('Export timelines', () => { exportTimeline(this.timelineId); cy.wait('@export').then(({ response }) => { - cy.wrap(response!.statusCode).should('eql', 200); + cy.wrap(response?.statusCode).should('eql', 200); - cy.wrap(response!.body).should('eql', expectedExportedTimeline(this.timelineResponse)); + cy.wrap(response?.body).should('eql', expectedExportedTimeline(this.timelineResponse)); }); }); }); diff --git a/x-pack/plugins/security_solution/cypress/integration/timelines/search_or_filter.spec.ts b/x-pack/plugins/security_solution/cypress/integration/timelines/search_or_filter.spec.ts index 9d019cf23ebb1..b42bdcdd6fb8d 100644 --- a/x-pack/plugins/security_solution/cypress/integration/timelines/search_or_filter.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/timelines/search_or_filter.spec.ts @@ -54,8 +54,8 @@ describe('Update kqlMode for timeline', () => { it('should be able to update timeline kqlMode with filter', () => { cy.get(TIMELINE_KQLMODE_FILTER).click(); cy.wait('@update').then(({ response }) => { - cy.wrap(response!.statusCode).should('eql', 200); - cy.wrap(response!.body.data.persistTimeline.timeline.kqlMode).should('eql', 'filter'); + cy.wrap(response?.statusCode).should('eql', 200); + cy.wrap(response?.body.data.persistTimeline.timeline.kqlMode).should('eql', 'filter'); cy.get(ADD_FILTER).should('exist'); }); }); @@ -63,8 +63,8 @@ describe('Update kqlMode for timeline', () => { it('should be able to update timeline kqlMode with search', () => { cy.get(TIMELINE_KQLMODE_SEARCH).click(); cy.wait('@update').then(({ response }) => { - cy.wrap(response!.statusCode).should('eql', 200); - cy.wrap(response!.body.data.persistTimeline.timeline.kqlMode).should('eql', 'search'); + cy.wrap(response?.statusCode).should('eql', 200); + cy.wrap(response?.body.data.persistTimeline.timeline.kqlMode).should('eql', 'search'); cy.get(ADD_FILTER).should('not.exist'); }); }); diff --git a/x-pack/plugins/security_solution/cypress/integration/urls/state.spec.ts b/x-pack/plugins/security_solution/cypress/integration/urls/state.spec.ts index 47e6b0d34e3c5..73eb141f1ce3d 100644 --- a/x-pack/plugins/security_solution/cypress/integration/urls/state.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/urls/state.spec.ts @@ -250,8 +250,8 @@ describe('url state', () => { cy.wait('@timeline').then(({ response }) => { closeTimeline(); - cy.wrap(response!.statusCode).should('eql', 200); - const timelineId = response!.body.data.persistTimeline.timeline.savedObjectId; + cy.wrap(response?.statusCode).should('eql', 200); + const timelineId = response?.body.data.persistTimeline.timeline.savedObjectId; cy.visit('/app/home'); cy.visit(`/app/security/timelines?timeline=(id:'${timelineId}',isOpen:!t)`); cy.get(DATE_PICKER_APPLY_BUTTON_TIMELINE).should('exist'); diff --git a/x-pack/plugins/security_solution/cypress/integration/value_lists/value_lists.spec.ts b/x-pack/plugins/security_solution/cypress/integration/value_lists/value_lists.spec.ts index a7cc412a920c0..f2b87e42685e7 100644 --- a/x-pack/plugins/security_solution/cypress/integration/value_lists/value_lists.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/value_lists/value_lists.spec.ts @@ -174,8 +174,8 @@ describe('value lists', () => { cy.wait('@exportList').then(({ response }) => { cy.fixture(listName).then((list: string) => { const [lineOne, lineTwo] = list.split('\n'); - expect(response!.body).to.contain(lineOne); - expect(response!.body).to.contain(lineTwo); + expect(response?.body).to.contain(lineOne); + expect(response?.body).to.contain(lineTwo); }); }); }); @@ -189,8 +189,8 @@ describe('value lists', () => { cy.wait('@exportList').then(({ response }) => { cy.fixture(listName).then((list: string) => { const [lineOne, lineTwo] = list.split('\n'); - expect(response!.body).to.contain(lineOne); - expect(response!.body).to.contain(lineTwo); + expect(response?.body).to.contain(lineOne); + expect(response?.body).to.contain(lineTwo); }); }); }); @@ -204,8 +204,8 @@ describe('value lists', () => { cy.wait('@exportList').then(({ response }) => { cy.fixture(listName).then((list: string) => { const [lineOne, lineTwo] = list.split('\n'); - expect(response!.body).to.contain(lineOne); - expect(response!.body).to.contain(lineTwo); + expect(response?.body).to.contain(lineOne); + expect(response?.body).to.contain(lineTwo); }); }); }); @@ -219,7 +219,7 @@ describe('value lists', () => { cy.wait('@exportList').then(({ response }) => { cy.fixture(listName).then((list: string) => { const [lineOne] = list.split('\n'); - expect(response!.body).to.contain(lineOne); + expect(response?.body).to.contain(lineOne); }); }); }); diff --git a/x-pack/plugins/security_solution/cypress/screens/timelines.ts b/x-pack/plugins/security_solution/cypress/screens/timelines.ts index ca60250330f83..92522c44dd8e4 100644 --- a/x-pack/plugins/security_solution/cypress/screens/timelines.ts +++ b/x-pack/plugins/security_solution/cypress/screens/timelines.ts @@ -9,7 +9,10 @@ export const BULK_ACTIONS = '[data-test-subj="utility-bar-action-button"]'; export const EXPORT_TIMELINE_ACTION = '[data-test-subj="export-timeline-action"]'; -export const TIMELINE = (id: string) => { +export const TIMELINE = (id: string | undefined) => { + if (id == null) { + throw new TypeError('id should never be null or undefined'); + } return `[data-test-subj="title-${id}"]`; }; diff --git a/x-pack/plugins/security_solution/cypress/tasks/create_new_rule.ts b/x-pack/plugins/security_solution/cypress/tasks/create_new_rule.ts index 591be21b5682b..b9323fee44d5c 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/create_new_rule.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/create_new_rule.ts @@ -254,7 +254,7 @@ export const fillDefineCustomRuleWithImportedQueryAndContinue = ( rule: CustomRule | OverrideRule ) => { cy.get(IMPORT_QUERY_FROM_SAVED_TIMELINE_LINK).click(); - cy.get(TIMELINE(rule.timeline.id!)).click(); + cy.get(TIMELINE(rule.timeline.id)).click(); cy.get(CUSTOM_QUERY_INPUT).should('have.value', rule.customQuery); cy.get(DEFINE_CONTINUE_BUTTON).should('exist').click({ force: true }); @@ -273,7 +273,7 @@ export const fillDefineThresholdRule = (rule: ThresholdRule) => { const threshold = 1; cy.get(IMPORT_QUERY_FROM_SAVED_TIMELINE_LINK).click(); - cy.get(TIMELINE(rule.timeline.id!)).click(); + cy.get(TIMELINE(rule.timeline.id)).click(); cy.get(COMBO_BOX_CLEAR_BTN).first().click(); rule.index.forEach((index) => { @@ -298,7 +298,7 @@ export const fillDefineThresholdRuleAndContinue = (rule: ThresholdRule) => { cy.wrap($el).type(rule.thresholdField, { delay: 35 }); cy.get(IMPORT_QUERY_FROM_SAVED_TIMELINE_LINK).click(); - cy.get(TIMELINE(rule.timeline.id!)).click(); + cy.get(TIMELINE(rule.timeline.id)).click(); cy.get(CUSTOM_QUERY_INPUT).should('have.value', rule.customQuery); cy.get(THRESHOLD_INPUT_AREA) .find(INPUT) @@ -314,9 +314,12 @@ export const fillDefineThresholdRuleAndContinue = (rule: ThresholdRule) => { }; export const fillDefineEqlRuleAndContinue = (rule: CustomRule) => { + if (rule.customQuery == null) { + throw new TypeError('The rule custom query should never be undefined or null '); + } cy.get(RULES_CREATION_FORM).find(EQL_QUERY_INPUT).should('exist'); cy.get(RULES_CREATION_FORM).find(EQL_QUERY_INPUT).should('be.visible'); - cy.get(RULES_CREATION_FORM).find(EQL_QUERY_INPUT).type(rule.customQuery!); + cy.get(RULES_CREATION_FORM).find(EQL_QUERY_INPUT).type(rule.customQuery); cy.get(RULES_CREATION_FORM).find(EQL_QUERY_VALIDATION_SPINNER).should('not.exist'); cy.get(RULES_CREATION_PREVIEW) .find(QUERY_PREVIEW_BUTTON) diff --git a/x-pack/plugins/security_solution/cypress/tasks/login.ts b/x-pack/plugins/security_solution/cypress/tasks/login.ts index 5a935702131d6..96d37d2d9214a 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/login.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/login.ts @@ -57,7 +57,7 @@ const LOGIN_API_ENDPOINT = '/internal/security/login'; */ export const getUrlWithRoute = (role: ROLES, route: string) => { const url = Cypress.config().baseUrl; - const kibana = new URL(url!); + const kibana = new URL(String(url)); const theUrl = `${Url.format({ auth: `${role}:changeme`, username: role, @@ -83,7 +83,7 @@ interface User { */ export const constructUrlWithUser = (user: User, route: string) => { const url = Cypress.config().baseUrl; - const kibana = new URL(url!); + const kibana = new URL(String(url)); const hostname = kibana.hostname; const username = user.username; const password = user.password; diff --git a/x-pack/plugins/security_solution/cypress/tasks/rule_details.ts b/x-pack/plugins/security_solution/cypress/tasks/rule_details.ts index 37968e700fb39..f001af9df62d2 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/rule_details.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/rule_details.ts @@ -32,7 +32,7 @@ export const activatesRule = () => { cy.get(RULE_SWITCH).should('be.visible'); cy.get(RULE_SWITCH).click(); cy.wait('@bulk_update').then(({ response }) => { - cy.wrap(response!.statusCode).should('eql', 200); + cy.wrap(response?.statusCode).should('eql', 200); }); }; diff --git a/x-pack/plugins/security_solution/public/common/components/charts/barchart.tsx b/x-pack/plugins/security_solution/public/common/components/charts/barchart.tsx index 527ef2721ab86..20ab5cca89a76 100644 --- a/x-pack/plugins/security_solution/public/common/components/charts/barchart.tsx +++ b/x-pack/plugins/security_solution/public/common/components/charts/barchart.tsx @@ -94,7 +94,7 @@ export const BarChartBaseComponent = ({ yAccessors={yAccessors} timeZone={timeZone} splitSeriesAccessors={splitSeriesAccessors} - data={series.value!} + data={series.value ?? []} stackAccessors={get('configs.series.stackAccessors', chartConfigs)} color={series.color ? series.color : undefined} /> diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/helpers.test.tsx b/x-pack/plugins/security_solution/public/common/components/event_details/helpers.test.tsx index d164d1f8f0ba0..bcdec78fe0614 100644 --- a/x-pack/plugins/security_solution/public/common/components/event_details/helpers.test.tsx +++ b/x-pack/plugins/security_solution/public/common/components/event_details/helpers.test.tsx @@ -12,7 +12,7 @@ import { mockBrowserFields } from '../../containers/source/mock'; const aField = { ...mockDetailItemData[4], - ...mockBrowserFields.base.fields!['@timestamp'], + ...mockBrowserFields.base.fields?.['@timestamp'], }; describe('helpers', () => { diff --git a/x-pack/plugins/security_solution/public/common/components/event_details/helpers.tsx b/x-pack/plugins/security_solution/public/common/components/event_details/helpers.tsx index a1c74a603fbc3..47d0ccf5ba3b2 100644 --- a/x-pack/plugins/security_solution/public/common/components/event_details/helpers.tsx +++ b/x-pack/plugins/security_solution/public/common/components/event_details/helpers.tsx @@ -127,7 +127,7 @@ export const getColumnsWithTimestamp = ({ export const getExampleText = (example: string | number | null | undefined): string => !isEmpty(example) ? `Example: ${example}` : ''; -export const getIconFromType = (type: string | null) => { +export const getIconFromType = (type: string | null | undefined) => { switch (type) { case 'string': // fall through case 'keyword': diff --git a/x-pack/plugins/security_solution/public/common/components/events_viewer/events_viewer.tsx b/x-pack/plugins/security_solution/public/common/components/events_viewer/events_viewer.tsx index 632197aa6b219..fd644d1380ddb 100644 --- a/x-pack/plugins/security_solution/public/common/components/events_viewer/events_viewer.tsx +++ b/x-pack/plugins/security_solution/public/common/components/events_viewer/events_viewer.tsx @@ -236,7 +236,7 @@ const EventsViewerComponent: React.FC = ({ useTimelineEvents({ docValueFields, fields, - filterQuery: combinedQueries!.filterQuery, + filterQuery: combinedQueries?.filterQuery, id, indexNames, limit: itemsPerPage, @@ -300,7 +300,7 @@ const EventsViewerComponent: React.FC = ({ height={headerFilterGroup ? COMPACT_HEADER_HEIGHT : EVENTS_VIEWER_HEADER_HEIGHT} subtitle={utilityBar ? undefined : subtitle} title={globalFullScreen ? titleWithExitFullScreen : justTitle} - isInspectDisabled={combinedQueries!.filterQuery === undefined} + isInspectDisabled={combinedQueries?.filterQuery === undefined} > {HeaderSectionContent} diff --git a/x-pack/plugins/security_solution/public/common/components/events_viewer/index.tsx b/x-pack/plugins/security_solution/public/common/components/events_viewer/index.tsx index d60db8a4bc461..1e61e69180f91 100644 --- a/x-pack/plugins/security_solution/public/common/components/events_viewer/index.tsx +++ b/x-pack/plugins/security_solution/public/common/components/events_viewer/index.tsx @@ -181,7 +181,7 @@ const StatefulEventsViewerComponent: React.FC = ({ browserFields, bulkActions, columns, - dataProviders: dataProviders!, + dataProviders, defaultCellActions, deletedEventIds, docValueFields, @@ -199,7 +199,7 @@ const StatefulEventsViewerComponent: React.FC = ({ isLive, isLoadingIndexPattern, itemsPerPage, - itemsPerPageOptions: itemsPerPageOptions!, + itemsPerPageOptions, kqlMode, leadingControlColumns, onRuleChange, @@ -220,7 +220,7 @@ const StatefulEventsViewerComponent: React.FC = ({ columns={columns} docValueFields={docValueFields} id={id} - dataProviders={dataProviders!} + dataProviders={dataProviders} deletedEventIds={deletedEventIds} end={end} isLoadingIndexPattern={isLoadingIndexPattern} @@ -228,8 +228,8 @@ const StatefulEventsViewerComponent: React.FC = ({ indexNames={selectedPatterns} indexPattern={indexPattern} isLive={isLive} - itemsPerPage={itemsPerPage!} - itemsPerPageOptions={itemsPerPageOptions!} + itemsPerPage={itemsPerPage} + itemsPerPageOptions={itemsPerPageOptions} kqlMode={kqlMode} query={query} onRuleChange={onRuleChange} diff --git a/x-pack/plugins/security_solution/public/common/components/navigation/breadcrumbs/index.ts b/x-pack/plugins/security_solution/public/common/components/navigation/breadcrumbs/index.ts index f4e3814738f92..7262264d72103 100644 --- a/x-pack/plugins/security_solution/public/common/components/navigation/breadcrumbs/index.ts +++ b/x-pack/plugins/security_solution/public/common/components/navigation/breadcrumbs/index.ts @@ -54,6 +54,7 @@ export const useSetBreadcrumbs = () => { dispatch(timelineActions.showTimeline({ id: TimelineId.active, show: false })); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion navigateToUrl(breadcrumb.href!); }, } diff --git a/x-pack/plugins/security_solution/public/common/components/utils.ts b/x-pack/plugins/security_solution/public/common/components/utils.ts index fc27578487ca7..da92c94d3c1cd 100644 --- a/x-pack/plugins/security_solution/public/common/components/utils.ts +++ b/x-pack/plugins/security_solution/public/common/components/utils.ts @@ -22,6 +22,7 @@ export const getDaysDiff = (minDate: moment.Moment, maxDate: moment.Moment) => { }; export const histogramDateTimeFormatter = (domain: [string, string] | null, fixedDiff?: number) => { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const diff = fixedDiff ?? getDaysDiff(moment(domain![0]), moment(domain![1])); const format = niceTimeFormatByDay(diff); return timeFormatter(format); diff --git a/x-pack/plugins/security_solution/public/common/mock/endpoint/app_context_render.tsx b/x-pack/plugins/security_solution/public/common/mock/endpoint/app_context_render.tsx index 20d411a0437c2..ed2a2252bd0d2 100644 --- a/x-pack/plugins/security_solution/public/common/mock/endpoint/app_context_render.tsx +++ b/x-pack/plugins/security_solution/public/common/mock/endpoint/app_context_render.tsx @@ -78,7 +78,7 @@ const experimentalFeaturesReducer: Reducer { ...mockEcsDataWithAlert, signal: { rule: { - ...mockEcsDataWithAlert.signal?.rule!, + ...mockEcsDataWithAlert.signal?.rule, // @ts-expect-error timeline_id: null, }, @@ -317,7 +317,7 @@ describe('alert actions', () => { ...mockEcsDataWithAlert, signal: { rule: { - ...mockEcsDataWithAlert.signal?.rule!, + ...mockEcsDataWithAlert.signal?.rule, timeline_id: [''], }, }, @@ -343,7 +343,7 @@ describe('alert actions', () => { ...mockEcsDataWithAlert, signal: { rule: { - ...mockEcsDataWithAlert.signal?.rule!, + ...mockEcsDataWithAlert.signal?.rule, type: ['eql'], timeline_id: [''], }, @@ -387,7 +387,7 @@ describe('alert actions', () => { ...mockEcsDataWithAlert, signal: { rule: { - ...mockEcsDataWithAlert.signal?.rule!, + ...mockEcsDataWithAlert.signal?.rule, type: ['eql'], timeline_id: [''], }, diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/actions.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/actions.tsx index d48bc95f5d480..fb958c775e68c 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/actions.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/actions.tsx @@ -192,8 +192,10 @@ export const getThresholdAggregationData = ( }; } + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const originalTime = moment(thresholdData.signal?.original_time![0]); const now = moment(); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const ruleFrom = dateMath.parse(thresholdData.signal?.rule?.from![0]!); const ruleInterval = moment.duration(now.diff(ruleFrom)); const fromOriginalTime = originalTime.clone().subtract(ruleInterval); // This is the default... can overshoot diff --git a/x-pack/plugins/security_solution/public/detections/components/alerts_table/index.tsx b/x-pack/plugins/security_solution/public/detections/components/alerts_table/index.tsx index d7c48c4f18bc8..4bd516d0b1338 100644 --- a/x-pack/plugins/security_solution/public/detections/components/alerts_table/index.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/alerts_table/index.tsx @@ -142,14 +142,14 @@ export const AlertsTableComponent: React.FC = ({ const setEventsLoadingCallback = useCallback( ({ eventIds, isLoading }: SetEventsLoadingProps) => { - setEventsLoading!({ id: timelineId, eventIds, isLoading }); + setEventsLoading({ id: timelineId, eventIds, isLoading }); }, [setEventsLoading, timelineId] ); const setEventsDeletedCallback = useCallback( ({ eventIds, isDeleted }: SetEventsDeletedProps) => { - setEventsDeleted!({ id: timelineId, eventIds, isDeleted }); + setEventsDeleted({ id: timelineId, eventIds, isDeleted }); }, [setEventsDeleted, timelineId] ); @@ -216,7 +216,7 @@ export const AlertsTableComponent: React.FC = ({ // Callback for clearing entire selection from utility bar const clearSelectionCallback = useCallback(() => { - clearSelected!({ id: timelineId }); + clearSelected({ id: timelineId }); dispatch( timelineActions.setTGridSelectAll({ id: timelineId, diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/ml_job_select/index.tsx b/x-pack/plugins/security_solution/public/detections/components/rules/ml_job_select/index.tsx index 6d7b5d4acc5b8..f785ec43a8b31 100644 --- a/x-pack/plugins/security_solution/public/detections/components/rules/ml_job_select/index.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/rules/ml_job_select/index.tsx @@ -59,6 +59,7 @@ interface MlJobSelectProps { } const renderJobOption = (option: MlJobOption) => ( + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion ); @@ -69,6 +70,7 @@ export const MlJobSelect: React.FC = ({ describedByIds = [], f const mlUrl = useKibana().services.application.getUrlForApp('ml'); const handleJobSelect = useCallback( (selectedJobOptions: MlJobOption[]): void => { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const selectedJobIds = selectedJobOptions.map((option) => option.value!.id); field.setValue(selectedJobIds); }, diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/rule_switch/index.tsx b/x-pack/plugins/security_solution/public/detections/components/rules/rule_switch/index.tsx index dc20dd1aa9ca4..dd836a04f8263 100644 --- a/x-pack/plugins/security_solution/public/detections/components/rules/rule_switch/index.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/rules/rule_switch/index.tsx @@ -61,9 +61,9 @@ export const RuleSwitchComponent = ({ async (event: EuiSwitchEvent) => { setMyIsLoading(true); if (dispatch != null) { - await enableRulesAction([id], event.target.checked!, dispatch, dispatchToaster); + await enableRulesAction([id], event.target.checked, dispatch, dispatchToaster); } else { - const enabling = event.target.checked!; + const enabling = event.target.checked; const title = enabling ? i18n.BATCH_ACTION_ACTIVATE_SELECTED_ERROR(1) : i18n.BATCH_ACTION_DEACTIVATE_SELECTED_ERROR(1); diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/detection_engine.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/detection_engine.tsx index 848bdd7f8ef71..ebda4f2b4232f 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/detection_engine.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/detection_engine.tsx @@ -176,8 +176,8 @@ const DetectionEnginePageComponent: React.FC = ({ const onFilterGroupChangedCallback = useCallback( (newFilterGroup: Status) => { const timelineId = TimelineId.detectionsPage; - clearEventsLoading!({ id: timelineId }); - clearEventsDeleted!({ id: timelineId }); + clearEventsLoading({ id: timelineId }); + clearEventsDeleted({ id: timelineId }); setFilterGroup(newFilterGroup); }, [clearEventsLoading, clearEventsDeleted, setFilterGroup] diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/index.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/index.tsx index 492b8e461fb60..7167b07c7da5d 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/index.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/details/index.tsx @@ -302,6 +302,7 @@ const RuleDetailsPageComponent: React.FC = ({ const getLegacyUrlConflictCallout = useMemo(() => { const outcome = rule?.outcome; if (rule != null && spacesApi && outcome === 'conflict') { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const aliasTargetId = rule?.alias_target_id!; // This is always defined if outcome === 'conflict' // We have resolved to one rule, but there is another one with a legacy URL associated with this page. Display a // callout with a warning for the user, and provide a way for them to navigate to the other rule. @@ -401,9 +402,9 @@ const RuleDetailsPageComponent: React.FC = ({ const onFilterGroupChangedCallback = useCallback( (newFilterGroup: Status) => { const timelineId = TimelineId.detectionsRulesDetailsPage; - clearEventsLoading!({ id: timelineId }); - clearEventsDeleted!({ id: timelineId }); - clearSelected!({ id: timelineId }); + clearEventsLoading({ id: timelineId }); + clearEventsDeleted({ id: timelineId }); + clearSelected({ id: timelineId }); setFilterGroup(newFilterGroup); }, [clearEventsLoading, clearEventsDeleted, clearSelected, setFilterGroup] diff --git a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/helpers.tsx b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/helpers.tsx index 0f109214c6bf3..18b5d74516199 100644 --- a/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/helpers.tsx +++ b/x-pack/plugins/security_solution/public/detections/pages/detection_engine/rules/helpers.tsx @@ -174,6 +174,7 @@ export const getAboutStepsData = (rule: Rule, detailsView: boolean): AboutStepRu timestampOverride: timestampOverride ?? '', name, description, + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion note: note!, references, severity: { diff --git a/x-pack/plugins/security_solution/public/hosts/components/authentications_table/index.tsx b/x-pack/plugins/security_solution/public/hosts/components/authentications_table/index.tsx index b83853eec69a1..23e5da28a3559 100644 --- a/x-pack/plugins/security_solution/public/hosts/components/authentications_table/index.tsx +++ b/x-pack/plugins/security_solution/public/hosts/components/authentications_table/index.tsx @@ -229,8 +229,8 @@ const getAuthenticationColumns = (): AuthTableColumns => [ truncateText: false, hideForMobile: false, render: ({ node }) => - has('lastSuccess.timestamp', node) && node.lastSuccess!.timestamp != null ? ( - + has('lastSuccess.timestamp', node) && node.lastSuccess?.timestamp != null ? ( + ) : ( getEmptyTagValue() ), @@ -264,8 +264,8 @@ const getAuthenticationColumns = (): AuthTableColumns => [ truncateText: false, hideForMobile: false, render: ({ node }) => - has('lastFailure.timestamp', node) && node.lastFailure!.timestamp != null ? ( - + has('lastFailure.timestamp', node) && node.lastFailure?.timestamp != null ? ( + ) : ( getEmptyTagValue() ), diff --git a/x-pack/plugins/security_solution/public/management/components/artifact_card_grid/artifact_card_grid.tsx b/x-pack/plugins/security_solution/public/management/components/artifact_card_grid/artifact_card_grid.tsx index 9e9082ccc54e7..0218b83288d84 100644 --- a/x-pack/plugins/security_solution/public/management/components/artifact_card_grid/artifact_card_grid.tsx +++ b/x-pack/plugins/security_solution/public/management/components/artifact_card_grid/artifact_card_grid.tsx @@ -119,6 +119,7 @@ export const ArtifactCardGrid = memo( const handleItemComponentProps = useCallback( (item: AnyArtifact): ArtifactEntryCollapsibleCardProps => { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion return fullCardProps.get(item)!; }, [fullCardProps] diff --git a/x-pack/plugins/security_solution/public/management/components/back_to_external_app_button/back_to_external_app_button.tsx b/x-pack/plugins/security_solution/public/management/components/back_to_external_app_button/back_to_external_app_button.tsx index c71eea2aaf9db..47242ed7d1edc 100644 --- a/x-pack/plugins/security_solution/public/management/components/back_to_external_app_button/back_to_external_app_button.tsx +++ b/x-pack/plugins/security_solution/public/management/components/back_to_external_app_button/back_to_external_app_button.tsx @@ -31,7 +31,7 @@ const EuiButtonEmptyStyled = styled(EuiButtonEmpty)` export type BackToExternalAppButtonProps = CommonProps & ListPageRouteState; export const BackToExternalAppButton = memo( ({ backButtonLabel, backButtonUrl, onBackButtonNavigateTo, ...commonProps }) => { - const handleBackOnClick = useNavigateToAppEventHandler(...onBackButtonNavigateTo!); + const handleBackOnClick = useNavigateToAppEventHandler(...onBackButtonNavigateTo); return ( ( flush="left" size="xs" iconType="arrowLeft" - href={backButtonUrl!} + href={backButtonUrl} onClick={handleBackOnClick} textProps={{ className: 'text' }} > diff --git a/x-pack/plugins/security_solution/public/management/components/context_menu_with_router_support/context_menu_with_router_support.tsx b/x-pack/plugins/security_solution/public/management/components/context_menu_with_router_support/context_menu_with_router_support.tsx index 41abb0309a7d1..6e33ad9218bb6 100644 --- a/x-pack/plugins/security_solution/public/management/components/context_menu_with_router_support/context_menu_with_router_support.tsx +++ b/x-pack/plugins/security_solution/public/management/components/context_menu_with_router_support/context_menu_with_router_support.tsx @@ -75,6 +75,7 @@ export const ContextMenuWithRouterSupport = memo = (state, action) => { return { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion ...state!, isolationRequestState: action.payload, }; diff --git a/x-pack/plugins/security_solution/public/management/pages/event_filters/view/components/event_filter_delete_modal.test.tsx b/x-pack/plugins/security_solution/public/management/pages/event_filters/view/components/event_filter_delete_modal.test.tsx index ed18c084c2a05..108e3d06affa6 100644 --- a/x-pack/plugins/security_solution/public/management/pages/event_filters/view/components/event_filter_delete_modal.test.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/event_filters/view/components/event_filter_delete_modal.test.tsx @@ -30,12 +30,12 @@ describe('When event filters delete modal is shown', () => { const getConfirmButton = () => renderResult.baseElement.querySelector( '[data-test-subj="eventFilterDeleteModalConfirmButton"]' - )! as HTMLButtonElement; + ) as HTMLButtonElement; const getCancelButton = () => renderResult.baseElement.querySelector( '[data-test-subj="eventFilterDeleteModalCancelButton"]' - )! as HTMLButtonElement; + ) as HTMLButtonElement; const getCurrentState = () => store.getState().management.eventFilters; diff --git a/x-pack/plugins/security_solution/public/management/pages/event_filters/view/components/flyout/index.test.tsx b/x-pack/plugins/security_solution/public/management/pages/event_filters/view/components/flyout/index.test.tsx index d5a1c6624923b..83b4f005135ba 100644 --- a/x-pack/plugins/security_solution/public/management/pages/event_filters/view/components/flyout/index.test.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/event_filters/view/components/flyout/index.test.tsx @@ -80,7 +80,7 @@ describe('Event filter flyout', () => { }); expect(getFormEntryState(getState())).not.toBeUndefined(); - expect(getFormEntryState(getState())!.entries[0].field).toBe(''); + expect(getFormEntryState(getState())?.entries[0].field).toBe(''); }); it('should confirm form when button is disabled', () => { @@ -98,7 +98,7 @@ describe('Event filter flyout', () => { type: 'eventFiltersChangeForm', payload: { entry: { - ...(getState().form!.entry as CreateExceptionListItemSchema), + ...(getState().form?.entry as CreateExceptionListItemSchema), name: 'test', os_types: ['windows'], }, @@ -125,7 +125,7 @@ describe('Event filter flyout', () => { type: 'eventFiltersFormStateChanged', payload: { type: 'LoadedResourceState', - data: getState().form!.entry as ExceptionListItemSchema, + data: getState().form?.entry as ExceptionListItemSchema, }, }); }); @@ -193,6 +193,6 @@ describe('Event filter flyout', () => { }); expect(getFormEntryState(getState())).not.toBeUndefined(); - expect(getFormEntryState(getState())!.item_id).toBe(createdEventFilterEntryMock().item_id); + expect(getFormEntryState(getState())?.item_id).toBe(createdEventFilterEntryMock().item_id); }); }); diff --git a/x-pack/plugins/security_solution/public/management/pages/event_filters/view/components/form/index.test.tsx b/x-pack/plugins/security_solution/public/management/pages/event_filters/view/components/form/index.test.tsx index 3934e3a389c36..f8dd9ac632cd0 100644 --- a/x-pack/plugins/security_solution/public/management/pages/event_filters/view/components/form/index.test.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/event_filters/view/components/form/index.test.tsx @@ -99,7 +99,7 @@ describe('Event filter form', () => { }); }); - expect(getState().form.entry!.name).toBe('Exception name'); + expect(getState().form.entry?.name).toBe('Exception name'); expect(getState().form.hasNameError).toBeFalsy(); }); @@ -116,7 +116,7 @@ describe('Event filter form', () => { }); }); - expect(getState().form.entry!.name).toBe(''); + expect(getState().form.entry?.name).toBe(''); expect(getState().form.hasNameError).toBeTruthy(); }); diff --git a/x-pack/plugins/security_solution/public/management/pages/event_filters/view/components/modal/index.test.tsx b/x-pack/plugins/security_solution/public/management/pages/event_filters/view/components/modal/index.test.tsx index c77188694f507..8ea50ecd460e4 100644 --- a/x-pack/plugins/security_solution/public/management/pages/event_filters/view/components/modal/index.test.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/event_filters/view/components/modal/index.test.tsx @@ -81,7 +81,7 @@ describe('Event filter modal', () => { await waitForAction('eventFiltersInitForm'); }); - expect(getState().form!.entry).not.toBeUndefined(); + expect(getState().form?.entry).not.toBeUndefined(); }); it('should set OS with the enriched data', async () => { @@ -90,7 +90,7 @@ describe('Event filter modal', () => { await waitForAction('eventFiltersInitForm'); }); - expect(getState().form!.entry?.os_types).toContain('linux'); + expect(getState().form?.entry?.os_types).toContain('linux'); }); it('should confirm form when button is disabled', async () => { @@ -103,7 +103,7 @@ describe('Event filter modal', () => { act(() => { fireEvent.click(confirmButton); }); - expect(getState().form!.submissionResourceState.type).toBe('UninitialisedResourceState'); + expect(getState().form?.submissionResourceState.type).toBe('UninitialisedResourceState'); }); it('should confirm form when button is enabled', async () => { @@ -116,7 +116,7 @@ describe('Event filter modal', () => { type: 'eventFiltersChangeForm', payload: { entry: { - ...(getState().form!.entry as CreateExceptionListItemSchema), + ...(getState().form?.entry as CreateExceptionListItemSchema), name: 'test', }, hasNameError: false, @@ -126,7 +126,7 @@ describe('Event filter modal', () => { act(() => { fireEvent.click(confirmButton); }); - expect(getState().form!.submissionResourceState.type).toBe('LoadingResourceState'); + expect(getState().form?.submissionResourceState.type).toBe('LoadingResourceState'); expect(confirmButton.hasAttribute('disabled')).toBeTruthy(); }); @@ -143,7 +143,7 @@ describe('Event filter modal', () => { type: 'eventFiltersFormStateChanged', payload: { type: 'LoadedResourceState', - data: getState().form!.entry as ExceptionListItemSchema, + data: getState().form?.entry as ExceptionListItemSchema, }, }); }); diff --git a/x-pack/plugins/security_solution/public/management/pages/event_filters/view/use_event_filters_notification.test.tsx b/x-pack/plugins/security_solution/public/management/pages/event_filters/view/use_event_filters_notification.test.tsx index 039aeb9f8e596..82fe231505ad5 100644 --- a/x-pack/plugins/security_solution/public/management/pages/event_filters/view/use_event_filters_notification.test.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/event_filters/view/use_event_filters_notification.test.tsx @@ -79,14 +79,14 @@ describe('EventFiltersNotification', () => { type: 'eventFiltersFormStateChanged', payload: { type: 'LoadedResourceState', - data: store.getState()!.management!.eventFilters!.form!.entry as ExceptionListItemSchema, + data: store.getState().management.eventFilters.form.entry as ExceptionListItemSchema, }, }); }); expect(notifications.toasts.addSuccess).toBeCalledWith( getCreationSuccessMessage( - store.getState()!.management!.eventFilters!.form!.entry as CreateExceptionListItemSchema + store.getState().management.eventFilters.form.entry as CreateExceptionListItemSchema ) ); expect(notifications.toasts.addDanger).not.toBeCalled(); @@ -110,14 +110,14 @@ describe('EventFiltersNotification', () => { type: 'eventFiltersFormStateChanged', payload: { type: 'LoadedResourceState', - data: store.getState()!.management!.eventFilters!.form!.entry as ExceptionListItemSchema, + data: store.getState().management.eventFilters.form.entry as ExceptionListItemSchema, }, }); }); expect(notifications.toasts.addSuccess).toBeCalledWith( getUpdateSuccessMessage( - store.getState()!.management!.eventFilters!.form!.entry as CreateExceptionListItemSchema + store.getState().management.eventFilters.form.entry as CreateExceptionListItemSchema ) ); expect(notifications.toasts.addDanger).not.toBeCalled(); @@ -144,7 +144,7 @@ describe('EventFiltersNotification', () => { type: 'FailedResourceState', error: { message: 'error message', statusCode: 500, error: 'error' }, lastLoadedState: getLastLoadedResourceState( - store.getState()!.management!.eventFilters!.form!.submissionResourceState + store.getState().management.eventFilters.form.submissionResourceState ), }, }); @@ -154,7 +154,7 @@ describe('EventFiltersNotification', () => { expect(notifications.toasts.addDanger).toBeCalledWith( getCreationErrorMessage( ( - store.getState()!.management!.eventFilters!.form! + store.getState().management.eventFilters.form .submissionResourceState as FailedResourceState ).error ) @@ -181,7 +181,7 @@ describe('EventFiltersNotification', () => { type: 'FailedResourceState', error: { message: 'error message', statusCode: 500, error: 'error' }, lastLoadedState: getLastLoadedResourceState( - store.getState()!.management!.eventFilters!.form!.submissionResourceState + store.getState().management.eventFilters.form.submissionResourceState ), }, }); @@ -191,7 +191,7 @@ describe('EventFiltersNotification', () => { expect(notifications.toasts.addDanger).toBeCalledWith( getUpdateErrorMessage( ( - store.getState()!.management!.eventFilters!.form! + store.getState().management.eventFilters.form .submissionResourceState as FailedResourceState ).error ) @@ -211,7 +211,7 @@ describe('EventFiltersNotification', () => { type: 'FailedResourceState', error: { message: 'error message', statusCode: 500, error: 'error' }, lastLoadedState: getLastLoadedResourceState( - store.getState()!.management!.eventFilters!.form!.submissionResourceState + store.getState().management.eventFilters.form.submissionResourceState ), }, }); @@ -221,7 +221,7 @@ describe('EventFiltersNotification', () => { expect(notifications.toasts.addWarning).toBeCalledWith( getGetErrorMessage( ( - store.getState()!.management!.eventFilters!.form! + store.getState().management.eventFilters.form .submissionResourceState as FailedResourceState ).error ) diff --git a/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/view/components/delete_modal.test.tsx b/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/view/components/delete_modal.test.tsx index 2a75ab0622128..2118a8de9b9ed 100644 --- a/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/view/components/delete_modal.test.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/view/components/delete_modal.test.tsx @@ -53,11 +53,11 @@ describe('When on the host isolation exceptions delete modal', () => { const submitButton = renderResult.baseElement.querySelector( '[data-test-subj="hostIsolationExceptionsDeleteModalConfirmButton"]' - )! as HTMLButtonElement; + ) as HTMLButtonElement; const cancelButton = renderResult.baseElement.querySelector( '[data-test-subj="hostIsolationExceptionsDeleteModalConfirmButton"]' - )! as HTMLButtonElement; + ) as HTMLButtonElement; act(() => { fireEvent.click(submitButton); @@ -72,7 +72,7 @@ describe('When on the host isolation exceptions delete modal', () => { render(); const cancelButton = renderResult.baseElement.querySelector( '[data-test-subj="hostIsolationExceptionsDeleteModalConfirmButton"]' - )! as HTMLButtonElement; + ) as HTMLButtonElement; const waiter = waitForAction('hostIsolationExceptionsMarkToDelete', { validate: ({ payload }) => { @@ -96,7 +96,7 @@ describe('When on the host isolation exceptions delete modal', () => { const submitButton = renderResult.baseElement.querySelector( '[data-test-subj="hostIsolationExceptionsDeleteModalConfirmButton"]' - )! as HTMLButtonElement; + ) as HTMLButtonElement; await act(async () => { fireEvent.click(submitButton); @@ -121,7 +121,7 @@ describe('When on the host isolation exceptions delete modal', () => { const submitButton = renderResult.baseElement.querySelector( '[data-test-subj="hostIsolationExceptionsDeleteModalConfirmButton"]' - )! as HTMLButtonElement; + ) as HTMLButtonElement; await act(async () => { fireEvent.click(submitButton); diff --git a/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/view/components/form_flyout.tsx b/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/view/components/form_flyout.tsx index de12616c67a3c..799e327a3fb4c 100644 --- a/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/view/components/form_flyout.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/host_isolation_exceptions/view/components/form_flyout.tsx @@ -97,7 +97,7 @@ export const HostIsolationExceptionsFormFlyout: React.FC<{}> = memo(() => { if (!exceptionToEdit || location.id !== exceptionToEdit.id) { dispatch({ type: 'hostIsolationExceptionsMarkToEdit', - payload: { id: location.id! }, + payload: { id: location.id }, }); } else { setException(exceptionToEdit); diff --git a/x-pack/plugins/security_solution/public/management/pages/mocks/trusted_apps_http_mocks.ts b/x-pack/plugins/security_solution/public/management/pages/mocks/trusted_apps_http_mocks.ts index 6f90fcd629485..0a440afcb2c30 100644 --- a/x-pack/plugins/security_solution/public/management/pages/mocks/trusted_apps_http_mocks.ts +++ b/x-pack/plugins/security_solution/public/management/pages/mocks/trusted_apps_http_mocks.ts @@ -75,6 +75,7 @@ export const trustedAppPutHttpMocks = httpHandlerMockFactory { it('windows process events is enabled', () => { const config = policyConfig(getState()); - expect(config!.windows.events.process).toEqual(true); + expect(config.windows.events.process).toEqual(true); }); }); @@ -128,7 +128,7 @@ describe('policy details: ', () => { it('mac file events is enabled', () => { const config = policyConfig(getState()); - expect(config!.mac.events.file).toEqual(true); + expect(config.mac.events.file).toEqual(true); }); }); @@ -150,7 +150,7 @@ describe('policy details: ', () => { it('linux file events is enabled', () => { const config = policyConfig(getState()); - expect(config!.linux.events.file).toEqual(true); + expect(config.linux.events.file).toEqual(true); }); }); diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_package_custom_extension/components/exception_items_summary.test.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_package_custom_extension/components/exception_items_summary.test.tsx index 1d9edbe66fc78..b348a99d223b8 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_package_custom_extension/components/exception_items_summary.test.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_package_custom_extension/components/exception_items_summary.test.tsx @@ -20,7 +20,7 @@ const mockTheme = getMockTheme({ }); const getStatValue = (el: reactTestingLibrary.RenderResult, stat: string) => { - return el.getByText(stat)!.nextSibling?.lastChild?.textContent; + return el.getByText(stat).nextSibling?.lastChild?.textContent; }; describe('Fleet event filters card', () => { diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_forms/components/policy_form_layout.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_forms/components/policy_form_layout.tsx index a4a2ee65c84e7..4573b15b8fabc 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_forms/components/policy_form_layout.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_forms/components/policy_form_layout.tsx @@ -101,6 +101,7 @@ export const PolicyFormLayout = React.memo(() => { title: i18n.translate('xpack.securitySolution.endpoint.policy.details.updateErrorTitle', { defaultMessage: 'Failed!', }), + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion text: policyUpdateStatus.error!.message, }); } diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_hooks.ts b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_hooks.ts index c6b89b4137cc4..9e53eb9cfc40f 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_hooks.ts +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/policy_hooks.ts @@ -93,7 +93,7 @@ export const usePolicyTrustedAppsNotification = () => { 'xpack.securitySolution.endpoint.policy.trustedApps.layout.flyout.toastSuccess.textSingle', { defaultMessage: '"{name}" has been added to your trusted applications list.', - values: { name: updatedArtifacts[0]!.data.name }, + values: { name: updatedArtifacts[0].data.name }, } ), }); diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/trusted_apps/flyout/policy_trusted_apps_flyout.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/trusted_apps/flyout/policy_trusted_apps_flyout.tsx index 8728104aee637..f5880022383f9 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/trusted_apps/flyout/policy_trusted_apps_flyout.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/trusted_apps/flyout/policy_trusted_apps_flyout.tsx @@ -91,6 +91,7 @@ export const PolicyTrustedAppsFlyout = React.memo(() => { payload: { action: 'assign', artifacts: selectedArtifactIds.map>((selectedId) => { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion return assignableArtifactsList?.data?.find((trustedApp) => trustedApp.id === selectedId)!; }), }, diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/trusted_apps/list/policy_trusted_apps_list.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/trusted_apps/list/policy_trusted_apps_list.tsx index cb29d0ff868ac..5d6c9731c7070 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/trusted_apps/list/policy_trusted_apps_list.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/trusted_apps/list/policy_trusted_apps_list.tsx @@ -181,6 +181,7 @@ export const PolicyTrustedAppsList = memo(() => { const provideCardProps = useCallback['cardComponentProps']>( (item) => { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion return cardProps.get(item as Immutable)!; }, [cardProps] diff --git a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/store/middleware.ts b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/store/middleware.ts index 0ff6282f8a018..0de5761ccf074 100644 --- a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/store/middleware.ts +++ b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/store/middleware.ts @@ -191,6 +191,7 @@ const submitCreationIfNeeded = async ( if (editMode) { responseTrustedApp = ( await trustedAppsService.updateTrustedApp( + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion { id: editItemId(currentState)! }, // TODO: try to remove the cast entry as PostTrustedAppCreateRequest @@ -414,6 +415,7 @@ const fetchEditTrustedAppIfNeeded = async ( payload: { // @ts-expect-error-next-line will be fixed with when AsyncResourceState is refactored (#830) type: 'LoadingResourceState', + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion previousState: editItemState(currentState)!, }, }); diff --git a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/create_trusted_app_form.tsx b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/create_trusted_app_form.tsx index 50485ccde00ad..d4f456ab8e039 100644 --- a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/create_trusted_app_form.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/create_trusted_app_form.tsx @@ -86,7 +86,9 @@ const addResultToValidation = ( }; } const errorMarkup: React.ReactNode = type === 'warnings' ?
{resultValue}
: resultValue; + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion validation.result[field]![type].push(errorMarkup); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion validation.result[field]!.isInvalid = true; }; diff --git a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/effected_policy_select/effected_policy_select.tsx b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/effected_policy_select/effected_policy_select.tsx index e247602060384..07de303c155aa 100644 --- a/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/effected_policy_select/effected_policy_select.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/trusted_apps/view/components/effected_policy_select/effected_policy_select.tsx @@ -143,7 +143,7 @@ export const EffectedPolicySelect = memo( }); }, [isGlobal, onChange] - )!; + ); const handleGlobalButtonChange = useCallback( (selectedId) => { diff --git a/x-pack/plugins/security_solution/public/network/components/details/index.tsx b/x-pack/plugins/security_solution/public/network/components/details/index.tsx index 7658a6a76230c..0b53a4bfb3fe2 100644 --- a/x-pack/plugins/security_solution/public/network/components/details/index.tsx +++ b/x-pack/plugins/security_solution/public/network/components/details/index.tsx @@ -71,7 +71,7 @@ export const IpOverview = React.memo( const capabilities = useMlCapabilities(); const userPermissions = hasMlUserPermissions(capabilities); const [darkMode] = useUiSetting$(DEFAULT_DARK_MODE); - const typeData = data[flowTarget]!; + const typeData = data[flowTarget]; const column: DescriptionList[] = [ { title: i18n.LOCATION, diff --git a/x-pack/plugins/security_solution/public/network/components/network_dns_table/index.test.tsx b/x-pack/plugins/security_solution/public/network/components/network_dns_table/index.test.tsx index a811f5c92c37a..fc28067866146 100644 --- a/x-pack/plugins/security_solution/public/network/components/network_dns_table/index.test.tsx +++ b/x-pack/plugins/security_solution/public/network/components/network_dns_table/index.test.tsx @@ -78,7 +78,7 @@ describe('NetworkTopNFlow Table Component', () => { ); - expect(store.getState().network.page.queries!.dns.sort).toEqual({ + expect(store.getState().network.page.queries?.dns.sort).toEqual({ direction: 'desc', field: 'queryCount', }); @@ -87,7 +87,7 @@ describe('NetworkTopNFlow Table Component', () => { wrapper.update(); - expect(store.getState().network.page.queries!.dns.sort).toEqual({ + expect(store.getState().network.page.queries?.dns.sort).toEqual({ direction: 'asc', field: 'dnsName', }); diff --git a/x-pack/plugins/security_solution/public/network/components/network_http_table/index.test.tsx b/x-pack/plugins/security_solution/public/network/components/network_http_table/index.test.tsx index f05372c76b36f..2a85b31791f5a 100644 --- a/x-pack/plugins/security_solution/public/network/components/network_http_table/index.test.tsx +++ b/x-pack/plugins/security_solution/public/network/components/network_http_table/index.test.tsx @@ -80,7 +80,7 @@ describe('NetworkHttp Table Component', () => { ); - expect(store.getState().network.page.queries!.http.sort).toEqual({ + expect(store.getState().network.page.queries?.http.sort).toEqual({ direction: 'desc', }); @@ -88,7 +88,7 @@ describe('NetworkHttp Table Component', () => { wrapper.update(); - expect(store.getState().network.page.queries!.http.sort).toEqual({ + expect(store.getState().network.page.queries?.http.sort).toEqual({ direction: 'asc', }); expect(wrapper.find('.euiTable thead tr th button').first().find('svg')).toBeTruthy(); diff --git a/x-pack/plugins/security_solution/public/network/components/tls_table/index.test.tsx b/x-pack/plugins/security_solution/public/network/components/tls_table/index.test.tsx index 8f2c7a098a045..3a1a5efef6b89 100644 --- a/x-pack/plugins/security_solution/public/network/components/tls_table/index.test.tsx +++ b/x-pack/plugins/security_solution/public/network/components/tls_table/index.test.tsx @@ -77,7 +77,7 @@ describe('Tls Table Component', () => { /> ); - expect(store.getState().network.details.queries!.tls.sort).toEqual({ + expect(store.getState().network.details.queries?.tls.sort).toEqual({ direction: 'desc', field: '_id', }); @@ -86,7 +86,7 @@ describe('Tls Table Component', () => { wrapper.update(); - expect(store.getState().network.details.queries!.tls.sort).toEqual({ + expect(store.getState().network.details.queries?.tls.sort).toEqual({ direction: 'asc', field: '_id', }); diff --git a/x-pack/plugins/security_solution/public/network/components/users_table/index.test.tsx b/x-pack/plugins/security_solution/public/network/components/users_table/index.test.tsx index 69027ad9bd9f8..3861433b4dcb0 100644 --- a/x-pack/plugins/security_solution/public/network/components/users_table/index.test.tsx +++ b/x-pack/plugins/security_solution/public/network/components/users_table/index.test.tsx @@ -81,7 +81,7 @@ describe('Users Table Component', () => { /> ); - expect(store.getState().network.details.queries!.users.sort).toEqual({ + expect(store.getState().network.details.queries?.users.sort).toEqual({ direction: 'asc', field: 'name', }); @@ -90,7 +90,7 @@ describe('Users Table Component', () => { wrapper.update(); - expect(store.getState().network.details.queries!.users.sort).toEqual({ + expect(store.getState().network.details.queries?.users.sort).toEqual({ direction: 'desc', field: 'name', }); diff --git a/x-pack/plugins/security_solution/public/plugin.tsx b/x-pack/plugins/security_solution/public/plugin.tsx index 718487ccf7fc6..371b68e9bec8e 100644 --- a/x-pack/plugins/security_solution/public/plugin.tsx +++ b/x-pack/plugins/security_solution/public/plugin.tsx @@ -371,16 +371,23 @@ export class Plugin implements IPlugin node.id === originID)! ); const relatedEvents = [ diff --git a/x-pack/plugins/security_solution/public/resolver/models/indexed_process_tree/index.ts b/x-pack/plugins/security_solution/public/resolver/models/indexed_process_tree/index.ts index 3a8bf76e732a9..6dfeaa9723a33 100644 --- a/x-pack/plugins/security_solution/public/resolver/models/indexed_process_tree/index.ts +++ b/x-pack/plugins/security_solution/public/resolver/models/indexed_process_tree/index.ts @@ -162,6 +162,7 @@ export function root(tree: IndexedProcessTree) { // iteratively swap current w/ its parent while (parent(tree, current) !== undefined) { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion current = parent(tree, current)!; } return current; diff --git a/x-pack/plugins/security_solution/public/resolver/store/selectors.test.ts b/x-pack/plugins/security_solution/public/resolver/store/selectors.test.ts index 110ea476f5fb2..26cf874edda00 100644 --- a/x-pack/plugins/security_solution/public/resolver/store/selectors.test.ts +++ b/x-pack/plugins/security_solution/public/resolver/store/selectors.test.ts @@ -145,7 +145,7 @@ describe('resolver selectors', () => { }); }); it('the origin should be in view', () => { - const origin = selectors.graphNodeForID(state())(originID)!; + const origin = selectors.graphNodeForID(state())(originID); expect( selectors .visibleNodesAndEdgeLines(state())(0) @@ -153,7 +153,7 @@ describe('resolver selectors', () => { ).toBe(true); }); it('the first child should be in view', () => { - const firstChild = selectors.graphNodeForID(state())(firstChildID)!; + const firstChild = selectors.graphNodeForID(state())(firstChildID); expect( selectors .visibleNodesAndEdgeLines(state())(0) @@ -161,7 +161,7 @@ describe('resolver selectors', () => { ).toBe(true); }); it('the second child should not be in view', () => { - const secondChild = selectors.graphNodeForID(state())(secondChildID)!; + const secondChild = selectors.graphNodeForID(state())(secondChildID); expect( selectors .visibleNodesAndEdgeLines(state())(0) diff --git a/x-pack/plugins/security_solution/public/resolver/test_utilities/extend_jest.ts b/x-pack/plugins/security_solution/public/resolver/test_utilities/extend_jest.ts index 145e54dbbb7b2..7bb7180712c99 100644 --- a/x-pack/plugins/security_solution/public/resolver/test_utilities/extend_jest.ts +++ b/x-pack/plugins/security_solution/public/resolver/test_utilities/extend_jest.ts @@ -67,7 +67,7 @@ expect.extend({ ? () => `${this.utils.matcherHint(matcherName, undefined, undefined, options)}\n\n` + `Expected: not ${this.utils.printExpected(expected)}\n${ - this.utils.stringify(expected) !== this.utils.stringify(received[received.length - 1]!) + this.utils.stringify(expected) !== this.utils.stringify(received[received.length - 1]) ? `Received: ${this.utils.printReceived(received[received.length - 1])}` : '' }` @@ -131,7 +131,7 @@ expect.extend({ ? () => `${this.utils.matcherHint(matcherName, undefined, undefined, options)}\n\n` + `Expected: not ${this.utils.printExpected(expected)}\n${ - this.utils.stringify(expected) !== this.utils.stringify(received[received.length - 1]!) + this.utils.stringify(expected) !== this.utils.stringify(received[received.length - 1]) ? `Received: ${this.utils.printReceived(received[received.length - 1])}` : '' }` diff --git a/x-pack/plugins/security_solution/public/resolver/view/graph_controls.test.tsx b/x-pack/plugins/security_solution/public/resolver/view/graph_controls.test.tsx index 1a7477af3b3cf..6a146882fbab5 100644 --- a/x-pack/plugins/security_solution/public/resolver/view/graph_controls.test.tsx +++ b/x-pack/plugins/security_solution/public/resolver/view/graph_controls.test.tsx @@ -104,7 +104,7 @@ describe('graph controls: when relsover is loaded with an origin node', () => { describe('when the user clicks the west panning button', () => { beforeEach(async () => { - (await simulator.resolve('resolver:graph-controls:west-button'))!.simulate('click'); + (await simulator.resolve('resolver:graph-controls:west-button'))?.simulate('click'); simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); }); @@ -118,7 +118,7 @@ describe('graph controls: when relsover is loaded with an origin node', () => { describe('when the user clicks the south panning button', () => { beforeEach(async () => { - (await simulator.resolve('resolver:graph-controls:south-button'))!.simulate('click'); + (await simulator.resolve('resolver:graph-controls:south-button'))?.simulate('click'); simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); }); @@ -132,7 +132,7 @@ describe('graph controls: when relsover is loaded with an origin node', () => { describe('when the user clicks the east panning button', () => { beforeEach(async () => { - (await simulator.resolve('resolver:graph-controls:east-button'))!.simulate('click'); + (await simulator.resolve('resolver:graph-controls:east-button'))?.simulate('click'); simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); }); @@ -146,7 +146,7 @@ describe('graph controls: when relsover is loaded with an origin node', () => { describe('when the user clicks the north panning button', () => { beforeEach(async () => { - (await simulator.resolve('resolver:graph-controls:north-button'))!.simulate('click'); + (await simulator.resolve('resolver:graph-controls:north-button'))?.simulate('click'); simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); }); @@ -160,9 +160,9 @@ describe('graph controls: when relsover is loaded with an origin node', () => { describe('when the user clicks the center panning button', () => { beforeEach(async () => { - (await simulator.resolve('resolver:graph-controls:north-button'))!.simulate('click'); + (await simulator.resolve('resolver:graph-controls:north-button'))?.simulate('click'); simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); - (await simulator.resolve('resolver:graph-controls:center-button'))!.simulate('click'); + (await simulator.resolve('resolver:graph-controls:center-button'))?.simulate('click'); simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); }); @@ -177,7 +177,7 @@ describe('graph controls: when relsover is loaded with an origin node', () => { describe('when the zoom in button is clicked', () => { beforeEach(async () => { - (await simulator.resolve('resolver:graph-controls:zoom-in'))!.simulate('click'); + (await simulator.resolve('resolver:graph-controls:zoom-in'))?.simulate('click'); simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); }); @@ -191,7 +191,7 @@ describe('graph controls: when relsover is loaded with an origin node', () => { describe('when the zoom out button is clicked', () => { beforeEach(async () => { - (await simulator.resolve('resolver:graph-controls:zoom-out'))!.simulate('click'); + (await simulator.resolve('resolver:graph-controls:zoom-out'))?.simulate('click'); simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); }); @@ -207,7 +207,7 @@ describe('graph controls: when relsover is loaded with an origin node', () => { beforeEach(async () => { await expect(originNodeStyle()).toYieldObjectEqualTo(originalSizeStyle); - (await simulator.resolve('resolver:graph-controls:zoom-slider'))!.simulate('change', { + (await simulator.resolve('resolver:graph-controls:zoom-slider'))?.simulate('change', { target: { value: 0.8 }, }); simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); @@ -223,7 +223,7 @@ describe('graph controls: when relsover is loaded with an origin node', () => { describe('when the slider is moved downwards', () => { beforeEach(async () => { - (await simulator.resolve('resolver:graph-controls:zoom-slider'))!.simulate('change', { + (await simulator.resolve('resolver:graph-controls:zoom-slider'))?.simulate('change', { target: { value: 0.2 }, }); simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); @@ -239,7 +239,7 @@ describe('graph controls: when relsover is loaded with an origin node', () => { describe('when the schema information button is clicked', () => { beforeEach(async () => { - (await simulator.resolve('resolver:graph-controls:schema-info-button'))!.simulate('click', { + (await simulator.resolve('resolver:graph-controls:schema-info-button'))?.simulate('click', { button: 0, }); }); @@ -257,7 +257,7 @@ describe('graph controls: when relsover is loaded with an origin node', () => { describe('when the node legend button is clicked', () => { beforeEach(async () => { - (await simulator.resolve('resolver:graph-controls:node-legend-button'))!.simulate('click', { + (await simulator.resolve('resolver:graph-controls:node-legend-button'))?.simulate('click', { button: 0, }); }); @@ -275,7 +275,7 @@ describe('graph controls: when relsover is loaded with an origin node', () => { describe('when the node legend button is clicked while the schema info button is open', () => { beforeEach(async () => { - (await simulator.resolve('resolver:graph-controls:schema-info-button'))!.simulate('click', { + (await simulator.resolve('resolver:graph-controls:schema-info-button'))?.simulate('click', { button: 0, }); }); @@ -284,8 +284,8 @@ describe('graph controls: when relsover is loaded with an origin node', () => { expect(simulator.testSubject('resolver:graph-controls:schema-info').length).toBe(1); await simulator - .testSubject('resolver:graph-controls:node-legend-button')! - .simulate('click', { button: 0 }); + .testSubject('resolver:graph-controls:node-legend-button') + ?.simulate('click', { button: 0 }); await expect( simulator.map(() => ({ diff --git a/x-pack/plugins/security_solution/public/resolver/view/panel.test.tsx b/x-pack/plugins/security_solution/public/resolver/view/panel.test.tsx index 3b2d222ac3812..72db334e17c2c 100644 --- a/x-pack/plugins/security_solution/public/resolver/view/panel.test.tsx +++ b/x-pack/plugins/security_solution/public/resolver/view/panel.test.tsx @@ -150,13 +150,13 @@ describe(`Resolver: when analyzing a tree with no ancestors and two children and .filterWhere(Simulator.isDOM); expect(copyableFieldHoverArea).toHaveLength(1); - copyableFieldHoverArea!.simulate('mouseenter'); + copyableFieldHoverArea?.simulate('mouseenter'); }); describe('and when they click the copy-to-clipboard button', () => { beforeEach(async () => { const copyButton = await simulator().resolve('resolver:panel:clipboard'); expect(copyButton).toHaveLength(1); - copyButton!.simulate('click'); + copyButton?.simulate('click'); simulator().confirmTextWrittenToClipboard(); }); it(`should write ${value} to the clipboard`, async () => { @@ -232,11 +232,11 @@ describe(`Resolver: when analyzing a tree with no ancestors and two children and .filterWhere(Simulator.isDOM) ); }); - cExtHoverArea!.simulate('mouseenter'); + cExtHoverArea?.simulate('mouseenter'); }); describe('and when the user clicks the copy-to-clipboard button', () => { beforeEach(async () => { - (await simulator().resolve('resolver:panel:clipboard'))!.simulate('click'); + (await simulator().resolve('resolver:panel:clipboard'))?.simulate('click'); simulator().confirmTextWrittenToClipboard(); }); const expected = 'Sep 23, 2020 @ 08:25:32.316'; @@ -369,7 +369,7 @@ describe(`Resolver: when analyzing a tree with no ancestors and two children and beforeEach(async () => { const button = await simulator().resolve('resolver:panel:clipboard'); expect(button).toBeTruthy(); - button!.simulate('click'); + button?.simulate('click'); simulator().confirmTextWrittenToClipboard(); }); it(`should write ${expectedValue} to the clipboard`, async () => { diff --git a/x-pack/plugins/security_solution/public/resolver/view/side_effect_simulator_factory.ts b/x-pack/plugins/security_solution/public/resolver/view/side_effect_simulator_factory.ts index 8c3caf16eadd7..b3289a510deef 100644 --- a/x-pack/plugins/security_solution/public/resolver/view/side_effect_simulator_factory.ts +++ b/x-pack/plugins/security_solution/public/resolver/view/side_effect_simulator_factory.ts @@ -41,6 +41,7 @@ export const sideEffectSimulatorFactory: () => SideEffectSimulator = () => { */ const getBoundingClientRect: (target: Element) => DOMRect = (target) => { if (contentRects.has(target)) { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion return contentRects.get(target)!; } const domRect: DOMRect = { diff --git a/x-pack/plugins/security_solution/public/timelines/components/field_renderers/field_renderers.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/field_renderers/field_renderers.test.tsx index 9851f11d9adba..e76e2800908c2 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/field_renderers/field_renderers.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/field_renderers/field_renderers.test.tsx @@ -70,7 +70,7 @@ describe('Field Renderers', () => { describe('#dateRenderer', () => { test('it renders correctly against snapshot', () => { - const wrapper = shallow(dateRenderer(mockData.complete.source!.firstSeen)); + const wrapper = shallow(dateRenderer(mockData.complete.source?.firstSeen)); expect(wrapper).toMatchSnapshot(); }); @@ -307,7 +307,7 @@ describe('Field Renderers', () => { ); expect( - wrapper.find('[data-test-subj="more-container"]').first().props().style!.overflow + wrapper.find('[data-test-subj="more-container"]').first().props().style?.overflow ).toEqual('auto'); }); @@ -322,7 +322,7 @@ describe('Field Renderers', () => { ); expect( - wrapper.find('[data-test-subj="more-container"]').first().props().style!.maxHeight + wrapper.find('[data-test-subj="more-container"]').first().props().style?.maxHeight ).toEqual(DEFAULT_MORE_MAX_HEIGHT); }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/flyout/header/active_timelines.tsx b/x-pack/plugins/security_solution/public/timelines/components/flyout/header/active_timelines.tsx index 4eb91ca8ee272..639bc1ac6b57f 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/flyout/header/active_timelines.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/flyout/header/active_timelines.tsx @@ -77,6 +77,7 @@ const ActiveTimelinesComponent: React.FC = ({ diff --git a/x-pack/plugins/security_solution/public/timelines/components/flyout/header/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/flyout/header/index.tsx index 9f1730c367a81..1fdfb744f3071 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/flyout/header/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/flyout/header/index.tsx @@ -113,6 +113,7 @@ const FlyoutHeaderPanelComponent: React.FC = ({ timeline [dataProviders, kqlQuery] ); const getKqlQueryTimeline = useMemo(() => timelineSelectors.getKqlFilterQuerySelector(), []); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const kqlQueryTimeline = useSelector((state: State) => getKqlQueryTimeline(state, timelineId)!); const kqlQueryExpression = @@ -333,6 +334,7 @@ const TimelineStatusInfoComponent: React.FC = ({ timelineId } @@ -372,6 +374,7 @@ const FlyoutHeaderComponent: React.FC = ({ timelineId }) => { ); const { dataProviders, filters, timelineType, kqlMode, activeTab } = timeline; const getKqlQueryTimeline = useMemo(() => timelineSelectors.getKqlFilterQuerySelector(), []); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const kqlQueryTimeline = useSelector((state: State) => getKqlQueryTimeline(state, timelineId)!); const kqlQueryExpression = diff --git a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/helpers.ts b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/helpers.ts index 2a3b49517b456..1fbddf61f8cd3 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/helpers.ts +++ b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/helpers.ts @@ -205,9 +205,11 @@ const convertToDefaultField = ({ and, ...dataProvider }: DataProviderResult) => if (dataProvider.type === DataProviderType.template) { return deepMerge(dataProvider, { type: DataProviderType.default, + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion enabled: dataProvider.queryMatch!.operator !== IS_OPERATOR, queryMatch: { value: + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion dataProvider.queryMatch!.operator === IS_OPERATOR ? '' : dataProvider.queryMatch!.value, }, }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/index.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/index.test.tsx index d59b75fcfb506..f3ec55ea0ddef 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/index.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/index.test.tsx @@ -318,7 +318,7 @@ describe('StatefulOpenTimeline', () => { await waitFor(() => { expect( wrapper.find(`.${OPEN_TIMELINE_CLASS_NAME} input`).first().getDOMNode().id === - document.activeElement!.id + document.activeElement?.id ).toBe(true); }); }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/note_previews/index.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/note_previews/index.test.tsx index 1cca5a3999b81..607bccdbc039d 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/note_previews/index.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/note_previews/index.test.tsx @@ -44,7 +44,7 @@ describe('NotePreviews', () => { const wrapper = mountWithIntl(); - hasNotes[0].notes!.forEach(({ savedObjectId }) => { + hasNotes[0].notes?.forEach(({ savedObjectId }) => { expect(wrapper.find(`[data-test-subj="note-preview-${savedObjectId}"]`).exists()).toBe(true); }); }); @@ -54,7 +54,7 @@ describe('NotePreviews', () => { const wrapper = mountWithIntl(); - hasNotes[0].notes!.forEach(({ savedObjectId }) => { + hasNotes[0].notes?.forEach(({ savedObjectId }) => { expect(wrapper.find(`[data-test-subj="note-preview-${savedObjectId}"]`).exists()).toBe(true); }); }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/timelines_table/actions_columns.tsx b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/timelines_table/actions_columns.tsx index b3cd5eedd19c3..a7953d60ba767 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/open_timeline/timelines_table/actions_columns.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/open_timeline/timelines_table/actions_columns.tsx @@ -40,6 +40,7 @@ export const getActionsColumns = ({ onOpenTimeline({ duplicate: true, timelineType: TimelineType.default, + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion timelineId: savedObjectId!, }); }, @@ -58,6 +59,7 @@ export const getActionsColumns = ({ onOpenTimeline({ duplicate: true, timelineType: TimelineType.template, + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion timelineId: savedObjectId!, }); }, diff --git a/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/expandable_event.tsx b/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/expandable_event.tsx index 53382fe8fa21d..17d43d80a5a9a 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/expandable_event.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/side_panel/event_details/expandable_event.tsx @@ -108,7 +108,7 @@ export const ExpandableEvent = React.memo( ( {':'} - + {header.type}

diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/events/stateful_event.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/events/stateful_event.tsx index 8c71a3b38dcd3..82f9cedc57a9c 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/events/stateful_event.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/events/stateful_event.tsx @@ -185,6 +185,7 @@ const StatefulEventComponent: React.FC = ({ const handleOnEventDetailPanelOpened = useCallback(() => { const eventId = event._id; + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const indexName = event._index!; const updatedExpandedDetail: TimelineExpandedDetailType = { diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/index.tsx index fc8bf2086471c..3ee0ef8804e89 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/index.tsx @@ -111,7 +111,7 @@ export const BodyComponent = React.memo( const onRowSelected: OnRowSelected = useCallback( ({ eventIds, isSelected }: { eventIds: string[]; isSelected: boolean }) => { - setSelected!({ + setSelected({ id, eventIds: getEventIdToDataMapping(data, eventIds, queryFields), isSelected, @@ -125,7 +125,7 @@ export const BodyComponent = React.memo( const onSelectAll: OnSelectAll = useCallback( ({ isSelected }: { isSelected: boolean }) => isSelected - ? setSelected!({ + ? setSelected({ id, eventIds: getEventIdToDataMapping( data, @@ -135,7 +135,7 @@ export const BodyComponent = React.memo( isSelected, isSelectAllChecked: isSelected, }) - : clearSelected!({ id }), + : clearSelected({ id }), [setSelected, clearSelected, id, data, queryFields] ); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/suricata_row_renderer.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/suricata_row_renderer.test.tsx index 3703d6fe441c0..61ea659964e4d 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/suricata_row_renderer.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/suricata/suricata_row_renderer.test.tsx @@ -78,7 +78,7 @@ describe('suricata_row_renderer', () => { }); test('should render a suricata row even if it does not have a suricata signature', () => { - delete suricata!.suricata!.eve!.alert!.signature; + delete suricata?.suricata?.eve?.alert?.signature; const children = suricataRowRenderer.renderRow({ browserFields: mockBrowserFields, data: suricata, diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/zeek_signature.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/zeek_signature.tsx index 41f35e7c50e30..7c010795682ac 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/zeek_signature.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/body/renderers/zeek/zeek_signature.tsx @@ -76,12 +76,12 @@ export const DraggableZeekElement = React.memo<{ and: [], enabled: true, id: escapeDataProviderId(`draggable-zeek-element-draggable-wrapper-${id}-${field}-${value}`), - name: value!, + name: String(value), excluded: false, kqlQuery: '', queryMatch: { field, - value: value!, + value: String(value), operator: IS_OPERATOR as QueryOperator, }, }), @@ -97,7 +97,7 @@ export const DraggableZeekElement = React.memo<{ ) : ( - {stringRenderer(value!)} + {stringRenderer(String(value))} ), diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/add_data_provider_popover.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/add_data_provider_popover.tsx index 84f286b435a48..52443cf92a9cb 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/add_data_provider_popover.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/data_providers/add_data_provider_popover.tsx @@ -113,7 +113,7 @@ const AddDataProviderPopoverComponent: React.FC = ( width: 400, content: ( = ( width: 400, content: ( = ( return ( = ({ users }) => { const List = useMemo( () => users.map((user) => ( - - + + )), diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/query_tab_content/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/query_tab_content/index.tsx index d2cf158818f75..2082e7f5b69bb 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/query_tab_content/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/query_tab_content/index.tsx @@ -463,7 +463,7 @@ const makeMapStateToProps = () => { status, timelineType, } = timeline; - const kqlQueryTimeline = getKqlQueryTimeline(state, timelineId)!; + const kqlQueryTimeline = getKqlQueryTimeline(state, timelineId); const timelineFilter = kqlMode === 'filter' ? filters || [] : []; // return events on empty search diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/search_or_filter/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/search_or_filter/index.tsx index 33ab2e0049828..96ca26a099d2f 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/search_or_filter/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/search_or_filter/index.tsx @@ -74,7 +74,7 @@ const StatefulSearchOrFilterComponent = React.memo( from={from} fromStr={fromStr} isRefreshPaused={isRefreshPaused} - kqlMode={kqlMode!} + kqlMode={kqlMode} refreshInterval={refreshInterval} savedQueryId={savedQueryId} setFilters={setFiltersInTimeline} @@ -82,7 +82,7 @@ const StatefulSearchOrFilterComponent = React.memo( timelineId={timelineId} to={to} toStr={toStr} - updateKqlMode={updateKqlMode!} + updateKqlMode={updateKqlMode} updateReduxTime={updateReduxTime} /> ); @@ -119,15 +119,19 @@ const makeMapStateToProps = () => { const policy: inputsModel.Policy = getInputsPolicy(state); return { dataProviders: timeline.dataProviders, + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion filterQuery: getKqlFilterQuery(state, timelineId)!, + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion filters: timeline.filters!, from: input.timerange.from, + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion fromStr: input.timerange.fromStr!, isRefreshPaused: policy.kind === 'manual', kqlMode: getOr('filter', 'kqlMode', timeline), refreshInterval: policy.duration, savedQueryId: getOr(null, 'savedQueryId', timeline), to: input.timerange.to, + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion toStr: input.timerange.toStr!, }; }; diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/selectable_timeline/index.test.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/selectable_timeline/index.test.tsx index 44174009d0198..7269c005e9af5 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/selectable_timeline/index.test.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/selectable_timeline/index.test.tsx @@ -47,7 +47,7 @@ describe('SelectableTimeline', () => { const searchProps: EuiSelectableProps['searchProps'] = wrapper .find('[data-test-subj="selectable-input"]') .prop('searchProps'); - expect(searchProps!.placeholder).toEqual('e.g. Timeline name or description'); + expect(searchProps?.placeholder).toEqual('e.g. Timeline name or description'); }); }); @@ -65,7 +65,7 @@ describe('SelectableTimeline', () => { const searchProps: EuiSelectableProps['searchProps'] = wrapper .find('[data-test-subj="selectable-input"]') .prop('searchProps'); - expect(searchProps!.placeholder).toEqual('e.g. Timeline template name or description'); + expect(searchProps?.placeholder).toEqual('e.g. Timeline template name or description'); }); }); }); diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/selectable_timeline/index.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/selectable_timeline/index.tsx index 9d10584130194..e4070a051af46 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/selectable_timeline/index.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/selectable_timeline/index.tsx @@ -110,8 +110,8 @@ const SelectableTimelineComponent: React.FC = ({ selectableListOuterRef.current && selectableListInnerRef.current ) { - const clientHeight = selectableListOuterRef.current!.clientHeight; - const scrollHeight = selectableListInnerRef.current!.clientHeight; + const clientHeight = selectableListOuterRef.current.clientHeight; + const scrollHeight = selectableListInnerRef.current.clientHeight; const clientHeightTrigger = clientHeight * 1.2; if ( scrollOffset > 10 && diff --git a/x-pack/plugins/security_solution/public/timelines/components/timeline/styles.tsx b/x-pack/plugins/security_solution/public/timelines/components/timeline/styles.tsx index 3514766b334a0..af05198ef9974 100644 --- a/x-pack/plugins/security_solution/public/timelines/components/timeline/styles.tsx +++ b/x-pack/plugins/security_solution/public/timelines/components/timeline/styles.tsx @@ -271,13 +271,13 @@ export const EventsTrData = styled.div.attrs(({ className = '' }) => ({ const TIMELINE_EVENT_DETAILS_OFFSET = 40; interface WidthProp { - width?: number; + width: number; } export const EventsTrSupplementContainer = styled.div.attrs(({ width }) => ({ role: 'dialog', style: { - width: `${width! - TIMELINE_EVENT_DETAILS_OFFSET}px`, + width: `${width - TIMELINE_EVENT_DETAILS_OFFSET}px`, }, }))``; diff --git a/x-pack/plugins/security_solution/public/timelines/containers/api.ts b/x-pack/plugins/security_solution/public/timelines/containers/api.ts index 789c942d0e29a..7f74912be09b4 100644 --- a/x-pack/plugins/security_solution/public/timelines/containers/api.ts +++ b/x-pack/plugins/security_solution/public/timelines/containers/api.ts @@ -156,6 +156,7 @@ export const persistTimeline = async ({ try { if (isEmpty(timelineId) && timeline.status === TimelineStatus.draft && timeline) { const temp: TimelineResponse | TimelineErrorResponse = await cleanDraftTimeline({ + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion timelineType: timeline.timelineType!, templateTimelineId: timeline.templateTimelineId ?? undefined, templateTimelineVersion: timeline.templateTimelineVersion ?? undefined, @@ -163,7 +164,7 @@ export const persistTimeline = async ({ const draftTimeline = decodeTimelineResponse(temp); const templateTimelineInfo = - timeline.timelineType! === TimelineType.template + timeline.timelineType === TimelineType.template ? { templateTimelineId: draftTimeline.data.persistTimeline.timeline.templateTimelineId ?? diff --git a/x-pack/plugins/security_solution/public/timelines/store/timeline/epic.ts b/x-pack/plugins/security_solution/public/timelines/store/timeline/epic.ts index 9d95036cb6076..164f293edee65 100644 --- a/x-pack/plugins/security_solution/public/timelines/store/timeline/epic.ts +++ b/x-pack/plugins/security_solution/public/timelines/store/timeline/epic.ts @@ -235,7 +235,7 @@ export const createTimelineEpic = mergeMap(([result, recentTimeline, allTimelineQuery, kibana]) => { const error = result as TimelineErrorResponse; if (error.status_code != null && error.status_code === 405) { - kibana.notifications!.toasts.addDanger({ + kibana.notifications.toasts.addDanger({ title: i18n.UPDATE_TIMELINE_ERROR_TITLE, text: error.message ?? i18n.UPDATE_TIMELINE_ERROR_TEXT, }); diff --git a/x-pack/plugins/security_solution/public/timelines/store/timeline/reducer.test.ts b/x-pack/plugins/security_solution/public/timelines/store/timeline/reducer.test.ts index eceafb9b56cdd..639d1b1e4f489 100644 --- a/x-pack/plugins/security_solution/public/timelines/store/timeline/reducer.test.ts +++ b/x-pack/plugins/security_solution/public/timelines/store/timeline/reducer.test.ts @@ -1126,8 +1126,8 @@ describe('Timeline', () => { const newAndProvider = update.foo.dataProviders[indexProvider].and.find( (i) => i.id === '456' ); - expect(oldAndProvider!.enabled).toEqual(false); - expect(newAndProvider!.enabled).toEqual(true); + expect(oldAndProvider?.enabled).toEqual(false); + expect(newAndProvider?.enabled).toEqual(true); }); }); @@ -1386,8 +1386,8 @@ describe('Timeline', () => { const newAndProvider = update.foo.dataProviders[indexProvider].and.find( (i) => i.id === '456' ); - expect(oldAndProvider!.excluded).toEqual(true); - expect(newAndProvider!.excluded).toEqual(false); + expect(oldAndProvider?.excluded).toEqual(true); + expect(newAndProvider?.excluded).toEqual(false); }); }); diff --git a/x-pack/plugins/security_solution/server/endpoint/lib/artifacts/task.ts b/x-pack/plugins/security_solution/server/endpoint/lib/artifacts/task.ts index a116311becfe5..cf6665a5dde2b 100644 --- a/x-pack/plugins/security_solution/server/endpoint/lib/artifacts/task.ts +++ b/x-pack/plugins/security_solution/server/endpoint/lib/artifacts/task.ts @@ -135,6 +135,7 @@ export class ManifestTask { } } + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion if (oldManifest! == null) { this.logger.debug('Last computed manifest not available yet'); return; diff --git a/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts b/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts index a1b93b5bd59f7..32d5806a4b47a 100644 --- a/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts +++ b/x-pack/plugins/security_solution/server/endpoint/lib/policy/license_watch.test.ts @@ -130,7 +130,7 @@ describe('Policy-Changing license watcher', () => { expect(packagePolicySvcMock.update).toHaveBeenCalled(); expect( - packagePolicySvcMock.update.mock.calls[0][3].inputs[0].config!.policy.value.windows.popup + packagePolicySvcMock.update.mock.calls[0][3].inputs[0].config?.policy.value.windows.popup .malware.message ).not.toEqual(CustomMessage); }); diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/actions/isolation.ts b/x-pack/plugins/security_solution/server/endpoint/routes/actions/isolation.ts index 4652630649ffc..e12299bedbb34 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/actions/isolation.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/actions/isolation.ts @@ -189,6 +189,7 @@ export const isolationRequestHandler = function ( }, } as Omit, user: { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion id: user!.username, }, }; diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/enrichment.test.ts b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/enrichment.test.ts index 39aa0bf2d8cf7..9b454a266834c 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/enrichment.test.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/enrichment.test.ts @@ -114,8 +114,8 @@ describe('test document enrichment', () => { const enrichedHostList = await enrichHostMetadata(docGen.generateHostMetadata(), metaReqCtx); expect(enrichedHostList.policy_info).toBeDefined(); - expect(enrichedHostList.policy_info!.agent.applied.id).toEqual(policyID); - expect(enrichedHostList.policy_info!.agent.applied.revision).toEqual(policyRev); + expect(enrichedHostList.policy_info?.agent.applied.id).toEqual(policyID); + expect(enrichedHostList.policy_info?.agent.applied.revision).toEqual(policyRev); }); it('reflects current fleet agent info', async () => { @@ -130,8 +130,8 @@ describe('test document enrichment', () => { const enrichedHostList = await enrichHostMetadata(docGen.generateHostMetadata(), metaReqCtx); expect(enrichedHostList.policy_info).toBeDefined(); - expect(enrichedHostList.policy_info!.agent.configured.id).toEqual(policyID); - expect(enrichedHostList.policy_info!.agent.configured.revision).toEqual(policyRev); + expect(enrichedHostList.policy_info?.agent.configured.id).toEqual(policyID); + expect(enrichedHostList.policy_info?.agent.configured.revision).toEqual(policyRev); }); it('reflects current endpoint policy info', async () => { @@ -151,8 +151,8 @@ describe('test document enrichment', () => { const enrichedHostList = await enrichHostMetadata(docGen.generateHostMetadata(), metaReqCtx); expect(enrichedHostList.policy_info).toBeDefined(); - expect(enrichedHostList.policy_info!.endpoint.id).toEqual(policyID); - expect(enrichedHostList.policy_info!.endpoint.revision).toEqual(policyRev); + expect(enrichedHostList.policy_info?.endpoint.id).toEqual(policyID); + expect(enrichedHostList.policy_info?.endpoint.revision).toEqual(policyRev); }); }); }); diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/handlers.ts b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/handlers.ts index 5c06dbd3db14c..027107bcf1a59 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/handlers.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/handlers.ts @@ -114,6 +114,7 @@ export const getMetadataListRequestHandler = function ( } const endpointPolicies = await getAllEndpointPackagePolicies( + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion endpointAppContext.service.getPackagePolicyService()!, context.core.savedObjects.client ); @@ -344,6 +345,7 @@ export async function enrichHostMetadata( const status = await metadataRequestContext.endpointAppContextService ?.getAgentService() ?.getAgentStatusById(esClient.asCurrentUser, elasticAgentId); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion hostStatus = fleetAgentStatusToEndpointHostStatus(status!); } catch (e) { if (e instanceof AgentNotFoundError) { @@ -361,6 +363,7 @@ export async function enrichHostMetadata( ?.getAgent(esClient.asCurrentUser, elasticAgentId); const agentPolicy = await metadataRequestContext.endpointAppContextService .getAgentPolicyService() + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion ?.get(esSavedObjectClient, agent?.policy_id!, true); const endpointPolicy = ((agentPolicy?.package_policies || []) as PackagePolicy[]).find( (policy: PackagePolicy) => policy.package?.name === 'endpoint' @@ -404,6 +407,7 @@ async function legacyListMetadataQuery( logger: Logger, endpointPolicies: PackagePolicy[] ): Promise { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const agentService = endpointAppContext.service.getAgentService()!; const metadataRequestContext: MetadataRequestContext = { @@ -512,11 +516,15 @@ async function queryUnitedIndex( return metadata && agent; }) .map((doc) => { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const { endpoint: metadata, agent } = doc!._source!.united!; + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const agentPolicy = agentPoliciesMap[agent.policy_id!]; + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const endpointPolicy = endpointPoliciesMap[agent.policy_id!]; return { metadata, + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion host_status: fleetAgentStatusToEndpointHostStatus(agent.last_checkin_status!), policy_info: { agent: { diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/metadata.test.ts b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/metadata.test.ts index d9016e7a9c7cb..3e5050c05814a 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/metadata.test.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/metadata.test.ts @@ -171,8 +171,8 @@ describe('test endpoint route', () => { const esSearchMock = mockScopedClient.asCurrentUser.search; // should be called twice, united index first, then legacy index expect(esSearchMock).toHaveBeenCalledTimes(2); - expect(esSearchMock.mock.calls[0][0]!.index).toEqual(METADATA_UNITED_INDEX); - expect(esSearchMock.mock.calls[1][0]!.index).toEqual(metadataCurrentIndexPattern); + expect(esSearchMock.mock.calls[0][0]?.index).toEqual(METADATA_UNITED_INDEX); + expect(esSearchMock.mock.calls[1][0]?.index).toEqual(metadataCurrentIndexPattern); expect(routeConfig.options).toEqual({ authRequired: true, tags: ['access:securitySolution'], @@ -224,7 +224,7 @@ describe('test endpoint route', () => { ); expect(esSearchMock).toHaveBeenCalledTimes(1); - expect(esSearchMock.mock.calls[0][0]!.index).toEqual(METADATA_UNITED_INDEX); + expect(esSearchMock.mock.calls[0][0]?.index).toEqual(METADATA_UNITED_INDEX); expect(esSearchMock.mock.calls[0][0]?.body?.query).toEqual({ bool: { must: [ diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/query_builders.ts b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/query_builders.ts index 448496671b4f9..7b09013496c6d 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/query_builders.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/query_builders.ts @@ -53,8 +53,8 @@ export async function kibanaRequestToMetadataListESQuery( body: { query: buildQueryBody( request, - queryBuilderOptions?.unenrolledAgentIds!, - queryBuilderOptions?.statusAgentIds! + queryBuilderOptions?.unenrolledAgentIds, + queryBuilderOptions?.statusAgentIds ), track_total_hits: true, sort: MetadataSortMethod, diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/policy/service.ts b/x-pack/plugins/security_solution/server/endpoint/routes/policy/service.ts index 987bef15afe98..ce46395a1f09f 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/policy/service.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/policy/service.ts @@ -120,12 +120,14 @@ export async function agentVersionsMap( const result: Map = new Map(); let hasMore = true; while (hasMore) { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const queryResult = await endpointAppContext.service .getAgentService()! .listAgents(esClient, searchOptions(page++)); queryResult.agents.forEach((agent: Agent) => { const agentVersion = agent.local_metadata?.elastic?.agent?.version; if (result.has(agentVersion)) { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion result.set(agentVersion, result.get(agentVersion)! + 1); } else { result.set(agentVersion, 1); diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/trusted_apps/service.ts b/x-pack/plugins/security_solution/server/endpoint/routes/trusted_apps/service.ts index 9cefc55eddec4..856a615c1ffa2 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/trusted_apps/service.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/trusted_apps/service.ts @@ -142,6 +142,7 @@ export const getTrustedAppsList = async ( data: results?.data.map(exceptionListItemToTrustedApp) ?? [], total: results?.total ?? 0, page: results?.page ?? 1, + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion per_page: results?.per_page ?? perPage!, }; }; @@ -262,6 +263,7 @@ export const getTrustedAppsSummary = async ( let page = 1; while (paging) { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const { data, total } = (await exceptionsListClient.findExceptionListItem({ listId: ENDPOINT_TRUSTED_APPS_LIST_ID, page, diff --git a/x-pack/plugins/security_solution/server/endpoint/services/actions.ts b/x-pack/plugins/security_solution/server/endpoint/services/actions.ts index a04a6eea5ab65..711d78ba51b59 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/actions.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/actions.ts @@ -200,6 +200,7 @@ export const getPendingActionCounts = async ( }, { ignore: [404] } ) + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion .then((result) => result.body?.hits?.hits?.map((a) => a._source!) || []) .catch(catchAndWrapError); @@ -272,6 +273,7 @@ const fetchActionResponseIds = async ( }, { ignore: [404] } ) + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion .then((result) => result.body?.hits?.hits?.map((a) => a._source!) || []) .catch(catchAndWrapError); diff --git a/x-pack/plugins/security_solution/server/endpoint/services/artifacts/artifact_client.ts b/x-pack/plugins/security_solution/server/endpoint/services/artifacts/artifact_client.ts index ac19757e037b2..062702bb14a49 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/artifacts/artifact_client.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/artifacts/artifact_client.ts @@ -37,6 +37,7 @@ export class EndpointArtifactClient implements EndpointArtifactClientInterface { return { type: idPieces[1], + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion decodedSha256: idPieces.pop()!, identifier: idPieces.join('-'), }; @@ -74,7 +75,7 @@ export class EndpointArtifactClient implements EndpointArtifactClientInterface { async deleteArtifact(id: string) { // Ignoring the `id` not being in the type until we can refactor the types in endpoint. - // @ts-ignore + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const artifactId = (await this.getArtifact(id))?.id!; return this.fleetArtifacts.deleteArtifact(artifactId); } diff --git a/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.mock.ts b/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.mock.ts index 87a73e0130113..a7fb5dc23877c 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.mock.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/artifacts/manifest_manager/manifest_manager.mock.ts @@ -42,14 +42,14 @@ export const mockFindExceptionListItemResponses = ( responses: Record> ) => { return jest.fn().mockImplementation((options: FindExceptionListItemOptions) => { - const matches = options.filter!.match(FILTER_REGEXP) || []; + const matches = options.filter?.match(FILTER_REGEXP) || []; - if (matches[4] && responses[options.listId]?.[`${matches![1]}-${matches[4]}`]) { + if (matches[4] && responses[options.listId]?.[`${matches?.[1]}-${matches[4]}`]) { return createExceptionListResponse( - responses[options.listId]?.[`${matches![1]}-${matches[4]}`] || [] + responses[options.listId]?.[`${matches?.[1]}-${matches[4]}`] || [] ); } else { - return createExceptionListResponse(responses[options.listId]?.[matches![1] || ''] || []); + return createExceptionListResponse(responses[options.listId]?.[matches?.[1] || ''] || []); } }); }; diff --git a/x-pack/plugins/security_solution/server/endpoint/services/metadata/endpoint_metadata_service.ts b/x-pack/plugins/security_solution/server/endpoint/services/metadata/endpoint_metadata_service.ts index 5e2f46aa4c285..23c21e431a344 100644 --- a/x-pack/plugins/security_solution/server/endpoint/services/metadata/endpoint_metadata_service.ts +++ b/x-pack/plugins/security_solution/server/endpoint/services/metadata/endpoint_metadata_service.ts @@ -171,6 +171,7 @@ export class EndpointMetadataService { // Get Agent Policy and Endpoint Package Policy if (fleetAgent) { try { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion fleetAgentPolicy = await this.getFleetAgentPolicy(fleetAgent.policy_id!); endpointPackagePolicy = fleetAgentPolicy.package_policies.find( (policy) => policy.package?.name === 'endpoint' @@ -183,7 +184,8 @@ export class EndpointMetadataService { return { metadata: endpointMetadata, host_status: fleetAgent - ? fleetAgentStatusToEndpointHostStatus(fleetAgent.status!) + ? // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + fleetAgentStatusToEndpointHostStatus(fleetAgent.status!) : DEFAULT_ENDPOINT_HOST_STATUS, policy_info: { agent: { diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/migrations/create_migration.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/migrations/create_migration.ts index f9693c87631b7..8914e8eec87d0 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/migrations/create_migration.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/migrations/create_migration.ts @@ -94,7 +94,7 @@ export const createMigration = async ({ return { destinationIndex: migrationIndex, sourceIndex: index, - taskId: String(response.body.task!), + taskId: String(response.body.task), version, }; }; diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/create_index_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/create_index_route.ts index 61635fdcef9f0..6ec23c32e4976 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/create_index_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/index/create_index_route.ts @@ -58,7 +58,7 @@ export const createIndexRoute = ( if (!siemClient) { return siemResponse.error({ statusCode: 404 }); } - await createDetectionIndex(context, siemClient!, ruleDataService, ruleRegistryEnabled); + await createDetectionIndex(context, siemClient, ruleDataService, ruleRegistryEnabled); return response.ok({ body: { acknowledged: true } }); } catch (err) { const error = transformError(err); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/add_prepackaged_rules_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/add_prepackaged_rules_route.test.ts index 48efcc4495aff..26e09d69d3a45 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/add_prepackaged_rules_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/add_prepackaged_rules_route.test.ts @@ -124,7 +124,7 @@ describe.each([ }); test('returns 404 if rulesClient is not available on the route', async () => { - context.alerting!.getRulesClient = jest.fn(); + context.alerting.getRulesClient = jest.fn(); const request = addPrepackagedRulesRequest(); const response = await server.inject(request, context); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_bulk_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_bulk_route.test.ts index 2c8696dbd4554..6f721bb2bb9c5 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_bulk_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_bulk_route.test.ts @@ -55,7 +55,7 @@ describe.each([ }); test('returns 404 if alertClient is not available on the route', async () => { - context.alerting!.getRulesClient = jest.fn(); + context.alerting.getRulesClient = jest.fn(); const response = await server.inject(getReadBulkRequest(), context); expect(response.status).toEqual(404); expect(response.body).toEqual({ message: 'Not Found', status_code: 404 }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_route.test.ts index d1be96a44930a..59fe5c0ff68a1 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/create_rules_route.test.ts @@ -56,7 +56,7 @@ describe.each([ }); test('returns 404 if alertClient is not available on the route', async () => { - context.alerting!.getRulesClient = jest.fn(); + context.alerting.getRulesClient = jest.fn(); const response = await server.inject(getCreateRequest(), context); expect(response.status).toEqual(404); expect(response.body).toEqual({ message: 'Not Found', status_code: 404 }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/delete_rules_bulk_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/delete_rules_bulk_route.test.ts index 7db5651de2c34..49580fc09ca63 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/delete_rules_bulk_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/delete_rules_bulk_route.test.ts @@ -84,7 +84,7 @@ describe.each([ }); test('returns 404 if alertClient is not available on the route', async () => { - context.alerting!.getRulesClient = jest.fn(); + context.alerting.getRulesClient = jest.fn(); const response = await server.inject(getDeleteBulkRequest(), context); expect(response.status).toEqual(404); expect(response.body).toEqual({ message: 'Not Found', status_code: 404 }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/delete_rules_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/delete_rules_route.test.ts index 7c447660acb45..466012a045eb3 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/delete_rules_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/delete_rules_route.test.ts @@ -65,7 +65,7 @@ describe.each([ }); test('returns 404 if alertClient is not available on the route', async () => { - context.alerting!.getRulesClient = jest.fn(); + context.alerting.getRulesClient = jest.fn(); const response = await server.inject(getDeleteRequest(), context); expect(response.status).toEqual(404); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/find_rules_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/find_rules_route.test.ts index 7ae3f56b6fea9..0b0650d48872f 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/find_rules_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/find_rules_route.test.ts @@ -48,7 +48,7 @@ describe.each([ }); test('returns 404 if alertClient is not available on the route', async () => { - context.alerting!.getRulesClient = jest.fn(); + context.alerting.getRulesClient = jest.fn(); const response = await server.inject(getFindRequest(), context); expect(response.status).toEqual(404); expect(response.body).toEqual({ message: 'Not Found', status_code: 404 }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/find_rules_status_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/find_rules_status_route.test.ts index 053e0b7178de5..5d6b9810a2cda 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/find_rules_status_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/find_rules_status_route.test.ts @@ -41,7 +41,7 @@ describe.each([ }); test('returns 404 if alertClient is not available on the route', async () => { - context.alerting!.getRulesClient = jest.fn(); + context.alerting.getRulesClient = jest.fn(); const response = await server.inject(ruleStatusRequest(), context); expect(response.status).toEqual(404); expect(response.body).toEqual({ message: 'Not Found', status_code: 404 }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/get_prepackaged_rules_status_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/get_prepackaged_rules_status_route.test.ts index 78572863f7472..e97744a5fe5a8 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/get_prepackaged_rules_status_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/get_prepackaged_rules_status_route.test.ts @@ -100,7 +100,7 @@ describe.each([ }); test('returns 404 if alertClient is not available on the route', async () => { - context.alerting!.getRulesClient = jest.fn(); + context.alerting.getRulesClient = jest.fn(); const response = await server.inject(getPrepackagedRulesStatusRequest(), context); expect(response.status).toEqual(404); expect(response.body).toEqual({ message: 'Not Found', status_code: 404 }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/import_rules_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/import_rules_route.test.ts index bf29dbe870153..aa301bcc0335e 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/import_rules_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/import_rules_route.test.ts @@ -77,7 +77,7 @@ describe.each([ }); test('returns 404 if alertClient is not available on the route', async () => { - context.alerting!.getRulesClient = jest.fn(); + context.alerting.getRulesClient = jest.fn(); const response = await server.inject(request, context); expect(response.status).toEqual(404); expect(response.body).toEqual({ message: 'Not Found', status_code: 404 }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_bulk_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_bulk_route.test.ts index 2c3db023dccc4..d0d5937eab2d7 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_bulk_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_bulk_route.test.ts @@ -89,7 +89,7 @@ describe.each([ }); test('returns 404 if alertClient is not available on the route', async () => { - context.alerting!.getRulesClient = jest.fn(); + context.alerting.getRulesClient = jest.fn(); const response = await server.inject(getPatchBulkRequest(), context); expect(response.status).toEqual(404); expect(response.body).toEqual({ message: 'Not Found', status_code: 404 }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_route.test.ts index 97773c45ce0d9..00d7180dfc9be 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/patch_rules_route.test.ts @@ -69,7 +69,7 @@ describe.each([ }); test('returns 404 if alertClient is not available on the route', async () => { - context.alerting!.getRulesClient = jest.fn(); + context.alerting.getRulesClient = jest.fn(); const response = await server.inject(getPatchRequest(), context); expect(response.status).toEqual(404); expect(response.body).toEqual({ message: 'Not Found', status_code: 404 }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/perform_bulk_action_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/perform_bulk_action_route.test.ts index ebc86acc964e6..41b909bd718c0 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/perform_bulk_action_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/perform_bulk_action_route.test.ts @@ -65,7 +65,7 @@ describe.each([ }); it('returns 404 if alertClient is not available on the route', async () => { - context.alerting!.getRulesClient = jest.fn(); + context.alerting.getRulesClient = jest.fn(); const response = await server.inject(getBulkActionRequest(), context); expect(response.status).toEqual(404); expect(response.body).toEqual({ message: 'Not Found', status_code: 404 }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/read_rules_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/read_rules_route.test.ts index 37b8228ac1e9b..bc9fa43b56ae7 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/read_rules_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/read_rules_route.test.ts @@ -86,7 +86,7 @@ describe.each([ }); test('returns 404 if alertClient is not available on the route', async () => { - context.alerting!.getRulesClient = jest.fn(); + context.alerting.getRulesClient = jest.fn(); const response = await server.inject(getReadRequest(), context); expect(response.status).toEqual(404); expect(response.body).toEqual({ message: 'Not Found', status_code: 404 }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_bulk_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_bulk_route.test.ts index 746a40dfa8dc2..f7bef76944a97 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_bulk_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_bulk_route.test.ts @@ -65,7 +65,7 @@ describe.each([ }); test('returns 404 if alertClient is not available on the route', async () => { - context.alerting!.getRulesClient = jest.fn(); + context.alerting.getRulesClient = jest.fn(); const response = await server.inject(getUpdateBulkRequest(), context); expect(response.status).toEqual(404); expect(response.body).toEqual({ message: 'Not Found', status_code: 404 }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_route.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_route.test.ts index 5b3e2737418c2..7d611f3cccbf2 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_route.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/rules/update_rules_route.test.ts @@ -66,7 +66,7 @@ describe.each([ }); test('returns 404 if alertClient is not available on the route', async () => { - context.alerting!.getRulesClient = jest.fn(); + context.alerting.getRulesClient = jest.fn(); const response = await server.inject(getUpdateRequest(), context); expect(response.status).toEqual(404); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/query_signals_route.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/query_signals_route.ts index 279a824426cec..e2be04fc6e7df 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/query_signals_route.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/routes/signals/query_signals_route.ts @@ -51,7 +51,7 @@ export const querySignalsRoute = (router: SecuritySolutionPluginRouter, config: }); } const esClient = context.core.elasticsearch.client.asCurrentUser; - const siemClient = context.securitySolution!.getAppClient(); + const siemClient = context.securitySolution.getAppClient(); // TODO: Once we are past experimental phase this code should be removed const { ruleRegistryEnabled } = parseExperimentalConfigValue(config.enableExperimental); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_event_type_signal.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_event_type_signal.ts index d22ca0d1f5090..0dd2acfb88ffe 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_event_type_signal.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_event_type_signal.ts @@ -8,8 +8,8 @@ import { BaseSignalHit, SimpleHit } from './types'; import { getField } from './utils'; export const buildEventTypeSignal = (doc: BaseSignalHit): object => { - if (doc._source?.event != null && doc._source?.event instanceof Object) { - return { ...doc._source!.event, kind: 'signal' }; + if (doc._source != null && doc._source.event instanceof Object) { + return { ...doc._source.event, kind: 'signal' }; } else { return { kind: 'signal' }; } diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_rule.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_rule.test.ts index bd5444a325128..012977da2a00f 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_rule.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/build_rule.test.ts @@ -108,7 +108,7 @@ describe('buildRuleWithOverrides', () => { test('it applies rule name override in buildRule', () => { const ruleSO = sampleRuleSO(getQueryRuleParams()); ruleSO.attributes.params.ruleNameOverride = 'someKey'; - const rule = buildRuleWithOverrides(ruleSO, sampleDocNoSortId()._source!); + const rule = buildRuleWithOverrides(ruleSO, sampleDocNoSortId()._source); const expected = { ...expectedRule(), name: 'someValue', @@ -135,7 +135,7 @@ describe('buildRuleWithOverrides', () => { ]; const doc = sampleDocNoSortId(); doc._source.new_risk_score = newRiskScore; - const rule = buildRuleWithOverrides(ruleSO, doc._source!); + const rule = buildRuleWithOverrides(ruleSO, doc._source); const expected = { ...expectedRule(), risk_score: newRiskScore, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/enrich_signal_threat_matches.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/enrich_signal_threat_matches.ts index 9da5934489023..272c3f64fb105 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/enrich_signal_threat_matches.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threat_mapping/enrich_signal_threat_matches.ts @@ -107,7 +107,7 @@ export const enrichSignalThreatMatches = async ( return { ...signalHit, _source: { - ...signalHit._source!, + ...signalHit._source, threat: { ...threat, enrichments: [...existingEnrichments, ...enrichments[i]], diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/bulk_create_threshold_signals.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/bulk_create_threshold_signals.ts index 31bf7674b4f92..c202065176ff1 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/bulk_create_threshold_signals.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/bulk_create_threshold_signals.ts @@ -116,6 +116,7 @@ const getTransformedHits = ( ? [ { field: threshold.cardinality[0].field, + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion value: bucket.cardinality_count!.value, }, ] @@ -131,6 +132,7 @@ const getTransformedHits = ( }; return getCombinations( + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion (results.aggregations![aggParts.name] as { buckets: TermAggregationBucket[] }).buckets, 0, aggParts.field diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/get_threshold_bucket_filters.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/get_threshold_bucket_filters.ts index 5cafff24c544b..610be59deaa5f 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/get_threshold_bucket_filters.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/threshold/get_threshold_bucket_filters.ts @@ -40,6 +40,7 @@ export const getThresholdBucketFilters = async ({ // Terms to filter events older than `lastSignalTimestamp`. bucket.terms.forEach((term) => { if (term.field != null) { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion (filter.bool!.filter as ESFilter[]).push({ term: { [term.field]: `${term.value}`, diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.test.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.test.ts index 7d2eafa46d382..0e50db97d1256 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.test.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.test.ts @@ -1277,7 +1277,7 @@ describe('utils', () => { test('It returns timestampOverride date time if set', () => { const override = '2020-10-07T19:20:28.049Z'; const searchResult = sampleDocSearchResultsNoSortId(); - searchResult.hits.hits[0]._source!.different_timestamp = new Date(override).toISOString(); + searchResult.hits.hits[0]._source.different_timestamp = new Date(override).toISOString(); const date = lastValidDate({ searchResult, timestampOverride: 'different_timestamp' }); expect(date?.toISOString()).toEqual(override); }); diff --git a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.ts b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.ts index 2aefc7ea0bd64..79b36cf62573a 100644 --- a/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.ts +++ b/x-pack/plugins/security_solution/server/lib/detection_engine/signals/utils.ts @@ -874,6 +874,7 @@ export const mergeSearchResults = (searchResults: SignalSearchResponse[]) => { aggregations: newAggregations, hits: { total: calculateTotal(prev.hits.total, next.hits.total), + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion max_score: Math.max(newHits.max_score!, existingHits.max_score!), hits: [...existingHits.hits, ...newHits.hits], }, diff --git a/x-pack/plugins/security_solution/server/lib/timeline/utils/check_timelines_status.ts b/x-pack/plugins/security_solution/server/lib/timeline/utils/check_timelines_status.ts index 560df1112ac58..f524d0c7ca3a6 100644 --- a/x-pack/plugins/security_solution/server/lib/timeline/utils/check_timelines_status.ts +++ b/x-pack/plugins/security_solution/server/lib/timeline/utils/check_timelines_status.ts @@ -40,6 +40,7 @@ export const getTimelinesToUpdate = ( installedTimelines.some((installedTimeline) => { return ( timeline.templateTimelineId === installedTimeline.templateTimelineId && + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion timeline.templateTimelineVersion! > installedTimeline.templateTimelineVersion! ); }) diff --git a/x-pack/plugins/security_solution/server/lib/timeline/utils/failure_cases.ts b/x-pack/plugins/security_solution/server/lib/timeline/utils/failure_cases.ts index 99365a55a1d61..44f16c57ad2b4 100644 --- a/x-pack/plugins/security_solution/server/lib/timeline/utils/failure_cases.ts +++ b/x-pack/plugins/security_solution/server/lib/timeline/utils/failure_cases.ts @@ -227,7 +227,7 @@ export const checkIsUpdateViaImportFailureCases = ( return { body: UPDAT_TIMELINE_VIA_IMPORT_NOT_ALLOWED_ERROR_MESSAGE, statusCode: 405 }; } else { return { - body: getImportExistingTimelineError(existTimeline!.savedObjectId), + body: getImportExistingTimelineError(existTimeline.savedObjectId), statusCode: 405, }; } diff --git a/x-pack/plugins/security_solution/server/plugin.ts b/x-pack/plugins/security_solution/server/plugin.ts index 4cecabe52b588..0f908d7db8e05 100644 --- a/x-pack/plugins/security_solution/server/plugin.ts +++ b/x-pack/plugins/security_solution/server/plugin.ts @@ -361,6 +361,7 @@ export class Plugin implements IPlugin { ignoreUnavailable: true, index: ['filebeat-*'], }); - const parsedInspect = JSON.parse(parsedResponse.inspect!.dsl[0]); + const parsedInspect = JSON.parse(parsedResponse.inspect.dsl[0]); expect(parsedInspect).toEqual(expectedInspect); }); diff --git a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/details/helpers.ts b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/details/helpers.ts index c96e0040fd23d..ae68d81d6b922 100644 --- a/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/details/helpers.ts +++ b/x-pack/plugins/security_solution/server/search_strategy/security_solution/factory/hosts/details/helpers.ts @@ -223,6 +223,7 @@ export const getHostEndpoint = async ( endpointPolicy: endpointData.Endpoint.policy.applied.name, policyStatus: endpointData.Endpoint.policy.applied.status, sensorVersion: endpointData.agent.version, + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion elasticAgentStatus: fleetAgentStatusToEndpointHostStatus(fleetAgentStatus!), isolation: endpointData.Endpoint.state?.isolation ?? false, pendingActions, diff --git a/x-pack/plugins/timelines/public/components/hover_actions/index.tsx b/x-pack/plugins/timelines/public/components/hover_actions/index.tsx index 02ebcb8abe912..12aef1ad00a71 100644 --- a/x-pack/plugins/timelines/public/components/hover_actions/index.tsx +++ b/x-pack/plugins/timelines/public/components/hover_actions/index.tsx @@ -89,6 +89,7 @@ const getOverflowButtonLazy = (props: OverflowButtonProps) => { }; export const getHoverActions = (store?: Store): HoverActionsConfig => ({ + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion getAddToTimelineButton: getAddToTimelineButtonLazy.bind(null, store!), getColumnToggleButton: getColumnToggleButtonLazy, getCopyButton: getCopyButtonLazy, diff --git a/x-pack/plugins/timelines/public/components/index.tsx b/x-pack/plugins/timelines/public/components/index.tsx index 9959574464836..0ff8c9bf97e8b 100644 --- a/x-pack/plugins/timelines/public/components/index.tsx +++ b/x-pack/plugins/timelines/public/components/index.tsx @@ -41,6 +41,7 @@ export const TGrid = (props: TGridComponent) => { browserFields = (tGridProps as TGridIntegratedProps).browserFields; } return ( + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion diff --git a/x-pack/plugins/timelines/public/components/t_grid/body/column_headers/header_tooltip_content/index.tsx b/x-pack/plugins/timelines/public/components/t_grid/body/column_headers/header_tooltip_content/index.tsx index b973d99584d61..91dd64d8fed3a 100644 --- a/x-pack/plugins/timelines/public/components/t_grid/body/column_headers/header_tooltip_content/index.tsx +++ b/x-pack/plugins/timelines/public/components/t_grid/body/column_headers/header_tooltip_content/index.tsx @@ -61,7 +61,7 @@ export const HeaderToolTipContent = React.memo<{ header: ColumnHeaderOptions }>( {':'} - + {header.type}

diff --git a/x-pack/plugins/timelines/public/components/t_grid/body/events/stateful_event.tsx b/x-pack/plugins/timelines/public/components/t_grid/body/events/stateful_event.tsx index f448ba3831b14..d746368e389c8 100644 --- a/x-pack/plugins/timelines/public/components/t_grid/body/events/stateful_event.tsx +++ b/x-pack/plugins/timelines/public/components/t_grid/body/events/stateful_event.tsx @@ -122,6 +122,7 @@ const StatefulEventComponent: React.FC = ({ const handleOnEventDetailPanelOpened = useCallback(() => { const eventId = event._id; + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const indexName = event._index!; const updatedExpandedDetail: TimelineExpandedDetailType = { diff --git a/x-pack/plugins/timelines/public/components/t_grid/helpers.tsx b/x-pack/plugins/timelines/public/components/t_grid/helpers.tsx index 02c3d10a76058..e2eb1d4d04547 100644 --- a/x-pack/plugins/timelines/public/components/t_grid/helpers.tsx +++ b/x-pack/plugins/timelines/public/components/t_grid/helpers.tsx @@ -192,6 +192,7 @@ export const buildCombinedQuery = (combineQueriesParams: CombineQueries) => { const combinedQuery = combineQueries(combineQueriesParams); return combinedQuery ? { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion filterQuery: replaceStatusField(combinedQuery!.filterQuery), } : null; diff --git a/x-pack/plugins/timelines/public/components/t_grid/integrated/index.tsx b/x-pack/plugins/timelines/public/components/t_grid/integrated/index.tsx index b649dc36abe0a..e363297d04be5 100644 --- a/x-pack/plugins/timelines/public/components/t_grid/integrated/index.tsx +++ b/x-pack/plugins/timelines/public/components/t_grid/integrated/index.tsx @@ -237,7 +237,7 @@ const TGridIntegratedComponent: React.FC = ({ endDate: end, entityType, fields, - filterQuery: combinedQueries!.filterQuery, + filterQuery: combinedQueries?.filterQuery, id, indexNames, limit: itemsPerPage, diff --git a/x-pack/plugins/timelines/public/components/t_grid/standalone/index.tsx b/x-pack/plugins/timelines/public/components/t_grid/standalone/index.tsx index 1a374d0c6b87a..ae092d8634bb7 100644 --- a/x-pack/plugins/timelines/public/components/t_grid/standalone/index.tsx +++ b/x-pack/plugins/timelines/public/components/t_grid/standalone/index.tsx @@ -217,7 +217,7 @@ const TGridStandaloneComponent: React.FC = ({ entityType, excludeEcsData: true, fields, - filterQuery: combinedQueries!.filterQuery, + filterQuery: combinedQueries?.filterQuery, id: STANDALONE_ID, indexNames, limit: itemsPerPageStore, diff --git a/x-pack/plugins/timelines/public/components/t_grid/styles.tsx b/x-pack/plugins/timelines/public/components/t_grid/styles.tsx index 28e425f53824b..9f957e2c61910 100644 --- a/x-pack/plugins/timelines/public/components/t_grid/styles.tsx +++ b/x-pack/plugins/timelines/public/components/t_grid/styles.tsx @@ -270,13 +270,13 @@ export const EventsTrData = styled.div.attrs(({ className = '' }) => ({ const TIMELINE_EVENT_DETAILS_OFFSET = 40; interface WidthProp { - width?: number; + width: number; } export const EventsTrSupplementContainer = styled.div.attrs(({ width }) => ({ role: 'dialog', style: { - width: `${width! - TIMELINE_EVENT_DETAILS_OFFSET}px`, + width: `${width - TIMELINE_EVENT_DETAILS_OFFSET}px`, }, }))``; diff --git a/x-pack/plugins/timelines/public/components/t_grid/toolbar/fields_browser/field_browser.test.tsx b/x-pack/plugins/timelines/public/components/t_grid/toolbar/fields_browser/field_browser.test.tsx index e44ee1d45d19b..e19499628e8c1 100644 --- a/x-pack/plugins/timelines/public/components/t_grid/toolbar/fields_browser/field_browser.test.tsx +++ b/x-pack/plugins/timelines/public/components/t_grid/toolbar/fields_browser/field_browser.test.tsx @@ -235,7 +235,7 @@ describe('FieldsBrowser', () => { expect( wrapper.find('[data-test-subj="field-search"]').first().getDOMNode().id === - document.activeElement!.id + document.activeElement?.id ).toBe(true); }); @@ -266,7 +266,7 @@ describe('FieldsBrowser', () => { const changeEvent: any = { target: { value: inputText } }; const onChange = searchField.props().onChange; - onChange!(changeEvent); + onChange?.(changeEvent); searchField.simulate('change').update(); expect(onSearchInputChange).toBeCalledWith(inputText); diff --git a/x-pack/plugins/timelines/public/components/t_grid/toolbar/fields_browser/helpers.tsx b/x-pack/plugins/timelines/public/components/t_grid/toolbar/fields_browser/helpers.tsx index f4b608b456fed..552c228363e49 100644 --- a/x-pack/plugins/timelines/public/components/t_grid/toolbar/fields_browser/helpers.tsx +++ b/x-pack/plugins/timelines/public/components/t_grid/toolbar/fields_browser/helpers.tsx @@ -97,6 +97,7 @@ export const filterBrowserFieldsByFieldName = ({ fields: filter( (f) => f.name != null && f.name.includes(trimmedSubstring), browserFields[categoryId].fields + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion ).reduce((filtered, field) => ({ ...filtered, [field.name!]: field }), {}), }, }), diff --git a/x-pack/plugins/timelines/public/components/t_grid/toolbar/fields_browser/index.tsx b/x-pack/plugins/timelines/public/components/t_grid/toolbar/fields_browser/index.tsx index bdec76418dc8c..0b67f53cca76e 100644 --- a/x-pack/plugins/timelines/public/components/t_grid/toolbar/fields_browser/index.tsx +++ b/x-pack/plugins/timelines/public/components/t_grid/toolbar/fields_browser/index.tsx @@ -100,7 +100,9 @@ export const StatefulFieldsBrowserComponent: React.FC = ({ (selected, category) => newFilteredBrowserFields[category].fields != null && newFilteredBrowserFields[selected].fields != null && + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion Object.keys(newFilteredBrowserFields[category].fields!).length > + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion Object.keys(newFilteredBrowserFields[selected].fields!).length ? category : selected, diff --git a/x-pack/plugins/timelines/public/components/utils/helpers.ts b/x-pack/plugins/timelines/public/components/utils/helpers.ts index f02c86aecc108..23f92c119d574 100644 --- a/x-pack/plugins/timelines/public/components/utils/helpers.ts +++ b/x-pack/plugins/timelines/public/components/utils/helpers.ts @@ -53,7 +53,7 @@ export const getColumnsWithTimestamp = ({ : []; }; -export const getIconFromType = (type: string | null) => { +export const getIconFromType = (type: string | null | undefined) => { switch (type) { case 'string': // fall through case 'keyword': diff --git a/x-pack/plugins/timelines/public/container/use_update_alerts.ts b/x-pack/plugins/timelines/public/container/use_update_alerts.ts index b38c3b9a71fef..1b9e6218eecca 100644 --- a/x-pack/plugins/timelines/public/container/use_update_alerts.ts +++ b/x-pack/plugins/timelines/public/container/use_update_alerts.ts @@ -17,7 +17,7 @@ import { /** * Update alert status by query - * + * * @param useDetectionEngine logic flag for using the regular Detection Engine URL or the RAC URL * * @param status to update to('open' / 'closed' / 'acknowledged') @@ -40,7 +40,7 @@ export const useUpdateAlertsStatus = ( return { updateAlertStatus: async ({ status, index, query }) => { if (useDetectionEngine) { - return http!.fetch(DETECTION_ENGINE_SIGNALS_STATUS_URL, { + return http.fetch(DETECTION_ENGINE_SIGNALS_STATUS_URL, { method: 'POST', body: JSON.stringify({ status, query }), }); diff --git a/x-pack/plugins/timelines/public/plugin.ts b/x-pack/plugins/timelines/public/plugin.ts index 4b383ce392147..acb7b26d0cf84 100644 --- a/x-pack/plugins/timelines/public/plugin.ts +++ b/x-pack/plugins/timelines/public/plugin.ts @@ -45,7 +45,7 @@ export class TimelinesPlugin implements Plugin { } return { getHoverActions: () => { - return getHoverActions(this._store!); + return getHoverActions(this._store); }, getTGrid: (props: TGridProps) => { if (props.type === 'standalone' && this._store) { @@ -73,6 +73,7 @@ export class TimelinesPlugin implements Plugin { }, getFieldBrowser: (props: FieldBrowserProps) => { return getFieldsBrowserLazy(props, { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion store: this._store!, }); }, @@ -90,6 +91,7 @@ export class TimelinesPlugin implements Plugin { }, getAddToCaseAction: (props) => { return getAddToCaseLazy(props, { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion store: this._store!, storage: this._storage, setStore: this.setStore.bind(this), @@ -97,6 +99,7 @@ export class TimelinesPlugin implements Plugin { }, getAddToCasePopover: (props) => { return getAddToCasePopoverLazy(props, { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion store: this._store!, storage: this._storage, setStore: this.setStore.bind(this), @@ -104,6 +107,7 @@ export class TimelinesPlugin implements Plugin { }, getAddToExistingCaseButton: (props) => { return getAddToExistingCaseButtonLazy(props, { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion store: this._store!, storage: this._storage, setStore: this.setStore.bind(this), @@ -111,6 +115,7 @@ export class TimelinesPlugin implements Plugin { }, getAddToNewCaseButton: (props) => { return getAddToNewCaseButtonLazy(props, { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion store: this._store!, storage: this._storage, setStore: this.setStore.bind(this), From 97848ca62a35f7ed409ea31269ba124a24a21bc3 Mon Sep 17 00:00:00 2001 From: Jonathan Budzenski Date: Thu, 14 Oct 2021 22:06:43 -0500 Subject: [PATCH 10/24] skip flaky suite. #115100 --- .../list/remove_trusted_app_from_policy_modal.test.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/trusted_apps/list/remove_trusted_app_from_policy_modal.test.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/trusted_apps/list/remove_trusted_app_from_policy_modal.test.tsx index 0411751685a90..917ffe49c6090 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/trusted_apps/list/remove_trusted_app_from_policy_modal.test.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/trusted_apps/list/remove_trusted_app_from_policy_modal.test.tsx @@ -25,7 +25,8 @@ import { import { Immutable } from '../../../../../../../common/endpoint/types'; import { HttpFetchOptionsWithPath } from 'kibana/public'; -describe('When using the RemoveTrustedAppFromPolicyModal component', () => { +// FLAKY https://github.com/elastic/kibana/issues/115100 +describe.skip('When using the RemoveTrustedAppFromPolicyModal component', () => { let appTestContext: AppContextTestRender; let renderResult: ReturnType; let render: (waitForLoadedState?: boolean) => Promise>; From 8aeaa5a2ffc871a7802a8d000501539e307a66ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20S=C3=A1nchez?= Date: Fri, 15 Oct 2021 09:25:30 +0200 Subject: [PATCH 11/24] [Security Solution][Endpoint] Remove refresh button from policy trusted apps flyout (#114974) * Hide refresh button by prop and refactor unit test * Add test cases for policies selector when enable/disable license * Remove unused code when adding mock --- .../search_exceptions.test.tsx | 112 +++++++++++++----- .../search_exceptions/search_exceptions.tsx | 18 +-- .../flyout/policy_trusted_apps_flyout.tsx | 1 + 3 files changed, 97 insertions(+), 34 deletions(-) diff --git a/x-pack/plugins/security_solution/public/management/components/search_exceptions/search_exceptions.test.tsx b/x-pack/plugins/security_solution/public/management/components/search_exceptions/search_exceptions.test.tsx index ddee8e13f069d..084978d35d03a 100644 --- a/x-pack/plugins/security_solution/public/management/components/search_exceptions/search_exceptions.test.tsx +++ b/x-pack/plugins/security_solution/public/management/components/search_exceptions/search_exceptions.test.tsx @@ -5,50 +5,77 @@ * 2.0. */ -import { mount } from 'enzyme'; import React from 'react'; +import { act, fireEvent } from '@testing-library/react'; +import { AppContextTestRender, createAppRootMockRenderer } from '../../../common/mock/endpoint'; +import { + EndpointPrivileges, + useEndpointPrivileges, +} from '../../../common/components/user_privileges/use_endpoint_privileges'; +import { EndpointDocGenerator } from '../../../../common/endpoint/generate_data'; -import { SearchExceptions } from '.'; +import { SearchExceptions, SearchExceptionsProps } from '.'; +jest.mock('../../../common/components/user_privileges/use_endpoint_privileges'); let onSearchMock: jest.Mock; - -interface EuiFieldSearchPropsFake { - onSearch(value: string): void; -} +const mockUseEndpointPrivileges = useEndpointPrivileges as jest.Mock; describe('Search exceptions', () => { + let appTestContext: AppContextTestRender; + let renderResult: ReturnType; + let render: ( + props?: Partial + ) => ReturnType; + + const loadedUserEndpointPrivilegesState = ( + endpointOverrides: Partial = {} + ): EndpointPrivileges => ({ + loading: false, + canAccessFleet: true, + canAccessEndpointManagement: true, + isPlatinumPlus: false, + ...endpointOverrides, + }); + beforeEach(() => { onSearchMock = jest.fn(); + appTestContext = createAppRootMockRenderer(); + + render = (overrideProps = {}) => { + const props: SearchExceptionsProps = { + placeholder: 'search test', + onSearch: onSearchMock, + ...overrideProps, + }; + + renderResult = appTestContext.render(); + return renderResult; + }; + + mockUseEndpointPrivileges.mockReturnValue(loadedUserEndpointPrivilegesState()); }); - const getElement = (defaultValue: string = '') => ( - - ); + afterAll(() => { + mockUseEndpointPrivileges.mockReset(); + }); it('should have a default value', () => { const expectedDefaultValue = 'this is a default value'; - const element = mount(getElement(expectedDefaultValue)); - const defaultValue = element - .find('[data-test-subj="searchField"]') - .first() - .props().defaultValue; - expect(defaultValue).toBe(expectedDefaultValue); + const element = render({ defaultValue: expectedDefaultValue }); + + expect(element.getByDisplayValue(expectedDefaultValue)).not.toBeNull(); }); it('should dispatch search action when submit search field', () => { const expectedDefaultValue = 'this is a default value'; - const element = mount(getElement()); + const element = render(); expect(onSearchMock).toHaveBeenCalledTimes(0); - const searchFieldProps = element - .find('[data-test-subj="searchField"]') - .first() - .props() as EuiFieldSearchPropsFake; - searchFieldProps.onSearch(expectedDefaultValue); + act(() => { + fireEvent.change(element.getByTestId('searchField'), { + target: { value: expectedDefaultValue }, + }); + }); expect(onSearchMock).toHaveBeenCalledTimes(1); expect(onSearchMock).toHaveBeenCalledWith(expectedDefaultValue, '', ''); @@ -56,11 +83,42 @@ describe('Search exceptions', () => { it('should dispatch search action when click on button', () => { const expectedDefaultValue = 'this is a default value'; - const element = mount(getElement(expectedDefaultValue)); + const element = render({ defaultValue: expectedDefaultValue }); expect(onSearchMock).toHaveBeenCalledTimes(0); - element.find('[data-test-subj="searchButton"]').first().simulate('click'); + act(() => { + fireEvent.click(element.getByTestId('searchButton')); + }); + expect(onSearchMock).toHaveBeenCalledTimes(1); expect(onSearchMock).toHaveBeenCalledWith(expectedDefaultValue, '', ''); }); + + it('should hide refresh button', () => { + const element = render({ hideRefreshButton: true }); + + expect(element.queryByTestId('searchButton')).toBeNull(); + }); + + it('should hide policies selector when no license', () => { + const generator = new EndpointDocGenerator('policy-list'); + const policy = generator.generatePolicyPackagePolicy(); + mockUseEndpointPrivileges.mockReturnValue( + loadedUserEndpointPrivilegesState({ isPlatinumPlus: false }) + ); + const element = render({ policyList: [policy], hasPolicyFilter: true }); + + expect(element.queryByTestId('policiesSelectorButton')).toBeNull(); + }); + + it('should display policies selector when right license', () => { + const generator = new EndpointDocGenerator('policy-list'); + const policy = generator.generatePolicyPackagePolicy(); + mockUseEndpointPrivileges.mockReturnValue( + loadedUserEndpointPrivilegesState({ isPlatinumPlus: true }) + ); + const element = render({ policyList: [policy], hasPolicyFilter: true }); + + expect(element.queryByTestId('policiesSelectorButton')).not.toBeNull(); + }); }); diff --git a/x-pack/plugins/security_solution/public/management/components/search_exceptions/search_exceptions.tsx b/x-pack/plugins/security_solution/public/management/components/search_exceptions/search_exceptions.tsx index 2b7b2e6b66884..1f3eab5db2947 100644 --- a/x-pack/plugins/security_solution/public/management/components/search_exceptions/search_exceptions.tsx +++ b/x-pack/plugins/security_solution/public/management/components/search_exceptions/search_exceptions.tsx @@ -19,6 +19,7 @@ export interface SearchExceptionsProps { policyList?: ImmutableArray; defaultExcludedPolicies?: string; defaultIncludedPolicies?: string; + hideRefreshButton?: boolean; onSearch(query: string, includedPolicies?: string, excludedPolicies?: string): void; } @@ -31,6 +32,7 @@ export const SearchExceptions = memo( policyList, defaultIncludedPolicies, defaultExcludedPolicies, + hideRefreshButton = false, }) => { const { isPlatinumPlus } = useEndpointPrivileges(); const [query, setQuery] = useState(defaultValue); @@ -101,13 +103,15 @@ export const SearchExceptions = memo( ) : null} - - - {i18n.translate('xpack.securitySolution.management.search.button', { - defaultMessage: 'Refresh', - })} - - + {!hideRefreshButton ? ( + + + {i18n.translate('xpack.securitySolution.management.search.button', { + defaultMessage: 'Refresh', + })} + + + ) : null} ); } diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/trusted_apps/flyout/policy_trusted_apps_flyout.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/trusted_apps/flyout/policy_trusted_apps_flyout.tsx index f5880022383f9..bbf2f3b208754 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/trusted_apps/flyout/policy_trusted_apps_flyout.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/trusted_apps/flyout/policy_trusted_apps_flyout.tsx @@ -183,6 +183,7 @@ export const PolicyTrustedAppsFlyout = React.memo(() => { defaultMessage: 'Search trusted applications', } )} + hideRefreshButton /> From 008421f170214648336bd9d5afb5cc794efbd82c Mon Sep 17 00:00:00 2001 From: Dario Gieselaar Date: Fri, 15 Oct 2021 09:33:06 +0200 Subject: [PATCH 12/24] [APM] Revert multi-metric ML job. (#114961) --- .../plugins/apm/common/anomaly_detection.ts | 2 - .../apm/common/utils/apm_ml_anomaly_query.ts | 25 ----- .../create_anomaly_detection_jobs.ts | 20 ++-- .../lib/service_map/get_service_anomalies.ts | 9 +- .../transactions/get_anomaly_data/fetcher.ts | 4 +- .../modules/apm_transaction/manifest.json | 18 ++-- .../apm_transaction/ml/apm_metrics.json | 53 ----------- .../ml/datafeed_apm_metrics.json | 95 ------------------- ...tafeed_high_mean_transaction_duration.json | 14 +++ .../ml/high_mean_transaction_duration.json | 35 +++++++ .../apis/ml/modules/recognize_module.ts | 2 +- .../apis/ml/modules/setup_module.ts | 10 +- 12 files changed, 76 insertions(+), 211 deletions(-) delete mode 100644 x-pack/plugins/apm/common/utils/apm_ml_anomaly_query.ts delete mode 100644 x-pack/plugins/ml/server/models/data_recognizer/modules/apm_transaction/ml/apm_metrics.json delete mode 100644 x-pack/plugins/ml/server/models/data_recognizer/modules/apm_transaction/ml/datafeed_apm_metrics.json create mode 100644 x-pack/plugins/ml/server/models/data_recognizer/modules/apm_transaction/ml/datafeed_high_mean_transaction_duration.json create mode 100644 x-pack/plugins/ml/server/models/data_recognizer/modules/apm_transaction/ml/high_mean_transaction_duration.json diff --git a/x-pack/plugins/apm/common/anomaly_detection.ts b/x-pack/plugins/apm/common/anomaly_detection.ts index eb7c74a4540be..43a779407d2a4 100644 --- a/x-pack/plugins/apm/common/anomaly_detection.ts +++ b/x-pack/plugins/apm/common/anomaly_detection.ts @@ -33,8 +33,6 @@ export function getSeverityColor(score: number) { return mlGetSeverityColor(score); } -export const ML_TRANSACTION_LATENCY_DETECTOR_INDEX = 0; - export const ML_ERRORS = { INVALID_LICENSE: i18n.translate( 'xpack.apm.anomaly_detection.error.invalid_license', diff --git a/x-pack/plugins/apm/common/utils/apm_ml_anomaly_query.ts b/x-pack/plugins/apm/common/utils/apm_ml_anomaly_query.ts deleted file mode 100644 index 26b859d37cf7f..0000000000000 --- a/x-pack/plugins/apm/common/utils/apm_ml_anomaly_query.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* - * 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. - */ - -export function apmMlAnomalyQuery(detectorIndex: 0 | 1 | 2) { - return [ - { - bool: { - filter: [ - { - terms: { - result_type: ['model_plot', 'record'], - }, - }, - { - term: { detector_index: detectorIndex }, - }, - ], - }, - }, - ]; -} diff --git a/x-pack/plugins/apm/server/lib/anomaly_detection/create_anomaly_detection_jobs.ts b/x-pack/plugins/apm/server/lib/anomaly_detection/create_anomaly_detection_jobs.ts index 10758b6d90cdc..4d4bc8dc185ab 100644 --- a/x-pack/plugins/apm/server/lib/anomaly_detection/create_anomaly_detection_jobs.ts +++ b/x-pack/plugins/apm/server/lib/anomaly_detection/create_anomaly_detection_jobs.ts @@ -5,21 +5,21 @@ * 2.0. */ -import Boom from '@hapi/boom'; import { Logger } from 'kibana/server'; +import uuid from 'uuid/v4'; import { snakeCase } from 'lodash'; +import Boom from '@hapi/boom'; import moment from 'moment'; -import uuid from 'uuid/v4'; import { ML_ERRORS } from '../../../common/anomaly_detection'; -import { - METRICSET_NAME, - PROCESSOR_EVENT, -} from '../../../common/elasticsearch_fieldnames'; import { ProcessorEvent } from '../../../common/processor_event'; import { environmentQuery } from '../../../common/utils/environment_query'; -import { withApmSpan } from '../../utils/with_apm_span'; import { Setup } from '../helpers/setup_request'; +import { + TRANSACTION_DURATION, + PROCESSOR_EVENT, +} from '../../../common/elasticsearch_fieldnames'; import { APM_ML_JOB_GROUP, ML_MODULE_ID_APM_TRANSACTION } from './constants'; +import { withApmSpan } from '../../utils/with_apm_span'; import { getAnomalyDetectionJobs } from './get_anomaly_detection_jobs'; export async function createAnomalyDetectionJobs( @@ -92,8 +92,8 @@ async function createAnomalyDetectionJob({ query: { bool: { filter: [ - { term: { [PROCESSOR_EVENT]: ProcessorEvent.metric } }, - { term: { [METRICSET_NAME]: 'transaction' } }, + { term: { [PROCESSOR_EVENT]: ProcessorEvent.transaction } }, + { exists: { field: TRANSACTION_DURATION } }, ...environmentQuery(environment), ], }, @@ -105,7 +105,7 @@ async function createAnomalyDetectionJob({ job_tags: { environment, // identifies this as an APM ML job & facilitates future migrations - apm_ml_version: 3, + apm_ml_version: 2, }, }, }, diff --git a/x-pack/plugins/apm/server/lib/service_map/get_service_anomalies.ts b/x-pack/plugins/apm/server/lib/service_map/get_service_anomalies.ts index 97c95e4e40045..9b2d79dc726ee 100644 --- a/x-pack/plugins/apm/server/lib/service_map/get_service_anomalies.ts +++ b/x-pack/plugins/apm/server/lib/service_map/get_service_anomalies.ts @@ -11,11 +11,7 @@ import { estypes } from '@elastic/elasticsearch'; import { ESSearchResponse } from '../../../../../../src/core/types/elasticsearch'; import { MlPluginSetup } from '../../../../ml/server'; import { PromiseReturnType } from '../../../../observability/typings/common'; -import { - getSeverity, - ML_ERRORS, - ML_TRANSACTION_LATENCY_DETECTOR_INDEX, -} from '../../../common/anomaly_detection'; +import { getSeverity, ML_ERRORS } from '../../../common/anomaly_detection'; import { ENVIRONMENT_ALL } from '../../../common/environment_filter_values'; import { getServiceHealthStatus } from '../../../common/service_health_status'; import { @@ -26,7 +22,6 @@ import { rangeQuery } from '../../../../observability/server'; import { withApmSpan } from '../../utils/with_apm_span'; import { getMlJobsWithAPMGroup } from '../anomaly_detection/get_ml_jobs_with_apm_group'; import { Setup } from '../helpers/setup_request'; -import { apmMlAnomalyQuery } from '../../../common/utils/apm_ml_anomaly_query'; export const DEFAULT_ANOMALIES: ServiceAnomaliesResponse = { mlJobIds: [], @@ -61,7 +56,7 @@ export async function getServiceAnomalies({ query: { bool: { filter: [ - ...apmMlAnomalyQuery(ML_TRANSACTION_LATENCY_DETECTOR_INDEX), + { terms: { result_type: ['model_plot', 'record'] } }, ...rangeQuery( Math.min(end - 30 * 60 * 1000, start), end, diff --git a/x-pack/plugins/apm/server/lib/transactions/get_anomaly_data/fetcher.ts b/x-pack/plugins/apm/server/lib/transactions/get_anomaly_data/fetcher.ts index a7357bbc1dd34..a61e0614f5b1a 100644 --- a/x-pack/plugins/apm/server/lib/transactions/get_anomaly_data/fetcher.ts +++ b/x-pack/plugins/apm/server/lib/transactions/get_anomaly_data/fetcher.ts @@ -12,8 +12,6 @@ import { rangeQuery } from '../../../../../observability/server'; import { asMutableArray } from '../../../../common/utils/as_mutable_array'; import { withApmSpan } from '../../../utils/with_apm_span'; import { Setup } from '../../helpers/setup_request'; -import { apmMlAnomalyQuery } from '../../../../common/utils/apm_ml_anomaly_query'; -import { ML_TRANSACTION_LATENCY_DETECTOR_INDEX } from '../../../../common/anomaly_detection'; export type ESResponse = Exclude< PromiseReturnType, @@ -42,7 +40,7 @@ export function anomalySeriesFetcher({ query: { bool: { filter: [ - ...apmMlAnomalyQuery(ML_TRANSACTION_LATENCY_DETECTOR_INDEX), + { terms: { result_type: ['model_plot', 'record'] } }, { term: { partition_field_value: serviceName } }, { term: { by_field_value: transactionType } }, ...rangeQuery(start, end, 'timestamp'), diff --git a/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_transaction/manifest.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_transaction/manifest.json index 123232935df05..f8feaef3be5f8 100644 --- a/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_transaction/manifest.json +++ b/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_transaction/manifest.json @@ -1,29 +1,29 @@ { "id": "apm_transaction", "title": "APM", - "description": "Detect anomalies in transactions from your APM services for metric data.", + "description": "Detect anomalies in transactions from your APM services.", "type": "Transaction data", "logoFile": "logo.json", - "defaultIndexPattern": "apm-*-metric,metrics-apm*", + "defaultIndexPattern": "apm-*-transaction", "query": { "bool": { "filter": [ - { "term": { "processor.event": "metric" } }, - { "term": { "metricset.name": "transaction" } } + { "term": { "processor.event": "transaction" } }, + { "exists": { "field": "transaction.duration" } } ] } }, "jobs": [ { - "id": "apm_metrics", - "file": "apm_metrics.json" + "id": "high_mean_transaction_duration", + "file": "high_mean_transaction_duration.json" } ], "datafeeds": [ { - "id": "datafeed-apm_metrics", - "file": "datafeed_apm_metrics.json", - "job_id": "apm_metrics" + "id": "datafeed-high_mean_transaction_duration", + "file": "datafeed_high_mean_transaction_duration.json", + "job_id": "high_mean_transaction_duration" } ] } diff --git a/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_transaction/ml/apm_metrics.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_transaction/ml/apm_metrics.json deleted file mode 100644 index d5092f3ffc553..0000000000000 --- a/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_transaction/ml/apm_metrics.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "job_type": "anomaly_detector", - "groups": [ - "apm" - ], - "description": "Detects anomalies in transaction duration, throughput and error percentage for metric data.", - "analysis_config": { - "bucket_span": "15m", - "summary_count_field_name" : "doc_count", - "detectors" : [ - { - "detector_description" : "high duration by transaction type for an APM service", - "function" : "high_mean", - "field_name" : "transaction_duration", - "by_field_name" : "transaction.type", - "partition_field_name" : "service.name" - }, - { - "detector_description" : "transactions per minute for an APM service", - "function" : "mean", - "field_name" : "transactions_per_min", - "by_field_name" : "transaction.type", - "partition_field_name" : "service.name" - }, - { - "detector_description" : "percent failed for an APM service", - "function" : "high_mean", - "field_name" : "transaction_failure_percentage", - "by_field_name" : "transaction.type", - "partition_field_name" : "service.name" - } - ], - "influencers" : [ - "transaction.type", - "service.name" - ] - }, - "analysis_limits": { - "model_memory_limit": "32mb" - }, - "data_description": { - "time_field" : "@timestamp", - "time_format" : "epoch_ms" - }, - "model_plot_config": { - "enabled" : true, - "annotations_enabled" : true - }, - "results_index_name" : "custom-apm", - "custom_settings": { - "created_by": "ml-module-apm-transaction" - } -} diff --git a/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_transaction/ml/datafeed_apm_metrics.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_transaction/ml/datafeed_apm_metrics.json deleted file mode 100644 index ba45582252cd7..0000000000000 --- a/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_transaction/ml/datafeed_apm_metrics.json +++ /dev/null @@ -1,95 +0,0 @@ -{ - "job_id": "JOB_ID", - "indices": [ - "INDEX_PATTERN_NAME" - ], - "chunking_config" : { - "mode" : "off" - }, - "query": { - "bool": { - "filter": [ - { "term": { "processor.event": "metric" } }, - { "term": { "metricset.name": "transaction" } } - ] - } - }, - "aggregations" : { - "buckets" : { - "composite" : { - "size" : 5000, - "sources" : [ - { - "date" : { - "date_histogram" : { - "field" : "@timestamp", - "fixed_interval" : "90s" - } - } - }, - { - "transaction.type" : { - "terms" : { - "field" : "transaction.type" - } - } - }, - { - "service.name" : { - "terms" : { - "field" : "service.name" - } - } - } - ] - }, - "aggs" : { - "@timestamp" : { - "max" : { - "field" : "@timestamp" - } - }, - "transactions_per_min" : { - "rate" : { - "unit" : "minute" - } - }, - "transaction_duration" : { - "avg" : { - "field" : "transaction.duration.histogram" - } - }, - "error_count" : { - "filter" : { - "term" : { - "event.outcome" : "failure" - } - }, - "aggs" : { - "actual_error_count" : { - "value_count" : { - "field" : "event.outcome" - } - } - } - }, - "success_count" : { - "filter" : { - "term" : { - "event.outcome" : "success" - } - } - }, - "transaction_failure_percentage" : { - "bucket_script" : { - "buckets_path" : { - "failure_count" : "error_count>_count", - "success_count" : "success_count>_count" - }, - "script" : "if ((params.failure_count + params.success_count)==0){return 0;}else{return params.failure_count/(params.failure_count + params.success_count);}" - } - } - } - } - } -} diff --git a/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_transaction/ml/datafeed_high_mean_transaction_duration.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_transaction/ml/datafeed_high_mean_transaction_duration.json new file mode 100644 index 0000000000000..d312577902f51 --- /dev/null +++ b/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_transaction/ml/datafeed_high_mean_transaction_duration.json @@ -0,0 +1,14 @@ +{ + "job_id": "JOB_ID", + "indices": [ + "INDEX_PATTERN_NAME" + ], + "query": { + "bool": { + "filter": [ + { "term": { "processor.event": "transaction" } }, + { "exists": { "field": "transaction.duration.us" } } + ] + } + } +} diff --git a/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_transaction/ml/high_mean_transaction_duration.json b/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_transaction/ml/high_mean_transaction_duration.json new file mode 100644 index 0000000000000..77284cb275cd8 --- /dev/null +++ b/x-pack/plugins/ml/server/models/data_recognizer/modules/apm_transaction/ml/high_mean_transaction_duration.json @@ -0,0 +1,35 @@ +{ + "job_type": "anomaly_detector", + "groups": [ + "apm" + ], + "description": "Detect transaction duration anomalies across transaction types for your APM services.", + "analysis_config": { + "bucket_span": "15m", + "detectors": [ + { + "detector_description": "high duration by transaction type for an APM service", + "function": "high_mean", + "field_name": "transaction.duration.us", + "by_field_name": "transaction.type", + "partition_field_name": "service.name" + } + ], + "influencers": [ + "transaction.type", + "service.name" + ] + }, + "analysis_limits": { + "model_memory_limit": "32mb" + }, + "data_description": { + "time_field": "@timestamp" + }, + "model_plot_config": { + "enabled": true + }, + "custom_settings": { + "created_by": "ml-module-apm-transaction" + } +} diff --git a/x-pack/test/api_integration/apis/ml/modules/recognize_module.ts b/x-pack/test/api_integration/apis/ml/modules/recognize_module.ts index 00b820a025c8b..2742fbff294c0 100644 --- a/x-pack/test/api_integration/apis/ml/modules/recognize_module.ts +++ b/x-pack/test/api_integration/apis/ml/modules/recognize_module.ts @@ -44,7 +44,7 @@ export default ({ getService }: FtrProviderContext) => { user: USER.ML_POWERUSER, expected: { responseCode: 200, - moduleIds: ['apm_jsbase', 'apm_nodejs'], + moduleIds: ['apm_jsbase', 'apm_transaction', 'apm_nodejs'], }, }, { diff --git a/x-pack/test/api_integration/apis/ml/modules/setup_module.ts b/x-pack/test/api_integration/apis/ml/modules/setup_module.ts index 6ff6b8113cb1a..c4dd529ac14f5 100644 --- a/x-pack/test/api_integration/apis/ml/modules/setup_module.ts +++ b/x-pack/test/api_integration/apis/ml/modules/setup_module.ts @@ -187,11 +187,9 @@ export default ({ getService }: FtrProviderContext) => { dashboards: [] as string[], }, }, - // Set startDatafeed and estimateModelMemory to false for the APM transaction test - // until there is a new data set available with metric data. { testTitleSuffix: - 'for apm_transaction with prefix, startDatafeed false and estimateModelMemory false', + 'for apm_transaction with prefix, startDatafeed true and estimateModelMemory true', sourceDataArchive: 'x-pack/test/functional/es_archives/ml/module_apm', indexPattern: { name: 'ft_module_apm', timeField: '@timestamp' }, module: 'apm_transaction', @@ -199,14 +197,14 @@ export default ({ getService }: FtrProviderContext) => { requestBody: { prefix: 'pf5_', indexPatternName: 'ft_module_apm', - startDatafeed: false, - estimateModelMemory: false, + startDatafeed: true, + end: Date.now(), }, expected: { responseCode: 200, jobs: [ { - jobId: 'pf5_apm_metrics', + jobId: 'pf5_high_mean_transaction_duration', jobState: JOB_STATE.CLOSED, datafeedState: DATAFEED_STATE.STOPPED, }, From 402550c1654f8d6e0383440bba8e3db150499171 Mon Sep 17 00:00:00 2001 From: Giorgos Bamparopoulos Date: Fri, 15 Oct 2021 09:16:56 +0100 Subject: [PATCH 13/24] Update APM Plugin Routing and Linking (#115008) * Update client-side and server-side routing function names and files --- x-pack/plugins/apm/dev_docs/routing_and_linking.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/apm/dev_docs/routing_and_linking.md b/x-pack/plugins/apm/dev_docs/routing_and_linking.md index 478de0081fca4..af22bcdbdfa11 100644 --- a/x-pack/plugins/apm/dev_docs/routing_and_linking.md +++ b/x-pack/plugins/apm/dev_docs/routing_and_linking.md @@ -6,15 +6,15 @@ This document describes routing in the APM plugin. ### Server-side -Route definitions for APM's server-side API are in the [server/routes directory](../server/routes). Routes are created with [the `createRoute` function](../server/routes/create_route.ts). Routes are added to the API in [the `createApmApi` function](../server/routes/create_apm_api.ts), which is initialized in the plugin `start` lifecycle method. +Route definitions for APM's server-side API are in the [server/routes directory](../server/routes). Routes are created with [the `createApmServerRoute` function](../server/routes/create_apm_server_route.ts). Routes are added to the API in [the `registerRoutes` function](../server/routes/register_routes.ts), which is initialized in the plugin `setup` lifecycle method. -The path and query string parameters are defined in the calls to `createRoute` with io-ts types, so that each route has its parameters type checked. +The path and query string parameters are defined in the calls to `createApmServerRoute` with io-ts types, so that each route has its parameters type checked. ### Client-side The client-side routing uses `@kbn/typed-react-router-config`, which is a wrapper around [React Router](https://reactrouter.com/) and [React Router Config](https://www.npmjs.com/package/react-router-config). Its goal is to provide a layer of high-fidelity types that allows us to parse and format URLs for routes while making sure the needed parameters are provided and/or available (typed and validated at runtime). The `history` object used by React Router is injected by the Kibana Platform. -Routes (and their parameters) are defined in [public/components/routing/apm_config.tsx](../public/components/routing/apm_config.tsx). +Routes (and their parameters) are defined in [public/components/routing/apm_route_config.tsx](../public/components/routing/apm_route_config.tsx). #### Parameter handling From 00db6023e6af7c69f1462738289f824a8dd67a64 Mon Sep 17 00:00:00 2001 From: Marco Vettorello Date: Fri, 15 Oct 2021 10:20:30 +0200 Subject: [PATCH 14/24] [deps] Renovate-bot default to draftPR and datavis reviewers (#114060) New renovate-bot PRs are created as draft PR for elastic-charts. The PR will now ping the whole datavis team. --- renovate.json5 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/renovate.json5 b/renovate.json5 index 76923f01daba0..ab33ba7b844ee 100644 --- a/renovate.json5 +++ b/renovate.json5 @@ -37,9 +37,10 @@ { groupName: '@elastic/charts', packageNames: ['@elastic/charts'], - reviewers: ['markov00', 'nickofthyme'], + reviewers: ['team:datavis'], matchBaseBranches: ['master'], labels: ['release_note:skip', 'v8.0.0', 'v7.16.0', 'auto-backport'], + draftPR: true, enabled: true, }, { From 0fa440abad2592be442d88e557044dbfcdfc168a Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Fri, 15 Oct 2021 12:01:42 +0300 Subject: [PATCH 15/24] [Vega] Replacing the 'interval' property should only happen for the date_histogram aggregation (#115001) --- .../public/data_model/es_query_parser.test.js | 16 ++++++++++++++-- .../vega/public/data_model/es_query_parser.ts | 8 ++++---- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/plugins/vis_types/vega/public/data_model/es_query_parser.test.js b/src/plugins/vis_types/vega/public/data_model/es_query_parser.test.js index bb3c0276f4cf9..214a23d2ee935 100644 --- a/src/plugins/vis_types/vega/public/data_model/es_query_parser.test.js +++ b/src/plugins/vis_types/vega/public/data_model/es_query_parser.test.js @@ -178,11 +178,23 @@ describe(`EsQueryParser.injectQueryContextVars`, () => { ); test( `%autointerval% = true`, - check({ interval: { '%autointerval%': true } }, { calendar_interval: `1h` }, ctxObj) + check( + { date_histogram: { interval: { '%autointerval%': true } } }, + { date_histogram: { calendar_interval: `1h` } }, + ctxObj + ) ); test( `%autointerval% = 10`, - check({ interval: { '%autointerval%': 10 } }, { fixed_interval: `3h` }, ctxObj) + check( + { date_histogram: { interval: { '%autointerval%': 10 } } }, + { date_histogram: { fixed_interval: `3h` } }, + ctxObj + ) + ); + test( + `histogram with interval`, + check({ histogram: { interval: 1 } }, { histogram: { interval: 1 } }, ctxObj) ); test(`%timefilter% = min`, check({ a: { '%timefilter%': 'min' } }, { a: rangeStart })); test(`%timefilter% = max`, check({ a: { '%timefilter%': 'max' } }, { a: rangeEnd })); diff --git a/src/plugins/vis_types/vega/public/data_model/es_query_parser.ts b/src/plugins/vis_types/vega/public/data_model/es_query_parser.ts index 134e82d676763..7f6ca05df3d7a 100644 --- a/src/plugins/vis_types/vega/public/data_model/es_query_parser.ts +++ b/src/plugins/vis_types/vega/public/data_model/es_query_parser.ts @@ -235,7 +235,8 @@ export class EsQueryParser { interval?: { '%autointerval%': true | number } | string; } >, - isQuery: boolean + isQuery: boolean, + key?: string ) { if (obj && typeof obj === 'object') { if (Array.isArray(obj)) { @@ -281,9 +282,8 @@ export class EsQueryParser { if (!subObj || typeof obj !== 'object') continue; // replace "interval" with ES acceptable fixed_interval / calendar_interval - if (prop === 'interval') { + if (prop === 'interval' && key === 'date_histogram') { let intervalString: string; - if (typeof subObj === 'string') { intervalString = subObj; } else if (subObj[AUTOINTERVAL]) { @@ -322,7 +322,7 @@ export class EsQueryParser { this._createRangeFilter(subObj); continue; case undefined: - this._injectContextVars(subObj, isQuery); + this._injectContextVars(subObj, isQuery, prop); continue; default: throw new Error( From c11b38de7bba8a805a7979ea9095858d580b22cf Mon Sep 17 00:00:00 2001 From: mgiota Date: Fri, 15 Oct 2021 11:07:47 +0200 Subject: [PATCH 16/24] [RAC] create functional tests for add to case (#114075) * [RAC] create functional tests for add to case * use observability test helpers for user creation * basic tests for add to case options * add two more cases * test case for clicking on add to new case button * remove unused expect statement * clicking on add to existing case should open a modal * move add to case functionality in a separate file * address comments in the PR review Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../cases/add_to_existing_case_button.tsx | 2 +- .../timeline/cases/add_to_new_case_button.tsx | 2 +- .../observability/alerts/add_to_case.ts | 75 +++++++++++++++ .../services/observability/alerts/common.ts | 1 + .../services/observability/alerts/index.ts | 4 +- .../apps/observability/alerts/add_to_case.ts | 92 +++++++++++++++++++ .../apps/observability/index.ts | 1 + 7 files changed, 174 insertions(+), 3 deletions(-) create mode 100644 x-pack/test/functional/services/observability/alerts/add_to_case.ts create mode 100644 x-pack/test/observability_functional/apps/observability/alerts/add_to_case.ts diff --git a/x-pack/plugins/timelines/public/components/actions/timeline/cases/add_to_existing_case_button.tsx b/x-pack/plugins/timelines/public/components/actions/timeline/cases/add_to_existing_case_button.tsx index af19a6b7cdb74..30181a96aa70b 100644 --- a/x-pack/plugins/timelines/public/components/actions/timeline/cases/add_to_existing_case_button.tsx +++ b/x-pack/plugins/timelines/public/components/actions/timeline/cases/add_to_existing_case_button.tsx @@ -32,7 +32,7 @@ const AddToCaseActionComponent: React.FC = ({ {userCanCrud && ( = ({ {userCanCrud && ( { + return await testSubjects.find(ADD_TO_EXISTING_CASE_SELECTOR); + }; + + const getAddToExistingCaseSelectorOrFail = async () => { + return await testSubjects.existOrFail(ADD_TO_EXISTING_CASE_SELECTOR); + }; + + const missingAddToExistingCaseSelectorOrFail = async () => { + return await testSubjects.missingOrFail(ADD_TO_EXISTING_CASE_SELECTOR); + }; + + const getAddToNewCaseSelector = async () => { + return await testSubjects.find(ADD_TO_NEW_CASE_SELECTOR); + }; + + const getAddToNewCaseSelectorOrFail = async () => { + return await testSubjects.existOrFail(ADD_TO_NEW_CASE_SELECTOR); + }; + + const missingAddToNewCaseSelectorOrFail = async () => { + return await testSubjects.missingOrFail(ADD_TO_NEW_CASE_SELECTOR); + }; + + const addToNewCaseButtonClick = async () => { + return await (await getAddToNewCaseSelector()).click(); + }; + + const addToExistingCaseButtonClick = async () => { + return await (await getAddToExistingCaseSelector()).click(); + }; + + const getCreateCaseFlyoutOrFail = async () => { + return await testSubjects.existOrFail(CREATE_CASE_FLYOUT); + }; + + const closeFlyout = async () => { + return await (await testSubjects.find('euiFlyoutCloseButton')).click(); + }; + + const getAddtoExistingCaseModalOrFail = async () => { + return await testSubjects.existOrFail(SELECT_CASE_MODAL); + }; + + return { + getAddToExistingCaseSelector, + getAddToExistingCaseSelectorOrFail, + missingAddToExistingCaseSelectorOrFail, + getAddToNewCaseSelector, + getAddToNewCaseSelectorOrFail, + missingAddToNewCaseSelectorOrFail, + getCreateCaseFlyoutOrFail, + closeFlyout, + addToNewCaseButtonClick, + addToExistingCaseButtonClick, + getAddtoExistingCaseModalOrFail, + }; +} diff --git a/x-pack/test/functional/services/observability/alerts/common.ts b/x-pack/test/functional/services/observability/alerts/common.ts index 7098fdec2a9d4..d5a2ce2a18c41 100644 --- a/x-pack/test/functional/services/observability/alerts/common.ts +++ b/x-pack/test/functional/services/observability/alerts/common.ts @@ -204,5 +204,6 @@ export function ObservabilityAlertsCommonProvider({ setWorkflowStatusFilter, submitQuery, typeInQueryBar, + openActionsMenuForRow, }; } diff --git a/x-pack/test/functional/services/observability/alerts/index.ts b/x-pack/test/functional/services/observability/alerts/index.ts index f373b0d75c543..f2b5173dfe5b0 100644 --- a/x-pack/test/functional/services/observability/alerts/index.ts +++ b/x-pack/test/functional/services/observability/alerts/index.ts @@ -7,15 +7,17 @@ import { ObservabilityAlertsPaginationProvider } from './pagination'; import { ObservabilityAlertsCommonProvider } from './common'; +import { ObservabilityAlertsAddToCaseProvider } from './add_to_case'; import { FtrProviderContext } from '../../../ftr_provider_context'; export function ObservabilityAlertsProvider(context: FtrProviderContext) { const common = ObservabilityAlertsCommonProvider(context); const pagination = ObservabilityAlertsPaginationProvider(context); - + const addToCase = ObservabilityAlertsAddToCaseProvider(context); return { common, pagination, + addToCase, }; } diff --git a/x-pack/test/observability_functional/apps/observability/alerts/add_to_case.ts b/x-pack/test/observability_functional/apps/observability/alerts/add_to_case.ts new file mode 100644 index 0000000000000..f29111f2cb66b --- /dev/null +++ b/x-pack/test/observability_functional/apps/observability/alerts/add_to_case.ts @@ -0,0 +1,92 @@ +/* + * 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 { FtrProviderContext } from '../../../ftr_provider_context'; + +export default ({ getService, getPageObjects }: FtrProviderContext) => { + const esArchiver = getService('esArchiver'); + const observability = getService('observability'); + const retry = getService('retry'); + + describe('Observability alerts / Add to case', function () { + this.tags('includeFirefox'); + + before(async () => { + await esArchiver.load('x-pack/test/functional/es_archives/observability/alerts'); + }); + + after(async () => { + await esArchiver.unload('x-pack/test/functional/es_archives/observability/alerts'); + }); + + describe('When user has all priviledges for cases', () => { + before(async () => { + await observability.users.setTestUserRole( + observability.users.defineBasicObservabilityRole({ + observabilityCases: ['all'], + logs: ['all'], + }) + ); + await observability.alerts.common.navigateToTimeWithData(); + }); + + after(async () => { + await observability.users.restoreDefaultTestUserRole(); + }); + + it('renders case options in the overflow menu', async () => { + await observability.alerts.common.openActionsMenuForRow(0); + await retry.try(async () => { + await observability.alerts.addToCase.getAddToExistingCaseSelectorOrFail(); + await observability.alerts.addToCase.getAddToNewCaseSelectorOrFail(); + }); + }); + + it('opens a flyout when Add to new case is clicked', async () => { + await observability.alerts.addToCase.addToNewCaseButtonClick(); + + await retry.try(async () => { + await observability.alerts.addToCase.getCreateCaseFlyoutOrFail(); + await observability.alerts.addToCase.closeFlyout(); + }); + }); + + it('opens a modal when Add to existing case is clicked', async () => { + await observability.alerts.common.openActionsMenuForRow(0); + + await retry.try(async () => { + await observability.alerts.addToCase.addToExistingCaseButtonClick(); + await observability.alerts.addToCase.getAddtoExistingCaseModalOrFail(); + }); + }); + }); + + describe('When user has read permissions for cases', () => { + before(async () => { + await observability.users.setTestUserRole( + observability.users.defineBasicObservabilityRole({ + observabilityCases: ['read'], + logs: ['all'], + }) + ); + await observability.alerts.common.navigateToTimeWithData(); + }); + + after(async () => { + await observability.users.restoreDefaultTestUserRole(); + }); + + it('does not render case options in the overflow menu', async () => { + await observability.alerts.common.openActionsMenuForRow(0); + await retry.try(async () => { + await observability.alerts.addToCase.missingAddToExistingCaseSelectorOrFail(); + await observability.alerts.addToCase.missingAddToNewCaseSelectorOrFail(); + }); + }); + }); + }); +}; diff --git a/x-pack/test/observability_functional/apps/observability/index.ts b/x-pack/test/observability_functional/apps/observability/index.ts index b163d4d6bb8d5..43e056bae65c0 100644 --- a/x-pack/test/observability_functional/apps/observability/index.ts +++ b/x-pack/test/observability_functional/apps/observability/index.ts @@ -15,5 +15,6 @@ export default function ({ loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./alerts')); loadTestFile(require.resolve('./alerts/workflow_status')); loadTestFile(require.resolve('./alerts/pagination')); + loadTestFile(require.resolve('./alerts/add_to_case')); }); } From d19510535a4774a58ac37384ad0b09b99f821399 Mon Sep 17 00:00:00 2001 From: Ahmad Bamieh Date: Fri, 15 Oct 2021 12:09:19 +0300 Subject: [PATCH 17/24] [i18n] remove angular i18n and move the remains to monitoring plugin (#115003) --- .../external-plugin-localization.asciidoc | 21 --- package.json | 2 - packages/kbn-i18n/BUILD.bazel | 2 - packages/kbn-i18n/GUIDELINE.md | 57 ++----- packages/kbn-i18n/README.md | 92 ----------- packages/kbn-i18n/angular/package.json | 5 - .../__snapshots__/directive.test.ts.snap | 69 -------- .../kbn-i18n/src/angular/directive.test.ts | 150 ------------------ packages/kbn-i18n/src/angular/filter.test.ts | 46 ------ .../kbn-i18n/src/angular/provider.test.ts | 47 ------ packages/kbn-ui-shared-deps-src/src/entry.js | 1 - packages/kbn-ui-shared-deps-src/src/index.js | 1 - src/dev/i18n/README.md | 28 ---- x-pack/.i18nrc.json | 2 +- .../public/angular/angular_i18n}/directive.ts | 5 +- .../public/angular/angular_i18n}/filter.ts | 5 +- .../public/angular/angular_i18n}/index.ts | 5 +- .../public/angular/angular_i18n}/provider.ts | 7 +- .../monitoring/public/angular/app_modules.ts | 2 +- yarn.lock | 14 +- 20 files changed, 23 insertions(+), 538 deletions(-) delete mode 100644 packages/kbn-i18n/angular/package.json delete mode 100644 packages/kbn-i18n/src/angular/__snapshots__/directive.test.ts.snap delete mode 100644 packages/kbn-i18n/src/angular/directive.test.ts delete mode 100644 packages/kbn-i18n/src/angular/filter.test.ts delete mode 100644 packages/kbn-i18n/src/angular/provider.test.ts rename {packages/kbn-i18n/src/angular => x-pack/plugins/monitoring/public/angular/angular_i18n}/directive.ts (94%) rename {packages/kbn-i18n/src/angular => x-pack/plugins/monitoring/public/angular/angular_i18n}/filter.ts (71%) rename {packages/kbn-i18n/src/angular => x-pack/plugins/monitoring/public/angular/angular_i18n}/index.ts (71%) rename {packages/kbn-i18n/src/angular => x-pack/plugins/monitoring/public/angular/angular_i18n}/provider.ts (78%) diff --git a/docs/developer/plugin/external-plugin-localization.asciidoc b/docs/developer/plugin/external-plugin-localization.asciidoc index d30dec1a8f46b..656dff90fe0de 100644 --- a/docs/developer/plugin/external-plugin-localization.asciidoc +++ b/docs/developer/plugin/external-plugin-localization.asciidoc @@ -135,27 +135,6 @@ export const Component = () => { Full details are {kib-repo}tree/master/packages/kbn-i18n#react[here]. - - -[discrete] -==== i18n for Angular - -You are encouraged to use `i18n.translate()` by statically importing `i18n` from `@kbn/i18n` wherever possible in your Angular code. Angular wrappers use the translation `service` with the i18n engine under the hood. - -The translation directive has the following syntax: -["source","js"] ------------ - ------------ - -Full details are {kib-repo}tree/master/packages/kbn-i18n#angularjs[here]. - - [discrete] === Resources diff --git a/package.json b/package.json index f526f357ff347..9341ecd0bae35 100644 --- a/package.json +++ b/package.json @@ -489,7 +489,6 @@ "@testing-library/react-hooks": "^5.1.1", "@testing-library/user-event": "^13.1.1", "@types/angular": "^1.6.56", - "@types/angular-mocks": "^1.7.0", "@types/apidoc": "^0.22.3", "@types/archiver": "^5.1.0", "@types/babel__core": "^7.1.16", @@ -644,7 +643,6 @@ "@yarnpkg/lockfile": "^1.1.0", "abab": "^2.0.4", "aggregate-error": "^3.1.0", - "angular-mocks": "^1.7.9", "antlr4ts-cli": "^0.5.0-alpha.3", "apidoc": "^0.29.0", "apidoc-markdown": "^6.0.0", diff --git a/packages/kbn-i18n/BUILD.bazel b/packages/kbn-i18n/BUILD.bazel index 49d5603b2c516..256262bb8783b 100644 --- a/packages/kbn-i18n/BUILD.bazel +++ b/packages/kbn-i18n/BUILD.bazel @@ -27,7 +27,6 @@ filegroup( ) NPM_MODULE_EXTRA_FILES = [ - "angular/package.json", "react/package.json", "package.json", "GUIDELINE.md", @@ -47,7 +46,6 @@ TYPES_DEPS = [ "//packages/kbn-babel-preset", "@npm//intl-messageformat", "@npm//tslib", - "@npm//@types/angular", "@npm//@types/intl-relativeformat", "@npm//@types/jest", "@npm//@types/prop-types", diff --git a/packages/kbn-i18n/GUIDELINE.md b/packages/kbn-i18n/GUIDELINE.md index 806e799bd1106..7ffc4b078c79b 100644 --- a/packages/kbn-i18n/GUIDELINE.md +++ b/packages/kbn-i18n/GUIDELINE.md @@ -93,17 +93,6 @@ The long term plan is to rely on using `FormattedMessage` and `i18n.translate()` Currently, we support the following ReactJS `i18n` tools, but they will be removed in future releases: - Usage of `props.intl.formatmessage()` (where `intl` is passed to `props` by `injectI18n` HOC). -#### In AngularJS - -The long term plan is to rely on using `i18n.translate()` by statically importing `i18n` from the `@kbn/i18n` package. **Avoid using the `i18n` filter and the `i18n` service injected in controllers, directives, services.** - -- Call JS function `i18n.translate()` from the `@kbn/i18n` package. -- Use `i18nId` directive in template. - -Currently, we support the following AngluarJS `i18n` tools, but they will be removed in future releases: -- Usage of `i18n` service in controllers, directives, services by injecting it. -- Usage of `i18n` filter in template for attribute translation. Note: Use one-time binding ("{{:: ... }}") in filters wherever it's possible to prevent unnecessary expression re-evaluation. - #### In JavaScript - Use `i18n.translate()` in NodeJS or any other framework agnostic code, where `i18n` is the I18n engine from `@kbn/i18n` package. @@ -223,7 +212,6 @@ For example: - for button: ```js - @@ -232,11 +220,11 @@ For example: - for dropDown: ```js - +