diff --git a/x-pack/plugins/actions/README.md b/x-pack/plugins/actions/README.md index 432a4bfff7a6..fb0293dca5ff 100644 --- a/x-pack/plugins/actions/README.md +++ b/x-pack/plugins/actions/README.md @@ -529,7 +529,7 @@ The PagerDuty action uses the [V2 Events API](https://v2.developer.pagerduty.com | Property | Description | Type | | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------- | | eventAction | One of `trigger` _(default)_, `resolve`, or `acknowlege`. See [event action](https://v2.developer.pagerduty.com/docs/events-api-v2#event-action) for more details. | string _(optional)_ | -| dedupKey | All actions sharing this key will be associated with the same PagerDuty alert. Used to correlate trigger and resolution. Defaults to `action:`. The maximum length is **255** characters. See [alert deduplication](https://v2.developer.pagerduty.com/docs/events-api-v2#alert-de-duplication) for details. | string _(optional)_ | +| dedupKey | All actions sharing this key will be associated with the same PagerDuty alert. Used to correlate trigger and resolution. The maximum length is **255** characters. See [alert deduplication](https://v2.developer.pagerduty.com/docs/events-api-v2#alert-de-duplication) for details. | string _(optional)_ | | summary | A text summary of the event, defaults to `No summary provided`. The maximum length is **1024** characters. | string _(optional)_ | | source | The affected system, preferably a hostname or fully qualified domain name. Defaults to `Kibana Action `. | string _(optional)_ | | severity | The perceived severity of on the affected system. This can be one of `critical`, `error`, `warning` or `info`_(default)_. | string _(optional)_ | diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/jira/jira_params.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/jira/jira_params.test.tsx index 671a575695d6..29668c213f30 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/jira/jira_params.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/jira/jira_params.test.tsx @@ -12,6 +12,7 @@ import { coreMock } from 'src/core/public/mocks'; import { useGetIssueTypes } from './use_get_issue_types'; import { useGetFieldsByIssueType } from './use_get_fields_by_issue_type'; import { ActionConnector } from '../../../../types'; +import { AlertProvidedActionVariables } from '../../../lib/action_variables'; jest.mock('./use_get_issue_types'); jest.mock('./use_get_fields_by_issue_type'); @@ -90,7 +91,7 @@ describe('JiraParamsFields renders', () => { errors={{ title: [] }} editAction={() => {}} index={0} - messageVariables={[{ name: 'alertId', description: '' }]} + messageVariables={[{ name: AlertProvidedActionVariables.alertId, description: '' }]} docLinks={{ ELASTIC_WEBSITE_URL: '', DOC_LINK_VERSION: '' } as DocLinksStart} toastNotifications={mocks.notifications.toasts} http={mocks.http} diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/jira/jira_params.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/jira/jira_params.tsx index 880e39aada44..37cf3624e655 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/jira/jira_params.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/jira/jira_params.tsx @@ -29,6 +29,7 @@ import { useGetIssueTypes } from './use_get_issue_types'; import { useGetFieldsByIssueType } from './use_get_fields_by_issue_type'; import { SearchIssues } from './search_issues'; import { extractActionVariable } from '../extract_action_variable'; +import { AlertProvidedActionVariables } from '../../../lib/action_variables'; const JiraParamsFields: React.FunctionComponent> = ({ actionParams, @@ -48,7 +49,7 @@ const JiraParamsFields: React.FunctionComponent([]); const isActionBeingConfiguredByAnAlert = messageVariables - ? isSome(extractActionVariable(messageVariables, 'alertId')) + ? isSome(extractActionVariable(messageVariables, AlertProvidedActionVariables.alertId)) : false; useEffect(() => { @@ -141,7 +142,7 @@ const JiraParamsFields: React.FunctionComponent { expect(wrapper.find('[data-test-subj="severitySelect"]').first().prop('value')).toStrictEqual( 'critical' ); + expect(wrapper.find('[data-test-subj="dedupKeyInput"]').length > 0).toBeTruthy(); + expect(wrapper.find('[data-test-subj="dedupKeyInput"]').first().prop('value')).toStrictEqual( + 'test' + ); expect(wrapper.find('[data-test-subj="eventActionSelect"]').length > 0).toBeTruthy(); expect(wrapper.find('[data-test-subj="dedupKeyInput"]').length > 0).toBeTruthy(); expect(wrapper.find('[data-test-subj="timestampInput"]').length > 0).toBeTruthy(); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/resilient/resilient_params.test.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/resilient/resilient_params.test.tsx index b12307e1fdd1..d20935de2352 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/resilient/resilient_params.test.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/resilient/resilient_params.test.tsx @@ -11,6 +11,7 @@ import { DocLinksStart } from 'kibana/public'; import { useGetIncidentTypes } from './use_get_incident_types'; import { useGetSeverity } from './use_get_severity'; import { coreMock } from 'src/core/public/mocks'; +import { AlertProvidedActionVariables } from '../../../lib/action_variables'; const mocks = coreMock.createSetup(); @@ -86,7 +87,7 @@ describe('ResilientParamsFields renders', () => { errors={{ title: [] }} editAction={() => {}} index={0} - messageVariables={[{ name: 'alertId', description: '' }]} + messageVariables={[{ name: AlertProvidedActionVariables.alertId, description: '' }]} docLinks={{ ELASTIC_WEBSITE_URL: '', DOC_LINK_VERSION: '' } as DocLinksStart} toastNotifications={mocks.notifications.toasts} http={mocks.http} diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/resilient/resilient_params.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/resilient/resilient_params.tsx index 996e83b87f05..c68fa39a3c8d 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/resilient/resilient_params.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/resilient/resilient_params.tsx @@ -27,6 +27,7 @@ import { TextFieldWithMessageVariables } from '../../text_field_with_message_var import { useGetIncidentTypes } from './use_get_incident_types'; import { useGetSeverity } from './use_get_severity'; import { extractActionVariable } from '../extract_action_variable'; +import { AlertProvidedActionVariables } from '../../../lib/action_variables'; const ResilientParamsFields: React.FunctionComponent> = ({ actionParams, @@ -43,7 +44,7 @@ const ResilientParamsFields: React.FunctionComponent { test('all params fields is rendered', () => { @@ -32,7 +33,7 @@ describe('ServiceNowParamsFields renders', () => { errors={{ title: [] }} editAction={() => {}} index={0} - messageVariables={[{ name: 'alertId', description: '' }]} + messageVariables={[{ name: AlertProvidedActionVariables.alertId, description: '' }]} docLinks={{ ELASTIC_WEBSITE_URL: '', DOC_LINK_VERSION: '' } as DocLinksStart} toastNotifications={mocks.notifications.toasts} http={mocks.http} diff --git a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/servicenow_params.tsx b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/servicenow_params.tsx index 3e59f2199153..0ee1bbc05a8e 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/servicenow_params.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/components/builtin_action_types/servicenow/servicenow_params.tsx @@ -22,6 +22,7 @@ import { ServiceNowActionParams } from './types'; import { TextAreaWithMessageVariables } from '../../text_area_with_message_variables'; import { TextFieldWithMessageVariables } from '../../text_field_with_message_variables'; import { extractActionVariable } from '../extract_action_variable'; +import { AlertProvidedActionVariables } from '../../../lib/action_variables'; const ServiceNowParamsFields: React.FunctionComponent void; errors?: string[]; + defaultValue?: string | number | string[]; } export const TextFieldWithMessageVariables: React.FunctionComponent = ({ @@ -25,6 +26,7 @@ export const TextFieldWithMessageVariables: React.FunctionComponent = ({ inputTargetValue, editAction, errors, + defaultValue, }) => { const [currentTextElement, setCurrentTextElement] = useState(null); @@ -51,6 +53,7 @@ export const TextFieldWithMessageVariables: React.FunctionComponent = ({ isInvalid={errors && errors.length > 0 && inputTargetValue !== undefined} data-test-subj={`${paramsProperty}Input`} value={inputTargetValue || ''} + defaultValue={defaultValue} onChange={(e: React.ChangeEvent) => onChangeWithMessageVariable(e)} onFocus={(e: React.FocusEvent) => { setCurrentTextElement(e.target); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/action_variables.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/action_variables.ts index 296185211d04..d840f8ed3d1b 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/lib/action_variables.ts +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/action_variables.ts @@ -19,6 +19,14 @@ export function transformActionVariables(actionVariables: ActionVariables): Acti return alwaysProvidedVars.concat(contextVars, paramsVars, stateVars); } +export enum AlertProvidedActionVariables { + alertId = 'alertId', + alertName = 'alertName', + spaceId = 'spaceId', + tags = 'tags', + alertInstanceId = 'alertInstanceId', +} + function prefixKeys(actionVariables: ActionVariable[], prefix: string): ActionVariable[] { return actionVariables.map((actionVariable) => { return { name: `${prefix}${actionVariable.name}`, description: actionVariable.description }; @@ -31,28 +39,28 @@ function getAlwaysProvidedActionVariables(): ActionVariable[] { const result: ActionVariable[] = []; result.push({ - name: 'alertId', + name: AlertProvidedActionVariables.alertId, description: i18n.translate('xpack.triggersActionsUI.actionVariables.alertIdLabel', { defaultMessage: 'The id of the alert.', }), }); result.push({ - name: 'alertName', + name: AlertProvidedActionVariables.alertName, description: i18n.translate('xpack.triggersActionsUI.actionVariables.alertNameLabel', { defaultMessage: 'The name of the alert.', }), }); result.push({ - name: 'spaceId', + name: AlertProvidedActionVariables.spaceId, description: i18n.translate('xpack.triggersActionsUI.actionVariables.spaceIdLabel', { defaultMessage: 'The spaceId of the alert.', }), }); result.push({ - name: 'tags', + name: AlertProvidedActionVariables.tags, description: i18n.translate('xpack.triggersActionsUI.actionVariables.tagsLabel', { defaultMessage: 'The tags of the alert.', }), diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/get_defaults_for_action_params.test.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/get_defaults_for_action_params.test.ts new file mode 100644 index 000000000000..c1f7cbb9fafe --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/get_defaults_for_action_params.test.ts @@ -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; + * you may not use this file except in compliance with the Elastic License. + */ + +import { ResolvedActionGroup } from '../../../../alerts/common'; +import { AlertProvidedActionVariables } from './action_variables'; +import { getDefaultsForActionParams } from './get_defaults_for_action_params'; + +describe('getDefaultsForActionParams', () => { + test('pagerduty defaults', async () => { + expect(getDefaultsForActionParams('.pagerduty', 'test')).toEqual({ + dedupKey: `{{${AlertProvidedActionVariables.alertId}}}:{{${AlertProvidedActionVariables.alertInstanceId}}}`, + eventAction: 'trigger', + }); + }); + + test('pagerduty defaults for resolved action group', async () => { + expect(getDefaultsForActionParams('.pagerduty', ResolvedActionGroup.id)).toEqual({ + dedupKey: `{{${AlertProvidedActionVariables.alertId}}}:{{${AlertProvidedActionVariables.alertInstanceId}}}`, + eventAction: 'resolve', + }); + }); +}); diff --git a/x-pack/plugins/triggers_actions_ui/public/application/lib/get_defaults_for_action_params.ts b/x-pack/plugins/triggers_actions_ui/public/application/lib/get_defaults_for_action_params.ts new file mode 100644 index 000000000000..01a0f390783c --- /dev/null +++ b/x-pack/plugins/triggers_actions_ui/public/application/lib/get_defaults_for_action_params.ts @@ -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; + * you may not use this file except in compliance with the Elastic License. + */ + +import { ResolvedActionGroup } from '../../../../alerts/common'; +import { AlertProvidedActionVariables } from './action_variables'; + +export const getDefaultsForActionParams = ( + actionTypeId: string, + actionGroupId: string +): Record | undefined => { + switch (actionTypeId) { + case '.pagerduty': + const pagerDutyDefaults = { + dedupKey: `{{${AlertProvidedActionVariables.alertId}}}:{{${AlertProvidedActionVariables.alertInstanceId}}}`, + eventAction: 'trigger', + }; + if (actionGroupId === ResolvedActionGroup.id) { + pagerDutyDefaults.eventAction = 'resolve'; + } + return pagerDutyDefaults; + } +}; diff --git a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_type_form.tsx b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_type_form.tsx index bd40d35b15b2..87e3833512b7 100644 --- a/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_type_form.tsx +++ b/x-pack/plugins/triggers_actions_ui/public/application/sections/action_connector_form/action_type_form.tsx @@ -39,6 +39,7 @@ import { hasSaveActionsCapability } from '../../lib/capabilities'; import { ActionAccordionFormProps } from './action_form'; import { transformActionVariables } from '../../lib/action_variables'; import { resolvedActionGroupMessage } from '../../constants'; +import { getDefaultsForActionParams } from '../../lib/get_defaults_for_action_params'; export type ActionTypeFormProps = { actionItem: AlertAction; @@ -110,6 +111,12 @@ export const ActionTypeForm = ({ ? resolvedActionGroupMessage : defaultActionMessage; setAvailableDefaultActionMessage(res); + const paramsDefaults = getDefaultsForActionParams(actionItem.actionTypeId, actionItem.group); + if (paramsDefaults) { + for (const [key, paramValue] of Object.entries(paramsDefaults)) { + setActionParamsProperty(key, paramValue, index); + } + } // eslint-disable-next-line react-hooks/exhaustive-deps }, [actionItem.group]);