-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
## Summary Main ticket elastic/security-team#9327 With this changes we introduce the way to schedule rule run manually. There are two ways to do that in UI: 1. Via "All actions" button on rules management page 2. Via "All actions" button on rule's details page **NOTES**: 1. To be able to test these changes, you need to enable feature flag `manualRuleRunEnabled` first 2. Bulk action will be part of a separate ticket/PR **RECORDING**: https://github.com/elastic/kibana/assets/2700761/d49bad53-026e-49c2-aeea-481203260b23 ### Checklist Delete any items that are not applicable to this PR. - [x] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) - [x] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials - [x] elastic/security-docs#5264 - [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 - [ ] [Flaky Test Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was used on any tests changed - [x] [Cypress RM (100 ESS & 100 Serverless)](https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/6263) - [ ] [Cypress DE (100 ESS & 100 Serverless)](https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/6280) - [x] [Integration Rule Gaps (100 ESS & 100 Serverless)](https://buildkite.com/elastic/kibana-flaky-test-suite-runner/builds/6257) --------- Co-authored-by: Kibana Machine <[email protected]> Co-authored-by: Ryland Herrick <[email protected]>
- Loading branch information
1 parent
a1ededc
commit 4392ee8
Showing
37 changed files
with
1,445 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
17 changes: 17 additions & 0 deletions
17
x-pack/plugins/security_solution/public/detection_engine/rule_gaps/api/__mocks__/api.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
/* | ||
* 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 type { ScheduleBackfillResponseBody } from '@kbn/alerting-plugin/common/routes/backfill/apis/schedule'; | ||
import { scheduleRuleRunMock } from '../../logic/__mocks__/mock'; | ||
|
||
import type { ScheduleBackfillProps } from '../../types'; | ||
|
||
export const scheduleRuleRun = async ({ | ||
ruleIds, | ||
timeRange, | ||
}: ScheduleBackfillProps): Promise<ScheduleBackfillResponseBody> => | ||
Promise.resolve(scheduleRuleRunMock); |
44 changes: 44 additions & 0 deletions
44
x-pack/plugins/security_solution/public/detection_engine/rule_gaps/api/api.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
/* | ||
* 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 { INTERNAL_ALERTING_BACKFILL_SCHEDULE_API_PATH } from '@kbn/alerting-plugin/common'; | ||
|
||
import { KibanaServices } from '../../../common/lib/kibana'; | ||
import { scheduleRuleRunMock } from '../logic/__mocks__/mock'; | ||
import { scheduleRuleRun } from './api'; | ||
|
||
const mockKibanaServices = KibanaServices.get as jest.Mock; | ||
jest.mock('../../../common/lib/kibana'); | ||
|
||
const fetchMock = jest.fn(); | ||
mockKibanaServices.mockReturnValue({ http: { fetch: fetchMock } }); | ||
|
||
describe('Detections Rule Gaps API', () => { | ||
describe('scheduleRuleRun', () => { | ||
beforeEach(() => { | ||
fetchMock.mockClear(); | ||
fetchMock.mockResolvedValue(scheduleRuleRunMock); | ||
}); | ||
|
||
test('schedules rule run', async () => { | ||
const timeRange = { startDate: moment().subtract(1, 'd'), endDate: moment() }; | ||
await scheduleRuleRun({ | ||
ruleIds: ['rule-1'], | ||
timeRange, | ||
}); | ||
expect(fetchMock).toHaveBeenCalledWith( | ||
INTERNAL_ALERTING_BACKFILL_SCHEDULE_API_PATH, | ||
expect.objectContaining({ | ||
body: `[{"rule_id":"rule-1","start":"${timeRange.startDate.toISOString()}","end":"${timeRange.endDate.toISOString()}"}]`, | ||
method: 'POST', | ||
}) | ||
); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
52 changes: 52 additions & 0 deletions
52
...ution/public/detection_engine/rule_gaps/api/hooks/use_schedule_rule_run_mutation.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
/* | ||
* 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 { act } from '@testing-library/react-hooks'; | ||
import { useScheduleRuleRunMutation } from './use_schedule_rule_run_mutation'; | ||
import { renderMutation } from '../../../../management/hooks/test_utils'; | ||
import { scheduleRuleRunMock } from '../../logic/__mocks__/mock'; | ||
import { INTERNAL_ALERTING_BACKFILL_SCHEDULE_API_PATH } from '@kbn/alerting-plugin/common'; | ||
|
||
import { KibanaServices } from '../../../../common/lib/kibana'; | ||
|
||
const mockKibanaServices = KibanaServices.get as jest.Mock; | ||
jest.mock('../../../../common/lib/kibana'); | ||
|
||
const fetchMock = jest.fn(); | ||
mockKibanaServices.mockReturnValue({ http: { fetch: fetchMock } }); | ||
|
||
const apiVersion = '2023-10-31'; | ||
|
||
describe('Schedule rule run hook', () => { | ||
let result: ReturnType<typeof useScheduleRuleRunMutation>; | ||
|
||
beforeEach(() => { | ||
fetchMock.mockClear(); | ||
fetchMock.mockResolvedValue(scheduleRuleRunMock); | ||
}); | ||
|
||
it('schedules a rule run by calling the backfill API', async () => { | ||
result = await renderMutation(() => useScheduleRuleRunMutation()); | ||
|
||
expect(fetchMock).toHaveBeenCalledTimes(0); | ||
|
||
const timeRange = { startDate: moment().subtract(1, 'd'), endDate: moment() }; | ||
|
||
await act(async () => { | ||
const res = await result.mutateAsync({ ruleIds: ['rule-1'], timeRange }); | ||
expect(res).toEqual(scheduleRuleRunMock); | ||
expect(fetchMock).toHaveBeenCalledTimes(1); | ||
expect(fetchMock).toHaveBeenCalledWith(INTERNAL_ALERTING_BACKFILL_SCHEDULE_API_PATH, { | ||
body: `[{"rule_id":"rule-1","start":"${timeRange.startDate.toISOString()}","end":"${timeRange.endDate.toISOString()}"}]`, | ||
method: 'POST', | ||
version: apiVersion, | ||
}); | ||
}); | ||
}); | ||
}); |
25 changes: 25 additions & 0 deletions
25
...ty_solution/public/detection_engine/rule_gaps/api/hooks/use_schedule_rule_run_mutation.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
/* | ||
* 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 { INTERNAL_ALERTING_BACKFILL_SCHEDULE_API_PATH } from '@kbn/alerting-plugin/common'; | ||
import type { UseMutationOptions } from '@tanstack/react-query'; | ||
import { useMutation } from '@tanstack/react-query'; | ||
import type { ScheduleBackfillProps } from '../../types'; | ||
import { scheduleRuleRun } from '../api'; | ||
|
||
export const SCHEDULE_RULE_RUN_MUTATION_KEY = [ | ||
'POST', | ||
INTERNAL_ALERTING_BACKFILL_SCHEDULE_API_PATH, | ||
]; | ||
|
||
export const useScheduleRuleRunMutation = ( | ||
options?: UseMutationOptions<unknown, Error, ScheduleBackfillProps> | ||
) => { | ||
return useMutation((scheduleOptions: ScheduleBackfillProps) => scheduleRuleRun(scheduleOptions), { | ||
...options, | ||
mutationKey: SCHEDULE_RULE_RUN_MUTATION_KEY, | ||
}); | ||
}; |
78 changes: 78 additions & 0 deletions
78
...rity_solution/public/detection_engine/rule_gaps/components/manual_rule_run/index.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
/* | ||
* 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 React from 'react'; | ||
import { render, within } from '@testing-library/react'; | ||
import { ManualRuleRunModal } from '.'; | ||
|
||
describe('ManualRuleRunModal', () => { | ||
const onCancelMock = jest.fn(); | ||
const onConfirmMock = jest.fn(); | ||
|
||
afterEach(() => { | ||
onCancelMock.mockReset(); | ||
onConfirmMock.mockReset(); | ||
}); | ||
|
||
it('should render modal', () => { | ||
const wrapper = render( | ||
<ManualRuleRunModal onCancel={onCancelMock} onConfirm={onConfirmMock} /> | ||
); | ||
|
||
expect(wrapper.getByTestId('manual-rule-run-modal-form')).toBeInTheDocument(); | ||
expect(wrapper.getByTestId('confirmModalCancelButton')).toBeEnabled(); | ||
expect(wrapper.getByTestId('confirmModalConfirmButton')).toBeEnabled(); | ||
}); | ||
|
||
it('should render confirmation button disabled if invalid time range has been selected', () => { | ||
const wrapper = render( | ||
<ManualRuleRunModal onCancel={onCancelMock} onConfirm={onConfirmMock} /> | ||
); | ||
|
||
expect(wrapper.getByTestId('confirmModalConfirmButton')).toBeEnabled(); | ||
|
||
within(wrapper.getByTestId('end-date-picker')).getByText('Previous Month').click(); | ||
|
||
expect(wrapper.getByTestId('confirmModalConfirmButton')).toBeDisabled(); | ||
expect(wrapper.getByTestId('manual-rule-run-time-range-form')).toHaveTextContent( | ||
'Selected time range is invalid' | ||
); | ||
}); | ||
|
||
it('should render confirmation button disabled if selected start date is more than 90 days in the past', () => { | ||
const wrapper = render( | ||
<ManualRuleRunModal onCancel={onCancelMock} onConfirm={onConfirmMock} /> | ||
); | ||
|
||
expect(wrapper.getByTestId('confirmModalConfirmButton')).toBeEnabled(); | ||
|
||
within(wrapper.getByTestId('start-date-picker')).getByText('Previous Month').click(); | ||
within(wrapper.getByTestId('start-date-picker')).getByText('Previous Month').click(); | ||
within(wrapper.getByTestId('start-date-picker')).getByText('Previous Month').click(); | ||
within(wrapper.getByTestId('start-date-picker')).getByText('Previous Month').click(); | ||
|
||
expect(wrapper.getByTestId('confirmModalConfirmButton')).toBeDisabled(); | ||
expect(wrapper.getByTestId('manual-rule-run-time-range-form')).toHaveTextContent( | ||
'Manual rule run cannot be scheduled earlier than 90 days ago' | ||
); | ||
}); | ||
|
||
it('should render confirmation button disabled if selected end date is in future', () => { | ||
const wrapper = render( | ||
<ManualRuleRunModal onCancel={onCancelMock} onConfirm={onConfirmMock} /> | ||
); | ||
|
||
expect(wrapper.getByTestId('confirmModalConfirmButton')).toBeEnabled(); | ||
|
||
within(wrapper.getByTestId('end-date-picker')).getByText('Next month').click(); | ||
|
||
expect(wrapper.getByTestId('confirmModalConfirmButton')).toBeDisabled(); | ||
expect(wrapper.getByTestId('manual-rule-run-time-range-form')).toHaveTextContent( | ||
'Manual rule run cannot be scheduled for the future' | ||
); | ||
}); | ||
}); |
Oops, something went wrong.