diff --git a/oas_docs/output/kibana.yaml b/oas_docs/output/kibana.yaml index 9945bce1322a3..f12014443bb0b 100644 --- a/oas_docs/output/kibana.yaml +++ b/oas_docs/output/kibana.yaml @@ -4521,724 +4521,6 @@ paths: summary: Get information about rules tags: - alerting - /api/alerts/alert/{alertId}: - delete: - deprecated: true - description: | - Deprecated in 7.13.0. Use the delete rule API instead. WARNING: After you delete an alert, you cannot recover it. - operationId: legaryDeleteAlert - parameters: - - $ref: '#/components/parameters/Alerting_kbn_xsrf' - - description: The identifier for the alert. - in: path - name: alertId - required: true - schema: - example: 41893910-6bca-11eb-9e0d-85d233e3ee35 - type: string - responses: - '204': - description: Indicates a successful call. - '401': - content: - application/json; Elastic-Api-Version=2023-10-31: - schema: - $ref: '#/components/schemas/Alerting_401_response' - description: Authorization information is missing or invalid. - summary: Delete an alert - tags: - - alerting - get: - deprecated: true - description: Deprecated in 7.13.0. Use the get rule API instead. - operationId: legacyGetAlert - parameters: - - description: The identifier for the alert. - in: path - name: alertId - required: true - schema: - example: 41893910-6bca-11eb-9e0d-85d233e3ee35 - type: string - responses: - '200': - content: - application/json; Elastic-Api-Version=2023-10-31: - schema: - $ref: '#/components/schemas/Alerting_alert_response_properties' - description: Indicates a successful call. - '401': - content: - application/json; Elastic-Api-Version=2023-10-31: - schema: - $ref: '#/components/schemas/Alerting_401_response' - description: Authorization information is missing or invalid. - summary: Get an alert by identifier - tags: - - alerting - post: - deprecated: true - description: Deprecated in 7.13.0. Use the create rule API instead. - operationId: legacyCreateAlert - parameters: - - $ref: '#/components/parameters/Alerting_kbn_xsrf' - - description: An UUID v1 or v4 identifier for the alert. If this parameter is omitted, the identifier is randomly generated. - in: path - name: alertId - required: true - schema: - example: 41893910-6bca-11eb-9e0d-85d233e3ee35 - type: string - requestBody: - content: - application/json; Elastic-Api-Version=2023-10-31: - schema: - title: Legacy create alert request properties - type: object - properties: - actions: - items: - type: object - properties: - actionTypeId: - description: The identifier for the action type. - type: string - group: - description: | - Grouping actions is recommended for escalations for different types of alert instances. If you don't need this functionality, set it to `default`. - type: string - id: - description: The ID of the action saved object. - type: string - params: - description: | - The map to the `params` that the action type will receive. `params` are handled as Mustache templates and passed a default set of context. - type: object - required: - - actionTypeId - - group - - id - - params - type: array - alertTypeId: - description: The ID of the alert type that you want to call when the alert is scheduled to run. - type: string - consumer: - description: The name of the application that owns the alert. This name has to match the Kibana feature name, as that dictates the required role-based access control privileges. - type: string - enabled: - description: Indicates if you want to run the alert on an interval basis after it is created. - type: boolean - name: - description: A name to reference and search. - type: string - notifyWhen: - description: The condition for throttling the notification. - enum: - - onActionGroupChange - - onActiveAlert - - onThrottleInterval - type: string - params: - description: The parameters to pass to the alert type executor `params` value. This will also validate against the alert type params validator, if defined. - type: object - schedule: - description: | - The schedule specifying when this alert should be run. A schedule is structured such that the key specifies the format you wish to use and its value specifies the schedule. - type: object - properties: - interval: - description: The interval format specifies the interval in seconds, minutes, hours or days at which the alert should run. - example: 10s - type: string - tags: - description: A list of keywords to reference and search. - items: - type: string - type: array - throttle: - description: | - How often this alert should fire the same actions. This will prevent the alert from sending out the same notification over and over. For example, if an alert with a schedule of 1 minute stays in a triggered state for 90 minutes, setting a throttle of `10m` or `1h` will prevent it from sending 90 notifications during this period. - type: string - required: - - alertTypeId - - consumer - - name - - notifyWhen - - params - - schedule - required: true - responses: - '200': - content: - application/json; Elastic-Api-Version=2023-10-31: - schema: - $ref: '#/components/schemas/Alerting_alert_response_properties' - description: Indicates a successful call. - '401': - content: - application/json; Elastic-Api-Version=2023-10-31: - schema: - $ref: '#/components/schemas/Alerting_401_response' - description: Authorization information is missing or invalid. - summary: Create an alert - tags: - - alerting - put: - deprecated: true - description: Deprecated in 7.13.0. Use the update rule API instead. - operationId: legacyUpdateAlert - parameters: - - $ref: '#/components/parameters/Alerting_kbn_xsrf' - - description: The identifier for the alert. - in: path - name: alertId - required: true - schema: - example: 41893910-6bca-11eb-9e0d-85d233e3ee35 - type: string - requestBody: - content: - application/json; Elastic-Api-Version=2023-10-31: - schema: - title: Legacy update alert request properties - type: object - properties: - actions: - items: - type: object - properties: - actionTypeId: - description: The identifier for the action type. - type: string - group: - description: | - Grouping actions is recommended for escalations for different types of alert instances. If you don't need this functionality, set it to `default`. - type: string - id: - description: The ID of the action saved object. - type: string - params: - description: | - The map to the `params` that the action type will receive. `params` are handled as Mustache templates and passed a default set of context. - type: object - required: - - actionTypeId - - group - - id - - params - type: array - name: - description: A name to reference and search. - type: string - notifyWhen: - description: The condition for throttling the notification. - enum: - - onActionGroupChange - - onActiveAlert - - onThrottleInterval - type: string - params: - description: The parameters to pass to the alert type executor `params` value. This will also validate against the alert type params validator, if defined. - type: object - schedule: - description: | - The schedule specifying when this alert should be run. A schedule is structured such that the key specifies the format you wish to use and its value specifies the schedule. - type: object - properties: - interval: - description: The interval format specifies the interval in seconds, minutes, hours or days at which the alert should run. - example: 1d - type: string - tags: - description: A list of keywords to reference and search. - items: - type: string - type: array - throttle: - description: | - How often this alert should fire the same actions. This will prevent the alert from sending out the same notification over and over. For example, if an alert with a schedule of 1 minute stays in a triggered state for 90 minutes, setting a throttle of `10m` or `1h` will prevent it from sending 90 notifications during this period. - type: string - required: - - name - - notifyWhen - - params - - schedule - required: true - responses: - '200': - content: - application/json; Elastic-Api-Version=2023-10-31: - schema: - $ref: '#/components/schemas/Alerting_alert_response_properties' - description: Indicates a successful call. - '401': - content: - application/json; Elastic-Api-Version=2023-10-31: - schema: - $ref: '#/components/schemas/Alerting_401_response' - description: Authorization information is missing or invalid. - summary: Update an alert - tags: - - alerting - /api/alerts/alert/{alertId}/_disable: - post: - deprecated: true - description: Deprecated in 7.13.0. Use the disable rule API instead. - operationId: legacyDisableAlert - parameters: - - $ref: '#/components/parameters/Alerting_kbn_xsrf' - - description: The identifier for the alert. - in: path - name: alertId - required: true - schema: - example: 41893910-6bca-11eb-9e0d-85d233e3ee35 - type: string - responses: - '204': - description: Indicates a successful call. - '401': - content: - application/json; Elastic-Api-Version=2023-10-31: - schema: - $ref: '#/components/schemas/Alerting_401_response' - description: Authorization information is missing or invalid. - summary: Disable an alert - tags: - - alerting - /api/alerts/alert/{alertId}/_enable: - post: - deprecated: true - description: Deprecated in 7.13.0. Use the enable rule API instead. - operationId: legacyEnableAlert - parameters: - - $ref: '#/components/parameters/Alerting_kbn_xsrf' - - description: The identifier for the alert. - in: path - name: alertId - required: true - schema: - example: 41893910-6bca-11eb-9e0d-85d233e3ee35 - type: string - responses: - '204': - description: Indicates a successful call. - '401': - content: - application/json; Elastic-Api-Version=2023-10-31: - schema: - $ref: '#/components/schemas/Alerting_401_response' - description: Authorization information is missing or invalid. - summary: Enable an alert - tags: - - alerting - /api/alerts/alert/{alertId}/_mute_all: - post: - deprecated: true - description: Deprecated in 7.13.0. Use the mute all alerts API instead. - operationId: legacyMuteAllAlertInstances - parameters: - - $ref: '#/components/parameters/Alerting_kbn_xsrf' - - description: The identifier for the alert. - in: path - name: alertId - required: true - schema: - example: 41893910-6bca-11eb-9e0d-85d233e3ee35 - type: string - responses: - '204': - description: Indicates a successful call. - '401': - content: - application/json; Elastic-Api-Version=2023-10-31: - schema: - $ref: '#/components/schemas/Alerting_401_response' - description: Authorization information is missing or invalid. - summary: Mute all alert instances - tags: - - alerting - /api/alerts/alert/{alertId}/_unmute_all: - post: - deprecated: true - description: Deprecated in 7.13.0. Use the unmute all alerts API instead. - operationId: legacyUnmuteAllAlertInstances - parameters: - - $ref: '#/components/parameters/Alerting_kbn_xsrf' - - description: The identifier for the alert. - in: path - name: alertId - required: true - schema: - example: 41893910-6bca-11eb-9e0d-85d233e3ee35 - type: string - responses: - '204': - description: Indicates a successful call. - '401': - content: - application/json; Elastic-Api-Version=2023-10-31: - schema: - $ref: '#/components/schemas/Alerting_401_response' - description: Authorization information is missing or invalid. - summary: Unmute all alert instances - tags: - - alerting - /api/alerts/alert/{alertId}/alert_instance/{alertInstanceId}/_mute: - post: - deprecated: true - description: Deprecated in 7.13.0. Use the mute alert API instead. - operationId: legacyMuteAlertInstance - parameters: - - $ref: '#/components/parameters/Alerting_kbn_xsrf' - - description: An identifier for the alert. - in: path - name: alertId - required: true - schema: - example: 41893910-6bca-11eb-9e0d-85d233e3ee35 - type: string - - description: An identifier for the alert instance. - in: path - name: alertInstanceId - required: true - schema: - example: dceeb5d0-6b41-11eb-802b-85b0c1bc8ba2 - type: string - responses: - '204': - description: Indicates a successful call. - '401': - content: - application/json; Elastic-Api-Version=2023-10-31: - schema: - $ref: '#/components/schemas/Alerting_401_response' - description: Authorization information is missing or invalid. - summary: Mute an alert instance - tags: - - alerting - /api/alerts/alert/{alertId}/alert_instance/{alertInstanceId}/_unmute: - post: - deprecated: true - description: Deprecated in 7.13.0. Use the unmute alert API instead. - operationId: legacyUnmuteAlertInstance - parameters: - - $ref: '#/components/parameters/Alerting_kbn_xsrf' - - description: An identifier for the alert. - in: path - name: alertId - required: true - schema: - example: 41893910-6bca-11eb-9e0d-85d233e3ee35 - type: string - - description: An identifier for the alert instance. - in: path - name: alertInstanceId - required: true - schema: - example: dceeb5d0-6b41-11eb-802b-85b0c1bc8ba2 - type: string - responses: - '204': - description: Indicates a successful call. - '401': - content: - application/json; Elastic-Api-Version=2023-10-31: - schema: - $ref: '#/components/schemas/Alerting_401_response' - description: Authorization information is missing or invalid. - summary: Unmute an alert instance - tags: - - alerting - /api/alerts/alerts/_find: - get: - deprecated: true - description: | - Deprecated in 7.13.0. Use the find rules API instead. NOTE: Alert `params` are stored as a flattened field type and analyzed as keywords. As alerts change in Kibana, the results on each page of the response also change. Use the find API for traditional paginated results, but avoid using it to export large amounts of data. - operationId: legacyFindAlerts - parameters: - - description: The default operator to use for the `simple_query_string`. - example: OR - in: query - name: default_search_operator - schema: - default: OR - type: string - - description: The fields to return in the `attributes` key of the response. - in: query - name: fields - schema: - items: - type: string - type: array - - description: | - A KQL string that you filter with an attribute from your saved object. It should look like `savedObjectType.attributes.title: "myTitle"`. However, if you used a direct attribute of a saved object, such as `updatedAt`, you must define your filter, for example, `savedObjectType.updatedAt > 2018-12-22`. - in: query - name: filter - schema: - type: string - - description: Filters the rules that have a relation with the reference objects with a specific type and identifier. - in: query - name: has_reference - schema: - type: object - properties: - id: - type: string - type: - type: string - - description: The page number to return. - example: 1 - in: query - name: page - schema: - default: 1 - type: integer - - description: The number of alerts to return per page. - example: 20 - in: query - name: per_page - schema: - default: 20 - type: integer - - description: An Elasticsearch `simple_query_string` query that filters the alerts in the response. - in: query - name: search - schema: - type: string - - description: The fields to perform the `simple_query_string` parsed query against. - in: query - name: search_fields - schema: - oneOf: - - type: string - - items: - type: string - type: array - - description: | - Determines which field is used to sort the results. The field must exist in the `attributes` key of the response. - in: query - name: sort_field - schema: - type: string - - description: Determines the sort order. - example: asc - in: query - name: sort_order - schema: - default: desc - enum: - - asc - - desc - type: string - responses: - '200': - content: - application/json; Elastic-Api-Version=2023-10-31: - schema: - type: object - properties: - data: - items: - $ref: '#/components/schemas/Alerting_alert_response_properties' - type: array - page: - type: integer - perPage: - type: integer - total: - type: integer - description: Indicates a successful call. - '401': - content: - application/json; Elastic-Api-Version=2023-10-31: - schema: - $ref: '#/components/schemas/Alerting_401_response' - description: Authorization information is missing or invalid. - summary: Get a paginated set of alerts - tags: - - alerting - /api/alerts/alerts/_health: - get: - deprecated: true - description: Deprecated in 7.13.0. Use the get alerting framework health API instead. - operationId: legacyGetAlertingHealth - responses: - '200': - content: - application/json; Elastic-Api-Version=2023-10-31: - schema: - type: object - properties: - alertingFrameworkHealth: - description: | - Three substates identify the health of the alerting framework: `decryptionHealth`, `executionHealth`, and `readHealth`. - type: object - properties: - decryptionHealth: - description: The timestamp and status of the alert decryption. - type: object - properties: - status: - enum: - - error - - ok - - warn - example: ok - type: string - timestamp: - example: '2023-01-13T01:28:00.280Z' - format: date-time - type: string - executionHealth: - description: The timestamp and status of the alert execution. - type: object - properties: - status: - enum: - - error - - ok - - warn - example: ok - type: string - timestamp: - example: '2023-01-13T01:28:00.280Z' - format: date-time - type: string - readHealth: - description: The timestamp and status of the alert reading events. - type: object - properties: - status: - enum: - - error - - ok - - warn - example: ok - type: string - timestamp: - example: '2023-01-13T01:28:00.280Z' - format: date-time - type: string - hasPermanentEncryptionKey: - description: If `false`, the encrypted saved object plugin does not have a permanent encryption key. - example: true - type: boolean - isSufficientlySecure: - description: If `false`, security is enabled but TLS is not. - example: true - type: boolean - description: Indicates a successful call. - '401': - content: - application/json; Elastic-Api-Version=2023-10-31: - schema: - $ref: '#/components/schemas/Alerting_401_response' - description: Authorization information is missing or invalid. - summary: Get the alerting framework health - tags: - - alerting - /api/alerts/alerts/list_alert_types: - get: - deprecated: true - description: Deprecated in 7.13.0. Use the get rule types API instead. - operationId: legacyGetAlertTypes - responses: - '200': - content: - application/json; Elastic-Api-Version=2023-10-31: - schema: - items: - type: object - properties: - actionGroups: - description: | - An explicit list of groups for which the alert type can schedule actions, each with the action group's unique ID and human readable name. Alert actions validation uses this configuration to ensure that groups are valid. - items: - type: object - properties: - id: - type: string - name: - type: string - type: array - actionVariables: - description: | - A list of action variables that the alert type makes available via context and state in action parameter templates, and a short human readable description. The Alert UI will use this information to prompt users for these variables in action parameter editors. - type: object - properties: - context: - items: - type: object - properties: - description: - type: string - name: - type: string - type: array - params: - items: - type: object - properties: - description: - type: string - name: - type: string - type: array - state: - items: - type: object - properties: - description: - type: string - name: - type: string - type: array - authorizedConsumers: - description: The list of the plugins IDs that have access to the alert type. - type: object - defaultActionGroupId: - description: The default identifier for the alert type group. - type: string - enabledInLicense: - description: Indicates whether the rule type is enabled based on the subscription. - type: boolean - id: - description: The unique identifier for the alert type. - type: string - isExportable: - description: Indicates whether the alert type is exportable in Saved Objects Management UI. - type: boolean - minimumLicenseRequired: - description: The subscriptions required to use the alert type. - type: string - name: - description: The descriptive name of the alert type. - type: string - producer: - description: An identifier for the application that produces this alert type. - type: string - recoveryActionGroup: - description: | - An action group to use when an alert instance goes from an active state to an inactive one. If it is not specified, the default recovered action group is used. - type: object - properties: - id: - type: string - name: - type: string - type: array - description: Indicates a successful call. - '401': - content: - application/json; Elastic-Api-Version=2023-10-31: - schema: - $ref: '#/components/schemas/Alerting_401_response' - description: Authorization information is missing or invalid. - summary: Get the alert types - tags: - - alerting /api/apm/agent_keys: post: description: Create a new agent key for APM. @@ -44044,13 +43326,6 @@ components: disabledFeatures: [] imageUrl: '' parameters: - Alerting_kbn_xsrf: - description: Cross-site request forgery protection - in: header - name: kbn-xsrf - required: true - schema: - type: string APM_UI_elastic_api_version: description: The version of the API to use in: header @@ -44404,89 +43679,6 @@ components: type: integer title: Unsuccessful rule API response type: object - Alerting_alert_response_properties: - title: Legacy alert response properties - type: object - properties: - actions: - items: - type: object - type: array - alertTypeId: - example: .index-threshold - type: string - apiKeyOwner: - example: elastic - nullable: true - type: string - createdAt: - description: The date and time that the alert was created. - example: '2022-12-05T23:36:58.284Z' - format: date-time - type: string - createdBy: - description: The identifier for the user that created the alert. - example: elastic - type: string - enabled: - description: Indicates whether the alert is currently enabled. - example: true - type: boolean - executionStatus: - type: object - properties: - lastExecutionDate: - example: '2022-12-06T00:13:43.890Z' - format: date-time - type: string - status: - example: ok - type: string - id: - description: The identifier for the alert. - example: b530fed0-74f5-11ed-9801-35303b735aef - type: string - muteAll: - example: false - type: boolean - mutedInstanceIds: - items: - type: string - nullable: true - type: array - name: - description: The name of the alert. - example: my alert - type: string - notifyWhen: - example: onActionGroupChange - type: string - params: - additionalProperties: true - type: object - schedule: - type: object - properties: - interval: - type: string - scheduledTaskId: - example: b530fed0-74f5-11ed-9801-35303b735aef - type: string - tags: - items: - type: string - type: array - throttle: - nullable: true - type: string - updatedAt: - example: '2022-12-05T23:36:58.284Z' - type: string - updatedBy: - description: The identifier for the user that updated this alert most recently. - example: elastic - nullable: true - type: string Alerting_fieldmap_properties: title: Field map objects in the get rule types response type: object diff --git a/src/plugins/discover/public/application/view_alert/view_alert_utils.tsx b/src/plugins/discover/public/application/view_alert/view_alert_utils.tsx index a059b6f507259..ed56ee5f07c9c 100644 --- a/src/plugins/discover/public/application/view_alert/view_alert_utils.tsx +++ b/src/plugins/discover/public/application/view_alert/view_alert_utils.tsx @@ -33,7 +33,7 @@ export interface QueryParams { to: string | null; } -const LEGACY_BASE_ALERT_API_PATH = '/api/alerts'; +const BASE_ALERTING_API_PATH = '/api/alerting'; const buildTimeRangeFilter = ( dataView: DataView, @@ -77,7 +77,7 @@ export const getAlertUtils = ( const fetchAlert = async (id: string) => { try { return await core.http.get>( - `${LEGACY_BASE_ALERT_API_PATH}/alert/${id}` + `${BASE_ALERTING_API_PATH}/rule/${id}` ); } catch (error) { const errorTitle = i18n.translate('discover.viewAlert.alertRuleFetchErrorTitle', { diff --git a/x-pack/plugins/alerting/docs/openapi/bundled.json b/x-pack/plugins/alerting/docs/openapi/bundled.json index 7d6d85c229202..92e261620bde1 100644 --- a/x-pack/plugins/alerting/docs/openapi/bundled.json +++ b/x-pack/plugins/alerting/docs/openapi/bundled.json @@ -497,1059 +497,6 @@ } } } - }, - "/api/alerts/alert/{alertId}": { - "delete": { - "summary": "Delete an alert", - "operationId": "legaryDeleteAlert", - "deprecated": true, - "description": "Deprecated in 7.13.0. Use the delete rule API instead. WARNING: After you delete an alert, you cannot recover it.\n", - "tags": [ - "alerting" - ], - "parameters": [ - { - "$ref": "#/components/parameters/kbn_xsrf" - }, - { - "in": "path", - "name": "alertId", - "description": "The identifier for the alert.", - "required": true, - "schema": { - "type": "string", - "example": "41893910-6bca-11eb-9e0d-85d233e3ee35" - } - } - ], - "responses": { - "204": { - "description": "Indicates a successful call." - }, - "401": { - "description": "Authorization information is missing or invalid.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/401_response" - } - } - } - } - } - }, - "get": { - "summary": "Get an alert by identifier", - "operationId": "legacyGetAlert", - "deprecated": true, - "description": "Deprecated in 7.13.0. Use the get rule API instead.", - "tags": [ - "alerting" - ], - "parameters": [ - { - "in": "path", - "name": "alertId", - "description": "The identifier for the alert.", - "required": true, - "schema": { - "type": "string", - "example": "41893910-6bca-11eb-9e0d-85d233e3ee35" - } - } - ], - "responses": { - "200": { - "description": "Indicates a successful call.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/alert_response_properties" - } - } - } - }, - "401": { - "description": "Authorization information is missing or invalid.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/401_response" - } - } - } - } - } - }, - "post": { - "summary": "Create an alert", - "operationId": "legacyCreateAlert", - "deprecated": true, - "description": "Deprecated in 7.13.0. Use the create rule API instead.", - "tags": [ - "alerting" - ], - "parameters": [ - { - "$ref": "#/components/parameters/kbn_xsrf" - }, - { - "in": "path", - "name": "alertId", - "description": "An UUID v1 or v4 identifier for the alert. If this parameter is omitted, the identifier is randomly generated.", - "required": true, - "schema": { - "type": "string", - "example": "41893910-6bca-11eb-9e0d-85d233e3ee35" - } - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "title": "Legacy create alert request properties", - "type": "object", - "required": [ - "alertTypeId", - "consumer", - "name", - "notifyWhen", - "params", - "schedule" - ], - "properties": { - "actions": { - "type": "array", - "items": { - "type": "object", - "required": [ - "actionTypeId", - "group", - "id", - "params" - ], - "properties": { - "actionTypeId": { - "type": "string", - "description": "The identifier for the action type." - }, - "group": { - "type": "string", - "description": "Grouping actions is recommended for escalations for different types of alert instances. If you don't need this functionality, set it to `default`.\n" - }, - "id": { - "type": "string", - "description": "The ID of the action saved object." - }, - "params": { - "type": "object", - "description": "The map to the `params` that the action type will receive. `params` are handled as Mustache templates and passed a default set of context.\n" - } - } - } - }, - "alertTypeId": { - "type": "string", - "description": "The ID of the alert type that you want to call when the alert is scheduled to run." - }, - "consumer": { - "type": "string", - "description": "The name of the application that owns the alert. This name has to match the Kibana feature name, as that dictates the required role-based access control privileges." - }, - "enabled": { - "type": "boolean", - "description": "Indicates if you want to run the alert on an interval basis after it is created." - }, - "name": { - "type": "string", - "description": "A name to reference and search." - }, - "notifyWhen": { - "type": "string", - "description": "The condition for throttling the notification.", - "enum": [ - "onActionGroupChange", - "onActiveAlert", - "onThrottleInterval" - ] - }, - "params": { - "type": "object", - "description": "The parameters to pass to the alert type executor `params` value. This will also validate against the alert type params validator, if defined." - }, - "schedule": { - "type": "object", - "description": "The schedule specifying when this alert should be run. A schedule is structured such that the key specifies the format you wish to use and its value specifies the schedule.\n", - "properties": { - "interval": { - "type": "string", - "description": "The interval format specifies the interval in seconds, minutes, hours or days at which the alert should run.", - "example": "10s" - } - } - }, - "tags": { - "type": "array", - "items": { - "type": "string" - }, - "description": "A list of keywords to reference and search." - }, - "throttle": { - "type": "string", - "description": "How often this alert should fire the same actions. This will prevent the alert from sending out the same notification over and over. For example, if an alert with a schedule of 1 minute stays in a triggered state for 90 minutes, setting a throttle of `10m` or `1h` will prevent it from sending 90 notifications during this period.\n" - } - } - } - } - } - }, - "responses": { - "200": { - "description": "Indicates a successful call.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/alert_response_properties" - } - } - } - }, - "401": { - "description": "Authorization information is missing or invalid.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/401_response" - } - } - } - } - } - }, - "put": { - "summary": "Update an alert", - "operationId": "legacyUpdateAlert", - "deprecated": true, - "description": "Deprecated in 7.13.0. Use the update rule API instead.", - "tags": [ - "alerting" - ], - "parameters": [ - { - "$ref": "#/components/parameters/kbn_xsrf" - }, - { - "in": "path", - "name": "alertId", - "description": "The identifier for the alert.", - "required": true, - "schema": { - "type": "string", - "example": "41893910-6bca-11eb-9e0d-85d233e3ee35" - } - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "title": "Legacy update alert request properties", - "type": "object", - "required": [ - "name", - "notifyWhen", - "params", - "schedule" - ], - "properties": { - "actions": { - "type": "array", - "items": { - "type": "object", - "required": [ - "actionTypeId", - "group", - "id", - "params" - ], - "properties": { - "actionTypeId": { - "type": "string", - "description": "The identifier for the action type." - }, - "group": { - "type": "string", - "description": "Grouping actions is recommended for escalations for different types of alert instances. If you don't need this functionality, set it to `default`.\n" - }, - "id": { - "type": "string", - "description": "The ID of the action saved object." - }, - "params": { - "type": "object", - "description": "The map to the `params` that the action type will receive. `params` are handled as Mustache templates and passed a default set of context.\n" - } - } - } - }, - "name": { - "type": "string", - "description": "A name to reference and search." - }, - "notifyWhen": { - "type": "string", - "description": "The condition for throttling the notification.", - "enum": [ - "onActionGroupChange", - "onActiveAlert", - "onThrottleInterval" - ] - }, - "params": { - "type": "object", - "description": "The parameters to pass to the alert type executor `params` value. This will also validate against the alert type params validator, if defined." - }, - "schedule": { - "type": "object", - "description": "The schedule specifying when this alert should be run. A schedule is structured such that the key specifies the format you wish to use and its value specifies the schedule.\n", - "properties": { - "interval": { - "type": "string", - "description": "The interval format specifies the interval in seconds, minutes, hours or days at which the alert should run.", - "example": "1d" - } - } - }, - "tags": { - "type": "array", - "items": { - "type": "string" - }, - "description": "A list of keywords to reference and search." - }, - "throttle": { - "type": "string", - "description": "How often this alert should fire the same actions. This will prevent the alert from sending out the same notification over and over. For example, if an alert with a schedule of 1 minute stays in a triggered state for 90 minutes, setting a throttle of `10m` or `1h` will prevent it from sending 90 notifications during this period.\n" - } - } - } - } - } - }, - "responses": { - "200": { - "description": "Indicates a successful call.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/alert_response_properties" - } - } - } - }, - "401": { - "description": "Authorization information is missing or invalid.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/401_response" - } - } - } - } - } - } - }, - "/api/alerts/alert/{alertId}/_disable": { - "post": { - "summary": "Disable an alert", - "operationId": "legacyDisableAlert", - "deprecated": true, - "description": "Deprecated in 7.13.0. Use the disable rule API instead.", - "tags": [ - "alerting" - ], - "parameters": [ - { - "$ref": "#/components/parameters/kbn_xsrf" - }, - { - "in": "path", - "name": "alertId", - "description": "The identifier for the alert.", - "required": true, - "schema": { - "type": "string", - "example": "41893910-6bca-11eb-9e0d-85d233e3ee35" - } - } - ], - "responses": { - "204": { - "description": "Indicates a successful call." - }, - "401": { - "description": "Authorization information is missing or invalid.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/401_response" - } - } - } - } - } - } - }, - "/api/alerts/alert/{alertId}/_enable": { - "post": { - "summary": "Enable an alert", - "operationId": "legacyEnableAlert", - "deprecated": true, - "description": "Deprecated in 7.13.0. Use the enable rule API instead.", - "tags": [ - "alerting" - ], - "parameters": [ - { - "$ref": "#/components/parameters/kbn_xsrf" - }, - { - "in": "path", - "name": "alertId", - "description": "The identifier for the alert.", - "required": true, - "schema": { - "type": "string", - "example": "41893910-6bca-11eb-9e0d-85d233e3ee35" - } - } - ], - "responses": { - "204": { - "description": "Indicates a successful call." - }, - "401": { - "description": "Authorization information is missing or invalid.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/401_response" - } - } - } - } - } - } - }, - "/api/alerts/alert/{alertId}/_mute_all": { - "post": { - "summary": "Mute all alert instances", - "operationId": "legacyMuteAllAlertInstances", - "deprecated": true, - "description": "Deprecated in 7.13.0. Use the mute all alerts API instead.", - "tags": [ - "alerting" - ], - "parameters": [ - { - "$ref": "#/components/parameters/kbn_xsrf" - }, - { - "in": "path", - "name": "alertId", - "description": "The identifier for the alert.", - "required": true, - "schema": { - "type": "string", - "example": "41893910-6bca-11eb-9e0d-85d233e3ee35" - } - } - ], - "responses": { - "204": { - "description": "Indicates a successful call." - }, - "401": { - "description": "Authorization information is missing or invalid.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/401_response" - } - } - } - } - } - } - }, - "/api/alerts/alert/{alertId}/_unmute_all": { - "post": { - "summary": "Unmute all alert instances", - "operationId": "legacyUnmuteAllAlertInstances", - "deprecated": true, - "description": "Deprecated in 7.13.0. Use the unmute all alerts API instead.", - "tags": [ - "alerting" - ], - "parameters": [ - { - "$ref": "#/components/parameters/kbn_xsrf" - }, - { - "in": "path", - "name": "alertId", - "description": "The identifier for the alert.", - "required": true, - "schema": { - "type": "string", - "example": "41893910-6bca-11eb-9e0d-85d233e3ee35" - } - } - ], - "responses": { - "204": { - "description": "Indicates a successful call." - }, - "401": { - "description": "Authorization information is missing or invalid.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/401_response" - } - } - } - } - } - } - }, - "/api/alerts/alerts/_find": { - "get": { - "summary": "Get a paginated set of alerts", - "operationId": "legacyFindAlerts", - "deprecated": true, - "description": "Deprecated in 7.13.0. Use the find rules API instead. NOTE: Alert `params` are stored as a flattened field type and analyzed as keywords. As alerts change in Kibana, the results on each page of the response also change. Use the find API for traditional paginated results, but avoid using it to export large amounts of data.\n", - "tags": [ - "alerting" - ], - "parameters": [ - { - "name": "default_search_operator", - "in": "query", - "description": "The default operator to use for the `simple_query_string`.", - "schema": { - "type": "string", - "default": "OR" - }, - "example": "OR" - }, - { - "name": "fields", - "in": "query", - "description": "The fields to return in the `attributes` key of the response.", - "schema": { - "type": "array", - "items": { - "type": "string" - } - } - }, - { - "name": "filter", - "in": "query", - "description": "A KQL string that you filter with an attribute from your saved object. It should look like `savedObjectType.attributes.title: \"myTitle\"`. However, if you used a direct attribute of a saved object, such as `updatedAt`, you must define your filter, for example, `savedObjectType.updatedAt > 2018-12-22`.\n", - "schema": { - "type": "string" - } - }, - { - "name": "has_reference", - "in": "query", - "description": "Filters the rules that have a relation with the reference objects with a specific type and identifier.", - "schema": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "type": { - "type": "string" - } - } - } - }, - { - "name": "page", - "in": "query", - "description": "The page number to return.", - "schema": { - "type": "integer", - "default": 1 - }, - "example": 1 - }, - { - "name": "per_page", - "in": "query", - "description": "The number of alerts to return per page.", - "schema": { - "type": "integer", - "default": 20 - }, - "example": 20 - }, - { - "name": "search", - "in": "query", - "description": "An Elasticsearch `simple_query_string` query that filters the alerts in the response.", - "schema": { - "type": "string" - } - }, - { - "name": "search_fields", - "in": "query", - "description": "The fields to perform the `simple_query_string` parsed query against.", - "schema": { - "oneOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ] - } - }, - { - "name": "sort_field", - "in": "query", - "description": "Determines which field is used to sort the results. The field must exist in the `attributes` key of the response.\n", - "schema": { - "type": "string" - } - }, - { - "name": "sort_order", - "in": "query", - "description": "Determines the sort order.", - "schema": { - "type": "string", - "enum": [ - "asc", - "desc" - ], - "default": "desc" - }, - "example": "asc" - } - ], - "responses": { - "200": { - "description": "Indicates a successful call.", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "data": { - "type": "array", - "items": { - "$ref": "#/components/schemas/alert_response_properties" - } - }, - "page": { - "type": "integer" - }, - "perPage": { - "type": "integer" - }, - "total": { - "type": "integer" - } - } - } - } - } - }, - "401": { - "description": "Authorization information is missing or invalid.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/401_response" - } - } - } - } - } - } - }, - "/api/alerts/alerts/_health": { - "get": { - "summary": "Get the alerting framework health", - "operationId": "legacyGetAlertingHealth", - "deprecated": true, - "description": "Deprecated in 7.13.0. Use the get alerting framework health API instead.", - "tags": [ - "alerting" - ], - "responses": { - "200": { - "description": "Indicates a successful call.", - "content": { - "application/json": { - "schema": { - "type": "object", - "properties": { - "alertingFrameworkHealth": { - "type": "object", - "description": "Three substates identify the health of the alerting framework: `decryptionHealth`, `executionHealth`, and `readHealth`.\n", - "properties": { - "decryptionHealth": { - "type": "object", - "description": "The timestamp and status of the alert decryption.", - "properties": { - "status": { - "type": "string", - "example": "ok", - "enum": [ - "error", - "ok", - "warn" - ] - }, - "timestamp": { - "type": "string", - "format": "date-time", - "example": "2023-01-13T01:28:00.280Z" - } - } - }, - "executionHealth": { - "type": "object", - "description": "The timestamp and status of the alert execution.", - "properties": { - "status": { - "type": "string", - "example": "ok", - "enum": [ - "error", - "ok", - "warn" - ] - }, - "timestamp": { - "type": "string", - "format": "date-time", - "example": "2023-01-13T01:28:00.280Z" - } - } - }, - "readHealth": { - "type": "object", - "description": "The timestamp and status of the alert reading events.", - "properties": { - "status": { - "type": "string", - "example": "ok", - "enum": [ - "error", - "ok", - "warn" - ] - }, - "timestamp": { - "type": "string", - "format": "date-time", - "example": "2023-01-13T01:28:00.280Z" - } - } - } - } - }, - "hasPermanentEncryptionKey": { - "type": "boolean", - "description": "If `false`, the encrypted saved object plugin does not have a permanent encryption key.", - "example": true - }, - "isSufficientlySecure": { - "type": "boolean", - "description": "If `false`, security is enabled but TLS is not.", - "example": true - } - } - } - } - } - }, - "401": { - "description": "Authorization information is missing or invalid.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/401_response" - } - } - } - } - } - } - }, - "/api/alerts/alerts/list_alert_types": { - "get": { - "summary": "Get the alert types", - "operationId": "legacyGetAlertTypes", - "deprecated": true, - "description": "Deprecated in 7.13.0. Use the get rule types API instead.", - "tags": [ - "alerting" - ], - "responses": { - "200": { - "description": "Indicates a successful call.", - "content": { - "application/json": { - "schema": { - "type": "array", - "items": { - "type": "object", - "properties": { - "actionGroups": { - "description": "An explicit list of groups for which the alert type can schedule actions, each with the action group's unique ID and human readable name. Alert actions validation uses this configuration to ensure that groups are valid.\n", - "type": "array", - "items": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "name": { - "type": "string" - } - } - } - }, - "actionVariables": { - "description": "A list of action variables that the alert type makes available via context and state in action parameter templates, and a short human readable description. The Alert UI will use this information to prompt users for these variables in action parameter editors.\n", - "type": "object", - "properties": { - "context": { - "type": "array", - "items": { - "type": "object", - "properties": { - "name": { - "type": "string" - }, - "description": { - "type": "string" - } - } - } - }, - "params": { - "type": "array", - "items": { - "type": "object", - "properties": { - "description": { - "type": "string" - }, - "name": { - "type": "string" - } - } - } - }, - "state": { - "type": "array", - "items": { - "type": "object", - "properties": { - "description": { - "type": "string" - }, - "name": { - "type": "string" - } - } - } - } - } - }, - "authorizedConsumers": { - "description": "The list of the plugins IDs that have access to the alert type.", - "type": "object" - }, - "defaultActionGroupId": { - "description": "The default identifier for the alert type group.", - "type": "string" - }, - "enabledInLicense": { - "description": "Indicates whether the rule type is enabled based on the subscription.", - "type": "boolean" - }, - "id": { - "description": "The unique identifier for the alert type.", - "type": "string" - }, - "isExportable": { - "description": "Indicates whether the alert type is exportable in Saved Objects Management UI.", - "type": "boolean" - }, - "minimumLicenseRequired": { - "description": "The subscriptions required to use the alert type.", - "type": "string" - }, - "name": { - "description": "The descriptive name of the alert type.", - "type": "string" - }, - "producer": { - "description": "An identifier for the application that produces this alert type.", - "type": "string" - }, - "recoveryActionGroup": { - "description": "An action group to use when an alert instance goes from an active state to an inactive one. If it is not specified, the default recovered action group is used.\n", - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "name": { - "type": "string" - } - } - } - } - } - } - } - } - }, - "401": { - "description": "Authorization information is missing or invalid.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/401_response" - } - } - } - } - } - } - }, - "/api/alerts/alert/{alertId}/alert_instance/{alertInstanceId}/_mute": { - "post": { - "summary": "Mute an alert instance", - "operationId": "legacyMuteAlertInstance", - "deprecated": true, - "description": "Deprecated in 7.13.0. Use the mute alert API instead.", - "tags": [ - "alerting" - ], - "parameters": [ - { - "$ref": "#/components/parameters/kbn_xsrf" - }, - { - "in": "path", - "name": "alertId", - "description": "An identifier for the alert.", - "required": true, - "schema": { - "type": "string", - "example": "41893910-6bca-11eb-9e0d-85d233e3ee35" - } - }, - { - "in": "path", - "name": "alertInstanceId", - "description": "An identifier for the alert instance.", - "required": true, - "schema": { - "type": "string", - "example": "dceeb5d0-6b41-11eb-802b-85b0c1bc8ba2" - } - } - ], - "responses": { - "204": { - "description": "Indicates a successful call." - }, - "401": { - "description": "Authorization information is missing or invalid.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/401_response" - } - } - } - } - } - } - }, - "/api/alerts/alert/{alertId}/alert_instance/{alertInstanceId}/_unmute": { - "post": { - "summary": "Unmute an alert instance", - "operationId": "legacyUnmuteAlertInstance", - "deprecated": true, - "description": "Deprecated in 7.13.0. Use the unmute alert API instead.", - "tags": [ - "alerting" - ], - "parameters": [ - { - "$ref": "#/components/parameters/kbn_xsrf" - }, - { - "in": "path", - "name": "alertId", - "description": "An identifier for the alert.", - "required": true, - "schema": { - "type": "string", - "example": "41893910-6bca-11eb-9e0d-85d233e3ee35" - } - }, - { - "in": "path", - "name": "alertInstanceId", - "description": "An identifier for the alert instance.", - "required": true, - "schema": { - "type": "string", - "example": "dceeb5d0-6b41-11eb-802b-85b0c1bc8ba2" - } - } - ], - "responses": { - "204": { - "description": "Indicates a successful call." - }, - "401": { - "description": "Authorization information is missing or invalid.", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/401_response" - } - } - } - } - } - } } }, "components": { @@ -1978,129 +925,6 @@ "example": "scaled_float" } } - }, - "alert_response_properties": { - "title": "Legacy alert response properties", - "type": "object", - "properties": { - "actions": { - "type": "array", - "items": { - "type": "object" - } - }, - "alertTypeId": { - "type": "string", - "example": ".index-threshold" - }, - "apiKeyOwner": { - "type": "string", - "nullable": true, - "example": "elastic" - }, - "createdAt": { - "type": "string", - "description": "The date and time that the alert was created.", - "format": "date-time", - "example": "2022-12-05T23:36:58.284Z" - }, - "createdBy": { - "type": "string", - "description": "The identifier for the user that created the alert.", - "example": "elastic" - }, - "enabled": { - "type": "boolean", - "description": "Indicates whether the alert is currently enabled.", - "example": true - }, - "executionStatus": { - "type": "object", - "properties": { - "lastExecutionDate": { - "type": "string", - "format": "date-time", - "example": "2022-12-06T00:13:43.890Z" - }, - "status": { - "type": "string", - "example": "ok" - } - } - }, - "id": { - "type": "string", - "description": "The identifier for the alert.", - "example": "b530fed0-74f5-11ed-9801-35303b735aef" - }, - "muteAll": { - "type": "boolean", - "example": false - }, - "mutedInstanceIds": { - "type": "array", - "nullable": true, - "items": { - "type": "string" - } - }, - "name": { - "type": "string", - "description": "The name of the alert.", - "example": "my alert" - }, - "notifyWhen": { - "type": "string", - "example": "onActionGroupChange" - }, - "params": { - "type": "object", - "additionalProperties": true - }, - "schedule": { - "type": "object", - "properties": { - "interval": { - "type": "string" - } - } - }, - "scheduledTaskId": { - "type": "string", - "example": "b530fed0-74f5-11ed-9801-35303b735aef" - }, - "tags": { - "type": "array", - "items": { - "type": "string" - } - }, - "throttle": { - "type": "string", - "nullable": true - }, - "updatedAt": { - "type": "string", - "example": "2022-12-05T23:36:58.284Z" - }, - "updatedBy": { - "type": "string", - "description": "The identifier for the user that updated this alert most recently.", - "nullable": true, - "example": "elastic" - } - } - } - }, - "parameters": { - "kbn_xsrf": { - "schema": { - "type": "string" - }, - "in": "header", - "name": "kbn-xsrf", - "description": "Cross-site request forgery protection", - "required": true } } } diff --git a/x-pack/plugins/alerting/docs/openapi/bundled.yaml b/x-pack/plugins/alerting/docs/openapi/bundled.yaml index 87601c463e50e..967d08eadf5fa 100644 --- a/x-pack/plugins/alerting/docs/openapi/bundled.yaml +++ b/x-pack/plugins/alerting/docs/openapi/bundled.yaml @@ -353,724 +353,6 @@ paths: application/json: schema: $ref: '#/components/schemas/401_response' - /api/alerts/alert/{alertId}: - delete: - summary: Delete an alert - operationId: legaryDeleteAlert - deprecated: true - description: | - Deprecated in 7.13.0. Use the delete rule API instead. WARNING: After you delete an alert, you cannot recover it. - tags: - - alerting - parameters: - - $ref: '#/components/parameters/kbn_xsrf' - - in: path - name: alertId - description: The identifier for the alert. - required: true - schema: - type: string - example: 41893910-6bca-11eb-9e0d-85d233e3ee35 - responses: - '204': - description: Indicates a successful call. - '401': - description: Authorization information is missing or invalid. - content: - application/json: - schema: - $ref: '#/components/schemas/401_response' - get: - summary: Get an alert by identifier - operationId: legacyGetAlert - deprecated: true - description: Deprecated in 7.13.0. Use the get rule API instead. - tags: - - alerting - parameters: - - in: path - name: alertId - description: The identifier for the alert. - required: true - schema: - type: string - example: 41893910-6bca-11eb-9e0d-85d233e3ee35 - responses: - '200': - description: Indicates a successful call. - content: - application/json: - schema: - $ref: '#/components/schemas/alert_response_properties' - '401': - description: Authorization information is missing or invalid. - content: - application/json: - schema: - $ref: '#/components/schemas/401_response' - post: - summary: Create an alert - operationId: legacyCreateAlert - deprecated: true - description: Deprecated in 7.13.0. Use the create rule API instead. - tags: - - alerting - parameters: - - $ref: '#/components/parameters/kbn_xsrf' - - in: path - name: alertId - description: An UUID v1 or v4 identifier for the alert. If this parameter is omitted, the identifier is randomly generated. - required: true - schema: - type: string - example: 41893910-6bca-11eb-9e0d-85d233e3ee35 - requestBody: - required: true - content: - application/json: - schema: - title: Legacy create alert request properties - type: object - required: - - alertTypeId - - consumer - - name - - notifyWhen - - params - - schedule - properties: - actions: - type: array - items: - type: object - required: - - actionTypeId - - group - - id - - params - properties: - actionTypeId: - type: string - description: The identifier for the action type. - group: - type: string - description: | - Grouping actions is recommended for escalations for different types of alert instances. If you don't need this functionality, set it to `default`. - id: - type: string - description: The ID of the action saved object. - params: - type: object - description: | - The map to the `params` that the action type will receive. `params` are handled as Mustache templates and passed a default set of context. - alertTypeId: - type: string - description: The ID of the alert type that you want to call when the alert is scheduled to run. - consumer: - type: string - description: The name of the application that owns the alert. This name has to match the Kibana feature name, as that dictates the required role-based access control privileges. - enabled: - type: boolean - description: Indicates if you want to run the alert on an interval basis after it is created. - name: - type: string - description: A name to reference and search. - notifyWhen: - type: string - description: The condition for throttling the notification. - enum: - - onActionGroupChange - - onActiveAlert - - onThrottleInterval - params: - type: object - description: The parameters to pass to the alert type executor `params` value. This will also validate against the alert type params validator, if defined. - schedule: - type: object - description: | - The schedule specifying when this alert should be run. A schedule is structured such that the key specifies the format you wish to use and its value specifies the schedule. - properties: - interval: - type: string - description: The interval format specifies the interval in seconds, minutes, hours or days at which the alert should run. - example: 10s - tags: - type: array - items: - type: string - description: A list of keywords to reference and search. - throttle: - type: string - description: | - How often this alert should fire the same actions. This will prevent the alert from sending out the same notification over and over. For example, if an alert with a schedule of 1 minute stays in a triggered state for 90 minutes, setting a throttle of `10m` or `1h` will prevent it from sending 90 notifications during this period. - responses: - '200': - description: Indicates a successful call. - content: - application/json: - schema: - $ref: '#/components/schemas/alert_response_properties' - '401': - description: Authorization information is missing or invalid. - content: - application/json: - schema: - $ref: '#/components/schemas/401_response' - put: - summary: Update an alert - operationId: legacyUpdateAlert - deprecated: true - description: Deprecated in 7.13.0. Use the update rule API instead. - tags: - - alerting - parameters: - - $ref: '#/components/parameters/kbn_xsrf' - - in: path - name: alertId - description: The identifier for the alert. - required: true - schema: - type: string - example: 41893910-6bca-11eb-9e0d-85d233e3ee35 - requestBody: - required: true - content: - application/json: - schema: - title: Legacy update alert request properties - type: object - required: - - name - - notifyWhen - - params - - schedule - properties: - actions: - type: array - items: - type: object - required: - - actionTypeId - - group - - id - - params - properties: - actionTypeId: - type: string - description: The identifier for the action type. - group: - type: string - description: | - Grouping actions is recommended for escalations for different types of alert instances. If you don't need this functionality, set it to `default`. - id: - type: string - description: The ID of the action saved object. - params: - type: object - description: | - The map to the `params` that the action type will receive. `params` are handled as Mustache templates and passed a default set of context. - name: - type: string - description: A name to reference and search. - notifyWhen: - type: string - description: The condition for throttling the notification. - enum: - - onActionGroupChange - - onActiveAlert - - onThrottleInterval - params: - type: object - description: The parameters to pass to the alert type executor `params` value. This will also validate against the alert type params validator, if defined. - schedule: - type: object - description: | - The schedule specifying when this alert should be run. A schedule is structured such that the key specifies the format you wish to use and its value specifies the schedule. - properties: - interval: - type: string - description: The interval format specifies the interval in seconds, minutes, hours or days at which the alert should run. - example: 1d - tags: - type: array - items: - type: string - description: A list of keywords to reference and search. - throttle: - type: string - description: | - How often this alert should fire the same actions. This will prevent the alert from sending out the same notification over and over. For example, if an alert with a schedule of 1 minute stays in a triggered state for 90 minutes, setting a throttle of `10m` or `1h` will prevent it from sending 90 notifications during this period. - responses: - '200': - description: Indicates a successful call. - content: - application/json: - schema: - $ref: '#/components/schemas/alert_response_properties' - '401': - description: Authorization information is missing or invalid. - content: - application/json: - schema: - $ref: '#/components/schemas/401_response' - /api/alerts/alert/{alertId}/_disable: - post: - summary: Disable an alert - operationId: legacyDisableAlert - deprecated: true - description: Deprecated in 7.13.0. Use the disable rule API instead. - tags: - - alerting - parameters: - - $ref: '#/components/parameters/kbn_xsrf' - - in: path - name: alertId - description: The identifier for the alert. - required: true - schema: - type: string - example: 41893910-6bca-11eb-9e0d-85d233e3ee35 - responses: - '204': - description: Indicates a successful call. - '401': - description: Authorization information is missing or invalid. - content: - application/json: - schema: - $ref: '#/components/schemas/401_response' - /api/alerts/alert/{alertId}/_enable: - post: - summary: Enable an alert - operationId: legacyEnableAlert - deprecated: true - description: Deprecated in 7.13.0. Use the enable rule API instead. - tags: - - alerting - parameters: - - $ref: '#/components/parameters/kbn_xsrf' - - in: path - name: alertId - description: The identifier for the alert. - required: true - schema: - type: string - example: 41893910-6bca-11eb-9e0d-85d233e3ee35 - responses: - '204': - description: Indicates a successful call. - '401': - description: Authorization information is missing or invalid. - content: - application/json: - schema: - $ref: '#/components/schemas/401_response' - /api/alerts/alert/{alertId}/_mute_all: - post: - summary: Mute all alert instances - operationId: legacyMuteAllAlertInstances - deprecated: true - description: Deprecated in 7.13.0. Use the mute all alerts API instead. - tags: - - alerting - parameters: - - $ref: '#/components/parameters/kbn_xsrf' - - in: path - name: alertId - description: The identifier for the alert. - required: true - schema: - type: string - example: 41893910-6bca-11eb-9e0d-85d233e3ee35 - responses: - '204': - description: Indicates a successful call. - '401': - description: Authorization information is missing or invalid. - content: - application/json: - schema: - $ref: '#/components/schemas/401_response' - /api/alerts/alert/{alertId}/_unmute_all: - post: - summary: Unmute all alert instances - operationId: legacyUnmuteAllAlertInstances - deprecated: true - description: Deprecated in 7.13.0. Use the unmute all alerts API instead. - tags: - - alerting - parameters: - - $ref: '#/components/parameters/kbn_xsrf' - - in: path - name: alertId - description: The identifier for the alert. - required: true - schema: - type: string - example: 41893910-6bca-11eb-9e0d-85d233e3ee35 - responses: - '204': - description: Indicates a successful call. - '401': - description: Authorization information is missing or invalid. - content: - application/json: - schema: - $ref: '#/components/schemas/401_response' - /api/alerts/alerts/_find: - get: - summary: Get a paginated set of alerts - operationId: legacyFindAlerts - deprecated: true - description: | - Deprecated in 7.13.0. Use the find rules API instead. NOTE: Alert `params` are stored as a flattened field type and analyzed as keywords. As alerts change in Kibana, the results on each page of the response also change. Use the find API for traditional paginated results, but avoid using it to export large amounts of data. - tags: - - alerting - parameters: - - name: default_search_operator - in: query - description: The default operator to use for the `simple_query_string`. - schema: - type: string - default: OR - example: OR - - name: fields - in: query - description: The fields to return in the `attributes` key of the response. - schema: - type: array - items: - type: string - - name: filter - in: query - description: | - A KQL string that you filter with an attribute from your saved object. It should look like `savedObjectType.attributes.title: "myTitle"`. However, if you used a direct attribute of a saved object, such as `updatedAt`, you must define your filter, for example, `savedObjectType.updatedAt > 2018-12-22`. - schema: - type: string - - name: has_reference - in: query - description: Filters the rules that have a relation with the reference objects with a specific type and identifier. - schema: - type: object - properties: - id: - type: string - type: - type: string - - name: page - in: query - description: The page number to return. - schema: - type: integer - default: 1 - example: 1 - - name: per_page - in: query - description: The number of alerts to return per page. - schema: - type: integer - default: 20 - example: 20 - - name: search - in: query - description: An Elasticsearch `simple_query_string` query that filters the alerts in the response. - schema: - type: string - - name: search_fields - in: query - description: The fields to perform the `simple_query_string` parsed query against. - schema: - oneOf: - - type: string - - type: array - items: - type: string - - name: sort_field - in: query - description: | - Determines which field is used to sort the results. The field must exist in the `attributes` key of the response. - schema: - type: string - - name: sort_order - in: query - description: Determines the sort order. - schema: - type: string - enum: - - asc - - desc - default: desc - example: asc - responses: - '200': - description: Indicates a successful call. - content: - application/json: - schema: - type: object - properties: - data: - type: array - items: - $ref: '#/components/schemas/alert_response_properties' - page: - type: integer - perPage: - type: integer - total: - type: integer - '401': - description: Authorization information is missing or invalid. - content: - application/json: - schema: - $ref: '#/components/schemas/401_response' - /api/alerts/alerts/_health: - get: - summary: Get the alerting framework health - operationId: legacyGetAlertingHealth - deprecated: true - description: Deprecated in 7.13.0. Use the get alerting framework health API instead. - tags: - - alerting - responses: - '200': - description: Indicates a successful call. - content: - application/json: - schema: - type: object - properties: - alertingFrameworkHealth: - type: object - description: | - Three substates identify the health of the alerting framework: `decryptionHealth`, `executionHealth`, and `readHealth`. - properties: - decryptionHealth: - type: object - description: The timestamp and status of the alert decryption. - properties: - status: - type: string - example: ok - enum: - - error - - ok - - warn - timestamp: - type: string - format: date-time - example: '2023-01-13T01:28:00.280Z' - executionHealth: - type: object - description: The timestamp and status of the alert execution. - properties: - status: - type: string - example: ok - enum: - - error - - ok - - warn - timestamp: - type: string - format: date-time - example: '2023-01-13T01:28:00.280Z' - readHealth: - type: object - description: The timestamp and status of the alert reading events. - properties: - status: - type: string - example: ok - enum: - - error - - ok - - warn - timestamp: - type: string - format: date-time - example: '2023-01-13T01:28:00.280Z' - hasPermanentEncryptionKey: - type: boolean - description: If `false`, the encrypted saved object plugin does not have a permanent encryption key. - example: true - isSufficientlySecure: - type: boolean - description: If `false`, security is enabled but TLS is not. - example: true - '401': - description: Authorization information is missing or invalid. - content: - application/json: - schema: - $ref: '#/components/schemas/401_response' - /api/alerts/alerts/list_alert_types: - get: - summary: Get the alert types - operationId: legacyGetAlertTypes - deprecated: true - description: Deprecated in 7.13.0. Use the get rule types API instead. - tags: - - alerting - responses: - '200': - description: Indicates a successful call. - content: - application/json: - schema: - type: array - items: - type: object - properties: - actionGroups: - description: | - An explicit list of groups for which the alert type can schedule actions, each with the action group's unique ID and human readable name. Alert actions validation uses this configuration to ensure that groups are valid. - type: array - items: - type: object - properties: - id: - type: string - name: - type: string - actionVariables: - description: | - A list of action variables that the alert type makes available via context and state in action parameter templates, and a short human readable description. The Alert UI will use this information to prompt users for these variables in action parameter editors. - type: object - properties: - context: - type: array - items: - type: object - properties: - name: - type: string - description: - type: string - params: - type: array - items: - type: object - properties: - description: - type: string - name: - type: string - state: - type: array - items: - type: object - properties: - description: - type: string - name: - type: string - authorizedConsumers: - description: The list of the plugins IDs that have access to the alert type. - type: object - defaultActionGroupId: - description: The default identifier for the alert type group. - type: string - enabledInLicense: - description: Indicates whether the rule type is enabled based on the subscription. - type: boolean - id: - description: The unique identifier for the alert type. - type: string - isExportable: - description: Indicates whether the alert type is exportable in Saved Objects Management UI. - type: boolean - minimumLicenseRequired: - description: The subscriptions required to use the alert type. - type: string - name: - description: The descriptive name of the alert type. - type: string - producer: - description: An identifier for the application that produces this alert type. - type: string - recoveryActionGroup: - description: | - An action group to use when an alert instance goes from an active state to an inactive one. If it is not specified, the default recovered action group is used. - type: object - properties: - id: - type: string - name: - type: string - '401': - description: Authorization information is missing or invalid. - content: - application/json: - schema: - $ref: '#/components/schemas/401_response' - /api/alerts/alert/{alertId}/alert_instance/{alertInstanceId}/_mute: - post: - summary: Mute an alert instance - operationId: legacyMuteAlertInstance - deprecated: true - description: Deprecated in 7.13.0. Use the mute alert API instead. - tags: - - alerting - parameters: - - $ref: '#/components/parameters/kbn_xsrf' - - in: path - name: alertId - description: An identifier for the alert. - required: true - schema: - type: string - example: 41893910-6bca-11eb-9e0d-85d233e3ee35 - - in: path - name: alertInstanceId - description: An identifier for the alert instance. - required: true - schema: - type: string - example: dceeb5d0-6b41-11eb-802b-85b0c1bc8ba2 - responses: - '204': - description: Indicates a successful call. - '401': - description: Authorization information is missing or invalid. - content: - application/json: - schema: - $ref: '#/components/schemas/401_response' - /api/alerts/alert/{alertId}/alert_instance/{alertInstanceId}/_unmute: - post: - summary: Unmute an alert instance - operationId: legacyUnmuteAlertInstance - deprecated: true - description: Deprecated in 7.13.0. Use the unmute alert API instead. - tags: - - alerting - parameters: - - $ref: '#/components/parameters/kbn_xsrf' - - in: path - name: alertId - description: An identifier for the alert. - required: true - schema: - type: string - example: 41893910-6bca-11eb-9e0d-85d233e3ee35 - - in: path - name: alertInstanceId - description: An identifier for the alert instance. - required: true - schema: - type: string - example: dceeb5d0-6b41-11eb-802b-85b0c1bc8ba2 - responses: - '204': - description: Indicates a successful call. - '401': - description: Authorization information is missing or invalid. - content: - application/json: - schema: - $ref: '#/components/schemas/401_response' components: examples: get_health_response: @@ -1370,94 +652,3 @@ components: type: string description: Specifies the data type for the field. example: scaled_float - alert_response_properties: - title: Legacy alert response properties - type: object - properties: - actions: - type: array - items: - type: object - alertTypeId: - type: string - example: .index-threshold - apiKeyOwner: - type: string - nullable: true - example: elastic - createdAt: - type: string - description: The date and time that the alert was created. - format: date-time - example: '2022-12-05T23:36:58.284Z' - createdBy: - type: string - description: The identifier for the user that created the alert. - example: elastic - enabled: - type: boolean - description: Indicates whether the alert is currently enabled. - example: true - executionStatus: - type: object - properties: - lastExecutionDate: - type: string - format: date-time - example: '2022-12-06T00:13:43.890Z' - status: - type: string - example: ok - id: - type: string - description: The identifier for the alert. - example: b530fed0-74f5-11ed-9801-35303b735aef - muteAll: - type: boolean - example: false - mutedInstanceIds: - type: array - nullable: true - items: - type: string - name: - type: string - description: The name of the alert. - example: my alert - notifyWhen: - type: string - example: onActionGroupChange - params: - type: object - additionalProperties: true - schedule: - type: object - properties: - interval: - type: string - scheduledTaskId: - type: string - example: b530fed0-74f5-11ed-9801-35303b735aef - tags: - type: array - items: - type: string - throttle: - type: string - nullable: true - updatedAt: - type: string - example: '2022-12-05T23:36:58.284Z' - updatedBy: - type: string - description: The identifier for the user that updated this alert most recently. - nullable: true - example: elastic - parameters: - kbn_xsrf: - schema: - type: string - in: header - name: kbn-xsrf - description: Cross-site request forgery protection - required: true diff --git a/x-pack/plugins/alerting/docs/openapi/entrypoint.yaml b/x-pack/plugins/alerting/docs/openapi/entrypoint.yaml index 48f7efd53b839..1b169a6c4f760 100644 --- a/x-pack/plugins/alerting/docs/openapi/entrypoint.yaml +++ b/x-pack/plugins/alerting/docs/openapi/entrypoint.yaml @@ -15,24 +15,3 @@ paths: $ref: paths/api@alerting@_health.yaml '/api/alerting/rule_types': $ref: 'paths/api@alerting@rule_types.yaml' -# Deprecated APIs - '/api/alerts/alert/{alertId}': - $ref: 'paths/api@alerts@alert@{alertid}.yaml' - '/api/alerts/alert/{alertId}/_disable': - $ref: 'paths/api@alerts@alert@{alertid}@_disable.yaml' - '/api/alerts/alert/{alertId}/_enable': - $ref: 'paths/api@alerts@alert@{alertid}@_enable.yaml' - '/api/alerts/alert/{alertId}/_mute_all': - $ref: 'paths/api@alerts@alert@{alertid}@_mute_all.yaml' - '/api/alerts/alert/{alertId}/_unmute_all': - $ref: 'paths/api@alerts@alert@{alertid}@_unmute_all.yaml' - '/api/alerts/alerts/_find': - $ref: 'paths/api@alerts@_find.yaml' - '/api/alerts/alerts/_health': - $ref: 'paths/api@alerts@_health.yaml' - '/api/alerts/alerts/list_alert_types': - $ref: 'paths/api@alerts@list_alert_types.yaml' - '/api/alerts/alert/{alertId}/alert_instance/{alertInstanceId}/_mute': - $ref: 'paths/api@alerts@alert@{alertid}@alert_instance@{alertinstanceid}@_mute.yaml' - '/api/alerts/alert/{alertId}/alert_instance/{alertInstanceId}/_unmute': - $ref: 'paths/api@alerts@alert@{alertid}@alert_instance@{alertinstanceid}@_unmute.yaml' diff --git a/x-pack/plugins/alerting/docs/openapi/paths/api@alerts@_find.yaml b/x-pack/plugins/alerting/docs/openapi/paths/api@alerts@_find.yaml deleted file mode 100644 index 397653acb1c90..0000000000000 --- a/x-pack/plugins/alerting/docs/openapi/paths/api@alerts@_find.yaml +++ /dev/null @@ -1,115 +0,0 @@ -get: - summary: Get a paginated set of alerts - operationId: legacyFindAlerts - deprecated: true - description: > - Deprecated in 7.13.0. Use the find rules API instead. - NOTE: Alert `params` are stored as a flattened field type and analyzed as keywords. - As alerts change in Kibana, the results on each page of the response also change. - Use the find API for traditional paginated results, but avoid using it to export large amounts of data. - tags: - - alerting - parameters: - - name: default_search_operator - in: query - description: The default operator to use for the `simple_query_string`. - schema: - type: string - default: OR - example: OR - - name: fields - in: query - description: The fields to return in the `attributes` key of the response. - schema: - type: array - items: - type: string - - name: filter - in: query - description: > - A KQL string that you filter with an attribute from your saved object. - It should look like `savedObjectType.attributes.title: "myTitle"`. - However, if you used a direct attribute of a saved object, such as - `updatedAt`, you must define your filter, for example, - `savedObjectType.updatedAt > 2018-12-22`. - schema: - type: string - - name: has_reference - in: query - description: Filters the rules that have a relation with the reference objects with a specific type and identifier. - schema: - type: object - properties: - id: - type: string - type: - type: string - - name: page - in: query - description: The page number to return. - schema: - type: integer - default: 1 - example: 1 - - name: per_page - in: query - description: The number of alerts to return per page. - schema: - type: integer - default: 20 - example: 20 - - name: search - in: query - description: An Elasticsearch `simple_query_string` query that filters the alerts in the response. - schema: - type: string - - name: search_fields - in: query - description: The fields to perform the `simple_query_string` parsed query against. - schema: - oneOf: - - type: string - - type: array - items: - type: string - - name: sort_field - in: query - description: > - Determines which field is used to sort the results. The field must exist - in the `attributes` key of the response. - schema: - type: string - - name: sort_order - in: query - description: Determines the sort order. - schema: - type: string - enum: - - asc - - desc - default: desc - example: asc - responses: - '200': - description: Indicates a successful call. - content: - application/json: - schema: - type: object - properties: - data: - type: array - items: - $ref: '../components/schemas/alert_response_properties.yaml' - page: - type: integer - perPage: - type: integer - total: - type: integer - '401': - description: Authorization information is missing or invalid. - content: - application/json: - schema: - $ref: '../components/schemas/401_response.yaml' \ No newline at end of file diff --git a/x-pack/plugins/alerting/docs/openapi/paths/api@alerts@_health.yaml b/x-pack/plugins/alerting/docs/openapi/paths/api@alerts@_health.yaml deleted file mode 100644 index b8436a08abf1f..0000000000000 --- a/x-pack/plugins/alerting/docs/openapi/paths/api@alerts@_health.yaml +++ /dev/null @@ -1,79 +0,0 @@ -get: - summary: Get the alerting framework health - operationId: legacyGetAlertingHealth - deprecated: true - description: Deprecated in 7.13.0. Use the get alerting framework health API instead. - tags: - - alerting - responses: - '200': - description: Indicates a successful call. - content: - application/json: - schema: - type: object - properties: - alertingFrameworkHealth: - type: object - description: > - Three substates identify the health of the alerting framework: `decryptionHealth`, `executionHealth`, and `readHealth`. - properties: - decryptionHealth: - type: object - description: The timestamp and status of the alert decryption. - properties: - status: - type: string - example: ok - enum: - - error - - ok - - warn - timestamp: - type: string - format: date-time - example: "2023-01-13T01:28:00.280Z" - executionHealth: - type: object - description: The timestamp and status of the alert execution. - properties: - status: - type: string - example: ok - enum: - - error - - ok - - warn - timestamp: - type: string - format: date-time - example: "2023-01-13T01:28:00.280Z" - readHealth: - type: object - description: The timestamp and status of the alert reading events. - properties: - status: - type: string - example: ok - enum: - - error - - ok - - warn - timestamp: - type: string - format: date-time - example: "2023-01-13T01:28:00.280Z" - hasPermanentEncryptionKey: - type: boolean - description: If `false`, the encrypted saved object plugin does not have a permanent encryption key. - example: true - isSufficientlySecure: - type: boolean - description: If `false`, security is enabled but TLS is not. - example: true - '401': - description: Authorization information is missing or invalid. - content: - application/json: - schema: - $ref: '../components/schemas/401_response.yaml' \ No newline at end of file diff --git a/x-pack/plugins/alerting/docs/openapi/paths/api@alerts@alert@{alertid}.yaml b/x-pack/plugins/alerting/docs/openapi/paths/api@alerts@alert@{alertid}.yaml deleted file mode 100644 index bf6d69d117450..0000000000000 --- a/x-pack/plugins/alerting/docs/openapi/paths/api@alerts@alert@{alertid}.yaml +++ /dev/null @@ -1,275 +0,0 @@ -delete: - summary: Delete an alert - operationId: legaryDeleteAlert - deprecated: true - description: > - Deprecated in 7.13.0. Use the delete rule API instead. - WARNING: After you delete an alert, you cannot recover it. - tags: - - alerting - parameters: - - $ref: ../components/headers/kbn_xsrf.yaml - - in: path - name: alertId - description: The identifier for the alert. - required: true - schema: - type: string - example: 41893910-6bca-11eb-9e0d-85d233e3ee35 - responses: - '204': - description: Indicates a successful call. - '401': - description: Authorization information is missing or invalid. - content: - application/json: - schema: - $ref: '../components/schemas/401_response.yaml' - -get: - summary: Get an alert by identifier - operationId: legacyGetAlert - deprecated: true - description: Deprecated in 7.13.0. Use the get rule API instead. - tags: - - alerting - parameters: - - in: path - name: alertId - description: The identifier for the alert. - required: true - schema: - type: string - example: 41893910-6bca-11eb-9e0d-85d233e3ee35 - responses: - '200': - description: Indicates a successful call. - content: - application/json: - schema: - $ref: '../components/schemas/alert_response_properties.yaml' - '401': - description: Authorization information is missing or invalid. - content: - application/json: - schema: - $ref: '../components/schemas/401_response.yaml' - -post: - summary: Create an alert - operationId: legacyCreateAlert - deprecated: true - description: Deprecated in 7.13.0. Use the create rule API instead. - tags: - - alerting - parameters: - - $ref: ../components/headers/kbn_xsrf.yaml - - in: path - name: alertId - description: An UUID v1 or v4 identifier for the alert. If this parameter is omitted, the identifier is randomly generated. - required: true - schema: - type: string - example: 41893910-6bca-11eb-9e0d-85d233e3ee35 - requestBody: - required: true - content: - application/json: - schema: - title: Legacy create alert request properties - type: object - required: - - alertTypeId - - consumer - - name - - notifyWhen - - params - - schedule - properties: - actions: - type: array - items: - type: object - required: - - actionTypeId - - group - - id - - params - properties: - actionTypeId: - type: string - description: The identifier for the action type. - group: - type: string - description: > - Grouping actions is recommended for escalations for different types of alert instances. - If you don't need this functionality, set it to `default`. - id: - type: string - description: The ID of the action saved object. - params: - type: object - description: > - The map to the `params` that the action type will receive. - `params` are handled as Mustache templates and passed a default set of context. - alertTypeId: - type: string - description: The ID of the alert type that you want to call when the alert is scheduled to run. - consumer: - type: string - description: The name of the application that owns the alert. This name has to match the Kibana feature name, as that dictates the required role-based access control privileges. - enabled: - type: boolean - description: Indicates if you want to run the alert on an interval basis after it is created. - name: - type: string - description: A name to reference and search. - notifyWhen: - type: string - description: The condition for throttling the notification. - enum: - - onActionGroupChange - - onActiveAlert - - onThrottleInterval - params: - type: object - description: The parameters to pass to the alert type executor `params` value. This will also validate against the alert type params validator, if defined. - schedule: - type: object - description: > - The schedule specifying when this alert should be run. - A schedule is structured such that the key specifies the format you wish to use and its value specifies the schedule. - properties: - interval: - type: string - description: The interval format specifies the interval in seconds, minutes, hours or days at which the alert should run. - example: "10s" - tags: - type: array - items: - type: string - description: A list of keywords to reference and search. - throttle: - type: string - description: > - How often this alert should fire the same actions. - This will prevent the alert from sending out the same notification over and over. - For example, if an alert with a schedule of 1 minute stays in a triggered state for 90 minutes, - setting a throttle of `10m` or `1h` will prevent it from sending 90 notifications during this period. - responses: - '200': - description: Indicates a successful call. - content: - application/json: - schema: - $ref: '../components/schemas/alert_response_properties.yaml' - '401': - description: Authorization information is missing or invalid. - content: - application/json: - schema: - $ref: '../components/schemas/401_response.yaml' - -put: - summary: Update an alert - operationId: legacyUpdateAlert - deprecated: true - description: Deprecated in 7.13.0. Use the update rule API instead. - tags: - - alerting - parameters: - - $ref: ../components/headers/kbn_xsrf.yaml - - in: path - name: alertId - description: The identifier for the alert. - required: true - schema: - type: string - example: 41893910-6bca-11eb-9e0d-85d233e3ee35 - requestBody: - required: true - content: - application/json: - schema: - title: Legacy update alert request properties - type: object - required: - - name - - notifyWhen - - params - - schedule - properties: - actions: - type: array - items: - type: object - required: - - actionTypeId - - group - - id - - params - properties: - actionTypeId: - type: string - description: The identifier for the action type. - group: - type: string - description: > - Grouping actions is recommended for escalations for different types of alert instances. - If you don't need this functionality, set it to `default`. - id: - type: string - description: The ID of the action saved object. - params: - type: object - description: > - The map to the `params` that the action type will receive. - `params` are handled as Mustache templates and passed a default set of context. - name: - type: string - description: A name to reference and search. - notifyWhen: - type: string - description: The condition for throttling the notification. - enum: - - onActionGroupChange - - onActiveAlert - - onThrottleInterval - params: - type: object - description: The parameters to pass to the alert type executor `params` value. This will also validate against the alert type params validator, if defined. - schedule: - type: object - description: > - The schedule specifying when this alert should be run. - A schedule is structured such that the key specifies the format you wish to use and its value specifies the schedule. - properties: - interval: - type: string - description: The interval format specifies the interval in seconds, minutes, hours or days at which the alert should run. - example: "1d" - tags: - type: array - items: - type: string - description: A list of keywords to reference and search. - throttle: - type: string - description: > - How often this alert should fire the same actions. - This will prevent the alert from sending out the same notification over and over. - For example, if an alert with a schedule of 1 minute stays in a triggered state for 90 minutes, - setting a throttle of `10m` or `1h` will prevent it from sending 90 notifications during this period. - responses: - '200': - description: Indicates a successful call. - content: - application/json: - schema: - $ref: '../components/schemas/alert_response_properties.yaml' - '401': - description: Authorization information is missing or invalid. - content: - application/json: - schema: - $ref: '../components/schemas/401_response.yaml' \ No newline at end of file diff --git a/x-pack/plugins/alerting/docs/openapi/paths/api@alerts@alert@{alertid}@_disable.yaml b/x-pack/plugins/alerting/docs/openapi/paths/api@alerts@alert@{alertid}@_disable.yaml deleted file mode 100644 index 70874a8bea396..0000000000000 --- a/x-pack/plugins/alerting/docs/openapi/paths/api@alerts@alert@{alertid}@_disable.yaml +++ /dev/null @@ -1,25 +0,0 @@ -post: - summary: Disable an alert - operationId: legacyDisableAlert - deprecated: true - description: Deprecated in 7.13.0. Use the disable rule API instead. - tags: - - alerting - parameters: - - $ref: ../components/headers/kbn_xsrf.yaml - - in: path - name: alertId - description: The identifier for the alert. - required: true - schema: - type: string - example: 41893910-6bca-11eb-9e0d-85d233e3ee35 - responses: - '204': - description: Indicates a successful call. - '401': - description: Authorization information is missing or invalid. - content: - application/json: - schema: - $ref: '../components/schemas/401_response.yaml' \ No newline at end of file diff --git a/x-pack/plugins/alerting/docs/openapi/paths/api@alerts@alert@{alertid}@_enable.yaml b/x-pack/plugins/alerting/docs/openapi/paths/api@alerts@alert@{alertid}@_enable.yaml deleted file mode 100644 index 3b79778c26c6c..0000000000000 --- a/x-pack/plugins/alerting/docs/openapi/paths/api@alerts@alert@{alertid}@_enable.yaml +++ /dev/null @@ -1,25 +0,0 @@ -post: - summary: Enable an alert - operationId: legacyEnableAlert - deprecated: true - description: Deprecated in 7.13.0. Use the enable rule API instead. - tags: - - alerting - parameters: - - $ref: ../components/headers/kbn_xsrf.yaml - - in: path - name: alertId - description: The identifier for the alert. - required: true - schema: - type: string - example: 41893910-6bca-11eb-9e0d-85d233e3ee35 - responses: - '204': - description: Indicates a successful call. - '401': - description: Authorization information is missing or invalid. - content: - application/json: - schema: - $ref: '../components/schemas/401_response.yaml' \ No newline at end of file diff --git a/x-pack/plugins/alerting/docs/openapi/paths/api@alerts@alert@{alertid}@_mute_all.yaml b/x-pack/plugins/alerting/docs/openapi/paths/api@alerts@alert@{alertid}@_mute_all.yaml deleted file mode 100644 index 462e6994d4553..0000000000000 --- a/x-pack/plugins/alerting/docs/openapi/paths/api@alerts@alert@{alertid}@_mute_all.yaml +++ /dev/null @@ -1,25 +0,0 @@ -post: - summary: Mute all alert instances - operationId: legacyMuteAllAlertInstances - deprecated: true - description: Deprecated in 7.13.0. Use the mute all alerts API instead. - tags: - - alerting - parameters: - - $ref: ../components/headers/kbn_xsrf.yaml - - in: path - name: alertId - description: The identifier for the alert. - required: true - schema: - type: string - example: 41893910-6bca-11eb-9e0d-85d233e3ee35 - responses: - '204': - description: Indicates a successful call. - '401': - description: Authorization information is missing or invalid. - content: - application/json: - schema: - $ref: '../components/schemas/401_response.yaml' \ No newline at end of file diff --git a/x-pack/plugins/alerting/docs/openapi/paths/api@alerts@alert@{alertid}@_unmute_all.yaml b/x-pack/plugins/alerting/docs/openapi/paths/api@alerts@alert@{alertid}@_unmute_all.yaml deleted file mode 100644 index bfdec84525aae..0000000000000 --- a/x-pack/plugins/alerting/docs/openapi/paths/api@alerts@alert@{alertid}@_unmute_all.yaml +++ /dev/null @@ -1,25 +0,0 @@ -post: - summary: Unmute all alert instances - operationId: legacyUnmuteAllAlertInstances - deprecated: true - description: Deprecated in 7.13.0. Use the unmute all alerts API instead. - tags: - - alerting - parameters: - - $ref: ../components/headers/kbn_xsrf.yaml - - in: path - name: alertId - description: The identifier for the alert. - required: true - schema: - type: string - example: 41893910-6bca-11eb-9e0d-85d233e3ee35 - responses: - '204': - description: Indicates a successful call. - '401': - description: Authorization information is missing or invalid. - content: - application/json: - schema: - $ref: '../components/schemas/401_response.yaml' \ No newline at end of file diff --git a/x-pack/plugins/alerting/docs/openapi/paths/api@alerts@alert@{alertid}@alert_instance@{alertinstanceid}@_mute.yaml b/x-pack/plugins/alerting/docs/openapi/paths/api@alerts@alert@{alertid}@alert_instance@{alertinstanceid}@_mute.yaml deleted file mode 100644 index 4af89ec42616c..0000000000000 --- a/x-pack/plugins/alerting/docs/openapi/paths/api@alerts@alert@{alertid}@alert_instance@{alertinstanceid}@_mute.yaml +++ /dev/null @@ -1,32 +0,0 @@ -post: - summary: Mute an alert instance - operationId: legacyMuteAlertInstance - deprecated: true - description: Deprecated in 7.13.0. Use the mute alert API instead. - tags: - - alerting - parameters: - - $ref: ../components/headers/kbn_xsrf.yaml - - in: path - name: alertId - description: An identifier for the alert. - required: true - schema: - type: string - example: 41893910-6bca-11eb-9e0d-85d233e3ee35 - - in: path - name: alertInstanceId - description: An identifier for the alert instance. - required: true - schema: - type: string - example: dceeb5d0-6b41-11eb-802b-85b0c1bc8ba2 - responses: - '204': - description: Indicates a successful call. - '401': - description: Authorization information is missing or invalid. - content: - application/json: - schema: - $ref: '../components/schemas/401_response.yaml' \ No newline at end of file diff --git a/x-pack/plugins/alerting/docs/openapi/paths/api@alerts@alert@{alertid}@alert_instance@{alertinstanceid}@_unmute.yaml b/x-pack/plugins/alerting/docs/openapi/paths/api@alerts@alert@{alertid}@alert_instance@{alertinstanceid}@_unmute.yaml deleted file mode 100644 index a939d74c3d1d0..0000000000000 --- a/x-pack/plugins/alerting/docs/openapi/paths/api@alerts@alert@{alertid}@alert_instance@{alertinstanceid}@_unmute.yaml +++ /dev/null @@ -1,32 +0,0 @@ -post: - summary: Unmute an alert instance - operationId: legacyUnmuteAlertInstance - deprecated: true - description: Deprecated in 7.13.0. Use the unmute alert API instead. - tags: - - alerting - parameters: - - $ref: ../components/headers/kbn_xsrf.yaml - - in: path - name: alertId - description: An identifier for the alert. - required: true - schema: - type: string - example: 41893910-6bca-11eb-9e0d-85d233e3ee35 - - in: path - name: alertInstanceId - description: An identifier for the alert instance. - required: true - schema: - type: string - example: dceeb5d0-6b41-11eb-802b-85b0c1bc8ba2 - responses: - '204': - description: Indicates a successful call. - '401': - description: Authorization information is missing or invalid. - content: - application/json: - schema: - $ref: '../components/schemas/401_response.yaml' \ No newline at end of file diff --git a/x-pack/plugins/alerting/docs/openapi/paths/api@alerts@list_alert_types.yaml b/x-pack/plugins/alerting/docs/openapi/paths/api@alerts@list_alert_types.yaml deleted file mode 100644 index 14b3cd4e07b9b..0000000000000 --- a/x-pack/plugins/alerting/docs/openapi/paths/api@alerts@list_alert_types.yaml +++ /dev/null @@ -1,107 +0,0 @@ -get: - summary: Get the alert types - operationId: legacyGetAlertTypes - deprecated: true - description: Deprecated in 7.13.0. Use the get rule types API instead. - tags: - - alerting - responses: - '200': - description: Indicates a successful call. - content: - application/json: - schema: - type: array - items: - type: object - properties: - actionGroups: - description: > - An explicit list of groups for which the alert type can - schedule actions, each with the action group's unique ID and - human readable name. Alert actions validation uses this - configuration to ensure that groups are valid. - type: array - items: - type: object - properties: - id: - type: string - name: - type: string - actionVariables: - description: > - A list of action variables that the alert type makes available - via context and state in action parameter templates, and a - short human readable description. The Alert UI will use this - information to prompt users for these variables in action - parameter editors. - type: object - properties: - context: - type: array - items: - type: object - properties: - name: - type: string - description: - type: string - params: - type: array - items: - type: object - properties: - description: - type: string - name: - type: string - state: - type: array - items: - type: object - properties: - description: - type: string - name: - type: string - authorizedConsumers: - description: The list of the plugins IDs that have access to the alert type. - type: object - defaultActionGroupId: - description: The default identifier for the alert type group. - type: string - enabledInLicense: - description: Indicates whether the rule type is enabled based on the subscription. - type: boolean - id: - description: The unique identifier for the alert type. - type: string - isExportable: - description: Indicates whether the alert type is exportable in Saved Objects Management UI. - type: boolean - minimumLicenseRequired: - description: The subscriptions required to use the alert type. - type: string - name: - description: The descriptive name of the alert type. - type: string - producer: - description: An identifier for the application that produces this alert type. - type: string - recoveryActionGroup: - description: > - An action group to use when an alert instance goes from an active state to an inactive one. - If it is not specified, the default recovered action group is used. - type: object - properties: - id: - type: string - name: - type: string - '401': - description: Authorization information is missing or invalid. - content: - application/json: - schema: - $ref: '../components/schemas/401_response.yaml' \ No newline at end of file diff --git a/x-pack/plugins/alerting/server/routes/index.ts b/x-pack/plugins/alerting/server/routes/index.ts index d9692dec9c0f8..58c6cda9f3b12 100644 --- a/x-pack/plugins/alerting/server/routes/index.ts +++ b/x-pack/plugins/alerting/server/routes/index.ts @@ -11,7 +11,6 @@ import { EncryptedSavedObjectsPluginSetup } from '@kbn/encrypted-saved-objects-p import type { ConfigSchema } from '@kbn/unified-search-plugin/server/config'; import { Observable } from 'rxjs'; import { GetAlertIndicesAlias, ILicenseState } from '../lib'; -import { defineLegacyRoutes } from './legacy'; import { AlertingRequestHandlerContext } from '../types'; import { createRuleRoute } from './rule/apis/create'; import { getRuleRoute, getInternalRuleRoute } from './rule/apis/get/get_rule_route'; @@ -94,10 +93,6 @@ export function defineRoutes(opts: RouteOptions) { getAlertIndicesAlias, } = opts; - // Legacy APIs - defineLegacyRoutes(opts); - - // Rule APIs createRuleRoute(opts); getRuleRoute(router, licenseState); getInternalRuleRoute(router, licenseState); diff --git a/x-pack/plugins/alerting/server/routes/legacy/create.test.ts b/x-pack/plugins/alerting/server/routes/legacy/create.test.ts deleted file mode 100644 index f3df843899f22..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/create.test.ts +++ /dev/null @@ -1,617 +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. - */ - -import { createAlertRoute } from './create'; -import { httpServiceMock } from '@kbn/core/server/mocks'; -import { usageCountersServiceMock } from '@kbn/usage-collection-plugin/server/usage_counters/usage_counters_service.mock'; -import { licenseStateMock } from '../../lib/license_state.mock'; -import { verifyApiAccess } from '../../lib/license_api_access'; -import { mockHandlerArguments } from '../_mock_handler_arguments'; -import { rulesClientMock } from '../../rules_client.mock'; -import { Rule, RuleSystemAction } from '../../../common/rule'; -import { RuleTypeDisabledError } from '../../lib/errors/rule_type_disabled'; -import { encryptedSavedObjectsMock } from '@kbn/encrypted-saved-objects-plugin/server/mocks'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; -import { docLinksServiceMock } from '@kbn/core/server/mocks'; - -const rulesClient = rulesClientMock.create(); - -jest.mock('../../lib/license_api_access', () => ({ - verifyApiAccess: jest.fn(), -})); - -jest.mock('../../lib/track_legacy_route_usage', () => ({ - trackLegacyRouteUsage: jest.fn(), -})); - -beforeEach(() => { - jest.resetAllMocks(); -}); - -describe('createAlertRoute', () => { - const docLinks = docLinksServiceMock.createSetupContract(); - const createdAt = new Date(); - const updatedAt = new Date(); - - const mockedAlert = { - alertTypeId: '1', - consumer: 'bar', - name: 'abc', - schedule: { interval: '10s' }, - tags: ['foo'], - params: { - bar: true, - }, - throttle: '30s', - notifyWhen: 'onActionGroupChange', - actions: [ - { - group: 'default', - id: '2', - params: { - foo: true, - }, - }, - ], - }; - - const systemAction: RuleSystemAction = { - actionTypeId: 'test-2', - id: 'system_action-id', - params: { - foo: true, - }, - uuid: '123-456', - }; - - const createResult: Rule<{ bar: boolean }> = { - ...mockedAlert, - enabled: true, - muteAll: false, - createdBy: '', - updatedBy: '', - apiKey: '', - apiKeyOwner: '', - mutedInstanceIds: [], - notifyWhen: 'onActionGroupChange', - createdAt, - updatedAt, - id: '123', - actions: [ - { - ...mockedAlert.actions[0], - actionTypeId: 'test', - }, - ], - executionStatus: { - status: 'unknown', - lastExecutionDate: new Date('2020-08-20T19:23:38Z'), - }, - revision: 0, - }; - - it('creates an alert with proper parameters', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true }); - const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); - const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test'); - - createAlertRoute({ - router, - licenseState, - encryptedSavedObjects, - usageCounter: mockUsageCounter, - docLinks, - }); - - const [config, handler] = router.post.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id?}"`); - - expect(config.options?.access).toBe('public'); - - rulesClient.create.mockResolvedValueOnce(createResult); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - body: mockedAlert, - }, - ['ok'] - ); - - expect(await handler(context, req, res)).toEqual({ body: createResult }); - - expect(mockUsageCounter.incrementCounter).not.toHaveBeenCalled(); - expect(rulesClient.create).toHaveBeenCalledTimes(1); - expect(rulesClient.create.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "data": Object { - "actions": Array [ - Object { - "group": "default", - "id": "2", - "params": Object { - "foo": true, - }, - }, - ], - "alertTypeId": "1", - "consumer": "bar", - "name": "abc", - "notifyWhen": "onActionGroupChange", - "params": Object { - "bar": true, - }, - "schedule": Object { - "interval": "10s", - }, - "tags": Array [ - "foo", - ], - "throttle": "30s", - }, - "options": Object { - "id": undefined, - }, - }, - ] - `); - - expect(res.ok).toHaveBeenCalledWith({ - body: createResult, - }); - }); - - it('should have internal access for serverless', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true }); - const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); - const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test'); - - createAlertRoute({ - router, - licenseState, - encryptedSavedObjects, - usageCounter: mockUsageCounter, - isServerless: true, - docLinks, - }); - - const [config] = router.post.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id?}"`); - - expect(config.options?.access).toBe('internal'); - }); - - it('allows providing a custom id when space is undefined', async () => { - const expectedResult = { - ...createResult, - id: 'custom-id', - }; - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true }); - const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); - const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test'); - - createAlertRoute({ - router, - licenseState, - encryptedSavedObjects, - usageCounter: mockUsageCounter, - docLinks, - }); - - const [config, handler] = router.post.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id?}"`); - - rulesClient.create.mockResolvedValueOnce(expectedResult); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: { id: 'custom-id' }, - body: mockedAlert, - }, - ['ok'] - ); - - expect(await handler(context, req, res)).toEqual({ body: expectedResult }); - - expect(mockUsageCounter.incrementCounter).toHaveBeenCalledTimes(1); - expect(rulesClient.create).toHaveBeenCalledTimes(1); - expect(rulesClient.create.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "data": Object { - "actions": Array [ - Object { - "group": "default", - "id": "2", - "params": Object { - "foo": true, - }, - }, - ], - "alertTypeId": "1", - "consumer": "bar", - "name": "abc", - "notifyWhen": "onActionGroupChange", - "params": Object { - "bar": true, - }, - "schedule": Object { - "interval": "10s", - }, - "tags": Array [ - "foo", - ], - "throttle": "30s", - }, - "options": Object { - "id": "custom-id", - }, - }, - ] - `); - - expect(res.ok).toHaveBeenCalledWith({ - body: expectedResult, - }); - }); - - it('allows providing a custom id in default space', async () => { - const expectedResult = { - ...createResult, - id: 'custom-id', - }; - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true }); - const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); - const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test'); - - createAlertRoute({ - router, - licenseState, - encryptedSavedObjects, - usageCounter: mockUsageCounter, - docLinks, - }); - - const [config, handler] = router.post.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id?}"`); - - rulesClient.create.mockResolvedValueOnce(expectedResult); - rulesClient.getSpaceId.mockReturnValueOnce('default'); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: { id: 'custom-id' }, - body: mockedAlert, - }, - ['ok'] - ); - - expect(await handler(context, req, res)).toEqual({ body: expectedResult }); - - expect(mockUsageCounter.incrementCounter).toHaveBeenCalledTimes(1); - expect(rulesClient.create).toHaveBeenCalledTimes(1); - expect(rulesClient.create.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "data": Object { - "actions": Array [ - Object { - "group": "default", - "id": "2", - "params": Object { - "foo": true, - }, - }, - ], - "alertTypeId": "1", - "consumer": "bar", - "name": "abc", - "notifyWhen": "onActionGroupChange", - "params": Object { - "bar": true, - }, - "schedule": Object { - "interval": "10s", - }, - "tags": Array [ - "foo", - ], - "throttle": "30s", - }, - "options": Object { - "id": "custom-id", - }, - }, - ] - `); - - expect(res.ok).toHaveBeenCalledWith({ - body: expectedResult, - }); - }); - - it('allows providing a custom id in non-default space', async () => { - const expectedResult = { - ...createResult, - id: 'custom-id', - }; - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true }); - const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); - const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test'); - - createAlertRoute({ - router, - licenseState, - encryptedSavedObjects, - usageCounter: mockUsageCounter, - docLinks, - }); - - const [config, handler] = router.post.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id?}"`); - - rulesClient.create.mockResolvedValueOnce(expectedResult); - rulesClient.getSpaceId.mockReturnValueOnce('another-space'); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: { id: 'custom-id' }, - body: mockedAlert, - }, - ['ok'] - ); - - expect(await handler(context, req, res)).toEqual({ body: expectedResult }); - - expect(mockUsageCounter.incrementCounter).toHaveBeenCalledTimes(2); - expect(rulesClient.create).toHaveBeenCalledTimes(1); - expect(rulesClient.create.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "data": Object { - "actions": Array [ - Object { - "group": "default", - "id": "2", - "params": Object { - "foo": true, - }, - }, - ], - "alertTypeId": "1", - "consumer": "bar", - "name": "abc", - "notifyWhen": "onActionGroupChange", - "params": Object { - "bar": true, - }, - "schedule": Object { - "interval": "10s", - }, - "tags": Array [ - "foo", - ], - "throttle": "30s", - }, - "options": Object { - "id": "custom-id", - }, - }, - ] - `); - - expect(res.ok).toHaveBeenCalledWith({ - body: expectedResult, - }); - }); - - it('ensures the license allows creating alerts', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true }); - - createAlertRoute({ router, licenseState, encryptedSavedObjects, docLinks }); - - const [, handler] = router.post.mock.calls[0]; - - rulesClient.create.mockResolvedValueOnce(createResult); - - const [context, req, res] = mockHandlerArguments({ rulesClient }, {}); - - await handler(context, req, res); - - expect(verifyApiAccess).toHaveBeenCalledWith(licenseState); - }); - - it('ensures the license check prevents creating alerts', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true }); - - (verifyApiAccess as jest.Mock).mockImplementation(() => { - throw new Error('OMG'); - }); - - createAlertRoute({ router, licenseState, encryptedSavedObjects, docLinks }); - - const [, handler] = router.post.mock.calls[0]; - - rulesClient.create.mockResolvedValueOnce(createResult); - - const [context, req, res] = mockHandlerArguments({ rulesClient }, {}); - - await expect(handler(context, req, res)).rejects.toMatchInlineSnapshot(`[Error: OMG]`); - - expect(verifyApiAccess).toHaveBeenCalledWith(licenseState); - }); - - it('ensures the alert type gets validated for the license', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true }); - - createAlertRoute({ router, licenseState, encryptedSavedObjects, docLinks }); - - const [, handler] = router.post.mock.calls[0]; - - rulesClient.create.mockRejectedValue(new RuleTypeDisabledError('Fail', 'license_invalid')); - - const [context, req, res] = mockHandlerArguments({ rulesClient }, {}, ['ok', 'forbidden']); - - await handler(context, req, res); - - expect(res.forbidden).toHaveBeenCalledWith({ body: { message: 'Fail' } }); - }); - - it('should track every call', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true }); - const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); - const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test'); - - createAlertRoute({ - router, - licenseState, - encryptedSavedObjects, - usageCounter: mockUsageCounter, - docLinks, - }); - const [, handler] = router.post.mock.calls[0]; - rulesClient.create.mockResolvedValueOnce(createResult); - const [context, req, res] = mockHandlerArguments({ rulesClient }, {}, ['ok']); - await handler(context, req, res); - expect(trackLegacyRouteUsage).toHaveBeenCalledWith('create', mockUsageCounter); - }); - - it('does not return system actions', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true }); - const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); - const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test'); - - createAlertRoute({ - router, - licenseState, - encryptedSavedObjects, - usageCounter: mockUsageCounter, - docLinks, - }); - - const [config, handler] = router.post.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id?}"`); - - rulesClient.create.mockResolvedValueOnce({ ...createResult, systemActions: [systemAction] }); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - body: mockedAlert, - }, - ['ok'] - ); - - expect(await handler(context, req, res)).toEqual({ body: createResult }); - - expect(mockUsageCounter.incrementCounter).not.toHaveBeenCalled(); - expect(rulesClient.create).toHaveBeenCalledTimes(1); - expect(rulesClient.create.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "data": Object { - "actions": Array [ - Object { - "group": "default", - "id": "2", - "params": Object { - "foo": true, - }, - }, - ], - "alertTypeId": "1", - "consumer": "bar", - "name": "abc", - "notifyWhen": "onActionGroupChange", - "params": Object { - "bar": true, - }, - "schedule": Object { - "interval": "10s", - }, - "tags": Array [ - "foo", - ], - "throttle": "30s", - }, - "options": Object { - "id": undefined, - }, - }, - ] - `); - - expect(res.ok).toHaveBeenCalledWith({ - body: createResult, - }); - }); - - it('should be deprecated', () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true }); - const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); - const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test'); - - createAlertRoute({ - router, - licenseState, - encryptedSavedObjects, - usageCounter: mockUsageCounter, - docLinks, - }); - - const [config] = router.post.mock.calls[0]; - - expect(config.options?.deprecated).toMatchInlineSnapshot( - { - documentationUrl: expect.stringMatching(/#breaking-201550$/), - }, - ` - Object { - "documentationUrl": StringMatching /#breaking-201550\\$/, - "reason": Object { - "newApiMethod": "POST", - "newApiPath": "/api/alerting/rule/{id?}", - "type": "migrate", - }, - "severity": "warning", - } - ` - ); - }); -}); diff --git a/x-pack/plugins/alerting/server/routes/legacy/create.ts b/x-pack/plugins/alerting/server/routes/legacy/create.ts deleted file mode 100644 index 7e18897554431..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/create.ts +++ /dev/null @@ -1,122 +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. - */ - -import { schema } from '@kbn/config-schema'; -import { verifyApiAccess } from '../../lib/license_api_access'; -import { validateDurationSchema } from '../../lib'; -import { handleDisabledApiKeysError } from '../lib/error_handler'; -import { - SanitizedRule, - RuleNotifyWhenType, - RuleTypeParams, - LEGACY_BASE_ALERT_API_PATH, - validateNotifyWhenType, -} from '../../types'; -import { RuleTypeDisabledError } from '../../lib/errors/rule_type_disabled'; -import { RouteOptions } from '..'; -import { countUsageOfPredefinedIds } from '../lib'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; -import { DEFAULT_ALERTING_ROUTE_SECURITY } from '../constants'; - -export const bodySchema = schema.object({ - name: schema.string(), - alertTypeId: schema.string(), - enabled: schema.boolean({ defaultValue: true }), - consumer: schema.string(), - tags: schema.arrayOf(schema.string(), { defaultValue: [] }), - throttle: schema.nullable(schema.string({ validate: validateDurationSchema })), - params: schema.recordOf(schema.string(), schema.any(), { defaultValue: {} }), - schedule: schema.object({ - interval: schema.string({ validate: validateDurationSchema }), - }), - actions: schema.arrayOf( - schema.object({ - group: schema.string(), - id: schema.string(), - actionTypeId: schema.maybe(schema.string()), - params: schema.recordOf(schema.string(), schema.any(), { defaultValue: {} }), - }), - { defaultValue: [] } - ), - notifyWhen: schema.nullable(schema.string({ validate: validateNotifyWhenType })), -}); - -export const createAlertRoute = ({ - router, - licenseState, - usageCounter, - isServerless, - docLinks, -}: RouteOptions) => { - router.post( - { - path: `${LEGACY_BASE_ALERT_API_PATH}/alert/{id?}`, - validate: { - params: schema.maybe( - schema.object({ - id: schema.maybe(schema.string()), - }) - ), - body: bodySchema, - }, - security: DEFAULT_ALERTING_ROUTE_SECURITY, - options: { - access: isServerless ? 'internal' : 'public', - summary: 'Create an alert', - tags: ['oas-tag:alerting'], - deprecated: { - documentationUrl: docLinks.links.alerting.legacyRuleApiDeprecations, - severity: 'warning', - reason: { - type: 'migrate', - newApiMethod: 'POST', - newApiPath: '/api/alerting/rule/{id?}', - }, - }, - }, - }, - handleDisabledApiKeysError( - router.handleLegacyErrors(async function (context, req, res) { - verifyApiAccess(licenseState); - - if (!context.alerting) { - return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); - } - - const alertingContext = await context.alerting; - const rulesClient = await alertingContext.getRulesClient(); - const alert = req.body; - const params = req.params; - const notifyWhen = alert?.notifyWhen ? (alert.notifyWhen as RuleNotifyWhenType) : null; - - trackLegacyRouteUsage('create', usageCounter); - - countUsageOfPredefinedIds({ - predefinedId: params?.id, - spaceId: rulesClient.getSpaceId(), - usageCounter, - }); - - try { - const { systemActions, ...alertRes }: SanitizedRule = - await rulesClient.create({ - data: { ...alert, notifyWhen }, - options: { id: params?.id }, - }); - return res.ok({ - body: alertRes, - }); - } catch (e) { - if (e instanceof RuleTypeDisabledError) { - return e.sendResponse(res); - } - throw e; - } - }) - ) - ); -}; diff --git a/x-pack/plugins/alerting/server/routes/legacy/delete.test.ts b/x-pack/plugins/alerting/server/routes/legacy/delete.test.ts deleted file mode 100644 index d8fd0effc50e4..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/delete.test.ts +++ /dev/null @@ -1,172 +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. - */ - -import { usageCountersServiceMock } from '@kbn/usage-collection-plugin/server/usage_counters/usage_counters_service.mock'; -import { deleteAlertRoute } from './delete'; -import { httpServiceMock } from '@kbn/core/server/mocks'; -import { licenseStateMock } from '../../lib/license_state.mock'; -import { verifyApiAccess } from '../../lib/license_api_access'; -import { mockHandlerArguments } from '../_mock_handler_arguments'; -import { rulesClientMock } from '../../rules_client.mock'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; -import { docLinksServiceMock } from '@kbn/core/server/mocks'; - -const rulesClient = rulesClientMock.create(); - -jest.mock('../../lib/license_api_access', () => ({ - verifyApiAccess: jest.fn(), -})); - -jest.mock('../../lib/track_legacy_route_usage', () => ({ - trackLegacyRouteUsage: jest.fn(), -})); - -beforeEach(() => { - jest.resetAllMocks(); -}); - -describe('deleteAlertRoute', () => { - const docLinks = docLinksServiceMock.createSetupContract(); - - it('deletes an alert with proper parameters', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - deleteAlertRoute(router, licenseState, docLinks); - - const [config, handler] = router.delete.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id}"`); - expect(config.options?.access).toBe('public'); - - rulesClient.delete.mockResolvedValueOnce({}); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: { - id: '1', - }, - }, - ['noContent'] - ); - - expect(await handler(context, req, res)).toEqual(undefined); - - expect(rulesClient.delete).toHaveBeenCalledTimes(1); - expect(rulesClient.delete.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "id": "1", - }, - ] - `); - - expect(res.noContent).toHaveBeenCalled(); - }); - - it('should have internal access for serverless', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - deleteAlertRoute(router, licenseState, docLinks, undefined, true); - - const [config] = router.delete.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id}"`); - expect(config.options?.access).toBe('internal'); - }); - - it('ensures the license allows deleting alerts', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - deleteAlertRoute(router, licenseState, docLinks); - - const [, handler] = router.delete.mock.calls[0]; - - rulesClient.delete.mockResolvedValueOnce({}); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: { id: '1' }, - } - ); - - await handler(context, req, res); - - expect(verifyApiAccess).toHaveBeenCalledWith(licenseState); - }); - - it('ensures the license check prevents deleting alerts', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - (verifyApiAccess as jest.Mock).mockImplementation(() => { - throw new Error('OMG'); - }); - - deleteAlertRoute(router, licenseState, docLinks); - - const [, handler] = router.delete.mock.calls[0]; - - rulesClient.delete.mockResolvedValueOnce({}); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - id: '1', - } - ); - - await expect(handler(context, req, res)).rejects.toMatchInlineSnapshot(`[Error: OMG]`); - - expect(verifyApiAccess).toHaveBeenCalledWith(licenseState); - }); - - it('should track every call', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); - const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test'); - - deleteAlertRoute(router, licenseState, docLinks, mockUsageCounter); - const [, handler] = router.delete.mock.calls[0]; - const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: { id: '1' } }, [ - 'ok', - ]); - await handler(context, req, res); - expect(trackLegacyRouteUsage).toHaveBeenCalledWith('delete', mockUsageCounter); - }); - - it('should be deprecated', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - deleteAlertRoute(router, licenseState, docLinks); - - const [config] = router.delete.mock.calls[0]; - - expect(config.options?.deprecated).toMatchInlineSnapshot( - { - documentationUrl: expect.stringMatching(/#breaking-201550$/), - }, - ` - Object { - "documentationUrl": StringMatching /#breaking-201550\\$/, - "reason": Object { - "newApiMethod": "DELETE", - "newApiPath": "/api/alerting/rule/{id}", - "type": "migrate", - }, - "severity": "warning", - } - ` - ); - }); -}); diff --git a/x-pack/plugins/alerting/server/routes/legacy/delete.ts b/x-pack/plugins/alerting/server/routes/legacy/delete.ts deleted file mode 100644 index 6afa7474d81e6..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/delete.ts +++ /dev/null @@ -1,64 +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. - */ - -import { schema } from '@kbn/config-schema'; -import { UsageCounter } from '@kbn/usage-collection-plugin/server'; -import { DocLinksServiceSetup } from '@kbn/core/server'; -import type { AlertingRouter } from '../../types'; -import { ILicenseState } from '../../lib/license_state'; -import { verifyApiAccess } from '../../lib/license_api_access'; -import { LEGACY_BASE_ALERT_API_PATH } from '../../../common'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; -import { DEFAULT_ALERTING_ROUTE_SECURITY } from '../constants'; - -const paramSchema = schema.object({ - id: schema.string(), -}); - -export const deleteAlertRoute = ( - router: AlertingRouter, - licenseState: ILicenseState, - docLinks: DocLinksServiceSetup, - usageCounter?: UsageCounter, - isServerless?: boolean -) => { - router.delete( - { - path: `${LEGACY_BASE_ALERT_API_PATH}/alert/{id}`, - validate: { - params: paramSchema, - }, - security: DEFAULT_ALERTING_ROUTE_SECURITY, - options: { - access: isServerless ? 'internal' : 'public', - summary: 'Delete an alert', - tags: ['oas-tag:alerting'], - deprecated: { - documentationUrl: docLinks.links.alerting.legacyRuleApiDeprecations, - severity: 'warning', - reason: { - type: 'migrate', - newApiMethod: 'DELETE', - newApiPath: '/api/alerting/rule/{id}', - }, - }, - }, - }, - router.handleLegacyErrors(async function (context, req, res) { - verifyApiAccess(licenseState); - if (!context.alerting) { - return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); - } - trackLegacyRouteUsage('delete', usageCounter); - const alertingContext = await context.alerting; - const rulesClient = await alertingContext.getRulesClient(); - const { id } = req.params; - await rulesClient.delete({ id }); - return res.noContent(); - }) - ); -}; diff --git a/x-pack/plugins/alerting/server/routes/legacy/disable.test.ts b/x-pack/plugins/alerting/server/routes/legacy/disable.test.ts deleted file mode 100644 index 13fec185429ed..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/disable.test.ts +++ /dev/null @@ -1,143 +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. - */ -import { usageCountersServiceMock } from '@kbn/usage-collection-plugin/server/usage_counters/usage_counters_service.mock'; -import { disableAlertRoute } from './disable'; -import { httpServiceMock } from '@kbn/core/server/mocks'; -import { licenseStateMock } from '../../lib/license_state.mock'; -import { mockHandlerArguments } from '../_mock_handler_arguments'; -import { rulesClientMock } from '../../rules_client.mock'; -import { RuleTypeDisabledError } from '../../lib/errors/rule_type_disabled'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; -import { docLinksServiceMock } from '@kbn/core/server/mocks'; - -const rulesClient = rulesClientMock.create(); - -jest.mock('../../lib/license_api_access', () => ({ - verifyApiAccess: jest.fn(), -})); - -jest.mock('../../lib/track_legacy_route_usage', () => ({ - trackLegacyRouteUsage: jest.fn(), -})); - -beforeEach(() => { - jest.resetAllMocks(); -}); - -describe('disableAlertRoute', () => { - const docLinks = docLinksServiceMock.createSetupContract(); - - it('disables an alert', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - disableAlertRoute(router, licenseState, docLinks); - - const [config, handler] = router.post.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id}/_disable"`); - expect(config.options?.access).toBe('public'); - - rulesClient.disableRule.mockResolvedValueOnce(); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: { - id: '1', - }, - }, - ['noContent'] - ); - - expect(await handler(context, req, res)).toEqual(undefined); - - expect(rulesClient.disableRule).toHaveBeenCalledTimes(1); - expect(rulesClient.disableRule.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "id": "1", - }, - ] - `); - - expect(res.noContent).toHaveBeenCalled(); - }); - - it('should have internal access for serverless', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - disableAlertRoute(router, licenseState, docLinks, undefined, true); - - const [config] = router.post.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id}/_disable"`); - expect(config.options?.access).toBe('internal'); - }); - - it('ensures the alert type gets validated for the license', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - disableAlertRoute(router, licenseState, docLinks); - - const [, handler] = router.post.mock.calls[0]; - - rulesClient.disableRule.mockRejectedValue(new RuleTypeDisabledError('Fail', 'license_invalid')); - - const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: {}, body: {} }, [ - 'ok', - 'forbidden', - ]); - - await handler(context, req, res); - - expect(res.forbidden).toHaveBeenCalledWith({ body: { message: 'Fail' } }); - }); - - it('should track every call', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); - const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test'); - - disableAlertRoute(router, licenseState, docLinks, mockUsageCounter); - const [, handler] = router.post.mock.calls[0]; - const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: { id: '1' } }, [ - 'ok', - ]); - await handler(context, req, res); - expect(trackLegacyRouteUsage).toHaveBeenCalledWith('disable', mockUsageCounter); - }); - - it('should be deprecated', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - disableAlertRoute(router, licenseState, docLinks); - - const [config] = router.post.mock.calls[0]; - - expect(config.options?.deprecated).toMatchInlineSnapshot( - { - documentationUrl: expect.stringMatching(/#breaking-201550$/), - }, - ` - Object { - "documentationUrl": StringMatching /#breaking-201550\\$/, - "reason": Object { - "newApiMethod": "POST", - "newApiPath": "/api/alerting/rule/{id}/_disable", - "type": "migrate", - }, - "severity": "warning", - } - ` - ); - }); -}); diff --git a/x-pack/plugins/alerting/server/routes/legacy/disable.ts b/x-pack/plugins/alerting/server/routes/legacy/disable.ts deleted file mode 100644 index 77fe548d06dac..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/disable.ts +++ /dev/null @@ -1,72 +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. - */ - -import { schema } from '@kbn/config-schema'; -import { UsageCounter } from '@kbn/usage-collection-plugin/server'; -import { DocLinksServiceSetup } from '@kbn/core/server'; -import type { AlertingRouter } from '../../types'; -import { ILicenseState } from '../../lib/license_state'; -import { verifyApiAccess } from '../../lib/license_api_access'; -import { LEGACY_BASE_ALERT_API_PATH } from '../../../common'; -import { RuleTypeDisabledError } from '../../lib/errors/rule_type_disabled'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; -import { DEFAULT_ALERTING_ROUTE_SECURITY } from '../constants'; - -const paramSchema = schema.object({ - id: schema.string(), -}); - -export const disableAlertRoute = ( - router: AlertingRouter, - licenseState: ILicenseState, - docLinks: DocLinksServiceSetup, - usageCounter?: UsageCounter, - isServerless?: boolean -) => { - router.post( - { - path: `${LEGACY_BASE_ALERT_API_PATH}/alert/{id}/_disable`, - validate: { - params: paramSchema, - }, - security: DEFAULT_ALERTING_ROUTE_SECURITY, - options: { - access: isServerless ? 'internal' : 'public', - summary: 'Disable an alert', - tags: ['oas-tag:alerting'], - deprecated: { - documentationUrl: docLinks.links.alerting.legacyRuleApiDeprecations, - severity: 'warning', - reason: { - type: 'migrate', - newApiMethod: 'POST', - newApiPath: '/api/alerting/rule/{id}/_disable', - }, - }, - }, - }, - router.handleLegacyErrors(async function (context, req, res) { - verifyApiAccess(licenseState); - if (!context.alerting) { - return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); - } - trackLegacyRouteUsage('disable', usageCounter); - const alertingContext = await context.alerting; - const rulesClient = await alertingContext.getRulesClient(); - const { id } = req.params; - try { - await rulesClient.disableRule({ id }); - return res.noContent(); - } catch (e) { - if (e instanceof RuleTypeDisabledError) { - return e.sendResponse(res); - } - throw e; - } - }) - ); -}; diff --git a/x-pack/plugins/alerting/server/routes/legacy/enable.test.ts b/x-pack/plugins/alerting/server/routes/legacy/enable.test.ts deleted file mode 100644 index 88df304ea07c0..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/enable.test.ts +++ /dev/null @@ -1,143 +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. - */ -import { usageCountersServiceMock } from '@kbn/usage-collection-plugin/server/usage_counters/usage_counters_service.mock'; -import { enableAlertRoute } from './enable'; -import { httpServiceMock } from '@kbn/core/server/mocks'; -import { licenseStateMock } from '../../lib/license_state.mock'; -import { mockHandlerArguments } from '../_mock_handler_arguments'; -import { rulesClientMock } from '../../rules_client.mock'; -import { RuleTypeDisabledError } from '../../lib/errors/rule_type_disabled'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; -import { docLinksServiceMock } from '@kbn/core/server/mocks'; - -const rulesClient = rulesClientMock.create(); - -jest.mock('../../lib/license_api_access', () => ({ - verifyApiAccess: jest.fn(), -})); - -jest.mock('../../lib/track_legacy_route_usage', () => ({ - trackLegacyRouteUsage: jest.fn(), -})); - -beforeEach(() => { - jest.resetAllMocks(); -}); - -describe('enableAlertRoute', () => { - const docLinks = docLinksServiceMock.createSetupContract(); - - it('enables an alert', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - enableAlertRoute(router, licenseState, docLinks); - - const [config, handler] = router.post.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id}/_enable"`); - expect(config.options?.access).toBe('public'); - - rulesClient.enableRule.mockResolvedValueOnce(); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: { - id: '1', - }, - }, - ['noContent'] - ); - - expect(await handler(context, req, res)).toEqual(undefined); - - expect(rulesClient.enableRule).toHaveBeenCalledTimes(1); - expect(rulesClient.enableRule.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "id": "1", - }, - ] - `); - - expect(res.noContent).toHaveBeenCalled(); - }); - - it('should have internal access for serverless', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - enableAlertRoute(router, licenseState, docLinks, undefined, true); - - const [config] = router.post.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id}/_enable"`); - expect(config.options?.access).toBe('internal'); - }); - - it('ensures the alert type gets validated for the license', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - enableAlertRoute(router, licenseState, docLinks); - - const [, handler] = router.post.mock.calls[0]; - - rulesClient.enableRule.mockRejectedValue(new RuleTypeDisabledError('Fail', 'license_invalid')); - - const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: {}, body: {} }, [ - 'ok', - 'forbidden', - ]); - - await handler(context, req, res); - - expect(res.forbidden).toHaveBeenCalledWith({ body: { message: 'Fail' } }); - }); - - it('should track every call', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); - const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test'); - - enableAlertRoute(router, licenseState, docLinks, mockUsageCounter); - const [, handler] = router.post.mock.calls[0]; - const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: { id: '1' } }, [ - 'ok', - ]); - await handler(context, req, res); - expect(trackLegacyRouteUsage).toHaveBeenCalledWith('enable', mockUsageCounter); - }); - - it('should be deprecated', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - enableAlertRoute(router, licenseState, docLinks, undefined, true); - - const [config] = router.post.mock.calls[0]; - - expect(config.options?.deprecated).toMatchInlineSnapshot( - { - documentationUrl: expect.stringMatching(/#breaking-201550$/), - }, - ` - Object { - "documentationUrl": StringMatching /#breaking-201550\\$/, - "reason": Object { - "newApiMethod": "POST", - "newApiPath": "/api/alerting/rule/{id}/_enable", - "type": "migrate", - }, - "severity": "warning", - } - ` - ); - }); -}); diff --git a/x-pack/plugins/alerting/server/routes/legacy/enable.ts b/x-pack/plugins/alerting/server/routes/legacy/enable.ts deleted file mode 100644 index 954c8bc727174..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/enable.ts +++ /dev/null @@ -1,75 +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. - */ - -import { schema } from '@kbn/config-schema'; -import { UsageCounter } from '@kbn/usage-collection-plugin/server'; -import { DocLinksServiceSetup } from '@kbn/core/server'; -import type { AlertingRouter } from '../../types'; -import { ILicenseState } from '../../lib/license_state'; -import { verifyApiAccess } from '../../lib/license_api_access'; -import { LEGACY_BASE_ALERT_API_PATH } from '../../../common'; -import { handleDisabledApiKeysError } from '../lib/error_handler'; -import { RuleTypeDisabledError } from '../../lib/errors/rule_type_disabled'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; -import { DEFAULT_ALERTING_ROUTE_SECURITY } from '../constants'; - -const paramSchema = schema.object({ - id: schema.string(), -}); - -export const enableAlertRoute = ( - router: AlertingRouter, - licenseState: ILicenseState, - docLinks: DocLinksServiceSetup, - usageCounter?: UsageCounter, - isServerless?: boolean -) => { - router.post( - { - path: `${LEGACY_BASE_ALERT_API_PATH}/alert/{id}/_enable`, - validate: { - params: paramSchema, - }, - security: DEFAULT_ALERTING_ROUTE_SECURITY, - options: { - access: isServerless ? 'internal' : 'public', - summary: 'Enable an alert', - tags: ['oas-tag:alerting'], - deprecated: { - documentationUrl: docLinks.links.alerting.legacyRuleApiDeprecations, - severity: 'warning', - reason: { - type: 'migrate', - newApiMethod: 'POST', - newApiPath: '/api/alerting/rule/{id}/_enable', - }, - }, - }, - }, - handleDisabledApiKeysError( - router.handleLegacyErrors(async function (context, req, res) { - verifyApiAccess(licenseState); - if (!context.alerting) { - return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); - } - trackLegacyRouteUsage('enable', usageCounter); - const alertingContext = await context.alerting; - const rulesClient = await alertingContext.getRulesClient(); - const { id } = req.params; - try { - await rulesClient.enableRule({ id }); - return res.noContent(); - } catch (e) { - if (e instanceof RuleTypeDisabledError) { - return e.sendResponse(res); - } - throw e; - } - }) - ) - ); -}; diff --git a/x-pack/plugins/alerting/server/routes/legacy/find.test.ts b/x-pack/plugins/alerting/server/routes/legacy/find.test.ts deleted file mode 100644 index 646f18fa072ea..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/find.test.ts +++ /dev/null @@ -1,439 +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. - */ - -import { omit } from 'lodash'; -import { usageCountersServiceMock } from '@kbn/usage-collection-plugin/server/usage_counters/usage_counters_service.mock'; -import { findAlertRoute } from './find'; -import { httpServiceMock } from '@kbn/core/server/mocks'; -import { licenseStateMock } from '../../lib/license_state.mock'; -import { verifyApiAccess } from '../../lib/license_api_access'; -import { mockHandlerArguments } from '../_mock_handler_arguments'; -import { rulesClientMock } from '../../rules_client.mock'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; -import { trackLegacyTerminology } from '../lib/track_legacy_terminology'; -import { docLinksServiceMock } from '@kbn/core/server/mocks'; - -const rulesClient = rulesClientMock.create(); - -jest.mock('../../lib/license_api_access', () => ({ - verifyApiAccess: jest.fn(), -})); - -jest.mock('../../lib/track_legacy_route_usage', () => ({ - trackLegacyRouteUsage: jest.fn(), -})); - -jest.mock('../lib/track_legacy_terminology', () => ({ - trackLegacyTerminology: jest.fn(), -})); - -beforeEach(() => { - jest.resetAllMocks(); -}); - -describe('findAlertRoute', () => { - const docLinks = docLinksServiceMock.createSetupContract(); - - it('finds alerts with proper parameters', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - findAlertRoute(router, licenseState, docLinks); - - const [config, handler] = router.get.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/_find"`); - expect(config.options?.access).toBe('public'); - - const findResult = { - page: 1, - perPage: 1, - total: 0, - data: [], - }; - rulesClient.find.mockResolvedValueOnce(findResult); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - query: { - per_page: 1, - page: 1, - default_search_operator: 'OR', - }, - }, - ['ok'] - ); - - expect(await handler(context, req, res)).toMatchInlineSnapshot(` - Object { - "body": Object { - "data": Array [], - "page": 1, - "perPage": 1, - "total": 0, - }, - } - `); - - expect(rulesClient.find).toHaveBeenCalledTimes(1); - expect(rulesClient.find.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "excludeFromPublicApi": true, - "options": Object { - "defaultSearchOperator": "OR", - "page": 1, - "perPage": 1, - }, - }, - ] - `); - - expect(res.ok).toHaveBeenCalledWith({ - body: findResult, - }); - }); - - it('should have internal access for serverless', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - findAlertRoute(router, licenseState, docLinks, undefined, true); - - const [config] = router.get.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/_find"`); - expect(config.options?.access).toBe('internal'); - }); - - it('ensures the license allows finding alerts', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - findAlertRoute(router, licenseState, docLinks); - - const [, handler] = router.get.mock.calls[0]; - - rulesClient.find.mockResolvedValueOnce({ - page: 1, - perPage: 1, - total: 0, - data: [], - }); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - query: { - per_page: 1, - page: 1, - default_search_operator: 'OR', - }, - } - ); - - await handler(context, req, res); - - expect(verifyApiAccess).toHaveBeenCalledWith(licenseState); - }); - - it('ensures the license check prevents finding alerts', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - (verifyApiAccess as jest.Mock).mockImplementation(() => { - throw new Error('OMG'); - }); - - findAlertRoute(router, licenseState, docLinks); - - const [, handler] = router.get.mock.calls[0]; - - const [context, req, res] = mockHandlerArguments( - {}, - { - query: { - per_page: 1, - page: 1, - default_search_operator: 'OR', - }, - }, - ['ok'] - ); - await expect(handler(context, req, res)).rejects.toMatchInlineSnapshot(`[Error: OMG]`); - - expect(verifyApiAccess).toHaveBeenCalledWith(licenseState); - }); - - it('should track every call', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); - const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test'); - - findAlertRoute(router, licenseState, docLinks, mockUsageCounter); - const [, handler] = router.get.mock.calls[0]; - const findResult = { - page: 1, - perPage: 1, - total: 0, - data: [], - }; - rulesClient.find.mockResolvedValueOnce(findResult); - const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: {}, query: {} }, [ - 'ok', - ]); - await handler(context, req, res); - expect(trackLegacyRouteUsage).toHaveBeenCalledWith('find', mockUsageCounter); - }); - - it('should track calls with deprecated param values', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); - const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test'); - - findAlertRoute(router, licenseState, docLinks, mockUsageCounter); - const [, handler] = router.get.mock.calls[0]; - - const findResult = { - page: 1, - perPage: 1, - total: 0, - data: [], - }; - rulesClient.find.mockResolvedValueOnce(findResult); - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: {}, - query: { - search_fields: ['alertTypeId:1', 'message:foo'], - search: 'alertTypeId:2', - sort_field: 'alertTypeId', - }, - }, - ['ok'] - ); - await handler(context, req, res); - expect(trackLegacyTerminology).toHaveBeenCalledTimes(1); - expect((trackLegacyTerminology as jest.Mock).mock.calls[0][0]).toStrictEqual([ - 'alertTypeId:2', - ['alertTypeId:1', 'message:foo'], - 'alertTypeId', - ]); - }); - - it('should track calls to deprecated functionality', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); - const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test'); - - findAlertRoute(router, licenseState, docLinks, mockUsageCounter); - const [, handler] = router.get.mock.calls[0]; - const findResult = { - page: 1, - perPage: 1, - total: 0, - data: [], - }; - rulesClient.find.mockResolvedValueOnce(findResult); - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: {}, - query: { - fields: ['foo', 'bar'], - }, - }, - ['ok'] - ); - await handler(context, req, res); - expect(mockUsageCounter.incrementCounter).toHaveBeenCalledWith({ - counterName: `legacyAlertingFieldsUsage`, - counterType: 'alertingFieldsUsage', - incrementBy: 1, - }); - }); - - it('does not return system actions', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - findAlertRoute(router, licenseState, docLinks); - - const [config, handler] = router.get.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/_find"`); - - const findResult = { - page: 1, - perPage: 1, - total: 0, - data: [ - { - id: '3d534c70-582b-11ec-8995-2b1578a3bc5d', - notifyWhen: 'onActiveAlert' as const, - alertTypeId: '.index-threshold', - name: 'stressing index-threshold 37/200', - consumer: 'alerts', - tags: [], - enabled: true, - throttle: null, - apiKey: null, - apiKeyOwner: '2889684073', - createdBy: 'elastic', - updatedBy: '2889684073', - muteAll: false, - mutedInstanceIds: [], - schedule: { - interval: '1s', - }, - actions: [ - { - actionTypeId: '.server-log', - params: { - message: 'alert 37: {{context.message}}', - }, - group: 'threshold met', - id: '3619a0d0-582b-11ec-8995-2b1578a3bc5d', - uuid: '123-456', - }, - ], - systemActions: [ - { actionTypeId: '.test', id: 'system_action-id', params: {}, uuid: '789' }, - ], - params: { x: 42 }, - updatedAt: '2024-03-21T13:15:00.498Z', - createdAt: '2024-03-21T13:15:00.498Z', - scheduledTaskId: '52125fb0-5895-11ec-ae69-bb65d1a71b72', - executionStatus: { - status: 'ok' as const, - lastExecutionDate: '2024-03-21T13:15:00.498Z', - lastDuration: 1194, - }, - revision: 0, - }, - ], - }; - - // @ts-expect-error: TS complains about dates being string and not a Date object - rulesClient.find.mockResolvedValueOnce(findResult); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - query: { - per_page: 1, - page: 1, - default_search_operator: 'OR', - }, - }, - ['ok'] - ); - - expect(await handler(context, req, res)).toMatchInlineSnapshot(` - Object { - "body": Object { - "data": Array [ - Object { - "actions": Array [ - Object { - "actionTypeId": ".server-log", - "group": "threshold met", - "id": "3619a0d0-582b-11ec-8995-2b1578a3bc5d", - "params": Object { - "message": "alert 37: {{context.message}}", - }, - "uuid": "123-456", - }, - ], - "alertTypeId": ".index-threshold", - "apiKey": null, - "apiKeyOwner": "2889684073", - "consumer": "alerts", - "createdAt": "2024-03-21T13:15:00.498Z", - "createdBy": "elastic", - "enabled": true, - "executionStatus": Object { - "lastDuration": 1194, - "lastExecutionDate": "2024-03-21T13:15:00.498Z", - "status": "ok", - }, - "id": "3d534c70-582b-11ec-8995-2b1578a3bc5d", - "muteAll": false, - "mutedInstanceIds": Array [], - "name": "stressing index-threshold 37/200", - "notifyWhen": "onActiveAlert", - "params": Object { - "x": 42, - }, - "revision": 0, - "schedule": Object { - "interval": "1s", - }, - "scheduledTaskId": "52125fb0-5895-11ec-ae69-bb65d1a71b72", - "tags": Array [], - "throttle": null, - "updatedAt": "2024-03-21T13:15:00.498Z", - "updatedBy": "2889684073", - }, - ], - "page": 1, - "perPage": 1, - "total": 0, - }, - } - `); - - expect(rulesClient.find).toHaveBeenCalledTimes(1); - expect(rulesClient.find.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "excludeFromPublicApi": true, - "options": Object { - "defaultSearchOperator": "OR", - "page": 1, - "perPage": 1, - }, - }, - ] - `); - - expect(res.ok).toHaveBeenCalledWith({ - body: omit(findResult, 'data[0].systemActions'), - }); - }); - - it('should be deprecated', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - findAlertRoute(router, licenseState, docLinks); - - const [config] = router.get.mock.calls[0]; - - expect(config.options?.deprecated).toMatchInlineSnapshot( - { - documentationUrl: expect.stringMatching(/#breaking-201550$/), - }, - ` - Object { - "documentationUrl": StringMatching /#breaking-201550\\$/, - "reason": Object { - "newApiMethod": "GET", - "newApiPath": "/api/alerting/rules/_find", - "type": "migrate", - }, - "severity": "warning", - } - ` - ); - }); -}); diff --git a/x-pack/plugins/alerting/server/routes/legacy/find.ts b/x-pack/plugins/alerting/server/routes/legacy/find.ts deleted file mode 100644 index ece93d082f785..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/find.ts +++ /dev/null @@ -1,150 +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. - */ - -import { schema } from '@kbn/config-schema'; -import { UsageCounter } from '@kbn/usage-collection-plugin/server'; -import { estypes } from '@elastic/elasticsearch'; -import { KueryNode } from '@kbn/es-query'; -import { DocLinksServiceSetup } from '@kbn/core/server'; -import type { AlertingRouter } from '../../types'; - -import { ILicenseState } from '../../lib/license_state'; -import { verifyApiAccess } from '../../lib/license_api_access'; -import { LEGACY_BASE_ALERT_API_PATH } from '../../../common'; -import { renameKeys } from '../lib/rename_keys'; -import { IndexType } from '../../rules_client'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; -import { trackLegacyTerminology } from '../lib/track_legacy_terminology'; -import { DEFAULT_ALERTING_ROUTE_SECURITY } from '../constants'; - -export interface FindOptions extends IndexType { - perPage?: number; - page?: number; - search?: string; - defaultSearchOperator?: 'AND' | 'OR'; - searchFields?: string[]; - sortField?: string; - sortOrder?: estypes.SortOrder; - hasReference?: { - type: string; - id: string; - }; - fields?: string[]; - filter?: string | KueryNode; - filterConsumers?: string[]; -} - -// config definition -const querySchema = schema.object({ - per_page: schema.number({ defaultValue: 10, min: 0 }), - page: schema.number({ defaultValue: 1, min: 1 }), - search: schema.maybe(schema.string()), - default_search_operator: schema.oneOf([schema.literal('OR'), schema.literal('AND')], { - defaultValue: 'OR', - }), - search_fields: schema.maybe(schema.oneOf([schema.arrayOf(schema.string()), schema.string()])), - sort_field: schema.maybe(schema.string()), - sort_order: schema.maybe(schema.oneOf([schema.literal('asc'), schema.literal('desc')])), - has_reference: schema.maybe( - // use nullable as maybe is currently broken - // in config-schema - schema.nullable( - schema.object({ - type: schema.string(), - id: schema.string(), - }) - ) - ), - fields: schema.maybe(schema.arrayOf(schema.string())), - filter: schema.maybe(schema.string()), -}); - -export const findAlertRoute = ( - router: AlertingRouter, - licenseState: ILicenseState, - docLinks: DocLinksServiceSetup, - usageCounter?: UsageCounter, - isServerless?: boolean -) => { - router.get( - { - path: `${LEGACY_BASE_ALERT_API_PATH}/_find`, - validate: { - query: querySchema, - }, - security: DEFAULT_ALERTING_ROUTE_SECURITY, - options: { - access: isServerless ? 'internal' : 'public', - summary: 'Find alerts', - tags: ['oas-tag:alerting'], - description: - 'Gets a paginated set of alerts. Alert `params` are stored as a flattened field type and analyzed as keywords. As alerts change in Kibana, the results on each page of the response also change. Use the find API for traditional paginated results, but avoid using it to export large amounts of data.', - deprecated: { - documentationUrl: docLinks.links.alerting.legacyRuleApiDeprecations, - severity: 'warning', - reason: { - type: 'migrate', - newApiMethod: 'GET', - newApiPath: '/api/alerting/rules/_find', - }, - }, - }, - }, - router.handleLegacyErrors(async function (context, req, res) { - verifyApiAccess(licenseState); - if (!context.alerting) { - return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); - } - trackLegacyRouteUsage('find', usageCounter); - trackLegacyTerminology( - [req.query.search, req.query.search_fields, req.query.sort_field].filter( - Boolean - ) as string[], - usageCounter - ); - const alertingContext = await context.alerting; - const rulesClient = await alertingContext.getRulesClient(); - - const query = req.query; - const renameMap = { - default_search_operator: 'defaultSearchOperator', - fields: 'fields', - has_reference: 'hasReference', - page: 'page', - per_page: 'perPage', - search: 'search', - sort_field: 'sortField', - sort_order: 'sortOrder', - filter: 'filter', - }; - - const options = renameKeys>(renameMap, query); - - if (query.search_fields) { - options.searchFields = Array.isArray(query.search_fields) - ? query.search_fields - : [query.search_fields]; - } - - if (query.fields) { - usageCounter?.incrementCounter({ - counterName: `legacyAlertingFieldsUsage`, - counterType: 'alertingFieldsUsage', - incrementBy: 1, - }); - } - - const findResult = await rulesClient.find({ options, excludeFromPublicApi: true }); - return res.ok({ - body: { - ...findResult, - data: findResult.data.map(({ systemActions, ...rule }) => rule), - }, - }); - }) - ); -}; diff --git a/x-pack/plugins/alerting/server/routes/legacy/get.test.ts b/x-pack/plugins/alerting/server/routes/legacy/get.test.ts deleted file mode 100644 index ca8154fc7adae..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/get.test.ts +++ /dev/null @@ -1,243 +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. - */ - -import { usageCountersServiceMock } from '@kbn/usage-collection-plugin/server/usage_counters/usage_counters_service.mock'; -import { getAlertRoute } from './get'; -import { httpServiceMock } from '@kbn/core/server/mocks'; -import { licenseStateMock } from '../../lib/license_state.mock'; -import { verifyApiAccess } from '../../lib/license_api_access'; -import { mockHandlerArguments } from '../_mock_handler_arguments'; -import { rulesClientMock } from '../../rules_client.mock'; -import { Rule, RuleSystemAction } from '../../../common'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; -import { docLinksServiceMock } from '@kbn/core/server/mocks'; - -const rulesClient = rulesClientMock.create(); -jest.mock('../../lib/license_api_access', () => ({ - verifyApiAccess: jest.fn(), -})); - -jest.mock('../../lib/track_legacy_route_usage', () => ({ - trackLegacyRouteUsage: jest.fn(), -})); - -beforeEach(() => { - jest.resetAllMocks(); -}); - -describe('getAlertRoute', () => { - const docLinks = docLinksServiceMock.createSetupContract(); - const mockedAlert: Rule<{ - bar: true; - }> = { - id: '1', - alertTypeId: '1', - schedule: { interval: '10s' }, - params: { - bar: true, - }, - createdAt: new Date(), - updatedAt: new Date(), - actions: [ - { - group: 'default', - id: '2', - actionTypeId: 'test', - params: { - foo: true, - }, - }, - ], - consumer: 'bar', - name: 'abc', - tags: ['foo'], - enabled: true, - muteAll: false, - notifyWhen: 'onActionGroupChange', - createdBy: '', - updatedBy: '', - apiKey: '', - apiKeyOwner: '', - throttle: '30s', - mutedInstanceIds: [], - executionStatus: { - status: 'unknown', - lastExecutionDate: new Date('2020-08-20T19:23:38Z'), - }, - revision: 0, - }; - - const systemAction: RuleSystemAction = { - actionTypeId: 'test-2', - id: 'system_action-id', - params: { - foo: true, - }, - uuid: '123-456', - }; - - it('gets an alert with proper parameters', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - getAlertRoute(router, licenseState, docLinks); - const [config, handler] = router.get.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id}"`); - expect(config.options?.access).toBe('public'); - - rulesClient.get.mockResolvedValueOnce(mockedAlert); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: { id: '1' }, - }, - ['ok'] - ); - await handler(context, req, res); - - expect(rulesClient.get).toHaveBeenCalledTimes(1); - expect(rulesClient.get.mock.calls[0][0].id).toEqual('1'); - - expect(res.ok).toHaveBeenCalledWith({ - body: mockedAlert, - }); - }); - - it('should have internal access for serverless', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - getAlertRoute(router, licenseState, docLinks, undefined, true); - const [config] = router.get.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id}"`); - expect(config.options?.access).toBe('internal'); - }); - - it('ensures the license allows getting alerts', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - getAlertRoute(router, licenseState, docLinks); - - const [, handler] = router.get.mock.calls[0]; - - rulesClient.get.mockResolvedValueOnce(mockedAlert); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: { id: '1' }, - }, - ['ok'] - ); - - await handler(context, req, res); - - expect(verifyApiAccess).toHaveBeenCalledWith(licenseState); - }); - - it('ensures the license check prevents getting alerts', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - (verifyApiAccess as jest.Mock).mockImplementation(() => { - throw new Error('OMG'); - }); - - getAlertRoute(router, licenseState, docLinks); - - const [, handler] = router.get.mock.calls[0]; - - rulesClient.get.mockResolvedValueOnce(mockedAlert); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: { id: '1' }, - }, - ['ok'] - ); - - await expect(handler(context, req, res)).rejects.toMatchInlineSnapshot(`[Error: OMG]`); - - expect(verifyApiAccess).toHaveBeenCalledWith(licenseState); - }); - - it('should track every call', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); - const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test'); - - getAlertRoute(router, licenseState, docLinks, mockUsageCounter); - const [, handler] = router.get.mock.calls[0]; - - rulesClient.get.mockResolvedValueOnce(mockedAlert); - - const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: { id: '1' } }, [ - 'ok', - ]); - await handler(context, req, res); - expect(trackLegacyRouteUsage).toHaveBeenCalledWith('get', mockUsageCounter); - }); - - it('does not return system actions', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - getAlertRoute(router, licenseState, docLinks); - const [config, handler] = router.get.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id}"`); - - rulesClient.get.mockResolvedValueOnce({ ...mockedAlert, systemActions: [systemAction] }); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: { id: '1' }, - }, - ['ok'] - ); - await handler(context, req, res); - - expect(rulesClient.get).toHaveBeenCalledTimes(1); - expect(rulesClient.get.mock.calls[0][0].id).toEqual('1'); - - expect(res.ok).toHaveBeenCalledWith({ - body: mockedAlert, - }); - }); - - it('should be deprecated', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - getAlertRoute(router, licenseState, docLinks); - const [config] = router.get.mock.calls[0]; - - expect(config.options?.deprecated).toMatchInlineSnapshot( - { - documentationUrl: expect.stringMatching(/#breaking-201550$/), - }, - ` - Object { - "documentationUrl": StringMatching /#breaking-201550\\$/, - "reason": Object { - "newApiMethod": "GET", - "newApiPath": "/api/alerting/rule/{id}", - "type": "migrate", - }, - "severity": "warning", - } - ` - ); - }); -}); diff --git a/x-pack/plugins/alerting/server/routes/legacy/get.ts b/x-pack/plugins/alerting/server/routes/legacy/get.ts deleted file mode 100644 index f1f83a5084c44..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/get.ts +++ /dev/null @@ -1,66 +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. - */ - -import { schema } from '@kbn/config-schema'; -import { UsageCounter } from '@kbn/usage-collection-plugin/server'; -import { DocLinksServiceSetup } from '@kbn/core/server'; -import { ILicenseState } from '../../lib/license_state'; -import { verifyApiAccess } from '../../lib/license_api_access'; -import { LEGACY_BASE_ALERT_API_PATH } from '../../../common'; -import type { AlertingRouter } from '../../types'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; -import { DEFAULT_ALERTING_ROUTE_SECURITY } from '../constants'; - -const paramSchema = schema.object({ - id: schema.string(), -}); - -export const getAlertRoute = ( - router: AlertingRouter, - licenseState: ILicenseState, - docLinks: DocLinksServiceSetup, - usageCounter?: UsageCounter, - isServerless?: boolean -) => { - router.get( - { - path: `${LEGACY_BASE_ALERT_API_PATH}/alert/{id}`, - validate: { - params: paramSchema, - }, - security: DEFAULT_ALERTING_ROUTE_SECURITY, - options: { - access: isServerless ? 'internal' : 'public', - summary: 'Get an alert', - tags: ['oas-tag:alerting'], - deprecated: { - documentationUrl: docLinks.links.alerting.legacyRuleApiDeprecations, - severity: 'warning', - reason: { - type: 'migrate', - newApiMethod: 'GET', - newApiPath: '/api/alerting/rule/{id}', - }, - }, - }, - }, - router.handleLegacyErrors(async function (context, req, res) { - verifyApiAccess(licenseState); - if (!context.alerting) { - return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); - } - trackLegacyRouteUsage('get', usageCounter); - const alertingContext = await context.alerting; - const rulesClient = await alertingContext.getRulesClient(); - const { id } = req.params; - const { systemActions, ...rule } = await rulesClient.get({ id, excludeFromPublicApi: true }); - return res.ok({ - body: rule, - }); - }) - ); -}; 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 deleted file mode 100644 index cc3deaad9af99..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/get_alert_instance_summary.test.ts +++ /dev/null @@ -1,177 +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. - */ -import { usageCountersServiceMock } from '@kbn/usage-collection-plugin/server/usage_counters/usage_counters_service.mock'; -import { getAlertInstanceSummaryRoute } from './get_alert_instance_summary'; -import { httpServiceMock } from '@kbn/core/server/mocks'; -import { licenseStateMock } from '../../lib/license_state.mock'; -import { mockHandlerArguments } from '../_mock_handler_arguments'; -import { SavedObjectsErrorHelpers } from '@kbn/core/server'; -import { rulesClientMock } from '../../rules_client.mock'; -import { AlertSummary } from '../../types'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; -import { RULE_SAVED_OBJECT_TYPE } from '../../saved_objects'; -import { docLinksServiceMock } from '@kbn/core/server/mocks'; - -const rulesClient = rulesClientMock.create(); -jest.mock('../../lib/license_api_access', () => ({ - verifyApiAccess: jest.fn(), -})); - -jest.mock('../../lib/track_legacy_route_usage', () => ({ - trackLegacyRouteUsage: jest.fn(), -})); - -beforeEach(() => { - jest.resetAllMocks(); -}); - -describe('getAlertInstanceSummaryRoute', () => { - const docLinks = docLinksServiceMock.createSetupContract(); - const dateString = new Date().toISOString(); - const mockedAlertInstanceSummary: AlertSummary = { - id: '', - name: '', - tags: [], - ruleTypeId: '', - consumer: '', - muteAll: false, - throttle: null, - enabled: false, - statusStartDate: dateString, - statusEndDate: dateString, - status: 'OK', - errorMessages: [], - alerts: {}, - executionDuration: { - average: 0, - valuesWithTimestamp: {}, - }, - revision: 0, - }; - - it('gets alert instance summary', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - getAlertInstanceSummaryRoute(router, licenseState, docLinks); - - const [config, handler] = router.get.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id}/_instance_summary"`); - expect(config.options?.access).toBe('public'); - - rulesClient.getAlertSummary.mockResolvedValueOnce(mockedAlertInstanceSummary); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: { - id: '1', - }, - query: {}, - }, - ['ok'] - ); - - await handler(context, req, res); - - expect(rulesClient.getAlertSummary).toHaveBeenCalledTimes(1); - expect(rulesClient.getAlertSummary.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "dateStart": undefined, - "id": "1", - }, - ] - `); - - expect(res.ok).toHaveBeenCalled(); - }); - - it('should have internal access for serverless', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - getAlertInstanceSummaryRoute(router, licenseState, docLinks, undefined, true); - - const [config] = router.get.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id}/_instance_summary"`); - expect(config.options?.access).toBe('internal'); - }); - - it('returns NOT-FOUND when alert is not found', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - getAlertInstanceSummaryRoute(router, licenseState, docLinks); - - const [, handler] = router.get.mock.calls[0]; - - rulesClient.getAlertSummary = jest - .fn() - .mockResolvedValueOnce( - SavedObjectsErrorHelpers.createGenericNotFoundError(RULE_SAVED_OBJECT_TYPE, '1') - ); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: { - id: '1', - }, - query: {}, - }, - ['notFound'] - ); - - expect(await handler(context, req, res)).toEqual(undefined); - }); - - it('should track every call', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); - const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test'); - - getAlertInstanceSummaryRoute(router, licenseState, docLinks, mockUsageCounter); - const [, handler] = router.get.mock.calls[0]; - - rulesClient.getAlertSummary.mockResolvedValueOnce(mockedAlertInstanceSummary); - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { params: { id: '1' }, query: {} }, - ['ok'] - ); - await handler(context, req, res); - expect(trackLegacyRouteUsage).toHaveBeenCalledWith('instanceSummary', mockUsageCounter); - }); - - it('should be deprecated', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - getAlertInstanceSummaryRoute(router, licenseState, docLinks); - - const [config] = router.get.mock.calls[0]; - - expect(config.options?.deprecated).toMatchInlineSnapshot( - { - documentationUrl: expect.stringMatching(/#breaking-201550$/), - }, - ` - Object { - "documentationUrl": StringMatching /#breaking-201550\\$/, - "reason": Object { - "type": "remove", - }, - "severity": "warning", - } - ` - ); - }); -}); diff --git a/x-pack/plugins/alerting/server/routes/legacy/get_alert_instance_summary.ts b/x-pack/plugins/alerting/server/routes/legacy/get_alert_instance_summary.ts deleted file mode 100644 index 918cdabc25a34..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/get_alert_instance_summary.ts +++ /dev/null @@ -1,75 +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. - */ - -import { schema } from '@kbn/config-schema'; -import { UsageCounter } from '@kbn/usage-collection-plugin/server'; -import { DocLinksServiceSetup } from '@kbn/core/server'; -import type { AlertingRouter } from '../../types'; -import { ILicenseState } from '../../lib/license_state'; -import { verifyApiAccess } from '../../lib/license_api_access'; -import { AlertSummary, LEGACY_BASE_ALERT_API_PATH } from '../../../common'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; -import { DEFAULT_ALERTING_ROUTE_SECURITY } from '../constants'; - -const paramSchema = schema.object({ - id: schema.string(), -}); - -const querySchema = schema.object({ - dateStart: schema.maybe(schema.string()), -}); - -const rewriteBodyRes = ({ ruleTypeId, alerts, ...rest }: AlertSummary) => ({ - ...rest, - alertTypeId: ruleTypeId, - instances: alerts, -}); - -export const getAlertInstanceSummaryRoute = ( - router: AlertingRouter, - licenseState: ILicenseState, - docLinks: DocLinksServiceSetup, - usageCounter?: UsageCounter, - isServerless?: boolean -) => { - router.get( - { - path: `${LEGACY_BASE_ALERT_API_PATH}/alert/{id}/_instance_summary`, - validate: { - params: paramSchema, - query: querySchema, - }, - security: DEFAULT_ALERTING_ROUTE_SECURITY, - options: { - access: isServerless ? 'internal' : 'public', - summary: 'Get an alert summary', - tags: ['oas-tag:alerting'], - deprecated: { - documentationUrl: docLinks.links.alerting.legacyRuleApiDeprecations, - severity: 'warning', - reason: { - type: 'remove', - }, - }, - }, - }, - router.handleLegacyErrors(async function (context, req, res) { - verifyApiAccess(licenseState); - if (!context.alerting) { - return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); - } - trackLegacyRouteUsage('instanceSummary', usageCounter); - const alertingContext = await context.alerting; - const rulesClient = await alertingContext.getRulesClient(); - const { id } = req.params; - const { dateStart } = req.query; - const summary = await rulesClient.getAlertSummary({ id, dateStart }); - - return res.ok({ body: rewriteBodyRes(summary) }); - }) - ); -}; diff --git a/x-pack/plugins/alerting/server/routes/legacy/get_alert_state.test.ts b/x-pack/plugins/alerting/server/routes/legacy/get_alert_state.test.ts deleted file mode 100644 index ca79291b23dbc..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/get_alert_state.test.ts +++ /dev/null @@ -1,212 +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. - */ -import { usageCountersServiceMock } from '@kbn/usage-collection-plugin/server/usage_counters/usage_counters_service.mock'; -import { getAlertStateRoute } from './get_alert_state'; -import { httpServiceMock } from '@kbn/core/server/mocks'; -import { licenseStateMock } from '../../lib/license_state.mock'; -import { mockHandlerArguments } from '../_mock_handler_arguments'; -import { SavedObjectsErrorHelpers } from '@kbn/core/server'; -import { rulesClientMock } from '../../rules_client.mock'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; -import { RULE_SAVED_OBJECT_TYPE } from '../../saved_objects'; -import { docLinksServiceMock } from '@kbn/core/server/mocks'; - -const rulesClient = rulesClientMock.create(); -jest.mock('../../lib/license_api_access', () => ({ - verifyApiAccess: jest.fn(), -})); - -jest.mock('../../lib/track_legacy_route_usage', () => ({ - trackLegacyRouteUsage: jest.fn(), -})); - -beforeEach(() => { - jest.resetAllMocks(); -}); - -describe('getAlertStateRoute', () => { - const docLinks = docLinksServiceMock.createSetupContract(); - const mockedAlertState = { - alertTypeState: { - some: 'value', - }, - alertInstances: { - first_instance: { - state: {}, - meta: { - lastScheduledActions: { - group: 'first_group', - date: new Date().toISOString(), - }, - }, - }, - second_instance: {}, - }, - }; - - it('gets alert state', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - getAlertStateRoute(router, licenseState, docLinks); - - const [config, handler] = router.get.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id}/state"`); - expect(config.options?.access).toBe('public'); - - rulesClient.getAlertState.mockResolvedValueOnce(mockedAlertState); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: { - id: '1', - }, - }, - ['ok'] - ); - - await handler(context, req, res); - - expect(rulesClient.getAlertState).toHaveBeenCalledTimes(1); - expect(rulesClient.getAlertState.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "id": "1", - }, - ] - `); - - expect(res.ok).toHaveBeenCalled(); - }); - - it('should have internal access for serverless', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - getAlertStateRoute(router, licenseState, docLinks, undefined, true); - - const [config] = router.get.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id}/state"`); - expect(config.options?.access).toBe('internal'); - }); - - it('returns NO-CONTENT when alert exists but has no task state yet', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - getAlertStateRoute(router, licenseState, docLinks); - - const [config, handler] = router.get.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id}/state"`); - - rulesClient.getAlertState.mockResolvedValueOnce(undefined); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: { - id: '1', - }, - }, - ['noContent'] - ); - - expect(await handler(context, req, res)).toEqual(undefined); - - expect(rulesClient.getAlertState).toHaveBeenCalledTimes(1); - expect(rulesClient.getAlertState.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "id": "1", - }, - ] - `); - - expect(res.noContent).toHaveBeenCalled(); - }); - - it('returns NOT-FOUND when alert is not found', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - getAlertStateRoute(router, licenseState, docLinks); - - const [config, handler] = router.get.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id}/state"`); - - rulesClient.getAlertState = jest - .fn() - .mockResolvedValueOnce( - SavedObjectsErrorHelpers.createGenericNotFoundError(RULE_SAVED_OBJECT_TYPE, '1') - ); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: { - id: '1', - }, - }, - ['notFound'] - ); - - expect(await handler(context, req, res)).toEqual(undefined); - - expect(rulesClient.getAlertState).toHaveBeenCalledTimes(1); - expect(rulesClient.getAlertState.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "id": "1", - }, - ] - `); - }); - - it('should track every call', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); - const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test'); - - getAlertStateRoute(router, licenseState, docLinks, mockUsageCounter); - const [, handler] = router.get.mock.calls[0]; - const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: { id: '1' } }, [ - 'ok', - ]); - await handler(context, req, res); - expect(trackLegacyRouteUsage).toHaveBeenCalledWith('state', mockUsageCounter); - }); - - it('should be deprecated', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - getAlertStateRoute(router, licenseState, docLinks); - - const [config] = router.get.mock.calls[0]; - - expect(config.options?.deprecated).toMatchInlineSnapshot( - { - documentationUrl: expect.stringMatching(/#breaking-201550$/), - }, - ` - Object { - "documentationUrl": StringMatching /#breaking-201550\\$/, - "reason": Object { - "type": "remove", - }, - "severity": "warning", - } - ` - ); - }); -}); diff --git a/x-pack/plugins/alerting/server/routes/legacy/get_alert_state.ts b/x-pack/plugins/alerting/server/routes/legacy/get_alert_state.ts deleted file mode 100644 index fbc82e560a45e..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/get_alert_state.ts +++ /dev/null @@ -1,62 +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. - */ - -import { schema } from '@kbn/config-schema'; -import { UsageCounter } from '@kbn/usage-collection-plugin/server'; -import { DocLinksServiceSetup } from '@kbn/core/server'; -import type { AlertingRouter } from '../../types'; -import { ILicenseState } from '../../lib/license_state'; -import { verifyApiAccess } from '../../lib/license_api_access'; -import { LEGACY_BASE_ALERT_API_PATH } from '../../../common'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; -import { DEFAULT_ALERTING_ROUTE_SECURITY } from '../constants'; - -const paramSchema = schema.object({ - id: schema.string(), -}); - -export const getAlertStateRoute = ( - router: AlertingRouter, - licenseState: ILicenseState, - docLinks: DocLinksServiceSetup, - usageCounter?: UsageCounter, - isServerless?: boolean -) => { - router.get( - { - path: `${LEGACY_BASE_ALERT_API_PATH}/alert/{id}/state`, - validate: { - params: paramSchema, - }, - security: DEFAULT_ALERTING_ROUTE_SECURITY, - options: { - access: isServerless ? 'internal' : 'public', - summary: 'Get the state of an alert', - tags: ['oas-tag:alerting'], - deprecated: { - documentationUrl: docLinks.links.alerting.legacyRuleApiDeprecations, - severity: 'warning', - reason: { - type: 'remove', - }, - }, - }, - }, - router.handleLegacyErrors(async function (context, req, res) { - verifyApiAccess(licenseState); - if (!context.alerting) { - return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); - } - trackLegacyRouteUsage('state', usageCounter); - const alertingContext = await context.alerting; - const rulesClient = await alertingContext.getRulesClient(); - const { id } = req.params; - const state = await rulesClient.getAlertState({ id }); - return state ? res.ok({ body: state }) : res.noContent(); - }) - ); -}; diff --git a/x-pack/plugins/alerting/server/routes/legacy/health.test.ts b/x-pack/plugins/alerting/server/routes/legacy/health.test.ts deleted file mode 100644 index fea24b831e97d..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/health.test.ts +++ /dev/null @@ -1,473 +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. - */ -import { usageCountersServiceMock } from '@kbn/usage-collection-plugin/server/usage_counters/usage_counters_service.mock'; -import { HealthStatus } from '@kbn/alerting-types'; -import { healthRoute } from './health'; -import { httpServiceMock } from '@kbn/core/server/mocks'; -import { mockHandlerArguments } from '../_mock_handler_arguments'; -import { licenseStateMock } from '../../lib/license_state.mock'; -import { encryptedSavedObjectsMock } from '@kbn/encrypted-saved-objects-plugin/server/mocks'; -import { rulesClientMock } from '../../rules_client.mock'; -import { RecoveredActionGroup } from '../../types'; -import { alertsMock } from '../../mocks'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; -import { RegistryAlertTypeWithAuth } from '../../authorization'; -import { docLinksServiceMock } from '@kbn/core/server/mocks'; - -const rulesClient = rulesClientMock.create(); - -jest.mock('../../lib/license_api_access', () => ({ - verifyApiAccess: jest.fn(), -})); - -jest.mock('../../lib/track_legacy_route_usage', () => ({ - trackLegacyRouteUsage: jest.fn(), -})); - -const alerting = alertsMock.createStart(); - -const currentDate = new Date().toISOString(); - -const ruleTypes = [ - { - id: '1', - name: 'name', - actionGroups: [ - { - id: 'default', - name: 'Default', - }, - ], - defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic', - isExportable: true, - ruleTaskTimeout: '10m', - recoveryActionGroup: RecoveredActionGroup, - authorizedConsumers: {}, - actionVariables: { - context: [], - state: [], - }, - category: 'test', - producer: 'test', - enabledInLicense: true, - defaultScheduleInterval: '10m', - hasAlertsMappings: false, - hasFieldsForAAD: false, - validLegacyConsumers: [], - } as RegistryAlertTypeWithAuth, -]; - -beforeEach(() => { - jest.resetAllMocks(); - alerting.getFrameworkHealth.mockResolvedValue({ - decryptionHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - executionHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - readHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - }); -}); - -describe('healthRoute', () => { - const docLinks = docLinksServiceMock.createSetupContract(); - - it('registers the route', async () => { - rulesClient.listRuleTypes.mockResolvedValueOnce(ruleTypes); - const router = httpServiceMock.createRouter(); - - const licenseState = licenseStateMock.create(); - const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true }); - healthRoute(router, licenseState, encryptedSavedObjects, docLinks); - - const [config] = router.get.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/_health"`); - expect(config.options?.access).toBe('public'); - }); - - it('should have internal access for serverless', async () => { - rulesClient.listRuleTypes.mockResolvedValueOnce(ruleTypes); - const router = httpServiceMock.createRouter(); - - const licenseState = licenseStateMock.create(); - const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true }); - healthRoute(router, licenseState, encryptedSavedObjects, docLinks, undefined, true); - - const [config] = router.get.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/_health"`); - expect(config.options?.access).toBe('internal'); - }); - - it('throws error when user does not have any access to any rule types', async () => { - rulesClient.listRuleTypes.mockResolvedValueOnce([]); - const router = httpServiceMock.createRouter(); - - const licenseState = licenseStateMock.create(); - const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: false }); - healthRoute(router, licenseState, encryptedSavedObjects, docLinks); - const [, handler] = router.get.mock.calls[0]; - - const [context, req, res] = mockHandlerArguments( - { - rulesClient, - getFrameworkHealth: alerting.getFrameworkHealth, - areApiKeysEnabled: () => Promise.resolve(true), - }, - {}, - ['ok'] - ); - - await handler(context, req, res); - - expect(res.forbidden).toHaveBeenCalledWith({ - body: { message: `Unauthorized to access alerting framework health` }, - }); - }); - - it('evaluates whether Encrypted Saved Objects is missing encryption key', async () => { - rulesClient.listRuleTypes.mockResolvedValueOnce(ruleTypes); - const router = httpServiceMock.createRouter(); - - const licenseState = licenseStateMock.create(); - const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: false }); - healthRoute(router, licenseState, encryptedSavedObjects, docLinks); - const [, handler] = router.get.mock.calls[0]; - - const [context, req, res] = mockHandlerArguments( - { - rulesClient, - getFrameworkHealth: alerting.getFrameworkHealth, - areApiKeysEnabled: () => Promise.resolve(true), - }, - {}, - ['ok'] - ); - - expect(await handler(context, req, res)).toStrictEqual({ - body: { - alertingFrameworkHeath: { - // Legacy: pre-v8.0 typo - _deprecated: 'This state property has a typo, use "alertingFrameworkHealth" instead.', - decryptionHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - executionHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - readHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - }, - alertingFrameworkHealth: { - decryptionHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - executionHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - readHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - }, - hasPermanentEncryptionKey: false, - isSufficientlySecure: true, - }, - }); - }); - - test('when ES security status cannot be determined from license state, isSufficientlySecure should return false', async () => { - rulesClient.listRuleTypes.mockResolvedValueOnce(ruleTypes); - const router = httpServiceMock.createRouter(); - const licenseState = licenseStateMock.create(); - const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true }); - licenseState.getIsSecurityEnabled.mockReturnValueOnce(null); - - healthRoute(router, licenseState, encryptedSavedObjects, docLinks); - const [, handler] = router.get.mock.calls[0]; - - const [context, req, res] = mockHandlerArguments( - { - rulesClient, - getFrameworkHealth: alerting.getFrameworkHealth, - areApiKeysEnabled: () => Promise.resolve(true), - }, - {}, - ['ok'] - ); - - expect(await handler(context, req, res)).toStrictEqual({ - body: { - alertingFrameworkHeath: { - // Legacy: pre-v8.0 typo - _deprecated: 'This state property has a typo, use "alertingFrameworkHealth" instead.', - decryptionHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - executionHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - readHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - }, - alertingFrameworkHealth: { - decryptionHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - executionHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - readHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - }, - hasPermanentEncryptionKey: true, - isSufficientlySecure: false, - }, - }); - }); - - test('when ES security is disabled, isSufficientlySecure should return true', async () => { - rulesClient.listRuleTypes.mockResolvedValueOnce(ruleTypes); - const router = httpServiceMock.createRouter(); - const licenseState = licenseStateMock.create(); - const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true }); - licenseState.getIsSecurityEnabled.mockReturnValueOnce(false); - - healthRoute(router, licenseState, encryptedSavedObjects, docLinks); - const [, handler] = router.get.mock.calls[0]; - - const [context, req, res] = mockHandlerArguments( - { - rulesClient, - getFrameworkHealth: alerting.getFrameworkHealth, - areApiKeysEnabled: () => Promise.resolve(false), - }, - {}, - ['ok'] - ); - - expect(await handler(context, req, res)).toStrictEqual({ - body: { - alertingFrameworkHeath: { - // Legacy: pre-v8.0 typo - _deprecated: 'This state property has a typo, use "alertingFrameworkHealth" instead.', - decryptionHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - executionHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - readHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - }, - alertingFrameworkHealth: { - decryptionHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - executionHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - readHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - }, - hasPermanentEncryptionKey: true, - isSufficientlySecure: true, - }, - }); - }); - - test('when ES security is enabled but user cannot generate api keys, isSufficientlySecure should return false', async () => { - rulesClient.listRuleTypes.mockResolvedValueOnce(ruleTypes); - const router = httpServiceMock.createRouter(); - const licenseState = licenseStateMock.create(); - const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true }); - licenseState.getIsSecurityEnabled.mockReturnValueOnce(true); - - healthRoute(router, licenseState, encryptedSavedObjects, docLinks); - const [, handler] = router.get.mock.calls[0]; - - const [context, req, res] = mockHandlerArguments( - { - rulesClient, - getFrameworkHealth: alerting.getFrameworkHealth, - areApiKeysEnabled: () => Promise.resolve(false), - }, - {}, - ['ok'] - ); - - expect(await handler(context, req, res)).toStrictEqual({ - body: { - alertingFrameworkHeath: { - // Legacy: pre-v8.0 typo - _deprecated: 'This state property has a typo, use "alertingFrameworkHealth" instead.', - decryptionHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - executionHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - readHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - }, - alertingFrameworkHealth: { - decryptionHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - executionHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - readHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - }, - hasPermanentEncryptionKey: true, - isSufficientlySecure: false, - }, - }); - }); - - test('when ES security is enabled and user can generate api keys, isSufficientlySecure should return true', async () => { - rulesClient.listRuleTypes.mockResolvedValueOnce(ruleTypes); - const router = httpServiceMock.createRouter(); - const licenseState = licenseStateMock.create(); - const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true }); - licenseState.getIsSecurityEnabled.mockReturnValueOnce(true); - - healthRoute(router, licenseState, encryptedSavedObjects, docLinks); - const [, handler] = router.get.mock.calls[0]; - - const [context, req, res] = mockHandlerArguments( - { - rulesClient, - getFrameworkHealth: alerting.getFrameworkHealth, - areApiKeysEnabled: () => Promise.resolve(true), - }, - {}, - ['ok'] - ); - - expect(await handler(context, req, res)).toStrictEqual({ - body: { - alertingFrameworkHeath: { - // Legacy: pre-v8.0 typo - _deprecated: 'This state property has a typo, use "alertingFrameworkHealth" instead.', - decryptionHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - executionHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - readHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - }, - alertingFrameworkHealth: { - decryptionHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - executionHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - readHealth: { - status: HealthStatus.OK, - timestamp: currentDate, - }, - }, - hasPermanentEncryptionKey: true, - isSufficientlySecure: true, - }, - }); - }); - - it('should track every call', async () => { - rulesClient.listRuleTypes.mockResolvedValueOnce(ruleTypes); - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true }); - const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); - const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test'); - - healthRoute(router, licenseState, encryptedSavedObjects, docLinks, mockUsageCounter); - const [, handler] = router.get.mock.calls[0]; - const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: { id: '1' } }, [ - 'ok', - ]); - await handler(context, req, res); - expect(trackLegacyRouteUsage).toHaveBeenCalledWith('health', mockUsageCounter); - }); - - it('should be deprecated', async () => { - rulesClient.listRuleTypes.mockResolvedValueOnce(ruleTypes); - const router = httpServiceMock.createRouter(); - - const licenseState = licenseStateMock.create(); - const encryptedSavedObjects = encryptedSavedObjectsMock.createSetup({ canEncrypt: true }); - healthRoute(router, licenseState, encryptedSavedObjects, docLinks); - - const [config] = router.get.mock.calls[0]; - - expect(config.options?.deprecated).toMatchInlineSnapshot( - { - documentationUrl: expect.stringMatching(/#breaking-201550$/), - }, - ` - Object { - "documentationUrl": StringMatching /#breaking-201550\\$/, - "reason": Object { - "newApiMethod": "GET", - "newApiPath": "/api/alerting/rule/_health", - "type": "migrate", - }, - "severity": "warning", - } - ` - ); - }); -}); diff --git a/x-pack/plugins/alerting/server/routes/legacy/health.ts b/x-pack/plugins/alerting/server/routes/legacy/health.ts deleted file mode 100644 index 8b8a64df14cd1..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/health.ts +++ /dev/null @@ -1,93 +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. - */ - -import { UsageCounter } from '@kbn/usage-collection-plugin/server'; -import { EncryptedSavedObjectsPluginSetup } from '@kbn/encrypted-saved-objects-plugin/server'; -import { DocLinksServiceSetup } from '@kbn/core/server'; -import type { AlertingRouter } from '../../types'; -import { ILicenseState } from '../../lib/license_state'; -import { verifyApiAccess } from '../../lib/license_api_access'; -import { AlertingFrameworkHealth } from '../../types'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; -import { getSecurityHealth } from '../../lib/get_security_health'; -import { DEFAULT_ALERTING_ROUTE_SECURITY } from '../constants'; - -export function healthRoute( - router: AlertingRouter, - licenseState: ILicenseState, - encryptedSavedObjects: EncryptedSavedObjectsPluginSetup, - docLinks: DocLinksServiceSetup, - usageCounter?: UsageCounter, - isServerless?: boolean -) { - router.get( - { - path: '/api/alerts/_health', - validate: false, - security: DEFAULT_ALERTING_ROUTE_SECURITY, - options: { - access: isServerless ? 'internal' : 'public', - summary: 'Get the alerting framework health', - tags: ['oas-tag:alerting'], - deprecated: { - documentationUrl: docLinks.links.alerting.legacyRuleApiDeprecations, - severity: 'warning', - reason: { - type: 'migrate', - newApiMethod: 'GET', - newApiPath: '/api/alerting/rule/_health', - }, - }, - }, - }, - router.handleLegacyErrors(async function (context, req, res) { - verifyApiAccess(licenseState); - if (!context.alerting) { - return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); - } - trackLegacyRouteUsage('health', usageCounter); - try { - const alertingContext = await context.alerting; - const rulesClient = await alertingContext.getRulesClient(); - // Verify that user has access to at least one rule type - const ruleTypes = Array.from(await rulesClient.listRuleTypes()); - if (ruleTypes.length > 0) { - const alertingFrameworkHealth = await alertingContext.getFrameworkHealth(); - - const securityHealth = await getSecurityHealth( - async () => (licenseState ? licenseState.getIsSecurityEnabled() : null), - async () => encryptedSavedObjects.canEncrypt, - alertingContext.areApiKeysEnabled - ); - - const frameworkHealth: AlertingFrameworkHealth = { - ...securityHealth, - alertingFrameworkHealth, - }; - - return res.ok({ - body: { - ...frameworkHealth, - alertingFrameworkHeath: { - // Legacy: pre-v8.0 typo - ...alertingFrameworkHealth, - _deprecated: - 'This state property has a typo, use "alertingFrameworkHealth" instead.', - }, - }, - }); - } else { - return res.forbidden({ - body: { message: `Unauthorized to access alerting framework health` }, - }); - } - } catch (error) { - return res.badRequest({ body: error }); - } - }) - ); -} diff --git a/x-pack/plugins/alerting/server/routes/legacy/index.ts b/x-pack/plugins/alerting/server/routes/legacy/index.ts deleted file mode 100644 index e9551d938e6c1..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/index.ts +++ /dev/null @@ -1,46 +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. - */ - -import { createAlertRoute } from './create'; -import { deleteAlertRoute } from './delete'; -import { findAlertRoute } from './find'; -import { getAlertRoute } from './get'; -import { getAlertStateRoute } from './get_alert_state'; -import { getAlertInstanceSummaryRoute } from './get_alert_instance_summary'; -import { listAlertTypesRoute } from './list_alert_types'; -import { updateAlertRoute } from './update'; -import { enableAlertRoute } from './enable'; -import { disableAlertRoute } from './disable'; -import { updateApiKeyRoute } from './update_api_key'; -import { muteAlertInstanceRoute } from './mute_instance'; -import { unmuteAlertInstanceRoute } from './unmute_instance'; -import { muteAllAlertRoute } from './mute_all'; -import { unmuteAllAlertRoute } from './unmute_all'; -import { healthRoute } from './health'; -import { RouteOptions } from '..'; - -export function defineLegacyRoutes(opts: RouteOptions) { - const { router, licenseState, encryptedSavedObjects, usageCounter, isServerless, docLinks } = - opts; - - createAlertRoute(opts); - deleteAlertRoute(router, licenseState, docLinks, usageCounter, isServerless); - findAlertRoute(router, licenseState, docLinks, usageCounter, isServerless); - getAlertRoute(router, licenseState, docLinks, usageCounter, isServerless); - getAlertStateRoute(router, licenseState, docLinks, usageCounter, isServerless); - getAlertInstanceSummaryRoute(router, licenseState, docLinks, usageCounter, isServerless); - listAlertTypesRoute(router, licenseState, docLinks, usageCounter, isServerless); - updateAlertRoute(router, licenseState, docLinks, usageCounter, isServerless); - enableAlertRoute(router, licenseState, docLinks, usageCounter, isServerless); - disableAlertRoute(router, licenseState, docLinks, usageCounter, isServerless); - updateApiKeyRoute(router, licenseState, docLinks, usageCounter, isServerless); - muteAllAlertRoute(router, licenseState, docLinks, usageCounter, isServerless); - unmuteAllAlertRoute(router, licenseState, docLinks, usageCounter, isServerless); - muteAlertInstanceRoute(router, licenseState, docLinks, usageCounter, isServerless); - unmuteAlertInstanceRoute(router, licenseState, docLinks, usageCounter, isServerless); - healthRoute(router, licenseState, encryptedSavedObjects, docLinks, usageCounter, isServerless); -} diff --git a/x-pack/plugins/alerting/server/routes/legacy/list_alert_types.test.ts b/x-pack/plugins/alerting/server/routes/legacy/list_alert_types.test.ts deleted file mode 100644 index 27e9d7ce44865..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/list_alert_types.test.ts +++ /dev/null @@ -1,287 +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. - */ - -import { usageCountersServiceMock } from '@kbn/usage-collection-plugin/server/usage_counters/usage_counters_service.mock'; -import { listAlertTypesRoute } from './list_alert_types'; -import { httpServiceMock } from '@kbn/core/server/mocks'; -import { licenseStateMock } from '../../lib/license_state.mock'; -import { verifyApiAccess } from '../../lib/license_api_access'; -import { mockHandlerArguments } from '../_mock_handler_arguments'; -import { rulesClientMock } from '../../rules_client.mock'; -import { RecoveredActionGroup } from '../../../common'; -import { RegistryAlertTypeWithAuth } from '../../authorization'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; -import { docLinksServiceMock } from '@kbn/core/server/mocks'; - -const rulesClient = rulesClientMock.create(); - -jest.mock('../../lib/license_api_access', () => ({ - verifyApiAccess: jest.fn(), -})); - -jest.mock('../../lib/track_legacy_route_usage', () => ({ - trackLegacyRouteUsage: jest.fn(), -})); - -beforeEach(() => { - jest.resetAllMocks(); -}); - -describe('listAlertTypesRoute', () => { - const docLinks = docLinksServiceMock.createSetupContract(); - it('lists alert types with proper parameters', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - listAlertTypesRoute(router, licenseState, docLinks); - - const [config, handler] = router.get.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/list_alert_types"`); - expect(config.options?.access).toBe('public'); - - const listTypes: RegistryAlertTypeWithAuth[] = [ - { - id: '1', - name: 'name', - actionGroups: [ - { - id: 'default', - name: 'Default', - }, - ], - defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic', - isExportable: true, - recoveryActionGroup: RecoveredActionGroup, - authorizedConsumers: {}, - actionVariables: { - context: [], - state: [], - }, - category: 'test', - producer: 'test', - enabledInLicense: true, - hasAlertsMappings: false, - hasFieldsForAAD: false, - validLegacyConsumers: [], - }, - ]; - - rulesClient.listRuleTypes.mockResolvedValueOnce(listTypes); - - const [context, req, res] = mockHandlerArguments({ rulesClient }, {}, ['ok']); - - expect(await handler(context, req, res)).toMatchInlineSnapshot(` - Object { - "body": Array [ - Object { - "actionGroups": Array [ - Object { - "id": "default", - "name": "Default", - }, - ], - "actionVariables": Object { - "context": Array [], - "state": Array [], - }, - "authorizedConsumers": Object {}, - "category": "test", - "defaultActionGroupId": "default", - "enabledInLicense": true, - "hasAlertsMappings": false, - "hasFieldsForAAD": false, - "id": "1", - "isExportable": true, - "minimumLicenseRequired": "basic", - "name": "name", - "producer": "test", - "recoveryActionGroup": Object { - "id": "recovered", - "name": "Recovered", - }, - "validLegacyConsumers": Array [], - }, - ], - } - `); - - expect(rulesClient.listRuleTypes).toHaveBeenCalledTimes(1); - - expect(res.ok).toHaveBeenCalledWith({ - body: listTypes, - }); - }); - - it('should have internal access for serverless', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - listAlertTypesRoute(router, licenseState, docLinks, undefined, true); - - const [config] = router.get.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/list_alert_types"`); - expect(config.options?.access).toBe('internal'); - }); - - it('ensures the license allows listing alert types', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - listAlertTypesRoute(router, licenseState, docLinks); - - const [config, handler] = router.get.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/list_alert_types"`); - - const listTypes = [ - { - id: '1', - name: 'name', - actionGroups: [ - { - id: 'default', - name: 'Default', - }, - ], - defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic', - isExportable: true, - recoveryActionGroup: RecoveredActionGroup, - authorizedConsumers: {}, - actionVariables: { - context: [], - state: [], - }, - category: 'test', - producer: 'alerts', - enabledInLicense: true, - hasAlertsMappings: false, - hasFieldsForAAD: false, - validLegacyConsumers: [], - } as RegistryAlertTypeWithAuth, - ]; - - rulesClient.listRuleTypes.mockResolvedValueOnce(listTypes); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: { id: '1' }, - }, - ['ok'] - ); - - await handler(context, req, res); - - expect(verifyApiAccess).toHaveBeenCalledWith(licenseState); - }); - - it('ensures the license check prevents listing alert types', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - (verifyApiAccess as jest.Mock).mockImplementation(() => { - throw new Error('OMG'); - }); - - listAlertTypesRoute(router, licenseState, docLinks); - - const [config, handler] = router.get.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/list_alert_types"`); - - const listTypes = [ - { - id: '1', - name: 'name', - actionGroups: [ - { - id: 'default', - name: 'Default', - }, - ], - defaultActionGroupId: 'default', - minimumLicenseRequired: 'basic', - isExportable: true, - recoveryActionGroup: RecoveredActionGroup, - authorizedConsumers: {}, - actionVariables: { - context: [], - state: [], - }, - category: 'test', - producer: 'alerts', - enabledInLicense: true, - hasAlertsMappings: false, - hasFieldsForAAD: false, - validLegacyConsumers: [], - } as RegistryAlertTypeWithAuth, - ]; - - rulesClient.listRuleTypes.mockResolvedValueOnce(listTypes); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: { id: '1' }, - }, - ['ok'] - ); - - await expect(handler(context, req, res)).rejects.toMatchInlineSnapshot(`[Error: OMG]`); - - expect(verifyApiAccess).toHaveBeenCalledWith(licenseState); - }); - - it('should track every call', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); - const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test'); - - rulesClient.listRuleTypes.mockResolvedValueOnce([]); - - listAlertTypesRoute(router, licenseState, docLinks, mockUsageCounter); - const [, handler] = router.get.mock.calls[0]; - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { params: { id: '1' }, body: {} }, - ['ok'] - ); - await handler(context, req, res); - expect(trackLegacyRouteUsage).toHaveBeenCalledWith('listAlertTypes', mockUsageCounter); - }); - - it('should be deprecated', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - listAlertTypesRoute(router, licenseState, docLinks); - - const [config] = router.get.mock.calls[0]; - - expect(config.options?.deprecated).toMatchInlineSnapshot( - { - documentationUrl: expect.stringMatching(/#breaking-201550$/), - }, - ` - Object { - "documentationUrl": StringMatching /#breaking-201550\\$/, - "reason": Object { - "newApiMethod": "GET", - "newApiPath": "/api/alerting/rule_types", - "type": "migrate", - }, - "severity": "warning", - } - ` - ); - }); -}); diff --git a/x-pack/plugins/alerting/server/routes/legacy/list_alert_types.ts b/x-pack/plugins/alerting/server/routes/legacy/list_alert_types.ts deleted file mode 100644 index 6e6b4e3499f72..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/list_alert_types.ts +++ /dev/null @@ -1,57 +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. - */ -import { UsageCounter } from '@kbn/usage-collection-plugin/server'; -import { DocLinksServiceSetup } from '@kbn/core/server'; -import type { AlertingRouter } from '../../types'; -import { ILicenseState } from '../../lib/license_state'; -import { verifyApiAccess } from '../../lib/license_api_access'; -import { LEGACY_BASE_ALERT_API_PATH } from '../../../common'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; -import { DEFAULT_ALERTING_ROUTE_SECURITY } from '../constants'; - -export const listAlertTypesRoute = ( - router: AlertingRouter, - licenseState: ILicenseState, - docLinks: DocLinksServiceSetup, - usageCounter?: UsageCounter, - isServerless?: boolean -) => { - router.get( - { - path: `${LEGACY_BASE_ALERT_API_PATH}/list_alert_types`, - validate: {}, - security: DEFAULT_ALERTING_ROUTE_SECURITY, - options: { - access: isServerless ? 'internal' : 'public', - summary: 'Get the alert types', - tags: ['oas-tag:alerting'], - deprecated: { - documentationUrl: docLinks.links.alerting.legacyRuleApiDeprecations, - severity: 'warning', - reason: { - type: 'migrate', - newApiMethod: 'GET', - newApiPath: '/api/alerting/rule_types', - }, - }, - }, - }, - router.handleLegacyErrors(async function (context, req, res) { - verifyApiAccess(licenseState); - if (!context.alerting) { - return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); - } - trackLegacyRouteUsage('listAlertTypes', usageCounter); - const alertingContext = await context.alerting; - const rulesClient = await alertingContext.getRulesClient(); - - return res.ok({ - body: Array.from(await rulesClient.listRuleTypes()), - }); - }) - ); -}; diff --git a/x-pack/plugins/alerting/server/routes/legacy/mute_all.test.ts b/x-pack/plugins/alerting/server/routes/legacy/mute_all.test.ts deleted file mode 100644 index d80cf415283d0..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/mute_all.test.ts +++ /dev/null @@ -1,143 +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. - */ - -import { usageCountersServiceMock } from '@kbn/usage-collection-plugin/server/usage_counters/usage_counters_service.mock'; -import { muteAllAlertRoute } from './mute_all'; -import { httpServiceMock } from '@kbn/core/server/mocks'; -import { licenseStateMock } from '../../lib/license_state.mock'; -import { mockHandlerArguments } from '../_mock_handler_arguments'; -import { rulesClientMock } from '../../rules_client.mock'; -import { RuleTypeDisabledError } from '../../lib/errors/rule_type_disabled'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; -import { docLinksServiceMock } from '@kbn/core/server/mocks'; - -const rulesClient = rulesClientMock.create(); -jest.mock('../../lib/license_api_access', () => ({ - verifyApiAccess: jest.fn(), -})); - -jest.mock('../../lib/track_legacy_route_usage', () => ({ - trackLegacyRouteUsage: jest.fn(), -})); - -beforeEach(() => { - jest.resetAllMocks(); -}); - -describe('muteAllAlertRoute', () => { - const docLinks = docLinksServiceMock.createSetupContract(); - - it('mute an alert', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - muteAllAlertRoute(router, licenseState, docLinks); - - const [config, handler] = router.post.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id}/_mute_all"`); - expect(config.options?.access).toBe('public'); - - rulesClient.muteAll.mockResolvedValueOnce(); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: { - id: '1', - }, - }, - ['noContent'] - ); - - expect(await handler(context, req, res)).toEqual(undefined); - - expect(rulesClient.muteAll).toHaveBeenCalledTimes(1); - expect(rulesClient.muteAll.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "id": "1", - }, - ] - `); - - expect(res.noContent).toHaveBeenCalled(); - }); - - it('should have internal access for serverless', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - muteAllAlertRoute(router, licenseState, docLinks, undefined, true); - - const [config] = router.post.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id}/_mute_all"`); - expect(config.options?.access).toBe('internal'); - }); - - it('ensures the alert type gets validated for the license', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - muteAllAlertRoute(router, licenseState, docLinks); - - const [, handler] = router.post.mock.calls[0]; - - rulesClient.muteAll.mockRejectedValue(new RuleTypeDisabledError('Fail', 'license_invalid')); - - const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: {}, body: {} }, [ - 'ok', - 'forbidden', - ]); - - await handler(context, req, res); - - expect(res.forbidden).toHaveBeenCalledWith({ body: { message: 'Fail' } }); - }); - - it('should track every call', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); - const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test'); - - muteAllAlertRoute(router, licenseState, docLinks, mockUsageCounter); - const [, handler] = router.post.mock.calls[0]; - const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: {}, body: {} }, [ - 'ok', - ]); - await handler(context, req, res); - expect(trackLegacyRouteUsage).toHaveBeenCalledWith('muteAll', mockUsageCounter); - }); - - it('should be deprecated', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - muteAllAlertRoute(router, licenseState, docLinks, undefined, true); - - const [config] = router.post.mock.calls[0]; - - expect(config.options?.deprecated).toMatchInlineSnapshot( - { - documentationUrl: expect.stringMatching(/#breaking-201550$/), - }, - ` - Object { - "documentationUrl": StringMatching /#breaking-201550\\$/, - "reason": Object { - "newApiMethod": "POST", - "newApiPath": "/api/alerting/rule/{id}/_mute_all", - "type": "migrate", - }, - "severity": "warning", - } - ` - ); - }); -}); diff --git a/x-pack/plugins/alerting/server/routes/legacy/mute_all.ts b/x-pack/plugins/alerting/server/routes/legacy/mute_all.ts deleted file mode 100644 index b978cc223b88b..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/mute_all.ts +++ /dev/null @@ -1,72 +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. - */ - -import { schema } from '@kbn/config-schema'; -import { UsageCounter } from '@kbn/usage-collection-plugin/server'; -import { DocLinksServiceSetup } from '@kbn/core/server'; -import type { AlertingRouter } from '../../types'; -import { ILicenseState } from '../../lib/license_state'; -import { verifyApiAccess } from '../../lib/license_api_access'; -import { LEGACY_BASE_ALERT_API_PATH } from '../../../common'; -import { RuleTypeDisabledError } from '../../lib/errors/rule_type_disabled'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; -import { DEFAULT_ALERTING_ROUTE_SECURITY } from '../constants'; - -const paramSchema = schema.object({ - id: schema.string(), -}); - -export const muteAllAlertRoute = ( - router: AlertingRouter, - licenseState: ILicenseState, - docLinks: DocLinksServiceSetup, - usageCounter?: UsageCounter, - isServerless?: boolean -) => { - router.post( - { - path: `${LEGACY_BASE_ALERT_API_PATH}/alert/{id}/_mute_all`, - validate: { - params: paramSchema, - }, - security: DEFAULT_ALERTING_ROUTE_SECURITY, - options: { - access: isServerless ? 'internal' : 'public', - summary: 'Mute all alert instances', - tags: ['oas-tag:alerting'], - deprecated: { - documentationUrl: docLinks.links.alerting.legacyRuleApiDeprecations, - severity: 'warning', - reason: { - type: 'migrate', - newApiMethod: 'POST', - newApiPath: '/api/alerting/rule/{id}/_mute_all', - }, - }, - }, - }, - router.handleLegacyErrors(async function (context, req, res) { - verifyApiAccess(licenseState); - if (!context.alerting) { - return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); - } - trackLegacyRouteUsage('muteAll', usageCounter); - const alertingContext = await context.alerting; - const rulesClient = await alertingContext.getRulesClient(); - const { id } = req.params; - try { - await rulesClient.muteAll({ id }); - return res.noContent(); - } catch (e) { - if (e instanceof RuleTypeDisabledError) { - return e.sendResponse(res); - } - throw e; - } - }) - ); -}; diff --git a/x-pack/plugins/alerting/server/routes/legacy/mute_instance.test.ts b/x-pack/plugins/alerting/server/routes/legacy/mute_instance.test.ts deleted file mode 100644 index 08e03a6d053ef..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/mute_instance.test.ts +++ /dev/null @@ -1,151 +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. - */ - -import { usageCountersServiceMock } from '@kbn/usage-collection-plugin/server/usage_counters/usage_counters_service.mock'; -import { muteAlertInstanceRoute } from './mute_instance'; -import { httpServiceMock } from '@kbn/core/server/mocks'; -import { licenseStateMock } from '../../lib/license_state.mock'; -import { mockHandlerArguments } from '../_mock_handler_arguments'; -import { rulesClientMock } from '../../rules_client.mock'; -import { RuleTypeDisabledError } from '../../lib/errors/rule_type_disabled'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; -import { docLinksServiceMock } from '@kbn/core/server/mocks'; - -const rulesClient = rulesClientMock.create(); -jest.mock('../../lib/license_api_access', () => ({ - verifyApiAccess: jest.fn(), -})); - -jest.mock('../../lib/track_legacy_route_usage', () => ({ - trackLegacyRouteUsage: jest.fn(), -})); - -beforeEach(() => { - jest.resetAllMocks(); -}); - -describe('muteAlertInstanceRoute', () => { - const docLinks = docLinksServiceMock.createSetupContract(); - - it('mutes an alert instance', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - muteAlertInstanceRoute(router, licenseState, docLinks); - - const [config, handler] = router.post.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot( - `"/api/alerts/alert/{alert_id}/alert_instance/{alert_instance_id}/_mute"` - ); - expect(config.options?.access).toBe('public'); - - rulesClient.muteInstance.mockResolvedValueOnce(); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: { - alert_id: '1', - alert_instance_id: '2', - }, - }, - ['noContent'] - ); - - expect(await handler(context, req, res)).toEqual(undefined); - - expect(rulesClient.muteInstance).toHaveBeenCalledTimes(1); - expect(rulesClient.muteInstance.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "alertId": "1", - "alertInstanceId": "2", - }, - ] - `); - - expect(res.noContent).toHaveBeenCalled(); - }); - - it('should have internal access for serverless', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - muteAlertInstanceRoute(router, licenseState, docLinks, undefined, true); - - const [config] = router.post.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot( - `"/api/alerts/alert/{alert_id}/alert_instance/{alert_instance_id}/_mute"` - ); - expect(config.options?.access).toBe('internal'); - }); - - it('ensures the alert type gets validated for the license', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - muteAlertInstanceRoute(router, licenseState, docLinks); - - const [, handler] = router.post.mock.calls[0]; - - rulesClient.muteInstance.mockRejectedValue( - new RuleTypeDisabledError('Fail', 'license_invalid') - ); - - const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: {}, body: {} }, [ - 'ok', - 'forbidden', - ]); - - await handler(context, req, res); - - expect(res.forbidden).toHaveBeenCalledWith({ body: { message: 'Fail' } }); - }); - - it('should track every call', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); - const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test'); - - muteAlertInstanceRoute(router, licenseState, docLinks, mockUsageCounter); - const [, handler] = router.post.mock.calls[0]; - const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: {}, body: {} }, [ - 'ok', - ]); - await handler(context, req, res); - expect(trackLegacyRouteUsage).toHaveBeenCalledWith('muteInstance', mockUsageCounter); - }); - - it('should be deprecated', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - muteAlertInstanceRoute(router, licenseState, docLinks); - - const [config] = router.post.mock.calls[0]; - - expect(config.options?.deprecated).toMatchInlineSnapshot( - { - documentationUrl: expect.stringMatching(/#breaking-201550$/), - }, - ` - Object { - "documentationUrl": StringMatching /#breaking-201550\\$/, - "reason": Object { - "newApiMethod": "POST", - "newApiPath": "/api/alerting/rule/{rule_id}/alert/{alert_id}/_mute", - "type": "migrate", - }, - "severity": "warning", - } - ` - ); - }); -}); diff --git a/x-pack/plugins/alerting/server/routes/legacy/mute_instance.ts b/x-pack/plugins/alerting/server/routes/legacy/mute_instance.ts deleted file mode 100644 index 155086ebc247d..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/mute_instance.ts +++ /dev/null @@ -1,83 +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. - */ - -import { schema } from '@kbn/config-schema'; -import { UsageCounter } from '@kbn/usage-collection-plugin/server'; -import { DocLinksServiceSetup } from '@kbn/core/server'; -import type { AlertingRouter } from '../../types'; -import { ILicenseState } from '../../lib/license_state'; -import { verifyApiAccess } from '../../lib/license_api_access'; -import { LEGACY_BASE_ALERT_API_PATH } from '../../../common'; -import { renameKeys } from '../lib/rename_keys'; -import { MuteOptions } from '../../rules_client'; -import { RuleTypeDisabledError } from '../../lib/errors/rule_type_disabled'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; -import { DEFAULT_ALERTING_ROUTE_SECURITY } from '../constants'; - -const paramSchema = schema.object({ - alert_id: schema.string(), - alert_instance_id: schema.string(), -}); - -export const muteAlertInstanceRoute = ( - router: AlertingRouter, - licenseState: ILicenseState, - docLinks: DocLinksServiceSetup, - usageCounter?: UsageCounter, - isServerless?: boolean -) => { - router.post( - { - path: `${LEGACY_BASE_ALERT_API_PATH}/alert/{alert_id}/alert_instance/{alert_instance_id}/_mute`, - validate: { - params: paramSchema, - }, - security: DEFAULT_ALERTING_ROUTE_SECURITY, - options: { - access: isServerless ? 'internal' : 'public', - summary: 'Mute an alert', - tags: ['oas-tag:alerting'], - deprecated: { - documentationUrl: docLinks.links.alerting.legacyRuleApiDeprecations, - severity: 'warning', - reason: { - type: 'migrate', - newApiMethod: 'POST', - newApiPath: '/api/alerting/rule/{rule_id}/alert/{alert_id}/_mute', - }, - }, - }, - }, - router.handleLegacyErrors(async function (context, req, res) { - verifyApiAccess(licenseState); - if (!context.alerting) { - return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); - } - - trackLegacyRouteUsage('muteInstance', usageCounter); - - const alertingContext = await context.alerting; - const rulesClient = await alertingContext.getRulesClient(); - - const renameMap = { - alert_id: 'alertId', - alert_instance_id: 'alertInstanceId', - }; - - const renamedQuery = renameKeys>(renameMap, req.params); - try { - await rulesClient.muteInstance(renamedQuery); - return res.noContent(); - } catch (e) { - if (e instanceof RuleTypeDisabledError) { - return e.sendResponse(res); - } - throw e; - } - }) - ); -}; diff --git a/x-pack/plugins/alerting/server/routes/legacy/unmute_all.test.ts b/x-pack/plugins/alerting/server/routes/legacy/unmute_all.test.ts deleted file mode 100644 index 5ae337e6a3f51..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/unmute_all.test.ts +++ /dev/null @@ -1,143 +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. - */ - -import { usageCountersServiceMock } from '@kbn/usage-collection-plugin/server/usage_counters/usage_counters_service.mock'; -import { unmuteAllAlertRoute } from './unmute_all'; -import { httpServiceMock } from '@kbn/core/server/mocks'; -import { licenseStateMock } from '../../lib/license_state.mock'; -import { mockHandlerArguments } from '../_mock_handler_arguments'; -import { rulesClientMock } from '../../rules_client.mock'; -import { RuleTypeDisabledError } from '../../lib/errors/rule_type_disabled'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; -import { docLinksServiceMock } from '@kbn/core/server/mocks'; - -const rulesClient = rulesClientMock.create(); -jest.mock('../../lib/license_api_access', () => ({ - verifyApiAccess: jest.fn(), -})); - -jest.mock('../../lib/track_legacy_route_usage', () => ({ - trackLegacyRouteUsage: jest.fn(), -})); - -beforeEach(() => { - jest.resetAllMocks(); -}); - -describe('unmuteAllAlertRoute', () => { - const docLinks = docLinksServiceMock.createSetupContract(); - - it('unmutes an alert', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - unmuteAllAlertRoute(router, licenseState, docLinks); - - const [config, handler] = router.post.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id}/_unmute_all"`); - expect(config.options?.access).toBe('public'); - - rulesClient.unmuteAll.mockResolvedValueOnce(); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: { - id: '1', - }, - }, - ['noContent'] - ); - - expect(await handler(context, req, res)).toEqual(undefined); - - expect(rulesClient.unmuteAll).toHaveBeenCalledTimes(1); - expect(rulesClient.unmuteAll.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "id": "1", - }, - ] - `); - - expect(res.noContent).toHaveBeenCalled(); - }); - - it('should have internal access for serverless', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - unmuteAllAlertRoute(router, licenseState, docLinks, undefined, true); - - const [config] = router.post.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id}/_unmute_all"`); - expect(config.options?.access).toBe('internal'); - }); - - it('ensures the alert type gets validated for the license', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - unmuteAllAlertRoute(router, licenseState, docLinks); - - const [, handler] = router.post.mock.calls[0]; - - rulesClient.unmuteAll.mockRejectedValue(new RuleTypeDisabledError('Fail', 'license_invalid')); - - const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: {}, body: {} }, [ - 'ok', - 'forbidden', - ]); - - await handler(context, req, res); - - expect(res.forbidden).toHaveBeenCalledWith({ body: { message: 'Fail' } }); - }); - - it('should track every call', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); - const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test'); - - unmuteAllAlertRoute(router, licenseState, docLinks, mockUsageCounter); - const [, handler] = router.post.mock.calls[0]; - const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: {}, body: {} }, [ - 'ok', - ]); - await handler(context, req, res); - expect(trackLegacyRouteUsage).toHaveBeenCalledWith('unmuteAll', mockUsageCounter); - }); - - it('should be deprecated', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - unmuteAllAlertRoute(router, licenseState, docLinks); - - const [config] = router.post.mock.calls[0]; - - expect(config.options?.deprecated).toMatchInlineSnapshot( - { - documentationUrl: expect.stringMatching(/#breaking-201550$/), - }, - ` - Object { - "documentationUrl": StringMatching /#breaking-201550\\$/, - "reason": Object { - "newApiMethod": "POST", - "newApiPath": "/api/alerting/rule/{id}/_unmute_all", - "type": "migrate", - }, - "severity": "warning", - } - ` - ); - }); -}); diff --git a/x-pack/plugins/alerting/server/routes/legacy/unmute_all.ts b/x-pack/plugins/alerting/server/routes/legacy/unmute_all.ts deleted file mode 100644 index 5ae7dedcc8666..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/unmute_all.ts +++ /dev/null @@ -1,72 +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. - */ - -import { schema } from '@kbn/config-schema'; -import { UsageCounter } from '@kbn/usage-collection-plugin/server'; -import { DocLinksServiceSetup } from '@kbn/core/server'; -import type { AlertingRouter } from '../../types'; -import { ILicenseState } from '../../lib/license_state'; -import { verifyApiAccess } from '../../lib/license_api_access'; -import { LEGACY_BASE_ALERT_API_PATH } from '../../../common'; -import { RuleTypeDisabledError } from '../../lib/errors/rule_type_disabled'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; -import { DEFAULT_ALERTING_ROUTE_SECURITY } from '../constants'; - -const paramSchema = schema.object({ - id: schema.string(), -}); - -export const unmuteAllAlertRoute = ( - router: AlertingRouter, - licenseState: ILicenseState, - docLinks: DocLinksServiceSetup, - usageCounter?: UsageCounter, - isServerless?: boolean -) => { - router.post( - { - path: `${LEGACY_BASE_ALERT_API_PATH}/alert/{id}/_unmute_all`, - validate: { - params: paramSchema, - }, - security: DEFAULT_ALERTING_ROUTE_SECURITY, - options: { - access: isServerless ? 'internal' : 'public', - summary: 'Unmute all alert instances', - tags: ['oas-tag:alerting'], - deprecated: { - documentationUrl: docLinks.links.alerting.legacyRuleApiDeprecations, - severity: 'warning', - reason: { - type: 'migrate', - newApiMethod: 'POST', - newApiPath: '/api/alerting/rule/{id}/_unmute_all', - }, - }, - }, - }, - router.handleLegacyErrors(async function (context, req, res) { - verifyApiAccess(licenseState); - if (!context.alerting) { - return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); - } - trackLegacyRouteUsage('unmuteAll', usageCounter); - const alertingContext = await context.alerting; - const rulesClient = await alertingContext.getRulesClient(); - const { id } = req.params; - try { - await rulesClient.unmuteAll({ id }); - return res.noContent(); - } catch (e) { - if (e instanceof RuleTypeDisabledError) { - return e.sendResponse(res); - } - throw e; - } - }) - ); -}; diff --git a/x-pack/plugins/alerting/server/routes/legacy/unmute_instance.test.ts b/x-pack/plugins/alerting/server/routes/legacy/unmute_instance.test.ts deleted file mode 100644 index b6fba61aaff8a..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/unmute_instance.test.ts +++ /dev/null @@ -1,151 +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. - */ - -import { usageCountersServiceMock } from '@kbn/usage-collection-plugin/server/usage_counters/usage_counters_service.mock'; -import { unmuteAlertInstanceRoute } from './unmute_instance'; -import { httpServiceMock } from '@kbn/core/server/mocks'; -import { licenseStateMock } from '../../lib/license_state.mock'; -import { mockHandlerArguments } from '../_mock_handler_arguments'; -import { rulesClientMock } from '../../rules_client.mock'; -import { RuleTypeDisabledError } from '../../lib/errors/rule_type_disabled'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; -import { docLinksServiceMock } from '@kbn/core/server/mocks'; - -const rulesClient = rulesClientMock.create(); -jest.mock('../../lib/license_api_access', () => ({ - verifyApiAccess: jest.fn(), -})); - -jest.mock('../../lib/track_legacy_route_usage', () => ({ - trackLegacyRouteUsage: jest.fn(), -})); - -beforeEach(() => { - jest.resetAllMocks(); -}); - -describe('unmuteAlertInstanceRoute', () => { - const docLinks = docLinksServiceMock.createSetupContract(); - - it('unmutes an alert instance', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - unmuteAlertInstanceRoute(router, licenseState, docLinks); - - const [config, handler] = router.post.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot( - `"/api/alerts/alert/{alertId}/alert_instance/{alertInstanceId}/_unmute"` - ); - expect(config.options?.access).toBe('public'); - - rulesClient.unmuteInstance.mockResolvedValueOnce(); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: { - alertId: '1', - alertInstanceId: '2', - }, - }, - ['noContent'] - ); - - expect(await handler(context, req, res)).toEqual(undefined); - - expect(rulesClient.unmuteInstance).toHaveBeenCalledTimes(1); - expect(rulesClient.unmuteInstance.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "alertId": "1", - "alertInstanceId": "2", - }, - ] - `); - - expect(res.noContent).toHaveBeenCalled(); - }); - - it('should have internal access for serverless', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - unmuteAlertInstanceRoute(router, licenseState, docLinks, undefined, true); - - const [config] = router.post.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot( - `"/api/alerts/alert/{alertId}/alert_instance/{alertInstanceId}/_unmute"` - ); - expect(config.options?.access).toBe('internal'); - }); - - it('ensures the alert type gets validated for the license', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - unmuteAlertInstanceRoute(router, licenseState, docLinks); - - const [, handler] = router.post.mock.calls[0]; - - rulesClient.unmuteInstance.mockRejectedValue( - new RuleTypeDisabledError('Fail', 'license_invalid') - ); - - const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: {}, body: {} }, [ - 'ok', - 'forbidden', - ]); - - await handler(context, req, res); - - expect(res.forbidden).toHaveBeenCalledWith({ body: { message: 'Fail' } }); - }); - - it('should track every call', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); - const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test'); - - unmuteAlertInstanceRoute(router, licenseState, docLinks, mockUsageCounter); - const [, handler] = router.post.mock.calls[0]; - const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: {}, body: {} }, [ - 'ok', - ]); - await handler(context, req, res); - expect(trackLegacyRouteUsage).toHaveBeenCalledWith('unmuteInstance', mockUsageCounter); - }); - - it('should be deprecated', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - unmuteAlertInstanceRoute(router, licenseState, docLinks); - - const [config] = router.post.mock.calls[0]; - - expect(config.options?.deprecated).toMatchInlineSnapshot( - { - documentationUrl: expect.stringMatching(/#breaking-201550$/), - }, - ` - Object { - "documentationUrl": StringMatching /#breaking-201550\\$/, - "reason": Object { - "newApiMethod": "POST", - "newApiPath": "/api/alerting/rule/{rule_id}/alert/{alert_id}/_unmute", - "type": "migrate", - }, - "severity": "warning", - } - ` - ); - }); -}); diff --git a/x-pack/plugins/alerting/server/routes/legacy/unmute_instance.ts b/x-pack/plugins/alerting/server/routes/legacy/unmute_instance.ts deleted file mode 100644 index 85cf06df83387..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/unmute_instance.ts +++ /dev/null @@ -1,73 +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. - */ - -import { schema } from '@kbn/config-schema'; -import { UsageCounter } from '@kbn/usage-collection-plugin/server'; -import { DocLinksServiceSetup } from '@kbn/core/server'; -import type { AlertingRouter } from '../../types'; -import { ILicenseState } from '../../lib/license_state'; -import { verifyApiAccess } from '../../lib/license_api_access'; -import { LEGACY_BASE_ALERT_API_PATH } from '../../../common'; -import { RuleTypeDisabledError } from '../../lib/errors/rule_type_disabled'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; -import { DEFAULT_ALERTING_ROUTE_SECURITY } from '../constants'; - -const paramSchema = schema.object({ - alertId: schema.string(), - alertInstanceId: schema.string(), -}); - -export const unmuteAlertInstanceRoute = ( - router: AlertingRouter, - licenseState: ILicenseState, - docLinks: DocLinksServiceSetup, - usageCounter?: UsageCounter, - isServerless?: boolean -) => { - router.post( - { - path: `${LEGACY_BASE_ALERT_API_PATH}/alert/{alertId}/alert_instance/{alertInstanceId}/_unmute`, - validate: { - params: paramSchema, - }, - security: DEFAULT_ALERTING_ROUTE_SECURITY, - options: { - access: isServerless ? 'internal' : 'public', - summary: 'Unmute an alert', - tags: ['oas-tag:alerting'], - deprecated: { - documentationUrl: docLinks.links.alerting.legacyRuleApiDeprecations, - severity: 'warning', - reason: { - type: 'migrate', - newApiMethod: 'POST', - newApiPath: '/api/alerting/rule/{rule_id}/alert/{alert_id}/_unmute', - }, - }, - }, - }, - router.handleLegacyErrors(async function (context, req, res) { - verifyApiAccess(licenseState); - if (!context.alerting) { - return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); - } - trackLegacyRouteUsage('unmuteInstance', usageCounter); - const alertingContext = await context.alerting; - const rulesClient = await alertingContext.getRulesClient(); - const { alertId, alertInstanceId } = req.params; - try { - await rulesClient.unmuteInstance({ alertId, alertInstanceId }); - return res.noContent(); - } catch (e) { - if (e instanceof RuleTypeDisabledError) { - return e.sendResponse(res); - } - throw e; - } - }) - ); -}; diff --git a/x-pack/plugins/alerting/server/routes/legacy/update.test.ts b/x-pack/plugins/alerting/server/routes/legacy/update.test.ts deleted file mode 100644 index 7aaee90b805c5..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/update.test.ts +++ /dev/null @@ -1,390 +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. - */ - -import { usageCountersServiceMock } from '@kbn/usage-collection-plugin/server/usage_counters/usage_counters_service.mock'; -import { updateAlertRoute } from './update'; -import { httpServiceMock } from '@kbn/core/server/mocks'; -import { licenseStateMock } from '../../lib/license_state.mock'; -import { verifyApiAccess } from '../../lib/license_api_access'; -import { mockHandlerArguments } from '../_mock_handler_arguments'; -import { rulesClientMock } from '../../rules_client.mock'; -import { RuleTypeDisabledError } from '../../lib/errors/rule_type_disabled'; -import { RuleNotifyWhen, SanitizedRule, RuleSystemAction } from '../../../common'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; -import { docLinksServiceMock } from '@kbn/core/server/mocks'; - -const rulesClient = rulesClientMock.create(); -jest.mock('../../lib/license_api_access', () => ({ - verifyApiAccess: jest.fn(), -})); - -jest.mock('../../lib/track_legacy_route_usage', () => ({ - trackLegacyRouteUsage: jest.fn(), -})); - -beforeEach(() => { - jest.resetAllMocks(); -}); - -describe('updateAlertRoute', () => { - const docLinks = docLinksServiceMock.createSetupContract(); - const mockedResponse = { - id: '1', - alertTypeId: '1', - tags: ['foo'], - schedule: { interval: '12s' }, - params: { - otherField: false, - }, - createdAt: new Date(), - updatedAt: new Date(), - actions: [ - { - group: 'default', - id: '2', - actionTypeId: 'test', - params: { - baz: true, - }, - }, - ], - notifyWhen: RuleNotifyWhen.CHANGE, - }; - - const systemAction: RuleSystemAction = { - actionTypeId: 'test-2', - id: 'system_action-id', - params: { - foo: true, - }, - uuid: '123-456', - }; - - it('updates an alert with proper parameters', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - updateAlertRoute(router, licenseState, docLinks); - - const [config, handler] = router.put.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id}"`); - expect(config.options?.access).toBe('public'); - - rulesClient.update.mockResolvedValueOnce(mockedResponse as unknown as SanitizedRule); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: { - id: '1', - }, - body: { - throttle: null, - name: 'abc', - tags: ['bar'], - schedule: { interval: '12s' }, - params: { - otherField: false, - }, - actions: [ - { - group: 'default', - id: '2', - params: { - baz: true, - }, - }, - ], - notifyWhen: 'onActionGroupChange', - }, - }, - ['ok'] - ); - - expect(await handler(context, req, res)).toEqual({ body: mockedResponse }); - - expect(rulesClient.update).toHaveBeenCalledTimes(1); - expect(rulesClient.update.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "data": Object { - "actions": Array [ - Object { - "group": "default", - "id": "2", - "params": Object { - "baz": true, - }, - }, - ], - "name": "abc", - "notifyWhen": "onActionGroupChange", - "params": Object { - "otherField": false, - }, - "schedule": Object { - "interval": "12s", - }, - "tags": Array [ - "bar", - ], - "throttle": null, - }, - "id": "1", - }, - ] - `); - - expect(res.ok).toHaveBeenCalled(); - }); - - it('should have internal access for serverless', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - updateAlertRoute(router, licenseState, docLinks, undefined, true); - - const [config] = router.put.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id}"`); - expect(config.options?.access).toBe('internal'); - }); - - it('ensures the license allows updating alerts', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - updateAlertRoute(router, licenseState, docLinks); - - const [, handler] = router.put.mock.calls[0]; - - rulesClient.update.mockResolvedValueOnce(mockedResponse as unknown as SanitizedRule); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: { - id: '1', - }, - body: { - throttle: null, - name: 'abc', - tags: ['bar'], - schedule: { interval: '12s' }, - params: { - otherField: false, - }, - actions: [ - { - group: 'default', - id: '2', - params: { - baz: true, - }, - }, - ], - }, - }, - ['ok'] - ); - - await handler(context, req, res); - - expect(verifyApiAccess).toHaveBeenCalledWith(licenseState); - }); - - it('ensures the license check prevents updating alerts', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - (verifyApiAccess as jest.Mock).mockImplementation(() => { - throw new Error('OMG'); - }); - - updateAlertRoute(router, licenseState, docLinks); - - const [, handler] = router.put.mock.calls[0]; - - rulesClient.update.mockResolvedValueOnce(mockedResponse as unknown as SanitizedRule); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: { - id: '1', - }, - body: { - throttle: null, - name: 'abc', - tags: ['bar'], - schedule: { interval: '12s' }, - params: { - otherField: false, - }, - actions: [ - { - group: 'default', - id: '2', - params: { - baz: true, - }, - }, - ], - }, - }, - ['ok'] - ); - - await expect(handler(context, req, res)).rejects.toMatchInlineSnapshot(`[Error: OMG]`); - - expect(verifyApiAccess).toHaveBeenCalledWith(licenseState); - }); - - it('ensures the alert type gets validated for the license', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - updateAlertRoute(router, licenseState, docLinks); - - const [, handler] = router.put.mock.calls[0]; - - rulesClient.update.mockRejectedValue(new RuleTypeDisabledError('Fail', 'license_invalid')); - - const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: {}, body: {} }, [ - 'ok', - 'forbidden', - ]); - - await handler(context, req, res); - - expect(res.forbidden).toHaveBeenCalledWith({ body: { message: 'Fail' } }); - }); - - it('should track every call', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); - const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test'); - - updateAlertRoute(router, licenseState, docLinks, mockUsageCounter); - const [, handler] = router.put.mock.calls[0]; - rulesClient.update.mockResolvedValueOnce(mockedResponse as unknown as SanitizedRule); - const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: {}, body: {} }, [ - 'ok', - ]); - await handler(context, req, res); - expect(trackLegacyRouteUsage).toHaveBeenCalledWith('update', mockUsageCounter); - }); - - it('does not return system actions', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - updateAlertRoute(router, licenseState, docLinks); - - const [config, handler] = router.put.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id}"`); - - rulesClient.update.mockResolvedValueOnce({ - ...mockedResponse, - systemActions: [systemAction], - } as unknown as SanitizedRule); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: { - id: '1', - }, - body: { - throttle: null, - name: 'abc', - tags: ['bar'], - schedule: { interval: '12s' }, - params: { - otherField: false, - }, - actions: [ - { - group: 'default', - id: '2', - params: { - baz: true, - }, - }, - ], - notifyWhen: 'onActionGroupChange', - }, - }, - ['ok'] - ); - - expect(await handler(context, req, res)).toEqual({ body: mockedResponse }); - - expect(rulesClient.update).toHaveBeenCalledTimes(1); - expect(rulesClient.update.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "data": Object { - "actions": Array [ - Object { - "group": "default", - "id": "2", - "params": Object { - "baz": true, - }, - }, - ], - "name": "abc", - "notifyWhen": "onActionGroupChange", - "params": Object { - "otherField": false, - }, - "schedule": Object { - "interval": "12s", - }, - "tags": Array [ - "bar", - ], - "throttle": null, - }, - "id": "1", - }, - ] - `); - - expect(res.ok).toHaveBeenCalled(); - }); - - it('should be deprecated', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - updateAlertRoute(router, licenseState, docLinks); - - const [config] = router.put.mock.calls[0]; - - expect(config.options?.deprecated).toMatchInlineSnapshot( - { - documentationUrl: expect.stringMatching(/#breaking-201550$/), - }, - ` - Object { - "documentationUrl": StringMatching /#breaking-201550\\$/, - "reason": Object { - "newApiMethod": "PUT", - "newApiPath": "/api/alerting/rule/rule/{id}", - "type": "migrate", - }, - "severity": "warning", - } - ` - ); - }); -}); diff --git a/x-pack/plugins/alerting/server/routes/legacy/update.ts b/x-pack/plugins/alerting/server/routes/legacy/update.ts deleted file mode 100644 index 95bb1bd651761..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/update.ts +++ /dev/null @@ -1,115 +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. - */ - -import { schema } from '@kbn/config-schema'; -import { UsageCounter } from '@kbn/usage-collection-plugin/server'; -import { DocLinksServiceSetup } from '@kbn/core/server'; -import type { AlertingRouter } from '../../types'; -import { ILicenseState } from '../../lib/license_state'; -import { verifyApiAccess } from '../../lib/license_api_access'; -import { validateDurationSchema } from '../../lib'; -import { handleDisabledApiKeysError } from '../lib/error_handler'; -import { RuleTypeDisabledError } from '../../lib/errors/rule_type_disabled'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; -import { - RuleNotifyWhenType, - LEGACY_BASE_ALERT_API_PATH, - validateNotifyWhenType, -} from '../../../common'; -import { DEFAULT_ALERTING_ROUTE_SECURITY } from '../constants'; - -const paramSchema = schema.object({ - id: schema.string(), -}); - -const bodySchema = schema.object({ - name: schema.string(), - tags: schema.arrayOf(schema.string(), { defaultValue: [] }), - schedule: schema.object({ - interval: schema.string({ validate: validateDurationSchema }), - }), - throttle: schema.nullable(schema.string({ validate: validateDurationSchema })), - params: schema.recordOf(schema.string(), schema.any(), { defaultValue: {} }), - actions: schema.arrayOf( - schema.object({ - group: schema.string(), - id: schema.string(), - params: schema.recordOf(schema.string(), schema.any(), { defaultValue: {} }), - actionTypeId: schema.maybe(schema.string()), - }), - { defaultValue: [] } - ), - notifyWhen: schema.nullable(schema.string({ validate: validateNotifyWhenType })), -}); - -export const updateAlertRoute = ( - router: AlertingRouter, - licenseState: ILicenseState, - docLinks: DocLinksServiceSetup, - usageCounter?: UsageCounter, - isServerless?: boolean -) => { - router.put( - { - path: `${LEGACY_BASE_ALERT_API_PATH}/alert/{id}`, - validate: { - body: bodySchema, - params: paramSchema, - }, - security: DEFAULT_ALERTING_ROUTE_SECURITY, - options: { - access: isServerless ? 'internal' : 'public', - summary: 'Update an alert', - tags: ['oas-tag:alerting'], - deprecated: { - documentationUrl: docLinks.links.alerting.legacyRuleApiDeprecations, - severity: 'warning', - reason: { - type: 'migrate', - newApiMethod: 'PUT', - newApiPath: '/api/alerting/rule/rule/{id}', - }, - }, - }, - }, - handleDisabledApiKeysError( - router.handleLegacyErrors(async function (context, req, res) { - verifyApiAccess(licenseState); - if (!context.alerting) { - return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); - } - trackLegacyRouteUsage('update', usageCounter); - const alertingContext = await context.alerting; - const rulesClient = await alertingContext.getRulesClient(); - const { id } = req.params; - const { name, actions, params, schedule, tags, throttle, notifyWhen } = req.body; - try { - const { systemActions, ...alertRes } = await rulesClient.update({ - id, - data: { - name, - actions, - params, - schedule, - tags, - throttle, - notifyWhen: notifyWhen as RuleNotifyWhenType, - }, - }); - return res.ok({ - body: alertRes, - }); - } catch (e) { - if (e instanceof RuleTypeDisabledError) { - return e.sendResponse(res); - } - throw e; - } - }) - ) - ); -}; diff --git a/x-pack/plugins/alerting/server/routes/legacy/update_api_key.test.ts b/x-pack/plugins/alerting/server/routes/legacy/update_api_key.test.ts deleted file mode 100644 index cb2817af2ed58..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/update_api_key.test.ts +++ /dev/null @@ -1,144 +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. - */ - -import { usageCountersServiceMock } from '@kbn/usage-collection-plugin/server/usage_counters/usage_counters_service.mock'; -import { updateApiKeyRoute } from './update_api_key'; -import { httpServiceMock } from '@kbn/core/server/mocks'; -import { licenseStateMock } from '../../lib/license_state.mock'; -import { mockHandlerArguments } from '../_mock_handler_arguments'; -import { rulesClientMock } from '../../rules_client.mock'; -import { RuleTypeDisabledError } from '../../lib/errors/rule_type_disabled'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; -import { docLinksServiceMock } from '@kbn/core/server/mocks'; - -const rulesClient = rulesClientMock.create(); -jest.mock('../../lib/license_api_access', () => ({ - verifyApiAccess: jest.fn(), -})); - -jest.mock('../../lib/track_legacy_route_usage', () => ({ - trackLegacyRouteUsage: jest.fn(), -})); - -beforeEach(() => { - jest.resetAllMocks(); -}); - -describe('updateApiKeyRoute', () => { - const docLinks = docLinksServiceMock.createSetupContract(); - - it('updates api key for an alert', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - updateApiKeyRoute(router, licenseState, docLinks); - - const [config, handler] = router.post.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id}/_update_api_key"`); - expect(config.options?.access).toBe('public'); - - rulesClient.updateRuleApiKey.mockResolvedValueOnce(); - - const [context, req, res] = mockHandlerArguments( - { rulesClient }, - { - params: { - id: '1', - }, - }, - ['noContent'] - ); - - expect(await handler(context, req, res)).toEqual(undefined); - - expect(rulesClient.updateRuleApiKey).toHaveBeenCalledTimes(1); - expect(rulesClient.updateRuleApiKey.mock.calls[0]).toMatchInlineSnapshot(` - Array [ - Object { - "id": "1", - }, - ] - `); - - expect(res.noContent).toHaveBeenCalled(); - }); - - it('should have internal access for serverless', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - updateApiKeyRoute(router, licenseState, docLinks, undefined, true); - - const [config] = router.post.mock.calls[0]; - - expect(config.path).toMatchInlineSnapshot(`"/api/alerts/alert/{id}/_update_api_key"`); - expect(config.options?.access).toBe('internal'); - }); - - it('ensures the alert type gets validated for the license', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - updateApiKeyRoute(router, licenseState, docLinks); - - const [, handler] = router.post.mock.calls[0]; - - rulesClient.updateRuleApiKey.mockRejectedValue( - new RuleTypeDisabledError('Fail', 'license_invalid') - ); - - const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: {}, body: {} }, [ - 'ok', - 'forbidden', - ]); - - await handler(context, req, res); - - expect(res.forbidden).toHaveBeenCalledWith({ body: { message: 'Fail' } }); - }); - - it('should track every call', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - const mockUsageCountersSetup = usageCountersServiceMock.createSetupContract(); - const mockUsageCounter = mockUsageCountersSetup.createUsageCounter('test'); - - updateApiKeyRoute(router, licenseState, docLinks, mockUsageCounter); - const [, handler] = router.post.mock.calls[0]; - const [context, req, res] = mockHandlerArguments({ rulesClient }, { params: {}, body: {} }, [ - 'ok', - ]); - await handler(context, req, res); - expect(trackLegacyRouteUsage).toHaveBeenCalledWith('updateApiKey', mockUsageCounter); - }); - - it('should be deprecated', async () => { - const licenseState = licenseStateMock.create(); - const router = httpServiceMock.createRouter(); - - updateApiKeyRoute(router, licenseState, docLinks); - - const [config] = router.post.mock.calls[0]; - expect(config.options?.deprecated).toMatchInlineSnapshot( - { - documentationUrl: expect.stringMatching(/#breaking-201550$/), - }, - ` - Object { - "documentationUrl": StringMatching /#breaking-201550\\$/, - "reason": Object { - "newApiMethod": "POST", - "newApiPath": "/api/alerting/rule/{id}/_update_api_key", - "type": "migrate", - }, - "severity": "warning", - } - ` - ); - }); -}); diff --git a/x-pack/plugins/alerting/server/routes/legacy/update_api_key.ts b/x-pack/plugins/alerting/server/routes/legacy/update_api_key.ts deleted file mode 100644 index 45a3d35e7e5d3..0000000000000 --- a/x-pack/plugins/alerting/server/routes/legacy/update_api_key.ts +++ /dev/null @@ -1,75 +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. - */ - -import { schema } from '@kbn/config-schema'; -import { UsageCounter } from '@kbn/usage-collection-plugin/server'; -import { DocLinksServiceSetup } from '@kbn/core/server'; -import type { AlertingRouter } from '../../types'; -import { ILicenseState } from '../../lib/license_state'; -import { verifyApiAccess } from '../../lib/license_api_access'; -import { LEGACY_BASE_ALERT_API_PATH } from '../../../common'; -import { handleDisabledApiKeysError } from '../lib/error_handler'; -import { RuleTypeDisabledError } from '../../lib/errors/rule_type_disabled'; -import { trackLegacyRouteUsage } from '../../lib/track_legacy_route_usage'; -import { DEFAULT_ALERTING_ROUTE_SECURITY } from '../constants'; - -const paramSchema = schema.object({ - id: schema.string(), -}); - -export const updateApiKeyRoute = ( - router: AlertingRouter, - licenseState: ILicenseState, - docLinks: DocLinksServiceSetup, - usageCounter?: UsageCounter, - isServerless?: boolean -) => { - router.post( - { - path: `${LEGACY_BASE_ALERT_API_PATH}/alert/{id}/_update_api_key`, - validate: { - params: paramSchema, - }, - security: DEFAULT_ALERTING_ROUTE_SECURITY, - options: { - access: isServerless ? 'internal' : 'public', - summary: 'Update the API key for an alert', - tags: ['oas-tag:alerting'], - deprecated: { - documentationUrl: docLinks.links.alerting.legacyRuleApiDeprecations, - severity: 'warning', - reason: { - type: 'migrate', - newApiMethod: 'POST', - newApiPath: '/api/alerting/rule/{id}/_update_api_key', - }, - }, - }, - }, - handleDisabledApiKeysError( - router.handleLegacyErrors(async function (context, req, res) { - verifyApiAccess(licenseState); - if (!context.alerting) { - return res.badRequest({ body: 'RouteHandlerContext is not registered for alerting' }); - } - trackLegacyRouteUsage('updateApiKey', usageCounter); - const alertingContext = await context.alerting; - const rulesClient = await alertingContext.getRulesClient(); - const { id } = req.params; - try { - await rulesClient.updateRuleApiKey({ id }); - return res.noContent(); - } catch (e) { - if (e instanceof RuleTypeDisabledError) { - return e.sendResponse(res); - } - throw e; - } - }) - ) - ); -}; diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/get_all.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/get_all.ts index 39da3ab33a6ea..b354f0f962d84 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/get_all.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/get_all.ts @@ -6,7 +6,6 @@ */ import expect from '@kbn/expect'; -import { RULE_SAVED_OBJECT_TYPE } from '@kbn/alerting-plugin/server'; import { UserAtSpaceScenarios } from '../../../scenarios'; import { getUrlPrefix, getTestRuleData, ObjectRemover } from '../../../../common/lib'; import { FtrProviderContext } from '../../../../common/ftr_provider_context'; @@ -199,7 +198,7 @@ export default function getAllConnectorTests({ getService }: FtrProviderContext) }) ) .expect(200); - objectRemover.add(space.id, createdAlert.id, RULE_SAVED_OBJECT_TYPE, 'alerts'); + objectRemover.add(space.id, createdAlert.id, 'rule', 'alerting'); const response = await supertestWithoutAuth .get(`${getUrlPrefix(space.id)}/api/actions/connectors`) diff --git a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/get_all_system.ts b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/get_all_system.ts index e19ade26171b1..860ab6daf3eca 100644 --- a/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/get_all_system.ts +++ b/x-pack/test/alerting_api_integration/security_and_spaces/group2/tests/actions/get_all_system.ts @@ -6,7 +6,6 @@ */ import expect from '@kbn/expect'; -import { RULE_SAVED_OBJECT_TYPE } from '@kbn/alerting-plugin/server'; import { SuperuserAtSpace1, UserAtSpaceScenarios } from '../../../scenarios'; import { getUrlPrefix, getTestRuleData, ObjectRemover } from '../../../../common/lib'; import { FtrProviderContext } from '../../../../common/ftr_provider_context'; @@ -244,7 +243,7 @@ export default function getAllConnectorTests({ getService }: FtrProviderContext) }) ) .expect(200); - objectRemover.add(space.id, createdAlert.id, RULE_SAVED_OBJECT_TYPE, 'alerts'); + objectRemover.add(space.id, createdAlert.id, 'rule', 'alerting'); const response = await supertestWithoutAuth .get(`${getUrlPrefix(space.id)}/internal/actions/connectors`) diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/connector_types/stack/preconfigured_alert_history_connector.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/connector_types/stack/preconfigured_alert_history_connector.ts index 22f81d7bb7e96..2e98d9129b553 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/actions/connector_types/stack/preconfigured_alert_history_connector.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/actions/connector_types/stack/preconfigured_alert_history_connector.ts @@ -137,10 +137,10 @@ export default function preconfiguredAlertHistoryConnectorTests({ expect().fail(`waiting for alert ${id} statuses ${Array.from(statuses)} timed out`); } - const response = await supertest.get(`/api/alerts/alert/${id}`); + const response = await supertest.get(`/api/alerting/rule/${id}`); expect(response.status).to.eql(200); - const { executionStatus } = response.body || {}; + const { execution_status: executionStatus } = response.body || {}; const { status } = executionStatus || {}; const message = `waitForStatus(${Array.from(statuses)}): got ${JSON.stringify( diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/create.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/create.ts index 5a6385a3895d2..ecef6541f7181 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/create.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/create.ts @@ -720,104 +720,5 @@ export default function createAlertTests({ getService }: FtrProviderContext) { }); }); }); - - describe('legacy', function () { - this.tags('skipFIPS'); - it('should handle create alert request appropriately', async () => { - const { body: createdAction } = await supertest - .post(`${getUrlPrefix(Spaces.space1.id)}/api/actions/connector`) - .set('kbn-xsrf', 'foo') - .send({ - name: 'MY action', - connector_type_id: 'test.noop', - config: {}, - secrets: {}, - }) - .expect(200); - - const { - rule_type_id: alertTypeId, - notify_when: notifyWhen, - ...testAlert - } = getTestRuleData({ - actions: [ - { - id: createdAction.id, - group: 'default', - params: {}, - }, - ], - }); - const response = await supertest - .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerts/alert`) - .set('kbn-xsrf', 'foo') - .send({ - ...testAlert, - alertTypeId, - notifyWhen, - }); - - expect(response.status).to.eql(200); - objectRemover.add(Spaces.space1.id, response.body.id, 'rule', 'alerting'); - expect(response.body).to.eql({ - id: response.body.id, - name: 'abc', - tags: ['foo'], - actions: [ - { - id: createdAction.id, - actionTypeId: createdAction.connector_type_id, - group: 'default', - params: {}, - uuid: response.body.actions[0].uuid, - }, - ], - enabled: true, - alertTypeId: 'test.noop', - consumer: 'alertsFixture', - params: {}, - createdBy: null, - schedule: { interval: '1m' }, - scheduledTaskId: response.body.scheduledTaskId, - updatedBy: null, - apiKeyOwner: null, - apiKeyCreatedByUser: null, - throttle: '1m', - notifyWhen: 'onThrottleInterval', - muteAll: false, - mutedInstanceIds: [], - createdAt: response.body.createdAt, - updatedAt: response.body.updatedAt, - executionStatus: response.body.executionStatus, - revision: 0, - running: false, - ...(response.body.next_run ? { next_run: response.body.next_run } : {}), - ...(response.body.last_run ? { last_run: response.body.last_run } : {}), - }); - expect(Date.parse(response.body.createdAt)).to.be.greaterThan(0); - expect(Date.parse(response.body.updatedAt)).to.be.greaterThan(0); - expect(Date.parse(response.body.updatedAt)).to.eql(Date.parse(response.body.createdAt)); - if (response.body.next_run) { - expect(Date.parse(response.body.next_run)).to.be.greaterThan(0); - } - expect(typeof response.body.scheduledTaskId).to.be('string'); - const taskRecord = await getScheduledTask(response.body.scheduledTaskId); - expect(taskRecord.type).to.eql('task'); - expect(taskRecord.task.taskType).to.eql('alerting:test.noop'); - expect(JSON.parse(taskRecord.task.params)).to.eql({ - alertId: response.body.id, - spaceId: Spaces.space1.id, - consumer: 'alertsFixture', - }); - expect(taskRecord.task.enabled).to.eql(true); - // Ensure AAD isn't broken - await checkAAD({ - supertest, - spaceId: Spaces.space1.id, - type: RULE_SAVED_OBJECT_TYPE, - id: response.body.id, - }); - }); - }); }); } diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/delete.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/delete.ts index 811fbbf2b1732..37f482a5d512e 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/delete.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/delete.ts @@ -65,27 +65,5 @@ export default function createDeleteTests({ getService }: FtrProviderContext) { message: `Saved object [alert/${createdAlert.id}] not found`, }); }); - - describe('legacy', () => { - it('should handle delete alert request appropriately', async () => { - const { body: createdAlert } = await supertest - .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`) - .set('kbn-xsrf', 'foo') - .send(getTestRuleData()) - .expect(200); - - await supertest - .delete(`${getUrlPrefix(Spaces.space1.id)}/api/alerts/alert/${createdAlert.id}`) - .set('kbn-xsrf', 'foo') - .expect(204, ''); - - try { - await getScheduledTask(createdAlert.scheduledTaskId); - throw new Error('Should have removed scheduled task'); - } catch (e) { - expect(e.meta.statusCode).to.eql(404); - } - }); - }); }); } diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/disable.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/disable.ts index 01fa746b65f2a..846c4a719522f 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/disable.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/disable.ts @@ -266,50 +266,5 @@ export default function createDisableRuleTests({ getService }: FtrProviderContex id: createdRule.id, }); }); - - describe('legacy', function () { - it('should handle disable rule request appropriately', async () => { - const { body: createdRule } = await supertestWithoutAuth - .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`) - .set('kbn-xsrf', 'foo') - .send(getTestRuleData({ enabled: true })) - .expect(200); - objectRemover.add(Spaces.space1.id, createdRule.id, 'rule', 'alerting'); - - await supertestWithoutAuth - .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerts/alert/${createdRule.id}/_disable`) - .set('kbn-xsrf', 'foo') - .expect(204); - - // task doc should still exist but be disabled - await retry.try(async () => { - const taskRecord = await getScheduledTask(createdRule.scheduled_task_id); - expect(taskRecord.type).to.eql('task'); - expect(taskRecord.task.taskType).to.eql('alerting:test.noop'); - expect(JSON.parse(taskRecord.task.params)).to.eql({ - alertId: createdRule.id, - spaceId: Spaces.space1.id, - consumer: 'alertsFixture', - }); - expect(taskRecord.task.enabled).to.eql(false); - }); - - const { body: disabledRule } = await supertestWithoutAuth - .get(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule/${createdRule.id}`) - .set('kbn-xsrf', 'foo') - .expect(200); - - // Ensure revision was not updated - expect(disabledRule.revision).to.eql(0); - - // Ensure AAD isn't broken - await checkAAD({ - supertest: supertestWithoutAuth, - spaceId: Spaces.space1.id, - type: RULE_SAVED_OBJECT_TYPE, - id: createdRule.id, - }); - }); - }); }); } diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/enable.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/enable.ts index 74b8fd0307a86..8eae2dfe7022b 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/enable.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/enable.ts @@ -94,48 +94,5 @@ export default function createEnableAlertTests({ getService }: FtrProviderContex }); }); }); - - describe('legacy', function () { - this.tags('skipFIPS'); - it('should handle enable alert request appropriately', async () => { - const { body: createdAlert } = await supertestWithoutAuth - .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`) - .set('kbn-xsrf', 'foo') - .send(getTestRuleData({ enabled: false })) - .expect(200); - objectRemover.add(Spaces.space1.id, createdAlert.id, 'rule', 'alerting'); - - await supertestWithoutAuth - .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerts/alert/${createdAlert.id}/_enable`) - .set('kbn-xsrf', 'foo') - .expect(204); - - const { body: updatedAlert } = await supertestWithoutAuth - .get(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule/${createdAlert.id}`) - .set('kbn-xsrf', 'foo') - .expect(200); - expect(typeof updatedAlert.scheduled_task_id).to.eql('string'); - const taskRecord = await getScheduledTask(updatedAlert.scheduled_task_id); - expect(taskRecord.type).to.eql('task'); - expect(taskRecord.task.taskType).to.eql('alerting:test.noop'); - expect(JSON.parse(taskRecord.task.params)).to.eql({ - alertId: createdAlert.id, - spaceId: Spaces.space1.id, - consumer: 'alertsFixture', - }); - expect(taskRecord.task.enabled).to.eql(true); - - // Ensure revision was not updated - expect(updatedAlert.revision).to.eql(0); - - // Ensure AAD isn't broken - await checkAAD({ - supertest: supertestWithoutAuth, - spaceId: Spaces.space1.id, - type: RULE_SAVED_OBJECT_TYPE, - id: createdAlert.id, - }); - }); - }); }); } diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/find.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/find.ts index f6b48df9b9f17..c902355b68fcc 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/find.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/find.ts @@ -336,58 +336,5 @@ export default function createFindTests({ getService }: FtrProviderContext) { }); }); }); - - describe('legacy', function () { - this.tags('skipFIPS'); - it('should handle find alert request appropriately', async () => { - const { body: createdAlert } = await supertest - .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`) - .set('kbn-xsrf', 'foo') - .send(getTestRuleData()) - .expect(200); - objectRemover.add(Spaces.space1.id, createdAlert.id, 'rule', 'alerting'); - - const response = await supertest.get( - `${getUrlPrefix( - Spaces.space1.id - )}/api/alerts/_find?search=test.noop&search_fields=alertTypeId` - ); - - expect(response.status).to.eql(200); - expect(response.body.page).to.equal(1); - expect(response.body.perPage).to.be.greaterThan(0); - expect(response.body.total).to.be.greaterThan(0); - const match = response.body.data.find((obj: any) => obj.id === createdAlert.id); - expect(match).to.eql({ - id: createdAlert.id, - name: 'abc', - tags: ['foo'], - alertTypeId: 'test.noop', - consumer: 'alertsFixture', - schedule: { interval: '1m' }, - enabled: true, - actions: [], - params: {}, - createdBy: null, - apiKeyOwner: null, - apiKeyCreatedByUser: null, - scheduledTaskId: match.scheduledTaskId, - updatedBy: null, - throttle: '1m', - notifyWhen: 'onThrottleInterval', - muteAll: false, - mutedInstanceIds: [], - createdAt: match.createdAt, - updatedAt: match.updatedAt, - executionStatus: match.executionStatus, - revision: 0, - running: false, - ...(match.nextRun ? { nextRun: match.nextRun } : {}), - ...(match.lastRun ? { lastRun: match.lastRun } : {}), - }); - expect(Date.parse(match.createdAt)).to.be.greaterThan(0); - expect(Date.parse(match.updatedAt)).to.be.greaterThan(0); - }); - }); }); } diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/find_internal.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/find_internal.ts index 7c10b9be598bb..e8dc9ac696842 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/find_internal.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/find_internal.ts @@ -337,54 +337,5 @@ export default function createFindTests({ getService }: FtrProviderContext) { expect(response.body.total).to.equal(1); expect(response.body.data[0].consumer).to.eql('alertsRestrictedFixture'); }); - - describe('legacy', function () { - this.tags('skipFIPS'); - it('should handle find alert request appropriately', async () => { - const { body: createdAlert } = await supertest - .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`) - .set('kbn-xsrf', 'foo') - .send(getTestRuleData()) - .expect(200); - objectRemover.add(Spaces.space1.id, createdAlert.id, 'rule', 'alerting'); - - const response = await supertest.get(`${getUrlPrefix(Spaces.space1.id)}/api/alerts/_find`); - - expect(response.status).to.eql(200); - expect(response.body.page).to.equal(1); - expect(response.body.perPage).to.be.greaterThan(0); - expect(response.body.total).to.be.greaterThan(0); - const match = response.body.data.find((obj: any) => obj.id === createdAlert.id); - expect(match).to.eql({ - id: createdAlert.id, - name: 'abc', - tags: ['foo'], - alertTypeId: 'test.noop', - consumer: 'alertsFixture', - schedule: { interval: '1m' }, - enabled: true, - actions: [], - params: {}, - createdBy: null, - apiKeyOwner: null, - apiKeyCreatedByUser: null, - scheduledTaskId: match.scheduledTaskId, - updatedBy: null, - throttle: '1m', - notifyWhen: 'onThrottleInterval', - muteAll: false, - mutedInstanceIds: [], - createdAt: match.createdAt, - updatedAt: match.updatedAt, - executionStatus: match.executionStatus, - revision: 0, - running: false, - ...(match.nextRun ? { nextRun: match.nextRun } : {}), - ...(match.lastRun ? { lastRun: match.lastRun } : {}), - }); - expect(Date.parse(match.createdAt)).to.be.greaterThan(0); - expect(Date.parse(match.updatedAt)).to.be.greaterThan(0); - }); - }); }); } diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/get.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/get.ts index e559b1d17f196..58fdbf377ecf1 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/get.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/get.ts @@ -124,55 +124,5 @@ export default function createGetTests({ getService }: FtrProviderContext) { getTestUtils('public', objectRemover, supertest); getTestUtils('internal', objectRemover, supertest); - - describe('legacy', function () { - this.tags('skipFIPS'); - it('should handle get alert request appropriately', async () => { - const { body: createdAlert } = await supertest - .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`) - .set('kbn-xsrf', 'foo') - .send(getTestRuleData()) - .expect(200); - objectRemover.add(Spaces.space1.id, createdAlert.id, 'rule', 'alerting'); - - const response = await supertest.get( - `${getUrlPrefix(Spaces.space1.id)}/api/alerts/alert/${createdAlert.id}` - ); - - expect(response.status).to.eql(200); - expect(response.body).to.eql({ - id: createdAlert.id, - name: 'abc', - tags: ['foo'], - alertTypeId: 'test.noop', - consumer: 'alertsFixture', - schedule: { interval: '1m' }, - enabled: true, - actions: [], - params: {}, - createdBy: null, - scheduledTaskId: response.body.scheduledTaskId, - updatedBy: null, - apiKeyOwner: null, - apiKeyCreatedByUser: null, - throttle: '1m', - notifyWhen: 'onThrottleInterval', - muteAll: false, - mutedInstanceIds: [], - createdAt: response.body.createdAt, - updatedAt: response.body.updatedAt, - executionStatus: response.body.executionStatus, - revision: 0, - running: false, - ...(response.body.nextRun ? { nextRun: response.body.nextRun } : {}), - ...(response.body.lastRun ? { lastRun: response.body.lastRun } : {}), - }); - expect(Date.parse(response.body.createdAt)).to.be.greaterThan(0); - expect(Date.parse(response.body.updatedAt)).to.be.greaterThan(0); - if (response.body.nextRun) { - expect(Date.parse(response.body.nextRun)).to.be.greaterThan(0); - } - }); - }); }); } diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/get_alert_state.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/get_alert_state.ts index 6082e6ff69eb8..87a8449fb37e1 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/get_alert_state.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/get_alert_state.ts @@ -91,53 +91,5 @@ export default function createGetAlertStateTests({ getService }: FtrProviderCont message: 'Saved object [alert/1] not found', }); }); - - describe('legacy', () => { - it('should fetch updated state', async () => { - const { body: createdAlert } = await supertest - .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`) - .set('kbn-xsrf', 'foo') - .send({ - enabled: true, - name: 'abc', - tags: ['foo'], - rule_type_id: 'test.cumulative-firing', - consumer: 'alertsFixture', - schedule: { interval: '5s' }, - throttle: '5s', - actions: [], - params: {}, - notify_when: 'onThrottleInterval', - }) - .expect(200); - objectRemover.add(Spaces.space1.id, createdAlert.id, 'rule', 'alerting'); - - // wait for alert to actually execute - await retry.try(async () => { - const response = await supertest.get( - `${getUrlPrefix(Spaces.space1.id)}/api/alerts/alert/${createdAlert.id}/state` - ); - - expect(response.status).to.eql(200); - expect(response.body).to.key('alertInstances', 'alertTypeState', 'previousStartedAt'); - expect(response.body.alertTypeState.runCount).to.greaterThan(1); - }); - - const response = await supertest.get( - `${getUrlPrefix(Spaces.space1.id)}/internal/alerting/rule/${createdAlert.id}/state` - ); - - expect(response.body.rule_type_state.runCount).to.greaterThan(0); - - const alertInstances = Object.entries>(response.body.alerts); - expect(alertInstances.length).to.eql(response.body.rule_type_state.runCount); - alertInstances.forEach(([key, value], index) => { - expect(key).to.eql(`instance-${index}`); - expect(value.state.instanceStateValue).to.be(true); - expect(value.state.start).not.to.be(undefined); - expect(value.state.duration).not.to.be(undefined); - }); - }); - }); }); } diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/get_alert_summary.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/get_alert_summary.ts index 86444543bde73..cee5e44afcc8d 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/get_alert_summary.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/get_alert_summary.ts @@ -384,78 +384,6 @@ export default function createGetAlertSummaryTests({ getService }: FtrProviderCo expect(actualAlerts).to.eql(expectedAlerts); }); }); - - describe('legacy', function () { - this.tags('skipFIPS'); - it('handles multi-alert status', async () => { - // wait so cache expires - await setTimeoutAsync(TEST_CACHE_EXPIRATION_TIME); - - // pattern of when the alert should fire - const pattern = { - alertA: [true, true, true, true], - alertB: [true, true, false, false], - alertC: [true, true, true, true], - }; - - const { body: createdRule } = await supertest - .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`) - .set('kbn-xsrf', 'foo') - .send( - getTestRuleData({ - rule_type_id: 'test.patternFiring', - params: { pattern }, - schedule: { interval: '1s' }, - }) - ) - .expect(200); - objectRemover.add(Spaces.space1.id, createdRule.id, 'rule', 'alerting'); - - await alertUtils.muteInstance(createdRule.id, 'alertC'); - await alertUtils.muteInstance(createdRule.id, 'alertD'); - await waitForEvents(createdRule.id, ['new-instance', 'recovered-instance']); - const response = await supertest.get( - `${getUrlPrefix(Spaces.space1.id)}/api/alerts/alert/${createdRule.id}/_instance_summary` - ); - - const actualAlerts = checkAndCleanActualAlerts(response.body.instances, [ - 'alertA', - 'alertB', - 'alertC', - ]); - const expectedAlerts = { - alertA: { - status: 'Active', - muted: false, - actionGroupId: 'default', - activeStartDate: actualAlerts.alertA.activeStartDate, - flapping: false, - tracked: true, - }, - alertB: { - status: 'OK', - muted: false, - flapping: false, - tracked: true, - }, - alertC: { - status: 'Active', - muted: true, - actionGroupId: 'default', - activeStartDate: actualAlerts.alertC.activeStartDate, - flapping: false, - tracked: true, - }, - alertD: { - status: 'OK', - muted: true, - flapping: false, - tracked: true, - }, - }; - expect(actualAlerts).to.eql(expectedAlerts); - }); - }); }); async function waitForEvents(id: string, actions: string[]) { diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/rule_types.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/rule_types.ts index e722d058e8b7c..9a0ad8133c02c 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/rule_types.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group1/rule_types.ts @@ -103,46 +103,5 @@ export default function listRuleTypes({ getService }: FtrProviderContext) { params: [], }); }); - - describe('legacy', () => { - it('should return 200 with list of alert types', async () => { - const response = await supertest.get( - `${getUrlPrefix(Spaces.space1.id)}/api/alerts/list_alert_types` - ); - expect(response.status).to.eql(200); - const { authorizedConsumers, ...fixtureAlertType } = response.body.find( - (alertType: any) => alertType.id === 'test.noop' - ); - expect(fixtureAlertType).to.eql({ - actionGroups: [ - { id: 'default', name: 'Default' }, - { id: 'recovered', name: 'Recovered' }, - ], - defaultActionGroupId: 'default', - doesSetRecoveryContext: false, - id: 'test.noop', - name: 'Test: Noop', - actionVariables: { - state: [], - params: [], - context: [], - }, - recoveryActionGroup: { - id: 'recovered', - name: 'Recovered', - }, - category: 'kibana', - producer: 'alertsFixture', - minimumLicenseRequired: 'basic', - isExportable: true, - enabledInLicense: true, - hasFieldsForAAD: false, - hasAlertsMappings: false, - ruleTaskTimeout: '5m', - validLegacyConsumers: ['alerts'], - }); - expect(Object.keys(authorizedConsumers)).to.contain('alertsFixture'); - }); - }); }); } diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/mute_all.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/mute_all.ts index e4cbec75460b0..09a12a1371454 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/mute_all.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/mute_all.ts @@ -51,35 +51,5 @@ export default function createMuteTests({ getService }: FtrProviderContext) { id: createdAlert.id, }); }); - - describe('legacy', () => { - it('should handle mute alert request appropriately', async () => { - const { body: createdAlert } = await supertestWithoutAuth - .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`) - .set('kbn-xsrf', 'foo') - .send(getTestRuleData({ enabled: false })) - .expect(200); - objectRemover.add(Spaces.space1.id, createdAlert.id, 'rule', 'alerting'); - - await supertestWithoutAuth - .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerts/alert/${createdAlert.id}/_mute_all`) - .set('kbn-xsrf', 'foo') - .expect(204); - - const { body: updatedAlert } = await supertestWithoutAuth - .get(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule/${createdAlert.id}`) - .set('kbn-xsrf', 'foo') - .expect(200); - expect(updatedAlert.mute_all).to.eql(true); - - // Ensure AAD isn't broken - await checkAAD({ - supertest: supertestWithoutAuth, - spaceId: Spaces.space1.id, - type: RULE_SAVED_OBJECT_TYPE, - id: createdAlert.id, - }); - }); - }); }); } diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/mute_instance.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/mute_instance.ts index ac580ad335c51..65791c86e833b 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/mute_instance.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/mute_instance.ts @@ -52,39 +52,5 @@ export default function createMuteInstanceTests({ getService }: FtrProviderConte id: createdAlert.id, }); }); - - describe('legacy', () => { - it('should handle mute alert instance request appropriately', async () => { - const { body: createdAlert } = await supertestWithoutAuth - .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`) - .set('kbn-xsrf', 'foo') - .send(getTestRuleData({ enabled: false })) - .expect(200); - objectRemover.add(Spaces.space1.id, createdAlert.id, 'rule', 'alerting'); - - await supertestWithoutAuth - .post( - `${getUrlPrefix(Spaces.space1.id)}/api/alerts/alert/${ - createdAlert.id - }/alert_instance/1/_mute` - ) - .set('kbn-xsrf', 'foo') - .expect(204); - - const { body: updatedAlert } = await supertestWithoutAuth - .get(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule/${createdAlert.id}`) - .set('kbn-xsrf', 'foo') - .expect(200); - expect(updatedAlert.muted_alert_ids).to.eql(['1']); - - // Ensure AAD isn't broken - await checkAAD({ - supertest: supertestWithoutAuth, - spaceId: Spaces.space1.id, - type: RULE_SAVED_OBJECT_TYPE, - id: createdAlert.id, - }); - }); - }); }); } diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/unmute_all.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/unmute_all.ts index 363086e1549fe..42bca18c07bfc 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/unmute_all.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/unmute_all.ts @@ -53,39 +53,5 @@ export default function createUnmuteTests({ getService }: FtrProviderContext) { id: createdAlert.id, }); }); - - describe('legacy', () => { - it('should handle unmute alert request appropriately', async () => { - const { body: createdAlert } = await supertestWithoutAuth - .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`) - .set('kbn-xsrf', 'foo') - .send(getTestRuleData({ enabled: false })) - .expect(200); - objectRemover.add(Spaces.space1.id, createdAlert.id, 'rule', 'alerting'); - - await supertestWithoutAuth - .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerts/alert/${createdAlert.id}/_mute_all`) - .set('kbn-xsrf', 'foo') - .expect(204); - await supertestWithoutAuth - .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerts/alert/${createdAlert.id}/_unmute_all`) - .set('kbn-xsrf', 'foo') - .expect(204); - - const { body: updatedAlert } = await supertestWithoutAuth - .get(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule/${createdAlert.id}`) - .set('kbn-xsrf', 'foo') - .expect(200); - expect(updatedAlert.mute_all).to.eql(false); - - // Ensure AAD isn't broken - await checkAAD({ - supertest: supertestWithoutAuth, - spaceId: Spaces.space1.id, - type: RULE_SAVED_OBJECT_TYPE, - id: createdAlert.id, - }); - }); - }); }); } diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/unmute_instance.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/unmute_instance.ts index 5655e52aa4d09..4b54c6c0c134f 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/unmute_instance.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/unmute_instance.ts @@ -53,47 +53,5 @@ export default function createUnmuteInstanceTests({ getService }: FtrProviderCon id: createdAlert.id, }); }); - - describe('legacy', () => { - it('should handle unmute alert instance request appropriately', async () => { - const { body: createdAlert } = await supertestWithoutAuth - .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`) - .set('kbn-xsrf', 'foo') - .send(getTestRuleData({ enabled: false })) - .expect(200); - objectRemover.add(Spaces.space1.id, createdAlert.id, 'rule', 'alerting'); - - await supertestWithoutAuth - .post( - `${getUrlPrefix(Spaces.space1.id)}/api/alerts/alert/${ - createdAlert.id - }/alert_instance/1/_mute` - ) - .set('kbn-xsrf', 'foo') - .expect(204); - await supertestWithoutAuth - .post( - `${getUrlPrefix(Spaces.space1.id)}/api/alerts/alert/${ - createdAlert.id - }/alert_instance/1/_unmute` - ) - .set('kbn-xsrf', 'foo') - .expect(204); - - const { body: updatedAlert } = await supertestWithoutAuth - .get(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule/${createdAlert.id}`) - .set('kbn-xsrf', 'foo') - .expect(200); - expect(updatedAlert.muted_alert_ids).to.eql([]); - - // Ensure AAD isn't broken - await checkAAD({ - supertest: supertestWithoutAuth, - spaceId: Spaces.space1.id, - type: RULE_SAVED_OBJECT_TYPE, - id: createdAlert.id, - }); - }); - }); }); } diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/update.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/update.ts index 025fa3b693dce..24fdf571f070d 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/update.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/update.ts @@ -408,75 +408,5 @@ export default function createUpdateTests({ getService }: FtrProviderContext) { .expect(400); }); }); - - describe('legacy', function () { - this.tags('skipFIPS'); - it('should handle update alert request appropriately', async () => { - const { body: createdAlert } = await supertest - .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`) - .set('kbn-xsrf', 'foo') - .send(getTestRuleData()) - .expect(200); - objectRemover.add(Spaces.space1.id, createdAlert.id, 'rule', 'alerting'); - - const updatedData = { - name: 'bcd', - tags: ['bar'], - params: { - foo: true, - }, - schedule: { interval: '12s' }, - actions: [], - throttle: '1m', - notifyWhen: 'onThrottleInterval', - }; - - const response = await supertest - .put(`${getUrlPrefix(Spaces.space1.id)}/api/alerts/alert/${createdAlert.id}`) - .set('kbn-xsrf', 'foo') - .send(updatedData) - .expect(200); - - expect(response.body).to.eql({ - ...updatedData, - id: createdAlert.id, - tags: ['bar'], - alertTypeId: 'test.noop', - consumer: 'alertsFixture', - createdBy: null, - enabled: true, - updatedBy: null, - apiKeyOwner: null, - apiKeyCreatedByUser: null, - muteAll: false, - mutedInstanceIds: [], - notifyWhen: 'onThrottleInterval', - scheduledTaskId: createdAlert.scheduled_task_id, - createdAt: response.body.createdAt, - updatedAt: response.body.updatedAt, - executionStatus: response.body.executionStatus, - revision: 1, - running: false, - ...(response.body.nextRun ? { nextRun: response.body.nextRun } : {}), - ...(response.body.lastRun ? { lastRun: response.body.lastRun } : {}), - }); - expect(Date.parse(response.body.createdAt)).to.be.greaterThan(0); - expect(Date.parse(response.body.updatedAt)).to.be.greaterThan(0); - expect(Date.parse(response.body.updatedAt)).to.be.greaterThan( - Date.parse(response.body.createdAt) - ); - if (response.body.nextRun) { - expect(Date.parse(response.body.nextRun)).to.be.greaterThan(0); - } - - // Ensure AAD isn't broken - await checkAAD({ - supertest, - spaceId: Spaces.space1.id, - type: RULE_SAVED_OBJECT_TYPE, - id: createdAlert.id, - }); - }); - }); }); } diff --git a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/update_api_key.ts b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/update_api_key.ts index 0aa9ec3354acd..e588d0e606543 100644 --- a/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/update_api_key.ts +++ b/x-pack/test/alerting_api_integration/spaces_only/tests/alerting/group2/update_api_key.ts @@ -79,41 +79,5 @@ export default function createUpdateApiKeyTests({ getService }: FtrProviderConte }); }); }); - - describe('legacy', function () { - this.tags('skipFIPS'); - it('should handle update alert api key appropriately', async () => { - const { body: createdAlert } = await supertestWithoutAuth - .post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`) - .set('kbn-xsrf', 'foo') - .send(getTestRuleData()) - .expect(200); - objectRemover.add(Spaces.space1.id, createdAlert.id, 'rule', 'alerting'); - - await supertestWithoutAuth - .post( - `${getUrlPrefix(Spaces.space1.id)}/api/alerts/alert/${createdAlert.id}/_update_api_key` - ) - .set('kbn-xsrf', 'foo') - .expect(204); - - const { body: updatedAlert } = await supertestWithoutAuth - .get(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule/${createdAlert.id}`) - .set('kbn-xsrf', 'foo') - .expect(200); - expect(updatedAlert.api_key_owner).to.eql(null); - - // Ensure revision is not incremented when API key is updated - expect(updatedAlert.revision).to.eql(0); - - // Ensure AAD isn't broken - await checkAAD({ - supertest: supertestWithoutAuth, - spaceId: Spaces.space1.id, - type: RULE_SAVED_OBJECT_TYPE, - id: createdAlert.id, - }); - }); - }); }); } diff --git a/x-pack/test/functional/services/monitoring/alerts.js b/x-pack/test/functional/services/monitoring/alerts.js index c480cc0c45c03..5e5d880da102c 100644 --- a/x-pack/test/functional/services/monitoring/alerts.js +++ b/x-pack/test/functional/services/monitoring/alerts.js @@ -10,12 +10,12 @@ export function MonitoringAlertsProvider({ getService }) { return new (class MonitoringAlerts { async deleteAlerts() { - const apiResponse = await supertest.get('/api/alerts/_find?per_page=20'); + const apiResponse = await supertest.get('/api/alerting/rules/_find?per_page=20'); const alerts = apiResponse.body.data.filter(({ consumer }) => consumer === 'monitoring'); return await Promise.all( alerts.map(async (alert) => - supertest.delete(`/api/alerts/alert/${alert.id}`).set('kbn-xsrf', 'true').expect(204) + supertest.delete(`/api/alerting/rule/${alert.id}`).set('kbn-xsrf', 'true').expect(204) ) ); } diff --git a/x-pack/test/functional_with_es_ssl/apps/discover_ml_uptime/uptime/alert_flyout.ts b/x-pack/test/functional_with_es_ssl/apps/discover_ml_uptime/uptime/alert_flyout.ts index 25f77cb8d41ef..8126a3e42d815 100644 --- a/x-pack/test/functional_with_es_ssl/apps/discover_ml_uptime/uptime/alert_flyout.ts +++ b/x-pack/test/functional_with_es_ssl/apps/discover_ml_uptime/uptime/alert_flyout.ts @@ -98,7 +98,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { await retry.tryForTime(60 * 1000, async () => { // add a delay before next call to not overload the server await setTimeoutAsync(1500); - const apiResponse = await supertest.get('/api/alerts/_find?search=uptime-test'); + const apiResponse = await supertest.get('/api/alerting/rules/_find?search=uptime-test'); const alertsFromThisTest = apiResponse.body.data.filter( ({ name }: { name: string }) => name === 'uptime-test' ); @@ -111,7 +111,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { // for our test helper to input into the flyout. const { actions, - alertTypeId, + rule_type_id: alertTypeId, consumer, id, params: { numTimes, timerangeUnit, timerangeCount, filters }, @@ -134,7 +134,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { `{"tags":[],"url.port":["5678"],"observer.geo.name":["mpls"],"monitor.type":["http"]}` ); } finally { - await supertest.delete(`/api/alerts/alert/${id}`).set('kbn-xsrf', 'true').expect(204); + await supertest.delete(`/api/alerting/rule/${id}`).set('kbn-xsrf', 'true').expect(204); } }); }); @@ -178,7 +178,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { it('has created a valid alert with expected parameters', async () => { let alert: any; await retry.tryForTime(60 * 1000, async () => { - const apiResponse = await supertest.get(`/api/alerts/_find?search=${alertId}`); + const apiResponse = await supertest.get(`/api/alerting/rules/_find?search=${alertId}`); const alertsFromThisTest = apiResponse.body.data.filter( ({ name }: { name: string }) => name === alertId ); @@ -191,7 +191,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { // for our test helper to input into the flyout. const { actions, - alertTypeId, + rule_type_id: alertTypeId, consumer, id, params, @@ -206,7 +206,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { expect(params).to.eql({}); expect(interval).to.eql('11m'); } finally { - await supertest.delete(`/api/alerts/alert/${id}`).set('kbn-xsrf', 'true').expect(204); + await supertest.delete(`/api/alerting/rule/${id}`).set('kbn-xsrf', 'true').expect(204); } }); }); diff --git a/x-pack/test/functional_with_es_ssl/apps/discover_ml_uptime/uptime/simple_down_alert.ts b/x-pack/test/functional_with_es_ssl/apps/discover_ml_uptime/uptime/simple_down_alert.ts index e5efd66060e31..d1c4c2c7742fd 100644 --- a/x-pack/test/functional_with_es_ssl/apps/discover_ml_uptime/uptime/simple_down_alert.ts +++ b/x-pack/test/functional_with_es_ssl/apps/discover_ml_uptime/uptime/simple_down_alert.ts @@ -83,7 +83,9 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { it('has created a valid simple alert with expected parameters', async () => { let alert: any; await retry.tryForTime(15000, async () => { - const apiResponse = await supertest.get(`/api/alerts/_find?search=Simple status alert`); + const apiResponse = await supertest.get( + `/api/alerting/rules/_find?search=Simple status alert` + ); const alertsFromThisTest = apiResponse.body.data.filter(({ params }: { params: any }) => params.search.includes(monitorId) ); @@ -91,10 +93,10 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { alert = alertsFromThisTest[0]; }); - const { actions, alertTypeId, consumer, tags } = alert ?? {}; + const { actions, rule_type_id: alertTypeId, consumer, tags } = alert ?? {}; expect(actions).to.eql([ { - actionTypeId: '.slack', + connector_type_id: '.slack', group: 'recovered', params: { message: MonitorStatusTranslations.defaultRecoveryMessage, @@ -103,7 +105,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { uuid: actions[0].uuid, }, { - actionTypeId: '.slack', + connector_type_id: '.slack', group: 'xpack.uptime.alerts.actionGroups.monitorStatus', params: { message: MonitorStatusTranslations.defaultActionMessage, diff --git a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/connectors/general.ts b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/connectors/general.ts index 25e6e169ec4a4..1e0123f7e9741 100644 --- a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/connectors/general.ts +++ b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/connectors/general.ts @@ -321,7 +321,7 @@ export default ({ getPageObjects, getPageObject, getService }: FtrProviderContex }, supertest ); - objectRemover.add(rule.id, 'alert', 'alerts'); + objectRemover.add(rule.id, 'rule', 'alerting'); // refresh to see rule await browser.refresh(); diff --git a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/connectors/slack.ts b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/connectors/slack.ts index a7ea6aef95c8a..6e89bcf411121 100644 --- a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/connectors/slack.ts +++ b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/connectors/slack.ts @@ -115,7 +115,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const getRuleIdByName = async (name: string) => { const response = await supertest - .get(`/api/alerts/_find?search=${name}&search_fields=name`) + .get(`/api/alerting/rules/_find?search=${name}&search_fields=name`) .expect(200); return response.body.data[0].id; }; diff --git a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/details.ts b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/details.ts index 56150e5693a39..ebe0007b1a4ef 100644 --- a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/details.ts +++ b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/details.ts @@ -47,7 +47,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { .set('kbn-xsrf', 'foo') .send(getTestAlertData(overwrites)) .expect(200); - objectRemover.add(createdRule.id, 'alert', 'alerts'); + objectRemover.add(createdRule.id, 'rule', 'alerting'); return createdRule; } @@ -62,7 +62,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { }) ) .expect(200); - objectRemover.add(createdRule.id, 'alert', 'alerts'); + objectRemover.add(createdRule.id, 'rule', 'alerting'); return createdRule; } diff --git a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/rules_list/rules_list.ts b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/rules_list/rules_list.ts index a9de637cd691a..b73659839c9e3 100644 --- a/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/rules_list/rules_list.ts +++ b/x-pack/test/functional_with_es_ssl/apps/triggers_actions_ui/rules_list/rules_list.ts @@ -223,7 +223,7 @@ export default ({ getPageObjects, getPageObject, getService }: FtrProviderContex ) .expect(200); - objectRemover.add(createdRule.id, 'alert', 'alerts'); + objectRemover.add(createdRule.id, 'rule', 'alerting'); await retry.try(async () => { const { alerts: alertInstances } = await getAlertSummary(createdRule.id); @@ -265,7 +265,7 @@ export default ({ getPageObjects, getPageObject, getService }: FtrProviderContex ) .expect(200); - objectRemover.add(createdRule.id, 'alert', 'alerts'); + objectRemover.add(createdRule.id, 'rule', 'alerting'); await retry.try(async () => { const { alerts: alertInstances } = await getAlertSummary(createdRule.id); diff --git a/x-pack/test/functional_with_es_ssl/lib/alert_api_actions.ts b/x-pack/test/functional_with_es_ssl/lib/alert_api_actions.ts index 09b875b43a359..72e1521b4f613 100644 --- a/x-pack/test/functional_with_es_ssl/lib/alert_api_actions.ts +++ b/x-pack/test/functional_with_es_ssl/lib/alert_api_actions.ts @@ -51,7 +51,7 @@ export async function createAlert({ overwrites?: Record; }) { const createdAlert = await createAlertManualCleanup({ supertest, overwrites }); - objectRemover.add(createdAlert.id, 'alert', 'alerts'); + objectRemover.add(createdAlert.id, 'rule', 'alerting'); return createdAlert; } diff --git a/x-pack/test/plugin_api_integration/test_suites/task_manager/metrics_route.ts b/x-pack/test/plugin_api_integration/test_suites/task_manager/metrics_route.ts index 50568fe1c206c..b456e35d5d673 100644 --- a/x-pack/test/plugin_api_integration/test_suites/task_manager/metrics_route.ts +++ b/x-pack/test/plugin_api_integration/test_suites/task_manager/metrics_route.ts @@ -301,7 +301,7 @@ export default function ({ getService }: FtrProviderContext) { // update apiKey to fix decryption error await request - .post(`/api/alerts/alert/${ruleId}/_update_api_key`) + .post(`/api/alerting/rule/${ruleId}/_update_api_key`) .set('kbn-xsrf', 'xxx') .expect(204); diff --git a/x-pack/test/rule_registry/common/lib/helpers/create_alert.ts b/x-pack/test/rule_registry/common/lib/helpers/create_alert.ts index 40d43ac80d210..b758ac4b1a041 100644 --- a/x-pack/test/rule_registry/common/lib/helpers/create_alert.ts +++ b/x-pack/test/rule_registry/common/lib/helpers/create_alert.ts @@ -17,7 +17,7 @@ export const createAlert = async ( ) => { const supertest = getService('supertestWithoutAuth'); const { body: response, status } = await supertest - .post(`${getSpaceUrlPrefix(spaceId)}/api/alerts/alert`) + .post(`${getSpaceUrlPrefix(spaceId)}/api/alerting/rule`) .auth(user.username, user.password) .send(alertDef) .set('kbn-xsrf', 'foo'); diff --git a/x-pack/test/rule_registry/common/lib/helpers/delete_alert.ts b/x-pack/test/rule_registry/common/lib/helpers/delete_alert.ts index 209b182a958c5..b373d0ffe8667 100644 --- a/x-pack/test/rule_registry/common/lib/helpers/delete_alert.ts +++ b/x-pack/test/rule_registry/common/lib/helpers/delete_alert.ts @@ -22,7 +22,7 @@ export const deleteAlert = async ( const { body: targetIndices } = await getAlertsTargetIndices(getService, user, spaceId); if (id) { const { body, status } = await supertest - .delete(`${getSpaceUrlPrefix(spaceId)}/api/alerts/alert/${id}`) + .delete(`${getSpaceUrlPrefix(spaceId)}/api/alerting/rule/${id}`) .auth(user.username, user.password) .set('kbn-xsrf', 'foo'); diff --git a/x-pack/test/rule_registry/common/lib/helpers/wait_until_next_execution.ts b/x-pack/test/rule_registry/common/lib/helpers/wait_until_next_execution.ts index 73e15c6cdbaeb..08613ba2c143d 100644 --- a/x-pack/test/rule_registry/common/lib/helpers/wait_until_next_execution.ts +++ b/x-pack/test/rule_registry/common/lib/helpers/wait_until_next_execution.ts @@ -27,7 +27,7 @@ export async function waitUntilNextExecution( }); const { body, status } = await supertest - .get(`${getSpaceUrlPrefix(spaceId)}/api/alerts/alert/${alert.id}`) + .get(`${getSpaceUrlPrefix(spaceId)}/api/alerting/rule/${alert.id}`) .auth(user.username, user.password) .set('kbn-xsrf', 'foo'); diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/alerts/wait_for_alert_to_complete.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/alerts/wait_for_alert_to_complete.ts index d6799e6be611c..c4a9b7d2a8548 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/alerts/wait_for_alert_to_complete.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/alerts/wait_for_alert_to_complete.ts @@ -17,7 +17,9 @@ export const waitForAlertToComplete = async ( ): Promise => { await waitFor( async () => { - const response = await supertest.get(`/api/alerts/alert/${id}/state`).set('kbn-xsrf', 'true'); + const response = await supertest + .get(`/internal/alerting/rule/${id}/state`) + .set('kbn-xsrf', 'true'); if (response.status !== 200) { log.debug( `Did not get an expected 200 "ok" when waiting for an alert to complete (waitForAlertToComplete). CI issues could happen. Suspect this line if you are seeing CI issues. body: ${JSON.stringify( @@ -25,7 +27,7 @@ export const waitForAlertToComplete = async ( )}, status: ${JSON.stringify(response.status)}` ); } - return response.body.previousStartedAt != null; + return response.body.previous_started_at != null; }, 'waitForAlertToComplete', log diff --git a/x-pack/test/task_manager_claimer_update_by_query/test_suites/task_manager/metrics_route.ts b/x-pack/test/task_manager_claimer_update_by_query/test_suites/task_manager/metrics_route.ts index 3e37c488e5190..2bab3cf0dc577 100644 --- a/x-pack/test/task_manager_claimer_update_by_query/test_suites/task_manager/metrics_route.ts +++ b/x-pack/test/task_manager_claimer_update_by_query/test_suites/task_manager/metrics_route.ts @@ -296,7 +296,7 @@ export default function ({ getService }: FtrProviderContext) { // update apiKey to fix decryption error await request - .post(`/api/alerts/alert/${ruleId}/_update_api_key`) + .post(`/api/alerting/rule/${ruleId}/_update_api_key`) .set('kbn-xsrf', 'xxx') .expect(204);