mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[Response Ops] Remove ephemeral tasks from action and alerting plugins (#197421)
## Summary Issue: https://github.com/elastic/kibana/issues/151461 Removes all reference to ephemeral tasks in the alerting and actions plugin. As well as unit and E2E tests while maintaining backwards compatibility for `xpack.alerting.maxEphemeralActionsPerAlert` flag. ### Checklist - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
parent
40905c14ad
commit
7e71e5a1eb
29 changed files with 912 additions and 1407 deletions
|
@ -577,12 +577,6 @@ For a <<servicenow-action-type,{sn-itsm}>>, <<servicenow-sir-action-type,{sn-sir
|
|||
[[alert-settings]]
|
||||
=== Alerting settings
|
||||
|
||||
`xpack.alerting.maxEphemeralActionsPerAlert` {ess-icon}::
|
||||
deprecated:[8.8.0]
|
||||
Sets the number of actions that will run ephemerally. To use this, enable
|
||||
ephemeral tasks in task manager first with
|
||||
<<task-manager-settings,`xpack.task_manager.ephemeral_tasks.enabled`>>
|
||||
|
||||
`xpack.alerting.cancelAlertsOnRuleTimeout` {ess-icon}::
|
||||
Specifies whether to skip writing alerts and scheduling actions if rule
|
||||
processing was cancelled due to a timeout. Default: `true`. This setting can be
|
||||
|
|
|
@ -22,7 +22,6 @@ const createActionsClientMock = () => {
|
|||
getBulk: jest.fn(),
|
||||
getOAuthAccessToken: jest.fn(),
|
||||
execute: jest.fn(),
|
||||
ephemeralEnqueuedExecution: jest.fn(),
|
||||
bulkEnqueueExecution: jest.fn(),
|
||||
listTypes: jest.fn(),
|
||||
isActionTypeEnabled: jest.fn(),
|
||||
|
|
|
@ -79,7 +79,6 @@ const unsecuredSavedObjectsClient = savedObjectsClientMock.create();
|
|||
const scopedClusterClient = elasticsearchServiceMock.createScopedClusterClient();
|
||||
const actionExecutor = actionExecutorMock.create();
|
||||
const authorization = actionsAuthorizationMock.create();
|
||||
const ephemeralExecutionEnqueuer = jest.fn();
|
||||
const bulkExecutionEnqueuer = jest.fn();
|
||||
const request = httpServerMock.createKibanaRequest();
|
||||
const auditLogger = auditLoggerMock.create();
|
||||
|
@ -138,7 +137,6 @@ beforeEach(() => {
|
|||
kibanaIndices,
|
||||
inMemoryConnectors: [],
|
||||
actionExecutor,
|
||||
ephemeralExecutionEnqueuer,
|
||||
bulkExecutionEnqueuer,
|
||||
request,
|
||||
authorization: authorization as unknown as ActionsAuthorization,
|
||||
|
@ -613,7 +611,6 @@ describe('create()', () => {
|
|||
kibanaIndices,
|
||||
inMemoryConnectors: [],
|
||||
actionExecutor,
|
||||
ephemeralExecutionEnqueuer,
|
||||
bulkExecutionEnqueuer,
|
||||
request,
|
||||
authorization: authorization as unknown as ActionsAuthorization,
|
||||
|
@ -739,7 +736,6 @@ describe('create()', () => {
|
|||
],
|
||||
|
||||
actionExecutor,
|
||||
ephemeralExecutionEnqueuer,
|
||||
bulkExecutionEnqueuer,
|
||||
request,
|
||||
authorization: authorization as unknown as ActionsAuthorization,
|
||||
|
@ -801,7 +797,6 @@ describe('create()', () => {
|
|||
scopedClusterClient,
|
||||
kibanaIndices,
|
||||
actionExecutor,
|
||||
ephemeralExecutionEnqueuer,
|
||||
bulkExecutionEnqueuer,
|
||||
request,
|
||||
authorization: authorization as unknown as ActionsAuthorization,
|
||||
|
@ -862,7 +857,6 @@ describe('get()', () => {
|
|||
scopedClusterClient,
|
||||
kibanaIndices,
|
||||
actionExecutor,
|
||||
ephemeralExecutionEnqueuer,
|
||||
bulkExecutionEnqueuer,
|
||||
request,
|
||||
authorization: authorization as unknown as ActionsAuthorization,
|
||||
|
@ -899,7 +893,6 @@ describe('get()', () => {
|
|||
scopedClusterClient,
|
||||
kibanaIndices,
|
||||
actionExecutor,
|
||||
ephemeralExecutionEnqueuer,
|
||||
bulkExecutionEnqueuer,
|
||||
request,
|
||||
authorization: authorization as unknown as ActionsAuthorization,
|
||||
|
@ -956,7 +949,6 @@ describe('get()', () => {
|
|||
scopedClusterClient,
|
||||
kibanaIndices,
|
||||
actionExecutor,
|
||||
ephemeralExecutionEnqueuer,
|
||||
bulkExecutionEnqueuer,
|
||||
request,
|
||||
authorization: authorization as unknown as ActionsAuthorization,
|
||||
|
@ -999,7 +991,6 @@ describe('get()', () => {
|
|||
scopedClusterClient,
|
||||
kibanaIndices,
|
||||
actionExecutor,
|
||||
ephemeralExecutionEnqueuer,
|
||||
bulkExecutionEnqueuer,
|
||||
request,
|
||||
authorization: authorization as unknown as ActionsAuthorization,
|
||||
|
@ -1121,7 +1112,6 @@ describe('get()', () => {
|
|||
scopedClusterClient,
|
||||
kibanaIndices,
|
||||
actionExecutor,
|
||||
ephemeralExecutionEnqueuer,
|
||||
bulkExecutionEnqueuer,
|
||||
request,
|
||||
authorization: authorization as unknown as ActionsAuthorization,
|
||||
|
@ -1165,7 +1155,6 @@ describe('get()', () => {
|
|||
scopedClusterClient,
|
||||
kibanaIndices,
|
||||
actionExecutor,
|
||||
ephemeralExecutionEnqueuer,
|
||||
bulkExecutionEnqueuer,
|
||||
request,
|
||||
authorization: authorization as unknown as ActionsAuthorization,
|
||||
|
@ -1199,7 +1188,6 @@ describe('get()', () => {
|
|||
scopedClusterClient,
|
||||
kibanaIndices,
|
||||
actionExecutor,
|
||||
ephemeralExecutionEnqueuer,
|
||||
bulkExecutionEnqueuer,
|
||||
request,
|
||||
authorization: authorization as unknown as ActionsAuthorization,
|
||||
|
@ -1270,7 +1258,6 @@ describe('getBulk()', () => {
|
|||
scopedClusterClient,
|
||||
kibanaIndices,
|
||||
actionExecutor,
|
||||
ephemeralExecutionEnqueuer,
|
||||
bulkExecutionEnqueuer,
|
||||
request,
|
||||
authorization: authorization as unknown as ActionsAuthorization,
|
||||
|
@ -1408,7 +1395,6 @@ describe('getBulk()', () => {
|
|||
scopedClusterClient,
|
||||
kibanaIndices,
|
||||
actionExecutor,
|
||||
ephemeralExecutionEnqueuer,
|
||||
bulkExecutionEnqueuer,
|
||||
request,
|
||||
authorization: authorization as unknown as ActionsAuthorization,
|
||||
|
@ -1503,7 +1489,6 @@ describe('getBulk()', () => {
|
|||
scopedClusterClient,
|
||||
kibanaIndices,
|
||||
actionExecutor,
|
||||
ephemeralExecutionEnqueuer,
|
||||
bulkExecutionEnqueuer,
|
||||
request,
|
||||
authorization: authorization as unknown as ActionsAuthorization,
|
||||
|
@ -1577,7 +1562,6 @@ describe('getBulk()', () => {
|
|||
scopedClusterClient,
|
||||
kibanaIndices,
|
||||
actionExecutor,
|
||||
ephemeralExecutionEnqueuer,
|
||||
bulkExecutionEnqueuer,
|
||||
request,
|
||||
authorization: authorization as unknown as ActionsAuthorization,
|
||||
|
@ -1662,7 +1646,6 @@ describe('getOAuthAccessToken()', () => {
|
|||
scopedClusterClient,
|
||||
kibanaIndices,
|
||||
actionExecutor,
|
||||
ephemeralExecutionEnqueuer,
|
||||
bulkExecutionEnqueuer,
|
||||
request,
|
||||
authorization: authorization as unknown as ActionsAuthorization,
|
||||
|
@ -2097,7 +2080,6 @@ describe('delete()', () => {
|
|||
},
|
||||
],
|
||||
actionExecutor,
|
||||
ephemeralExecutionEnqueuer,
|
||||
bulkExecutionEnqueuer,
|
||||
request,
|
||||
authorization: authorization as unknown as ActionsAuthorization,
|
||||
|
@ -2133,7 +2115,6 @@ describe('delete()', () => {
|
|||
},
|
||||
],
|
||||
actionExecutor,
|
||||
ephemeralExecutionEnqueuer,
|
||||
bulkExecutionEnqueuer,
|
||||
request,
|
||||
authorization: authorization as unknown as ActionsAuthorization,
|
||||
|
@ -2653,7 +2634,6 @@ describe('update()', () => {
|
|||
},
|
||||
],
|
||||
actionExecutor,
|
||||
ephemeralExecutionEnqueuer,
|
||||
bulkExecutionEnqueuer,
|
||||
request,
|
||||
authorization: authorization as unknown as ActionsAuthorization,
|
||||
|
@ -2696,7 +2676,6 @@ describe('update()', () => {
|
|||
},
|
||||
],
|
||||
actionExecutor,
|
||||
ephemeralExecutionEnqueuer,
|
||||
bulkExecutionEnqueuer,
|
||||
request,
|
||||
authorization: authorization as unknown as ActionsAuthorization,
|
||||
|
@ -2782,7 +2761,6 @@ describe('execute()', () => {
|
|||
scopedClusterClient,
|
||||
kibanaIndices,
|
||||
actionExecutor,
|
||||
ephemeralExecutionEnqueuer,
|
||||
bulkExecutionEnqueuer,
|
||||
request,
|
||||
authorization: authorization as unknown as ActionsAuthorization,
|
||||
|
@ -2845,7 +2823,6 @@ describe('execute()', () => {
|
|||
scopedClusterClient,
|
||||
kibanaIndices,
|
||||
actionExecutor,
|
||||
ephemeralExecutionEnqueuer,
|
||||
bulkExecutionEnqueuer,
|
||||
request,
|
||||
authorization: authorization as unknown as ActionsAuthorization,
|
||||
|
@ -2907,7 +2884,6 @@ describe('execute()', () => {
|
|||
scopedClusterClient,
|
||||
kibanaIndices,
|
||||
actionExecutor,
|
||||
ephemeralExecutionEnqueuer,
|
||||
bulkExecutionEnqueuer,
|
||||
request,
|
||||
authorization: authorization as unknown as ActionsAuthorization,
|
||||
|
@ -3180,7 +3156,6 @@ describe('isPreconfigured()', () => {
|
|||
scopedClusterClient,
|
||||
kibanaIndices,
|
||||
actionExecutor,
|
||||
ephemeralExecutionEnqueuer,
|
||||
bulkExecutionEnqueuer,
|
||||
request,
|
||||
authorization: authorization as unknown as ActionsAuthorization,
|
||||
|
@ -3230,7 +3205,6 @@ describe('isPreconfigured()', () => {
|
|||
scopedClusterClient,
|
||||
kibanaIndices,
|
||||
actionExecutor,
|
||||
ephemeralExecutionEnqueuer,
|
||||
bulkExecutionEnqueuer,
|
||||
request,
|
||||
authorization: authorization as unknown as ActionsAuthorization,
|
||||
|
@ -3282,7 +3256,6 @@ describe('isSystemAction()', () => {
|
|||
scopedClusterClient,
|
||||
kibanaIndices,
|
||||
actionExecutor,
|
||||
ephemeralExecutionEnqueuer,
|
||||
bulkExecutionEnqueuer,
|
||||
request,
|
||||
authorization: authorization as unknown as ActionsAuthorization,
|
||||
|
@ -3332,7 +3305,6 @@ describe('isSystemAction()', () => {
|
|||
scopedClusterClient,
|
||||
kibanaIndices,
|
||||
actionExecutor,
|
||||
ephemeralExecutionEnqueuer,
|
||||
bulkExecutionEnqueuer,
|
||||
request,
|
||||
authorization: authorization as unknown as ActionsAuthorization,
|
||||
|
|
|
@ -18,7 +18,6 @@ import {
|
|||
Logger,
|
||||
} from '@kbn/core/server';
|
||||
import { AuditLogger } from '@kbn/security-plugin/server';
|
||||
import { RunNowResult } from '@kbn/task-manager-plugin/server';
|
||||
import { IEventLogClient } from '@kbn/event-log-plugin/server';
|
||||
import { KueryNode } from '@kbn/es-query';
|
||||
import { Connector, ConnectorWithExtraFindData } from '../application/connector/types';
|
||||
|
@ -46,7 +45,6 @@ import {
|
|||
} from '../types';
|
||||
import { PreconfiguredActionDisabledModificationError } from '../lib/errors/preconfigured_action_disabled_modification';
|
||||
import {
|
||||
ExecutionEnqueuer,
|
||||
ExecuteOptions as EnqueueExecutionOptions,
|
||||
BulkExecutionEnqueuer,
|
||||
ExecutionResponse,
|
||||
|
@ -92,7 +90,6 @@ export interface ConstructorOptions {
|
|||
unsecuredSavedObjectsClient: SavedObjectsClientContract;
|
||||
inMemoryConnectors: InMemoryConnector[];
|
||||
actionExecutor: ActionExecutorContract;
|
||||
ephemeralExecutionEnqueuer: ExecutionEnqueuer<RunNowResult>;
|
||||
bulkExecutionEnqueuer: BulkExecutionEnqueuer<ExecutionResponse>;
|
||||
request: KibanaRequest;
|
||||
authorization: ActionsAuthorization;
|
||||
|
@ -112,7 +109,6 @@ export interface ActionsClientContext {
|
|||
actionExecutor: ActionExecutorContract;
|
||||
request: KibanaRequest;
|
||||
authorization: ActionsAuthorization;
|
||||
ephemeralExecutionEnqueuer: ExecutionEnqueuer<RunNowResult>;
|
||||
bulkExecutionEnqueuer: BulkExecutionEnqueuer<ExecutionResponse>;
|
||||
auditLogger?: AuditLogger;
|
||||
usageCounter?: UsageCounter;
|
||||
|
@ -131,7 +127,6 @@ export class ActionsClient {
|
|||
unsecuredSavedObjectsClient,
|
||||
inMemoryConnectors,
|
||||
actionExecutor,
|
||||
ephemeralExecutionEnqueuer,
|
||||
bulkExecutionEnqueuer,
|
||||
request,
|
||||
authorization,
|
||||
|
@ -148,7 +143,6 @@ export class ActionsClient {
|
|||
kibanaIndices,
|
||||
inMemoryConnectors,
|
||||
actionExecutor,
|
||||
ephemeralExecutionEnqueuer,
|
||||
bulkExecutionEnqueuer,
|
||||
request,
|
||||
authorization,
|
||||
|
@ -504,18 +498,6 @@ export class ActionsClient {
|
|||
return this.context.bulkExecutionEnqueuer(this.context.unsecuredSavedObjectsClient, options);
|
||||
}
|
||||
|
||||
public async ephemeralEnqueuedExecution(options: EnqueueExecutionOptions): Promise<RunNowResult> {
|
||||
await this.context.authorization.ensureAuthorized({
|
||||
operation: 'execute',
|
||||
actionTypeId: options.actionTypeId,
|
||||
});
|
||||
|
||||
return this.context.ephemeralExecutionEnqueuer(
|
||||
this.context.unsecuredSavedObjectsClient,
|
||||
options
|
||||
);
|
||||
}
|
||||
|
||||
public async listTypes({
|
||||
featureId,
|
||||
includeSystemActionTypes = false,
|
||||
|
|
|
@ -38,7 +38,6 @@ const unsecuredSavedObjectsClient = savedObjectsClientMock.create();
|
|||
const scopedClusterClient = elasticsearchServiceMock.createScopedClusterClient();
|
||||
const actionExecutor = actionExecutorMock.create();
|
||||
const authorization = actionsAuthorizationMock.create();
|
||||
const ephemeralExecutionEnqueuer = jest.fn();
|
||||
const bulkExecutionEnqueuer = jest.fn();
|
||||
const request = httpServerMock.createKibanaRequest();
|
||||
const auditLogger = auditLoggerMock.create();
|
||||
|
@ -131,7 +130,6 @@ beforeEach(() => {
|
|||
kibanaIndices,
|
||||
inMemoryConnectors: [],
|
||||
actionExecutor,
|
||||
ephemeralExecutionEnqueuer,
|
||||
bulkExecutionEnqueuer,
|
||||
request,
|
||||
authorization: authorization as unknown as ActionsAuthorization,
|
||||
|
|
|
@ -52,7 +52,6 @@ const unsecuredSavedObjectsClient = savedObjectsClientMock.create();
|
|||
const scopedClusterClient = elasticsearchServiceMock.createScopedClusterClient();
|
||||
const actionExecutor = actionExecutorMock.create();
|
||||
const authorization = actionsAuthorizationMock.create();
|
||||
const ephemeralExecutionEnqueuer = jest.fn();
|
||||
const bulkExecutionEnqueuer = jest.fn();
|
||||
const request = httpServerMock.createKibanaRequest();
|
||||
const auditLogger = auditLoggerMock.create();
|
||||
|
@ -78,7 +77,6 @@ describe('getAll()', () => {
|
|||
kibanaIndices,
|
||||
inMemoryConnectors: [],
|
||||
actionExecutor,
|
||||
ephemeralExecutionEnqueuer,
|
||||
bulkExecutionEnqueuer,
|
||||
request,
|
||||
authorization: authorization as unknown as ActionsAuthorization,
|
||||
|
@ -134,7 +132,6 @@ describe('getAll()', () => {
|
|||
scopedClusterClient,
|
||||
kibanaIndices,
|
||||
actionExecutor,
|
||||
ephemeralExecutionEnqueuer,
|
||||
bulkExecutionEnqueuer,
|
||||
request,
|
||||
authorization: authorization as unknown as ActionsAuthorization,
|
||||
|
@ -279,7 +276,6 @@ describe('getAll()', () => {
|
|||
scopedClusterClient,
|
||||
kibanaIndices,
|
||||
actionExecutor,
|
||||
ephemeralExecutionEnqueuer,
|
||||
bulkExecutionEnqueuer,
|
||||
request,
|
||||
authorization: authorization as unknown as ActionsAuthorization,
|
||||
|
@ -382,7 +378,6 @@ describe('getAll()', () => {
|
|||
scopedClusterClient,
|
||||
kibanaIndices,
|
||||
actionExecutor,
|
||||
ephemeralExecutionEnqueuer,
|
||||
bulkExecutionEnqueuer,
|
||||
request,
|
||||
authorization: authorization as unknown as ActionsAuthorization,
|
||||
|
@ -487,7 +482,6 @@ describe('getAll()', () => {
|
|||
scopedClusterClient,
|
||||
kibanaIndices,
|
||||
actionExecutor,
|
||||
ephemeralExecutionEnqueuer,
|
||||
bulkExecutionEnqueuer,
|
||||
request,
|
||||
authorization: authorization as unknown as ActionsAuthorization,
|
||||
|
@ -579,7 +573,6 @@ describe('getAll()', () => {
|
|||
scopedClusterClient,
|
||||
kibanaIndices,
|
||||
actionExecutor,
|
||||
ephemeralExecutionEnqueuer,
|
||||
bulkExecutionEnqueuer,
|
||||
request,
|
||||
authorization: authorization as unknown as ActionsAuthorization,
|
||||
|
@ -613,7 +606,6 @@ describe('getAll()', () => {
|
|||
scopedClusterClient,
|
||||
kibanaIndices,
|
||||
actionExecutor,
|
||||
ephemeralExecutionEnqueuer,
|
||||
bulkExecutionEnqueuer,
|
||||
request,
|
||||
authorization: authorization as unknown as ActionsAuthorization,
|
||||
|
@ -690,7 +682,6 @@ describe('getAll()', () => {
|
|||
scopedClusterClient,
|
||||
kibanaIndices,
|
||||
actionExecutor,
|
||||
ephemeralExecutionEnqueuer,
|
||||
bulkExecutionEnqueuer,
|
||||
request,
|
||||
authorization: authorization as unknown as ActionsAuthorization,
|
||||
|
|
|
@ -60,7 +60,6 @@ describe('listTypes()', () => {
|
|||
unsecuredSavedObjectsClient: savedObjectsClientMock.create(),
|
||||
inMemoryConnectors: [],
|
||||
actionExecutor: actionExecutorMock.create(),
|
||||
ephemeralExecutionEnqueuer: jest.fn(),
|
||||
bulkExecutionEnqueuer: jest.fn(),
|
||||
request: httpServerMock.createKibanaRequest(),
|
||||
authorization: actionsAuthorizationMock.create() as unknown as ActionsAuthorization,
|
||||
|
|
|
@ -6,13 +6,8 @@
|
|||
*/
|
||||
|
||||
import { SavedObjectsBulkResponse, SavedObjectsClientContract, Logger } from '@kbn/core/server';
|
||||
import { RunNowResult, TaskManagerStartContract } from '@kbn/task-manager-plugin/server';
|
||||
import {
|
||||
RawAction,
|
||||
ActionTypeRegistryContract,
|
||||
InMemoryConnector,
|
||||
ActionTaskExecutorParams,
|
||||
} from './types';
|
||||
import { TaskManagerStartContract } from '@kbn/task-manager-plugin/server';
|
||||
import { RawAction, ActionTypeRegistryContract, InMemoryConnector } from './types';
|
||||
import { ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE } from './constants/saved_objects';
|
||||
import { ExecuteOptions as ActionExecutorOptions } from './lib/action_executor';
|
||||
import { extractSavedObjectReferences, isSavedObjectExecutionSource } from './lib';
|
||||
|
@ -215,43 +210,6 @@ export function createBulkExecutionEnqueuerFunction({
|
|||
};
|
||||
}
|
||||
|
||||
export function createEphemeralExecutionEnqueuerFunction({
|
||||
taskManager,
|
||||
actionTypeRegistry,
|
||||
inMemoryConnectors,
|
||||
logger,
|
||||
}: CreateExecuteFunctionOptions): ExecutionEnqueuer<RunNowResult> {
|
||||
return async function execute(
|
||||
unsecuredSavedObjectsClient: SavedObjectsClientContract,
|
||||
{ id, params, spaceId, source, consumer, apiKey, executionId }: ExecuteOptions
|
||||
): Promise<RunNowResult> {
|
||||
const { connector } = await getConnector(unsecuredSavedObjectsClient, inMemoryConnectors, id);
|
||||
|
||||
validateConnector({ id, connector, actionTypeRegistry });
|
||||
|
||||
const taskParams: ActionTaskExecutorParams = {
|
||||
spaceId,
|
||||
taskParams: {
|
||||
actionId: id,
|
||||
consumer,
|
||||
// Saved Objects won't allow us to enforce unknown rather than any
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
params: params as Record<string, any>,
|
||||
...(apiKey ? { apiKey } : {}),
|
||||
...(executionId ? { executionId } : {}),
|
||||
},
|
||||
...executionSourceAsSavedObjectReferences(source),
|
||||
};
|
||||
|
||||
return taskManager.ephemeralRunNow({
|
||||
taskType: `actions:${connector.actionTypeId}`,
|
||||
params: taskParams,
|
||||
state: {},
|
||||
scope: ['actions'],
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function validateConnector({
|
||||
id,
|
||||
connector,
|
||||
|
@ -287,21 +245,6 @@ function executionSourceAsSavedObjectReferences(executionSource: ActionExecutorO
|
|||
: {};
|
||||
}
|
||||
|
||||
async function getConnector(
|
||||
unsecuredSavedObjectsClient: SavedObjectsClientContract,
|
||||
inMemoryConnectors: InMemoryConnector[],
|
||||
actionId: string
|
||||
): Promise<{ connector: InMemoryConnector | RawAction; isInMemory: boolean }> {
|
||||
const inMemoryAction = inMemoryConnectors.find((action) => action.id === actionId);
|
||||
|
||||
if (inMemoryAction) {
|
||||
return { connector: inMemoryAction, isInMemory: true };
|
||||
}
|
||||
|
||||
const { attributes } = await unsecuredSavedObjectsClient.get<RawAction>('action', actionId);
|
||||
return { connector: attributes, isInMemory: false };
|
||||
}
|
||||
|
||||
async function getConnectors(
|
||||
unsecuredSavedObjectsClient: SavedObjectsClientContract,
|
||||
inMemoryConnectors: InMemoryConnector[],
|
||||
|
|
|
@ -82,7 +82,6 @@ export interface ExecuteOptions<Source = unknown> {
|
|||
actionId: string;
|
||||
consumer?: string;
|
||||
executionId?: string;
|
||||
isEphemeral?: boolean;
|
||||
params: Record<string, unknown>;
|
||||
relatedSavedObjects?: RelatedSavedObjects;
|
||||
request: KibanaRequest;
|
||||
|
@ -133,7 +132,6 @@ export class ActionExecutor {
|
|||
actionId,
|
||||
consumer,
|
||||
executionId,
|
||||
isEphemeral,
|
||||
request,
|
||||
params,
|
||||
relatedSavedObjects,
|
||||
|
@ -175,7 +173,6 @@ export class ActionExecutor {
|
|||
},
|
||||
executeLabel: `execute_action`,
|
||||
executionId,
|
||||
isEphemeral,
|
||||
namespace,
|
||||
params,
|
||||
relatedSavedObjects,
|
||||
|
@ -367,7 +364,6 @@ export class ActionExecutor {
|
|||
checkCanExecuteFn,
|
||||
executeLabel,
|
||||
executionId,
|
||||
isEphemeral,
|
||||
namespace,
|
||||
params,
|
||||
relatedSavedObjects,
|
||||
|
@ -512,7 +508,6 @@ export class ActionExecutor {
|
|||
params: validatedParams,
|
||||
config: validatedConfig,
|
||||
secrets: validatedSecrets,
|
||||
isEphemeral,
|
||||
taskInfo,
|
||||
configurationUtilities,
|
||||
logger,
|
||||
|
|
|
@ -35,7 +35,6 @@ import { SavedObjectsErrorHelpers } from '@kbn/core-saved-objects-server';
|
|||
|
||||
const executeParamsFields = [
|
||||
'actionId',
|
||||
'isEphemeral',
|
||||
'params',
|
||||
'relatedSavedObjects',
|
||||
'executionId',
|
||||
|
@ -173,7 +172,6 @@ describe('Task Runner Factory', () => {
|
|||
const [executeParams] = mockedActionExecutor.execute.mock.calls[0];
|
||||
expect(pick(executeParams, executeParamsFields)).toEqual({
|
||||
actionId: '2',
|
||||
isEphemeral: false,
|
||||
params: { baz: true },
|
||||
relatedSavedObjects: [],
|
||||
executionId: '123abc',
|
||||
|
@ -233,7 +231,6 @@ describe('Task Runner Factory', () => {
|
|||
const [executeParams] = mockedActionExecutor.execute.mock.calls[0];
|
||||
expect(pick(executeParams, executeParamsFields)).toEqual({
|
||||
actionId: '9',
|
||||
isEphemeral: false,
|
||||
params: { baz: true },
|
||||
executionId: '123abc',
|
||||
relatedSavedObjects: [],
|
||||
|
@ -289,7 +286,6 @@ describe('Task Runner Factory', () => {
|
|||
expect(pick(executeParams, [...executeParamsFields, 'consumer'])).toEqual({
|
||||
actionId: '2',
|
||||
consumer: 'test-consumer',
|
||||
isEphemeral: false,
|
||||
params: { baz: true },
|
||||
relatedSavedObjects: [],
|
||||
executionId: '123abc',
|
||||
|
@ -346,7 +342,6 @@ describe('Task Runner Factory', () => {
|
|||
expect(pick(executeParams, [...executeParamsFields, 'consumer'])).toEqual({
|
||||
actionId: '2',
|
||||
consumer: 'test-consumer',
|
||||
isEphemeral: false,
|
||||
params: { baz: true },
|
||||
relatedSavedObjects: [],
|
||||
executionId: '123abc',
|
||||
|
@ -407,7 +402,6 @@ describe('Task Runner Factory', () => {
|
|||
expect(pick(executeParams, [...executeParamsFields, 'consumer'])).toEqual({
|
||||
actionId: '2',
|
||||
consumer: 'test-consumer',
|
||||
isEphemeral: false,
|
||||
params: { baz: true },
|
||||
relatedSavedObjects: [],
|
||||
executionId: '123abc',
|
||||
|
@ -569,7 +563,6 @@ describe('Task Runner Factory', () => {
|
|||
const [executeParams] = mockedActionExecutor.execute.mock.calls[0];
|
||||
expect(pick(executeParams, executeParamsFields)).toEqual({
|
||||
actionId: '2',
|
||||
isEphemeral: false,
|
||||
params: { baz: true },
|
||||
executionId: '123abc',
|
||||
relatedSavedObjects: [],
|
||||
|
@ -627,7 +620,6 @@ describe('Task Runner Factory', () => {
|
|||
const [executeParams] = mockedActionExecutor.execute.mock.calls[0];
|
||||
expect(pick(executeParams, executeParamsFields)).toEqual({
|
||||
actionId: '2',
|
||||
isEphemeral: false,
|
||||
params: { baz: true },
|
||||
executionId: '123abc',
|
||||
relatedSavedObjects: [
|
||||
|
@ -680,7 +672,6 @@ describe('Task Runner Factory', () => {
|
|||
const [executeParams] = mockedActionExecutor.execute.mock.calls[0];
|
||||
expect(pick(executeParams, executeParamsFields)).toEqual({
|
||||
actionId: '2',
|
||||
isEphemeral: false,
|
||||
params: { baz: true },
|
||||
executionId: '123abc',
|
||||
relatedSavedObjects: [
|
||||
|
@ -739,7 +730,6 @@ describe('Task Runner Factory', () => {
|
|||
const [executeParams] = mockedActionExecutor.execute.mock.calls[0];
|
||||
expect(pick(executeParams, executeParamsFields)).toEqual({
|
||||
actionId: '2',
|
||||
isEphemeral: false,
|
||||
params: { baz: true },
|
||||
request: {
|
||||
headers: {
|
||||
|
@ -785,7 +775,6 @@ describe('Task Runner Factory', () => {
|
|||
const [executeParams] = mockedActionExecutor.execute.mock.calls[0];
|
||||
expect(pick(executeParams, executeParamsFields)).toEqual({
|
||||
actionId: '2',
|
||||
isEphemeral: false,
|
||||
params: { baz: true },
|
||||
executionId: '123abc',
|
||||
relatedSavedObjects: [],
|
||||
|
|
|
@ -32,7 +32,6 @@ import {
|
|||
ActionTaskParams,
|
||||
ActionTypeExecutorResult,
|
||||
ActionTypeRegistryContract,
|
||||
isPersistedActionTask,
|
||||
SpaceIdToNamespaceFunction,
|
||||
} from '../types';
|
||||
import { ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE } from '../constants/saved_objects';
|
||||
|
@ -128,7 +127,6 @@ export class TaskRunnerFactory {
|
|||
executorResult = await actionExecutor.execute({
|
||||
params,
|
||||
actionId: actionId as string,
|
||||
isEphemeral: !isPersistedActionTask(actionTaskExecutorParams),
|
||||
request,
|
||||
taskInfo,
|
||||
executionId,
|
||||
|
@ -209,19 +207,17 @@ export class TaskRunnerFactory {
|
|||
},
|
||||
cleanup: async () => {
|
||||
// Cleanup action_task_params object now that we're done with it
|
||||
if (isPersistedActionTask(actionTaskExecutorParams)) {
|
||||
try {
|
||||
await savedObjectsRepository.delete(
|
||||
ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE,
|
||||
actionTaskExecutorParams.actionTaskParamsId,
|
||||
{ refresh: false, namespace: spaceIdToNamespace(actionTaskExecutorParams.spaceId) }
|
||||
);
|
||||
} catch (e) {
|
||||
// Log error only, we shouldn't fail the task because of an error here (if ever there's retry logic)
|
||||
logger.error(
|
||||
`Failed to cleanup ${ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE} object [id="${actionTaskExecutorParams.actionTaskParamsId}"]: ${e.message}`
|
||||
);
|
||||
}
|
||||
try {
|
||||
await savedObjectsRepository.delete(
|
||||
ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE,
|
||||
actionTaskExecutorParams.actionTaskParamsId,
|
||||
{ refresh: false, namespace: spaceIdToNamespace(actionTaskExecutorParams.spaceId) }
|
||||
);
|
||||
} catch (e) {
|
||||
// Log error only, we shouldn't fail the task because of an error here (if ever there's retry logic)
|
||||
logger.error(
|
||||
`Failed to cleanup ${ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE} object [id="${actionTaskExecutorParams.actionTaskParamsId}"]: ${e.message}`
|
||||
);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
@ -252,45 +248,41 @@ async function getActionTaskParams(
|
|||
): Promise<TaskParams> {
|
||||
const { spaceId } = executorParams;
|
||||
const namespace = spaceIdToNamespace(spaceId);
|
||||
if (isPersistedActionTask(executorParams)) {
|
||||
try {
|
||||
const actionTask =
|
||||
await encryptedSavedObjectsClient.getDecryptedAsInternalUser<ActionTaskParams>(
|
||||
ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE,
|
||||
executorParams.actionTaskParamsId,
|
||||
{ namespace }
|
||||
);
|
||||
const {
|
||||
attributes: { relatedSavedObjects },
|
||||
references,
|
||||
} = actionTask;
|
||||
|
||||
const { actionId, relatedSavedObjects: injectedRelatedSavedObjects } =
|
||||
injectSavedObjectReferences(references, relatedSavedObjects as RelatedSavedObjects);
|
||||
|
||||
return {
|
||||
...actionTask,
|
||||
attributes: {
|
||||
...actionTask.attributes,
|
||||
...(actionId ? { actionId } : {}),
|
||||
...(relatedSavedObjects ? { relatedSavedObjects: injectedRelatedSavedObjects } : {}),
|
||||
},
|
||||
};
|
||||
} catch (e) {
|
||||
const errorSource = SavedObjectsErrorHelpers.isNotFoundError(e)
|
||||
? TaskErrorSource.USER
|
||||
: TaskErrorSource.FRAMEWORK;
|
||||
logger.error(
|
||||
`Failed to load action task params ${executorParams.actionTaskParamsId}: ${e.message}`,
|
||||
{ tags: ['connector-run-failed', `${errorSource}-error`] }
|
||||
try {
|
||||
const actionTask =
|
||||
await encryptedSavedObjectsClient.getDecryptedAsInternalUser<ActionTaskParams>(
|
||||
ACTION_TASK_PARAMS_SAVED_OBJECT_TYPE,
|
||||
executorParams.actionTaskParamsId,
|
||||
{ namespace }
|
||||
);
|
||||
if (SavedObjectsErrorHelpers.isNotFoundError(e)) {
|
||||
throw createRetryableError(createTaskRunError(e, errorSource), true);
|
||||
}
|
||||
const {
|
||||
attributes: { relatedSavedObjects },
|
||||
references,
|
||||
} = actionTask;
|
||||
|
||||
const { actionId, relatedSavedObjects: injectedRelatedSavedObjects } =
|
||||
injectSavedObjectReferences(references, relatedSavedObjects as RelatedSavedObjects);
|
||||
|
||||
return {
|
||||
...actionTask,
|
||||
attributes: {
|
||||
...actionTask.attributes,
|
||||
...(actionId ? { actionId } : {}),
|
||||
...(relatedSavedObjects ? { relatedSavedObjects: injectedRelatedSavedObjects } : {}),
|
||||
},
|
||||
};
|
||||
} catch (e) {
|
||||
const errorSource = SavedObjectsErrorHelpers.isNotFoundError(e)
|
||||
? TaskErrorSource.USER
|
||||
: TaskErrorSource.FRAMEWORK;
|
||||
logger.error(
|
||||
`Failed to load action task params ${executorParams.actionTaskParamsId}: ${e.message}`,
|
||||
{ tags: ['connector-run-failed', `${errorSource}-error`] }
|
||||
);
|
||||
if (SavedObjectsErrorHelpers.isNotFoundError(e)) {
|
||||
throw createRetryableError(createTaskRunError(e, errorSource), true);
|
||||
}
|
||||
} else {
|
||||
return { attributes: executorParams.taskParams, references: executorParams.references ?? [] };
|
||||
throw createRetryableError(createTaskRunError(e, errorSource), true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -48,10 +48,7 @@ import { resolveCustomHosts } from './lib/custom_host_settings';
|
|||
import { events } from './lib/event_based_telemetry';
|
||||
import { ActionsClient } from './actions_client/actions_client';
|
||||
import { ActionTypeRegistry } from './action_type_registry';
|
||||
import {
|
||||
createEphemeralExecutionEnqueuerFunction,
|
||||
createBulkExecutionEnqueuerFunction,
|
||||
} from './create_execute_function';
|
||||
import { createBulkExecutionEnqueuerFunction } from './create_execute_function';
|
||||
import { registerActionsUsageCollector } from './usage';
|
||||
import {
|
||||
ActionExecutor,
|
||||
|
@ -480,14 +477,6 @@ export class ActionsPlugin implements Plugin<PluginSetupContract, PluginStartCon
|
|||
request,
|
||||
authorization: instantiateAuthorization(request),
|
||||
actionExecutor: actionExecutor!,
|
||||
ephemeralExecutionEnqueuer: createEphemeralExecutionEnqueuerFunction({
|
||||
taskManager: plugins.taskManager,
|
||||
actionTypeRegistry: actionTypeRegistry!,
|
||||
isESOCanEncrypt: isESOCanEncrypt!,
|
||||
inMemoryConnectors: this.inMemoryConnectors,
|
||||
configurationUtilities: actionsConfigUtils,
|
||||
logger,
|
||||
}),
|
||||
bulkExecutionEnqueuer: createBulkExecutionEnqueuerFunction({
|
||||
taskManager: plugins.taskManager,
|
||||
actionTypeRegistry: actionTypeRegistry!,
|
||||
|
@ -753,14 +742,6 @@ export class ActionsPlugin implements Plugin<PluginSetupContract, PluginStartCon
|
|||
request,
|
||||
authorization: instantiateAuthorization(request),
|
||||
actionExecutor: actionExecutor!,
|
||||
ephemeralExecutionEnqueuer: createEphemeralExecutionEnqueuerFunction({
|
||||
taskManager,
|
||||
actionTypeRegistry: actionTypeRegistry!,
|
||||
isESOCanEncrypt: isESOCanEncrypt!,
|
||||
inMemoryConnectors,
|
||||
configurationUtilities: actionsConfigUtils,
|
||||
logger,
|
||||
}),
|
||||
bulkExecutionEnqueuer: createBulkExecutionEnqueuerFunction({
|
||||
taskManager,
|
||||
actionTypeRegistry: actionTypeRegistry!,
|
||||
|
|
|
@ -13,7 +13,6 @@ import {
|
|||
SavedObjectAttributes,
|
||||
ElasticsearchClient,
|
||||
CustomRequestHandlerContext,
|
||||
SavedObjectReference,
|
||||
Logger,
|
||||
ISavedObjectsRepository,
|
||||
IScopedClusterClient,
|
||||
|
@ -88,7 +87,6 @@ export interface ActionTypeExecutorOptions<
|
|||
secrets: Secrets;
|
||||
params: Params;
|
||||
logger: Logger;
|
||||
isEphemeral?: boolean;
|
||||
taskInfo?: TaskInfo;
|
||||
configurationUtilities: ActionsConfigurationUtilities;
|
||||
source?: ActionExecutionSource<unknown>;
|
||||
|
@ -238,27 +236,11 @@ export interface ActionTaskParams extends SavedObjectAttributes {
|
|||
source?: string;
|
||||
}
|
||||
|
||||
interface PersistedActionTaskExecutorParams {
|
||||
export interface ActionTaskExecutorParams {
|
||||
spaceId: string;
|
||||
actionTaskParamsId: string;
|
||||
}
|
||||
|
||||
interface EphemeralActionTaskExecutorParams {
|
||||
spaceId: string;
|
||||
taskParams: ActionTaskParams;
|
||||
references?: SavedObjectReference[];
|
||||
}
|
||||
|
||||
export type ActionTaskExecutorParams =
|
||||
| PersistedActionTaskExecutorParams
|
||||
| EphemeralActionTaskExecutorParams;
|
||||
|
||||
export function isPersistedActionTask(
|
||||
actionTask: ActionTaskExecutorParams
|
||||
): actionTask is PersistedActionTaskExecutorParams {
|
||||
return typeof (actionTask as PersistedActionTaskExecutorParams).actionTaskParamsId === 'string';
|
||||
}
|
||||
|
||||
export interface ProxySettings {
|
||||
proxyUrl: string;
|
||||
proxyBypassHosts: Set<string> | undefined;
|
||||
|
|
|
@ -21,7 +21,6 @@ describe('config validation', () => {
|
|||
"interval": "5m",
|
||||
"removalDelay": "1h",
|
||||
},
|
||||
"maxEphemeralActionsPerAlert": 10,
|
||||
"rules": Object {
|
||||
"maxScheduledPerMinute": 32000,
|
||||
"minimumScheduleInterval": Object {
|
||||
|
|
|
@ -60,7 +60,6 @@ const rulesSchema = schema.object({
|
|||
}),
|
||||
});
|
||||
|
||||
export const DEFAULT_MAX_EPHEMERAL_ACTIONS_PER_ALERT = 10;
|
||||
export const configSchema = schema.object({
|
||||
healthCheck: schema.object({
|
||||
interval: schema.string({ validate: validateDurationSchema, defaultValue: '60m' }),
|
||||
|
@ -69,9 +68,7 @@ export const configSchema = schema.object({
|
|||
interval: schema.string({ validate: validateDurationSchema, defaultValue: '5m' }),
|
||||
removalDelay: schema.string({ validate: validateDurationSchema, defaultValue: '1h' }),
|
||||
}),
|
||||
maxEphemeralActionsPerAlert: schema.number({
|
||||
defaultValue: DEFAULT_MAX_EPHEMERAL_ACTIONS_PER_ALERT,
|
||||
}),
|
||||
maxEphemeralActionsPerAlert: schema.maybe(schema.number()),
|
||||
enableFrameworkAlerts: schema.boolean({ defaultValue: true }),
|
||||
cancelAlertsOnRuleTimeout: schema.boolean({ defaultValue: true }),
|
||||
rules: rulesSchema,
|
||||
|
|
|
@ -36,7 +36,6 @@ export type {
|
|||
export { DEFAULT_AAD_CONFIG } from './types';
|
||||
export { RULE_SAVED_OBJECT_TYPE, API_KEY_PENDING_INVALIDATION_TYPE } from './saved_objects';
|
||||
export { RuleNotifyWhen } from '../common';
|
||||
export { DEFAULT_MAX_EPHEMERAL_ACTIONS_PER_ALERT } from './config';
|
||||
export type { PluginSetupContract, PluginStartContract } from './plugin';
|
||||
export type { FindResult, BulkEditOperation, BulkOperationError } from './rules_client';
|
||||
export type { Rule } from './application/rule/types';
|
||||
|
@ -84,9 +83,9 @@ export const config: PluginConfigDescriptor<AlertingConfig> = {
|
|||
rules: { run: { alerts: { max: true } } },
|
||||
},
|
||||
deprecations: ({ renameFromRoot, deprecate }) => [
|
||||
deprecate('maxEphemeralActionsPerAlert', 'a future version', {
|
||||
deprecate('maxEphemeralActionsPerAlert', '9.0.0', {
|
||||
level: 'warning',
|
||||
message: `Configuring "xpack.alerting.maxEphemeralActionsPerAlert" is deprecated and will be removed in a future version. Remove this setting to increase action execution resiliency.`,
|
||||
message: `The setting "xpack.alerting.maxEphemeralActionsPerAlert" is deprecated and currently ignored by the system. Please remove this setting.`,
|
||||
}),
|
||||
],
|
||||
};
|
||||
|
|
|
@ -615,7 +615,6 @@ export class AlertingPlugin {
|
|||
logger,
|
||||
}),
|
||||
maxAlerts: this.config.rules.run.alerts.max,
|
||||
maxEphemeralActionsPerRule: this.config.maxEphemeralActionsPerAlert,
|
||||
ruleTypeRegistry: this.ruleTypeRegistry!,
|
||||
rulesSettingsService: new RulesSettingsService({
|
||||
cacheInterval: this.config.rulesSettings.cacheInterval,
|
||||
|
@ -626,7 +625,6 @@ export class AlertingPlugin {
|
|||
savedObjects: core.savedObjects,
|
||||
share: plugins.share,
|
||||
spaceIdToNamespace,
|
||||
supportsEphemeralTasks: plugins.taskManager.supportsEphemeralTasks(),
|
||||
uiSettings: core.uiSettings,
|
||||
usageCounter: this.usageCounter,
|
||||
isServerless: this.isServerless,
|
||||
|
|
|
@ -2617,7 +2617,6 @@ describe('Action Scheduler', () => {
|
|||
});
|
||||
|
||||
expect(buildActionParams).not.toHaveBeenCalledWith();
|
||||
expect(actionsClient.ephemeralEnqueuedExecution).not.toHaveBeenCalled();
|
||||
expect(actionsClient.bulkEnqueueExecution).not.toHaveBeenCalled();
|
||||
expect(alertingEventLogger.logAction).not.toHaveBeenCalled();
|
||||
expect(executorParams.logger.warn).toHaveBeenCalledWith(
|
||||
|
@ -2662,7 +2661,6 @@ describe('Action Scheduler', () => {
|
|||
expect(res).toEqual({ throttledSummaryActions: {} });
|
||||
expect(buildActionParams).not.toHaveBeenCalled();
|
||||
expect(alertsClient.getSummarizedAlerts).not.toHaveBeenCalled();
|
||||
expect(actionsClient.ephemeralEnqueuedExecution).not.toHaveBeenCalled();
|
||||
expect(actionsClient.bulkEnqueueExecution).not.toHaveBeenCalled();
|
||||
expect(alertingEventLogger.logAction).not.toHaveBeenCalled();
|
||||
});
|
||||
|
|
|
@ -5,13 +5,8 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { createTaskRunError, TaskErrorSource } from '@kbn/task-manager-plugin/server';
|
||||
import {
|
||||
createTaskRunError,
|
||||
isEphemeralTaskRejectedDueToCapacityError,
|
||||
TaskErrorSource,
|
||||
} from '@kbn/task-manager-plugin/server';
|
||||
import {
|
||||
ExecuteOptions as EnqueueExecutionOptions,
|
||||
ExecutionResponseItem,
|
||||
ExecutionResponseType,
|
||||
} from '@kbn/actions-plugin/server/create_execute_function';
|
||||
|
@ -51,8 +46,6 @@ export class ActionScheduler<
|
|||
IActionScheduler<State, Context, ActionGroupIds, RecoveryActionGroupId>
|
||||
> = [];
|
||||
|
||||
private ephemeralActionsToSchedule: number;
|
||||
|
||||
constructor(
|
||||
private readonly context: ActionSchedulerOptions<
|
||||
Params,
|
||||
|
@ -65,7 +58,6 @@ export class ActionScheduler<
|
|||
AlertData
|
||||
>
|
||||
) {
|
||||
this.ephemeralActionsToSchedule = context.taskRunnerContext.maxEphemeralActionsPerRule;
|
||||
for (const [_, scheduler] of Object.entries(schedulers)) {
|
||||
this.schedulers.push(new scheduler(context));
|
||||
}
|
||||
|
@ -101,37 +93,28 @@ export class ActionScheduler<
|
|||
return { throttledSummaryActions };
|
||||
}
|
||||
|
||||
const bulkScheduleRequest: EnqueueExecutionOptions[] = [];
|
||||
|
||||
for (const result of allActionsToScheduleResult) {
|
||||
await this.runActionAsEphemeralOrAddToBulkScheduleRequest({
|
||||
enqueueOptions: result.actionToEnqueue,
|
||||
bulkScheduleRequest,
|
||||
});
|
||||
}
|
||||
|
||||
let bulkScheduleResponse: ExecutionResponseItem[] = [];
|
||||
|
||||
if (!!bulkScheduleRequest.length) {
|
||||
for (const c of chunk(bulkScheduleRequest, BULK_SCHEDULE_CHUNK_SIZE)) {
|
||||
let enqueueResponse;
|
||||
try {
|
||||
enqueueResponse = await withAlertingSpan('alerting:bulk-enqueue-actions', () =>
|
||||
this.context.actionsClient!.bulkEnqueueExecution(c)
|
||||
);
|
||||
} catch (e) {
|
||||
if (e.statusCode === 404) {
|
||||
throw createTaskRunError(e, TaskErrorSource.USER);
|
||||
}
|
||||
throw createTaskRunError(e, TaskErrorSource.FRAMEWORK);
|
||||
}
|
||||
if (enqueueResponse.errors) {
|
||||
bulkScheduleResponse = bulkScheduleResponse.concat(
|
||||
enqueueResponse.items.filter(
|
||||
(i) => i.response === ExecutionResponseType.QUEUED_ACTIONS_LIMIT_ERROR
|
||||
)
|
||||
);
|
||||
for (const c of chunk(allActionsToScheduleResult, BULK_SCHEDULE_CHUNK_SIZE)) {
|
||||
let enqueueResponse;
|
||||
try {
|
||||
enqueueResponse = await withAlertingSpan('alerting:bulk-enqueue-actions', () =>
|
||||
this.context.actionsClient!.bulkEnqueueExecution(
|
||||
c.map((actions) => actions.actionToEnqueue)
|
||||
)
|
||||
);
|
||||
} catch (e) {
|
||||
if (e.statusCode === 404) {
|
||||
throw createTaskRunError(e, TaskErrorSource.USER);
|
||||
}
|
||||
throw createTaskRunError(e, TaskErrorSource.FRAMEWORK);
|
||||
}
|
||||
if (enqueueResponse.errors) {
|
||||
bulkScheduleResponse = bulkScheduleResponse.concat(
|
||||
enqueueResponse.items.filter(
|
||||
(i) => i.response === ExecutionResponseType.QUEUED_ACTIONS_LIMIT_ERROR
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -175,28 +158,4 @@ export class ActionScheduler<
|
|||
|
||||
return { throttledSummaryActions };
|
||||
}
|
||||
|
||||
private async runActionAsEphemeralOrAddToBulkScheduleRequest({
|
||||
enqueueOptions,
|
||||
bulkScheduleRequest,
|
||||
}: {
|
||||
enqueueOptions: EnqueueExecutionOptions;
|
||||
bulkScheduleRequest: EnqueueExecutionOptions[];
|
||||
}) {
|
||||
if (
|
||||
this.context.taskRunnerContext.supportsEphemeralTasks &&
|
||||
this.ephemeralActionsToSchedule > 0
|
||||
) {
|
||||
this.ephemeralActionsToSchedule--;
|
||||
try {
|
||||
await this.context.actionsClient!.ephemeralEnqueuedExecution(enqueueOptions);
|
||||
} catch (err) {
|
||||
if (isEphemeralTaskRejectedDueToCapacityError(err)) {
|
||||
bulkScheduleRequest.push(enqueueOptions);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
bulkScheduleRequest.push(enqueueOptions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -168,13 +168,11 @@ const taskRunnerFactoryInitializerParams: TaskRunnerFactoryInitializerParamsType
|
|||
kibanaBaseUrl: 'https://localhost:5601',
|
||||
logger,
|
||||
maxAlerts: 1000,
|
||||
maxEphemeralActionsPerRule: 10,
|
||||
ruleTypeRegistry,
|
||||
rulesSettingsService,
|
||||
savedObjects: savedObjectsService,
|
||||
share: {} as SharePluginStart,
|
||||
spaceIdToNamespace: jest.fn().mockReturnValue(undefined),
|
||||
supportsEphemeralTasks: false,
|
||||
uiSettings: uiSettingsService,
|
||||
usageCounter: mockUsageCounter,
|
||||
isServerless: false,
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -216,13 +216,11 @@ describe('Task Runner', () => {
|
|||
logger,
|
||||
maintenanceWindowsService,
|
||||
maxAlerts: 1000,
|
||||
maxEphemeralActionsPerRule: 10,
|
||||
ruleTypeRegistry,
|
||||
rulesSettingsService,
|
||||
savedObjects: savedObjectsService,
|
||||
share: {} as SharePluginStart,
|
||||
spaceIdToNamespace: jest.fn().mockReturnValue(undefined),
|
||||
supportsEphemeralTasks: false,
|
||||
uiSettings: uiSettingsService,
|
||||
usageCounter: mockUsageCounter,
|
||||
isServerless: false,
|
||||
|
|
|
@ -149,13 +149,11 @@ describe('Task Runner Cancel', () => {
|
|||
logger,
|
||||
maintenanceWindowsService,
|
||||
maxAlerts: 1000,
|
||||
maxEphemeralActionsPerRule: 10,
|
||||
ruleTypeRegistry,
|
||||
rulesSettingsService,
|
||||
savedObjects: savedObjectsService,
|
||||
share: {} as SharePluginStart,
|
||||
spaceIdToNamespace: jest.fn().mockReturnValue(undefined),
|
||||
supportsEphemeralTasks: false,
|
||||
uiSettings: uiSettingsService,
|
||||
usageCounter: mockUsageCounter,
|
||||
isServerless: false,
|
||||
|
|
|
@ -120,13 +120,11 @@ describe('Task Runner Factory', () => {
|
|||
logger: loggingSystemMock.create().get(),
|
||||
maintenanceWindowsService,
|
||||
maxAlerts: 1000,
|
||||
maxEphemeralActionsPerRule: 10,
|
||||
ruleTypeRegistry: ruleTypeRegistryMock.create(),
|
||||
rulesSettingsService,
|
||||
savedObjects: savedObjectsService,
|
||||
share: {} as SharePluginStart,
|
||||
spaceIdToNamespace: jest.fn().mockReturnValue(undefined),
|
||||
supportsEphemeralTasks: true,
|
||||
uiSettings: uiSettingsService,
|
||||
usageCounter: mockUsageCounter,
|
||||
isServerless: false,
|
||||
|
|
|
@ -172,13 +172,11 @@ export interface TaskRunnerContext {
|
|||
logger: Logger;
|
||||
maintenanceWindowsService: MaintenanceWindowsService;
|
||||
maxAlerts: number;
|
||||
maxEphemeralActionsPerRule: number;
|
||||
ruleTypeRegistry: RuleTypeRegistry;
|
||||
rulesSettingsService: RulesSettingsService;
|
||||
savedObjects: SavedObjectsServiceStart;
|
||||
share: SharePluginStart;
|
||||
spaceIdToNamespace: SpaceIdToNamespaceFunction;
|
||||
supportsEphemeralTasks: boolean;
|
||||
uiSettings: UiSettingsServiceStart;
|
||||
usageCounter?: UsageCounter;
|
||||
isServerless: boolean;
|
||||
|
|
|
@ -57,7 +57,6 @@ export function generateAlertingConfig(): AlertingConfig {
|
|||
interval: '5m',
|
||||
removalDelay: '1h',
|
||||
},
|
||||
maxEphemeralActionsPerAlert: 10,
|
||||
cancelAlertsOnRuleTimeout: true,
|
||||
rules: {
|
||||
maxScheduledPerMinute: 10000,
|
||||
|
|
|
@ -217,7 +217,6 @@ export function createTestConfig(name: string, options: CreateTestConfigOptions)
|
|||
...emailSettings,
|
||||
...maxScheduledPerMinuteSettings,
|
||||
'--xpack.eventLog.logEntries=true',
|
||||
'--xpack.task_manager.ephemeral_tasks.enabled=false',
|
||||
`--xpack.task_manager.unsafe.exclude_task_types=${JSON.stringify([
|
||||
'actions:test.excluded',
|
||||
])}`,
|
||||
|
|
|
@ -1,124 +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 expect from '@kbn/expect';
|
||||
import { flatten } from 'lodash';
|
||||
import { IValidatedEvent } from '@kbn/event-log-plugin/server';
|
||||
import { DEFAULT_MAX_EPHEMERAL_ACTIONS_PER_ALERT } from '@kbn/alerting-plugin/server/config';
|
||||
import { ESTestIndexTool, ES_TEST_INDEX_NAME } from '@kbn/alerting-api-integration-helpers';
|
||||
import { Spaces } from '../../../scenarios';
|
||||
import { getUrlPrefix, ObjectRemover, getTestRuleData, getEventLog } from '../../../../common/lib';
|
||||
import { FtrProviderContext } from '../../../../common/ftr_provider_context';
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default function createNotifyWhenTests({ getService }: FtrProviderContext) {
|
||||
const supertest = getService('supertest');
|
||||
const retry = getService('retry');
|
||||
const es = getService('es');
|
||||
|
||||
const esTestIndexTool = new ESTestIndexTool(es, retry);
|
||||
|
||||
describe('ephemeral', () => {
|
||||
const objectRemover = new ObjectRemover(supertest);
|
||||
|
||||
beforeEach(async () => {
|
||||
await esTestIndexTool.destroy();
|
||||
await esTestIndexTool.setup();
|
||||
});
|
||||
afterEach(async () => await esTestIndexTool.destroy());
|
||||
after(async () => {
|
||||
await objectRemover.removeAll();
|
||||
});
|
||||
|
||||
it('should execute all requests, when some will be ephemeral and some not', async () => {
|
||||
const nonEphemeralTasks = 3;
|
||||
const actionPromises = [];
|
||||
for (let i = 0; i < DEFAULT_MAX_EPHEMERAL_ACTIONS_PER_ALERT + nonEphemeralTasks; i++) {
|
||||
actionPromises.push(
|
||||
supertest
|
||||
.post(`${getUrlPrefix(Spaces.space1.id)}/api/actions/connector`)
|
||||
.set('kbn-xsrf', 'foo')
|
||||
.send({
|
||||
name: `My action${i}`,
|
||||
connector_type_id: 'test.index-record',
|
||||
config: {
|
||||
unencrypted: `This value shouldn't get encrypted`,
|
||||
},
|
||||
secrets: {
|
||||
encrypted: 'This value should be encrypted',
|
||||
},
|
||||
})
|
||||
.expect(200)
|
||||
);
|
||||
}
|
||||
const createdActions = await Promise.all(actionPromises);
|
||||
createdActions.forEach((createdAction) =>
|
||||
objectRemover.add(Spaces.space1.id, createdAction.body.id, 'connector', 'actions')
|
||||
);
|
||||
|
||||
const pattern = {
|
||||
instance: [true, true, true, false, true, true],
|
||||
};
|
||||
const alertData = getTestRuleData({
|
||||
rule_type_id: 'test.patternFiring',
|
||||
params: { pattern },
|
||||
schedule: { interval: '1m' },
|
||||
throttle: null,
|
||||
notify_when: 'onActiveAlert',
|
||||
actions: createdActions.map((createdAction) => {
|
||||
return {
|
||||
id: createdAction.body.id,
|
||||
group: 'default',
|
||||
params: {
|
||||
index: ES_TEST_INDEX_NAME,
|
||||
reference: '',
|
||||
message: 'test message',
|
||||
},
|
||||
};
|
||||
}),
|
||||
});
|
||||
const { body: createdAlert } = await supertest
|
||||
.post(`${getUrlPrefix(Spaces.space1.id)}/api/alerting/rule`)
|
||||
.set('kbn-xsrf', 'foo')
|
||||
.send(alertData)
|
||||
.expect(200);
|
||||
objectRemover.add(Spaces.space1.id, createdAlert.id, 'rule', 'alerting');
|
||||
|
||||
const events = flatten(
|
||||
await Promise.all(
|
||||
createdActions.map(async (createdAction) => {
|
||||
return await retry.try(async () => {
|
||||
return await getEventLog({
|
||||
getService,
|
||||
spaceId: Spaces.space1.id,
|
||||
type: 'action',
|
||||
id: createdAction.body.id,
|
||||
provider: 'actions',
|
||||
actions: new Map([['execute', { gte: 1 }]]),
|
||||
});
|
||||
});
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
const executeActionsEvents = getEventsByAction(events, 'execute');
|
||||
expect(executeActionsEvents.length).equal(
|
||||
nonEphemeralTasks + DEFAULT_MAX_EPHEMERAL_ACTIONS_PER_ALERT
|
||||
);
|
||||
|
||||
const searchResult = await esTestIndexTool.search('action:test.index-record');
|
||||
// @ts-expect-error doesnt handle total: number
|
||||
expect(searchResult.body.hits.total.value).equal(
|
||||
nonEphemeralTasks + DEFAULT_MAX_EPHEMERAL_ACTIONS_PER_ALERT
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function getEventsByAction(events: IValidatedEvent[], action: string) {
|
||||
return events.filter((event) => event?.event?.action === action);
|
||||
}
|
|
@ -18,7 +18,6 @@ export default function alertingTests({ loadTestFile, getService }: FtrProviderC
|
|||
loadTestFile(require.resolve('./builtin_alert_types'));
|
||||
loadTestFile(require.resolve('./mustache_templates.ts'));
|
||||
loadTestFile(require.resolve('./notify_when'));
|
||||
loadTestFile(require.resolve('./ephemeral'));
|
||||
loadTestFile(require.resolve('./event_log_alerts'));
|
||||
loadTestFile(require.resolve('./snooze'));
|
||||
loadTestFile(require.resolve('./unsnooze'));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue