mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
Make the actions plugin support generics (#71439)
* Initial attempt at making the actions plugin support generics * Export WebhookMethods * Fix typings for registry * Usage of Record<string, unknown> * Apply feedback from Gidi * Cleanup * Fix validate_with_schema * Cleanup pt2 * Fix failing tests * Add generics to ActionType for ActionTypeExecutorResult Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
parent
8e0e228dbf
commit
54e13ad6f6
30 changed files with 466 additions and 247 deletions
|
@ -41,7 +41,7 @@ beforeEach(() => {
|
|||
};
|
||||
});
|
||||
|
||||
const executor: ExecutorType = async (options) => {
|
||||
const executor: ExecutorType<{}, {}, {}, void> = async (options) => {
|
||||
return { status: 'ok', actionId: options.actionId };
|
||||
};
|
||||
|
||||
|
@ -203,7 +203,9 @@ describe('isActionTypeEnabled', () => {
|
|||
id: 'foo',
|
||||
name: 'Foo',
|
||||
minimumLicenseRequired: 'basic',
|
||||
executor: async () => {},
|
||||
executor: async (options) => {
|
||||
return { status: 'ok', actionId: options.actionId };
|
||||
},
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
|
@ -258,7 +260,9 @@ describe('ensureActionTypeEnabled', () => {
|
|||
id: 'foo',
|
||||
name: 'Foo',
|
||||
minimumLicenseRequired: 'basic',
|
||||
executor: async () => {},
|
||||
executor: async (options) => {
|
||||
return { status: 'ok', actionId: options.actionId };
|
||||
},
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
|
|
|
@ -8,9 +8,15 @@ import Boom from 'boom';
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import { RunContext, TaskManagerSetupContract } from '../../task_manager/server';
|
||||
import { ExecutorError, TaskRunnerFactory, ILicenseState } from './lib';
|
||||
import { ActionType, PreConfiguredAction } from './types';
|
||||
import { ActionType as CommonActionType } from '../common';
|
||||
import { ActionsConfigurationUtilities } from './actions_config';
|
||||
import {
|
||||
ActionType,
|
||||
PreConfiguredAction,
|
||||
ActionTypeConfig,
|
||||
ActionTypeSecrets,
|
||||
ActionTypeParams,
|
||||
} from './types';
|
||||
|
||||
export interface ActionTypeRegistryOpts {
|
||||
taskManager: TaskManagerSetupContract;
|
||||
|
@ -77,7 +83,12 @@ export class ActionTypeRegistry {
|
|||
/**
|
||||
* Registers an action type to the action type registry
|
||||
*/
|
||||
public register(actionType: ActionType) {
|
||||
public register<
|
||||
Config extends ActionTypeConfig = ActionTypeConfig,
|
||||
Secrets extends ActionTypeSecrets = ActionTypeSecrets,
|
||||
Params extends ActionTypeParams = ActionTypeParams,
|
||||
ExecutorResultData = void
|
||||
>(actionType: ActionType<Config, Secrets, Params, ExecutorResultData>) {
|
||||
if (this.has(actionType.id)) {
|
||||
throw new Error(
|
||||
i18n.translate(
|
||||
|
@ -91,7 +102,7 @@ export class ActionTypeRegistry {
|
|||
)
|
||||
);
|
||||
}
|
||||
this.actionTypes.set(actionType.id, { ...actionType });
|
||||
this.actionTypes.set(actionType.id, { ...actionType } as ActionType);
|
||||
this.taskManager.registerTaskDefinitions({
|
||||
[`actions:${actionType.id}`]: {
|
||||
title: actionType.name,
|
||||
|
@ -112,7 +123,12 @@ export class ActionTypeRegistry {
|
|||
/**
|
||||
* Returns an action type, throws if not registered
|
||||
*/
|
||||
public get(id: string): ActionType {
|
||||
public get<
|
||||
Config extends ActionTypeConfig = ActionTypeConfig,
|
||||
Secrets extends ActionTypeSecrets = ActionTypeSecrets,
|
||||
Params extends ActionTypeParams = ActionTypeParams,
|
||||
ExecutorResultData = void
|
||||
>(id: string): ActionType<Config, Secrets, Params, ExecutorResultData> {
|
||||
if (!this.has(id)) {
|
||||
throw Boom.badRequest(
|
||||
i18n.translate('xpack.actions.actionTypeRegistry.get.missingActionTypeErrorMessage', {
|
||||
|
@ -123,7 +139,7 @@ export class ActionTypeRegistry {
|
|||
})
|
||||
);
|
||||
}
|
||||
return this.actionTypes.get(id)!;
|
||||
return this.actionTypes.get(id)! as ActionType<Config, Secrets, Params, ExecutorResultData>;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -39,7 +39,7 @@ let actionsClient: ActionsClient;
|
|||
let mockedLicenseState: jest.Mocked<ILicenseState>;
|
||||
let actionTypeRegistry: ActionTypeRegistry;
|
||||
let actionTypeRegistryParams: ActionTypeRegistryOpts;
|
||||
const executor: ExecutorType = async (options) => {
|
||||
const executor: ExecutorType<{}, {}, {}, void> = async (options) => {
|
||||
return { status: 'ok', actionId: options.actionId };
|
||||
};
|
||||
|
||||
|
|
|
@ -298,7 +298,7 @@ export class ActionsClient {
|
|||
public async execute({
|
||||
actionId,
|
||||
params,
|
||||
}: Omit<ExecuteOptions, 'request'>): Promise<ActionTypeExecutorResult> {
|
||||
}: Omit<ExecuteOptions, 'request'>): Promise<ActionTypeExecutorResult<unknown>> {
|
||||
await this.authorization.ensureAuthorized('execute');
|
||||
return this.actionExecutor.execute({ actionId, params, request: this.request });
|
||||
}
|
||||
|
|
|
@ -10,6 +10,10 @@ import { schema } from '@kbn/config-schema';
|
|||
import { ActionTypeExecutorOptions, ActionTypeExecutorResult, ActionType } from '../../types';
|
||||
|
||||
import { ExecutorParamsSchema } from './schema';
|
||||
import {
|
||||
ExternalIncidentServiceConfiguration,
|
||||
ExternalIncidentServiceSecretConfiguration,
|
||||
} from './types';
|
||||
|
||||
import {
|
||||
CreateExternalServiceArgs,
|
||||
|
@ -23,6 +27,7 @@ import {
|
|||
TransformFieldsArgs,
|
||||
Comment,
|
||||
ExecutorSubActionPushParams,
|
||||
PushToServiceResponse,
|
||||
} from './types';
|
||||
|
||||
import { transformers } from './transformers';
|
||||
|
@ -63,14 +68,17 @@ export const createConnectorExecutor = ({
|
|||
api,
|
||||
createExternalService,
|
||||
}: CreateExternalServiceBasicArgs) => async (
|
||||
execOptions: ActionTypeExecutorOptions
|
||||
): Promise<ActionTypeExecutorResult> => {
|
||||
execOptions: ActionTypeExecutorOptions<
|
||||
ExternalIncidentServiceConfiguration,
|
||||
ExternalIncidentServiceSecretConfiguration,
|
||||
ExecutorParams
|
||||
>
|
||||
): Promise<ActionTypeExecutorResult<PushToServiceResponse | {}>> => {
|
||||
const { actionId, config, params, secrets } = execOptions;
|
||||
const { subAction, subActionParams } = params as ExecutorParams;
|
||||
const { subAction, subActionParams } = params;
|
||||
let data = {};
|
||||
|
||||
const res: Pick<ActionTypeExecutorResult, 'status'> &
|
||||
Pick<ActionTypeExecutorResult, 'actionId'> = {
|
||||
const res: ActionTypeExecutorResult<void> = {
|
||||
status: 'ok',
|
||||
actionId,
|
||||
};
|
||||
|
|
|
@ -10,7 +10,6 @@ jest.mock('./lib/send_email', () => ({
|
|||
|
||||
import { Logger } from '../../../../../src/core/server';
|
||||
|
||||
import { ActionType, ActionTypeExecutorOptions } from '../types';
|
||||
import { actionsConfigMock } from '../actions_config.mock';
|
||||
import { validateConfig, validateSecrets, validateParams } from '../lib';
|
||||
import { createActionTypeRegistry } from './index.test';
|
||||
|
@ -21,6 +20,8 @@ import {
|
|||
ActionTypeConfigType,
|
||||
ActionTypeSecretsType,
|
||||
getActionType,
|
||||
EmailActionType,
|
||||
EmailActionTypeExecutorOptions,
|
||||
} from './email';
|
||||
|
||||
const sendEmailMock = sendEmail as jest.Mock;
|
||||
|
@ -29,13 +30,17 @@ const ACTION_TYPE_ID = '.email';
|
|||
|
||||
const services = actionsMock.createServices();
|
||||
|
||||
let actionType: ActionType;
|
||||
let actionType: EmailActionType;
|
||||
let mockedLogger: jest.Mocked<Logger>;
|
||||
|
||||
beforeEach(() => {
|
||||
jest.resetAllMocks();
|
||||
const { actionTypeRegistry } = createActionTypeRegistry();
|
||||
actionType = actionTypeRegistry.get(ACTION_TYPE_ID);
|
||||
actionType = actionTypeRegistry.get<
|
||||
ActionTypeConfigType,
|
||||
ActionTypeSecretsType,
|
||||
ActionParamsType
|
||||
>(ACTION_TYPE_ID);
|
||||
});
|
||||
|
||||
describe('actionTypeRegistry.get() works', () => {
|
||||
|
@ -242,7 +247,7 @@ describe('execute()', () => {
|
|||
};
|
||||
|
||||
const actionId = 'some-id';
|
||||
const executorOptions: ActionTypeExecutorOptions = {
|
||||
const executorOptions: EmailActionTypeExecutorOptions = {
|
||||
actionId,
|
||||
config,
|
||||
params,
|
||||
|
@ -306,7 +311,7 @@ describe('execute()', () => {
|
|||
};
|
||||
|
||||
const actionId = 'some-id';
|
||||
const executorOptions: ActionTypeExecutorOptions = {
|
||||
const executorOptions: EmailActionTypeExecutorOptions = {
|
||||
actionId,
|
||||
config,
|
||||
params,
|
||||
|
@ -363,7 +368,7 @@ describe('execute()', () => {
|
|||
};
|
||||
|
||||
const actionId = 'some-id';
|
||||
const executorOptions: ActionTypeExecutorOptions = {
|
||||
const executorOptions: EmailActionTypeExecutorOptions = {
|
||||
actionId,
|
||||
config,
|
||||
params,
|
||||
|
|
|
@ -15,6 +15,18 @@ import { Logger } from '../../../../../src/core/server';
|
|||
import { ActionType, ActionTypeExecutorOptions, ActionTypeExecutorResult } from '../types';
|
||||
import { ActionsConfigurationUtilities } from '../actions_config';
|
||||
|
||||
export type EmailActionType = ActionType<
|
||||
ActionTypeConfigType,
|
||||
ActionTypeSecretsType,
|
||||
ActionParamsType,
|
||||
unknown
|
||||
>;
|
||||
export type EmailActionTypeExecutorOptions = ActionTypeExecutorOptions<
|
||||
ActionTypeConfigType,
|
||||
ActionTypeSecretsType,
|
||||
ActionParamsType
|
||||
>;
|
||||
|
||||
// config definition
|
||||
export type ActionTypeConfigType = TypeOf<typeof ConfigSchema>;
|
||||
|
||||
|
@ -30,10 +42,9 @@ const ConfigSchema = schema.object(ConfigSchemaProps);
|
|||
|
||||
function validateConfig(
|
||||
configurationUtilities: ActionsConfigurationUtilities,
|
||||
configObject: unknown
|
||||
configObject: ActionTypeConfigType
|
||||
): string | void {
|
||||
// avoids circular reference ...
|
||||
const config = configObject as ActionTypeConfigType;
|
||||
const config = configObject;
|
||||
|
||||
// Make sure service is set, or if not, both host/port must be set.
|
||||
// If service is set, host/port are ignored, when the email is sent.
|
||||
|
@ -113,7 +124,7 @@ interface GetActionTypeParams {
|
|||
}
|
||||
|
||||
// action type definition
|
||||
export function getActionType(params: GetActionTypeParams): ActionType {
|
||||
export function getActionType(params: GetActionTypeParams): EmailActionType {
|
||||
const { logger, configurationUtilities } = params;
|
||||
return {
|
||||
id: '.email',
|
||||
|
@ -136,12 +147,12 @@ export function getActionType(params: GetActionTypeParams): ActionType {
|
|||
|
||||
async function executor(
|
||||
{ logger }: { logger: Logger },
|
||||
execOptions: ActionTypeExecutorOptions
|
||||
): Promise<ActionTypeExecutorResult> {
|
||||
execOptions: EmailActionTypeExecutorOptions
|
||||
): Promise<ActionTypeExecutorResult<unknown>> {
|
||||
const actionId = execOptions.actionId;
|
||||
const config = execOptions.config as ActionTypeConfigType;
|
||||
const secrets = execOptions.secrets as ActionTypeSecretsType;
|
||||
const params = execOptions.params as ActionParamsType;
|
||||
const config = execOptions.config;
|
||||
const secrets = execOptions.secrets;
|
||||
const params = execOptions.params;
|
||||
|
||||
const transport: Transport = {};
|
||||
|
||||
|
|
|
@ -8,21 +8,25 @@ jest.mock('./lib/send_email', () => ({
|
|||
sendEmail: jest.fn(),
|
||||
}));
|
||||
|
||||
import { ActionType, ActionTypeExecutorOptions } from '../types';
|
||||
import { validateConfig, validateParams } from '../lib';
|
||||
import { createActionTypeRegistry } from './index.test';
|
||||
import { ActionParamsType, ActionTypeConfigType } from './es_index';
|
||||
import { actionsMock } from '../mocks';
|
||||
import {
|
||||
ActionParamsType,
|
||||
ActionTypeConfigType,
|
||||
ESIndexActionType,
|
||||
ESIndexActionTypeExecutorOptions,
|
||||
} from './es_index';
|
||||
|
||||
const ACTION_TYPE_ID = '.index';
|
||||
|
||||
const services = actionsMock.createServices();
|
||||
|
||||
let actionType: ActionType;
|
||||
let actionType: ESIndexActionType;
|
||||
|
||||
beforeAll(() => {
|
||||
const { actionTypeRegistry } = createActionTypeRegistry();
|
||||
actionType = actionTypeRegistry.get(ACTION_TYPE_ID);
|
||||
actionType = actionTypeRegistry.get<ActionTypeConfigType, {}, ActionParamsType>(ACTION_TYPE_ID);
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
|
@ -144,12 +148,12 @@ describe('params validation', () => {
|
|||
describe('execute()', () => {
|
||||
test('ensure parameters are as expected', async () => {
|
||||
const secrets = {};
|
||||
let config: Partial<ActionTypeConfigType>;
|
||||
let config: ActionTypeConfigType;
|
||||
let params: ActionParamsType;
|
||||
let executorOptions: ActionTypeExecutorOptions;
|
||||
let executorOptions: ESIndexActionTypeExecutorOptions;
|
||||
|
||||
// minimal params
|
||||
config = { index: 'index-value', refresh: false };
|
||||
config = { index: 'index-value', refresh: false, executionTimeField: null };
|
||||
params = {
|
||||
documents: [{ jim: 'bob' }],
|
||||
};
|
||||
|
@ -215,7 +219,7 @@ describe('execute()', () => {
|
|||
`);
|
||||
|
||||
// minimal params
|
||||
config = { index: 'index-value', executionTimeField: undefined, refresh: false };
|
||||
config = { index: 'index-value', executionTimeField: null, refresh: false };
|
||||
params = {
|
||||
documents: [{ jim: 'bob' }],
|
||||
};
|
||||
|
@ -245,7 +249,7 @@ describe('execute()', () => {
|
|||
`);
|
||||
|
||||
// multiple documents
|
||||
config = { index: 'index-value', executionTimeField: undefined, refresh: false };
|
||||
config = { index: 'index-value', executionTimeField: null, refresh: false };
|
||||
params = {
|
||||
documents: [{ a: 1 }, { b: 2 }],
|
||||
};
|
||||
|
|
|
@ -11,6 +11,13 @@ import { schema, TypeOf } from '@kbn/config-schema';
|
|||
import { Logger } from '../../../../../src/core/server';
|
||||
import { ActionType, ActionTypeExecutorOptions, ActionTypeExecutorResult } from '../types';
|
||||
|
||||
export type ESIndexActionType = ActionType<ActionTypeConfigType, {}, ActionParamsType, unknown>;
|
||||
export type ESIndexActionTypeExecutorOptions = ActionTypeExecutorOptions<
|
||||
ActionTypeConfigType,
|
||||
{},
|
||||
ActionParamsType
|
||||
>;
|
||||
|
||||
// config definition
|
||||
|
||||
export type ActionTypeConfigType = TypeOf<typeof ConfigSchema>;
|
||||
|
@ -33,7 +40,7 @@ const ParamsSchema = schema.object({
|
|||
});
|
||||
|
||||
// action type definition
|
||||
export function getActionType({ logger }: { logger: Logger }): ActionType {
|
||||
export function getActionType({ logger }: { logger: Logger }): ESIndexActionType {
|
||||
return {
|
||||
id: '.index',
|
||||
minimumLicenseRequired: 'basic',
|
||||
|
@ -52,11 +59,11 @@ export function getActionType({ logger }: { logger: Logger }): ActionType {
|
|||
|
||||
async function executor(
|
||||
{ logger }: { logger: Logger },
|
||||
execOptions: ActionTypeExecutorOptions
|
||||
): Promise<ActionTypeExecutorResult> {
|
||||
execOptions: ESIndexActionTypeExecutorOptions
|
||||
): Promise<ActionTypeExecutorResult<unknown>> {
|
||||
const actionId = execOptions.actionId;
|
||||
const config = execOptions.config as ActionTypeConfigType;
|
||||
const params = execOptions.params as ActionParamsType;
|
||||
const config = execOptions.config;
|
||||
const params = execOptions.params;
|
||||
const services = execOptions.services;
|
||||
|
||||
const index = config.index;
|
||||
|
|
|
@ -8,14 +8,21 @@ jest.mock('./lib/post_pagerduty', () => ({
|
|||
postPagerduty: jest.fn(),
|
||||
}));
|
||||
|
||||
import { getActionType } from './pagerduty';
|
||||
import { ActionType, Services, ActionTypeExecutorOptions } from '../types';
|
||||
import { Services } from '../types';
|
||||
import { validateConfig, validateSecrets, validateParams } from '../lib';
|
||||
import { postPagerduty } from './lib/post_pagerduty';
|
||||
import { createActionTypeRegistry } from './index.test';
|
||||
import { Logger } from '../../../../../src/core/server';
|
||||
import { actionsConfigMock } from '../actions_config.mock';
|
||||
import { actionsMock } from '../mocks';
|
||||
import {
|
||||
ActionParamsType,
|
||||
ActionTypeConfigType,
|
||||
ActionTypeSecretsType,
|
||||
getActionType,
|
||||
PagerDutyActionType,
|
||||
PagerDutyActionTypeExecutorOptions,
|
||||
} from './pagerduty';
|
||||
|
||||
const postPagerdutyMock = postPagerduty as jest.Mock;
|
||||
|
||||
|
@ -23,12 +30,16 @@ const ACTION_TYPE_ID = '.pagerduty';
|
|||
|
||||
const services: Services = actionsMock.createServices();
|
||||
|
||||
let actionType: ActionType;
|
||||
let actionType: PagerDutyActionType;
|
||||
let mockedLogger: jest.Mocked<Logger>;
|
||||
|
||||
beforeAll(() => {
|
||||
const { logger, actionTypeRegistry } = createActionTypeRegistry();
|
||||
actionType = actionTypeRegistry.get(ACTION_TYPE_ID);
|
||||
actionType = actionTypeRegistry.get<
|
||||
ActionTypeConfigType,
|
||||
ActionTypeSecretsType,
|
||||
ActionParamsType
|
||||
>(ACTION_TYPE_ID);
|
||||
mockedLogger = logger;
|
||||
});
|
||||
|
||||
|
@ -167,7 +178,7 @@ describe('execute()', () => {
|
|||
|
||||
test('should succeed with minimal valid params', async () => {
|
||||
const secrets = { routingKey: 'super-secret' };
|
||||
const config = {};
|
||||
const config = { apiUrl: null };
|
||||
const params = {};
|
||||
|
||||
postPagerdutyMock.mockImplementation(() => {
|
||||
|
@ -175,7 +186,7 @@ describe('execute()', () => {
|
|||
});
|
||||
|
||||
const actionId = 'some-action-id';
|
||||
const executorOptions: ActionTypeExecutorOptions = {
|
||||
const executorOptions: PagerDutyActionTypeExecutorOptions = {
|
||||
actionId,
|
||||
config,
|
||||
params,
|
||||
|
@ -219,7 +230,7 @@ describe('execute()', () => {
|
|||
const config = {
|
||||
apiUrl: 'the-api-url',
|
||||
};
|
||||
const params = {
|
||||
const params: ActionParamsType = {
|
||||
eventAction: 'trigger',
|
||||
dedupKey: 'a-dedup-key',
|
||||
summary: 'the summary',
|
||||
|
@ -236,7 +247,7 @@ describe('execute()', () => {
|
|||
});
|
||||
|
||||
const actionId = 'some-action-id';
|
||||
const executorOptions: ActionTypeExecutorOptions = {
|
||||
const executorOptions: PagerDutyActionTypeExecutorOptions = {
|
||||
actionId,
|
||||
config,
|
||||
params,
|
||||
|
@ -284,7 +295,7 @@ describe('execute()', () => {
|
|||
const config = {
|
||||
apiUrl: 'the-api-url',
|
||||
};
|
||||
const params = {
|
||||
const params: ActionParamsType = {
|
||||
eventAction: 'acknowledge',
|
||||
dedupKey: 'a-dedup-key',
|
||||
summary: 'the summary',
|
||||
|
@ -301,7 +312,7 @@ describe('execute()', () => {
|
|||
});
|
||||
|
||||
const actionId = 'some-action-id';
|
||||
const executorOptions: ActionTypeExecutorOptions = {
|
||||
const executorOptions: PagerDutyActionTypeExecutorOptions = {
|
||||
actionId,
|
||||
config,
|
||||
params,
|
||||
|
@ -340,7 +351,7 @@ describe('execute()', () => {
|
|||
const config = {
|
||||
apiUrl: 'the-api-url',
|
||||
};
|
||||
const params = {
|
||||
const params: ActionParamsType = {
|
||||
eventAction: 'resolve',
|
||||
dedupKey: 'a-dedup-key',
|
||||
summary: 'the summary',
|
||||
|
@ -357,7 +368,7 @@ describe('execute()', () => {
|
|||
});
|
||||
|
||||
const actionId = 'some-action-id';
|
||||
const executorOptions: ActionTypeExecutorOptions = {
|
||||
const executorOptions: PagerDutyActionTypeExecutorOptions = {
|
||||
actionId,
|
||||
config,
|
||||
params,
|
||||
|
@ -390,7 +401,7 @@ describe('execute()', () => {
|
|||
|
||||
test('should fail when sendPagerdury throws', async () => {
|
||||
const secrets = { routingKey: 'super-secret' };
|
||||
const config = {};
|
||||
const config = { apiUrl: null };
|
||||
const params = {};
|
||||
|
||||
postPagerdutyMock.mockImplementation(() => {
|
||||
|
@ -398,7 +409,7 @@ describe('execute()', () => {
|
|||
});
|
||||
|
||||
const actionId = 'some-action-id';
|
||||
const executorOptions: ActionTypeExecutorOptions = {
|
||||
const executorOptions: PagerDutyActionTypeExecutorOptions = {
|
||||
actionId,
|
||||
config,
|
||||
params,
|
||||
|
@ -418,7 +429,7 @@ describe('execute()', () => {
|
|||
|
||||
test('should fail when sendPagerdury returns 429', async () => {
|
||||
const secrets = { routingKey: 'super-secret' };
|
||||
const config = {};
|
||||
const config = { apiUrl: null };
|
||||
const params = {};
|
||||
|
||||
postPagerdutyMock.mockImplementation(() => {
|
||||
|
@ -426,7 +437,7 @@ describe('execute()', () => {
|
|||
});
|
||||
|
||||
const actionId = 'some-action-id';
|
||||
const executorOptions: ActionTypeExecutorOptions = {
|
||||
const executorOptions: PagerDutyActionTypeExecutorOptions = {
|
||||
actionId,
|
||||
config,
|
||||
params,
|
||||
|
@ -446,7 +457,7 @@ describe('execute()', () => {
|
|||
|
||||
test('should fail when sendPagerdury returns 501', async () => {
|
||||
const secrets = { routingKey: 'super-secret' };
|
||||
const config = {};
|
||||
const config = { apiUrl: null };
|
||||
const params = {};
|
||||
|
||||
postPagerdutyMock.mockImplementation(() => {
|
||||
|
@ -454,7 +465,7 @@ describe('execute()', () => {
|
|||
});
|
||||
|
||||
const actionId = 'some-action-id';
|
||||
const executorOptions: ActionTypeExecutorOptions = {
|
||||
const executorOptions: PagerDutyActionTypeExecutorOptions = {
|
||||
actionId,
|
||||
config,
|
||||
params,
|
||||
|
@ -474,7 +485,7 @@ describe('execute()', () => {
|
|||
|
||||
test('should fail when sendPagerdury returns 418', async () => {
|
||||
const secrets = { routingKey: 'super-secret' };
|
||||
const config = {};
|
||||
const config = { apiUrl: null };
|
||||
const params = {};
|
||||
|
||||
postPagerdutyMock.mockImplementation(() => {
|
||||
|
@ -482,7 +493,7 @@ describe('execute()', () => {
|
|||
});
|
||||
|
||||
const actionId = 'some-action-id';
|
||||
const executorOptions: ActionTypeExecutorOptions = {
|
||||
const executorOptions: PagerDutyActionTypeExecutorOptions = {
|
||||
actionId,
|
||||
config,
|
||||
params,
|
||||
|
|
|
@ -16,6 +16,18 @@ import { ActionsConfigurationUtilities } from '../actions_config';
|
|||
// https://v2.developer.pagerduty.com/docs/events-api-v2
|
||||
const PAGER_DUTY_API_URL = 'https://events.pagerduty.com/v2/enqueue';
|
||||
|
||||
export type PagerDutyActionType = ActionType<
|
||||
ActionTypeConfigType,
|
||||
ActionTypeSecretsType,
|
||||
ActionParamsType,
|
||||
unknown
|
||||
>;
|
||||
export type PagerDutyActionTypeExecutorOptions = ActionTypeExecutorOptions<
|
||||
ActionTypeConfigType,
|
||||
ActionTypeSecretsType,
|
||||
ActionParamsType
|
||||
>;
|
||||
|
||||
// config definition
|
||||
|
||||
export type ActionTypeConfigType = TypeOf<typeof ConfigSchema>;
|
||||
|
@ -100,7 +112,7 @@ export function getActionType({
|
|||
}: {
|
||||
logger: Logger;
|
||||
configurationUtilities: ActionsConfigurationUtilities;
|
||||
}): ActionType {
|
||||
}): PagerDutyActionType {
|
||||
return {
|
||||
id: '.pagerduty',
|
||||
minimumLicenseRequired: 'gold',
|
||||
|
@ -142,12 +154,12 @@ function getPagerDutyApiUrl(config: ActionTypeConfigType): string {
|
|||
|
||||
async function executor(
|
||||
{ logger }: { logger: Logger },
|
||||
execOptions: ActionTypeExecutorOptions
|
||||
): Promise<ActionTypeExecutorResult> {
|
||||
execOptions: PagerDutyActionTypeExecutorOptions
|
||||
): Promise<ActionTypeExecutorResult<unknown>> {
|
||||
const actionId = execOptions.actionId;
|
||||
const config = execOptions.config as ActionTypeConfigType;
|
||||
const secrets = execOptions.secrets as ActionTypeSecretsType;
|
||||
const params = execOptions.params as ActionParamsType;
|
||||
const config = execOptions.config;
|
||||
const secrets = execOptions.secrets;
|
||||
const params = execOptions.params;
|
||||
const services = execOptions.services;
|
||||
|
||||
const apiUrl = getPagerDutyApiUrl(config);
|
||||
|
|
|
@ -4,20 +4,24 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { ActionType } from '../types';
|
||||
import { validateParams } from '../lib';
|
||||
import { Logger } from '../../../../../src/core/server';
|
||||
import { createActionTypeRegistry } from './index.test';
|
||||
import { actionsMock } from '../mocks';
|
||||
import {
|
||||
ActionParamsType,
|
||||
ServerLogActionType,
|
||||
ServerLogActionTypeExecutorOptions,
|
||||
} from './server_log';
|
||||
|
||||
const ACTION_TYPE_ID = '.server-log';
|
||||
|
||||
let actionType: ActionType;
|
||||
let actionType: ServerLogActionType;
|
||||
let mockedLogger: jest.Mocked<Logger>;
|
||||
|
||||
beforeAll(() => {
|
||||
const { logger, actionTypeRegistry } = createActionTypeRegistry();
|
||||
actionType = actionTypeRegistry.get(ACTION_TYPE_ID);
|
||||
actionType = actionTypeRegistry.get<{}, {}, ActionParamsType>(ACTION_TYPE_ID);
|
||||
mockedLogger = logger;
|
||||
expect(actionType).toBeTruthy();
|
||||
});
|
||||
|
@ -88,13 +92,14 @@ describe('validateParams()', () => {
|
|||
describe('execute()', () => {
|
||||
test('calls the executor with proper params', async () => {
|
||||
const actionId = 'some-id';
|
||||
await actionType.executor({
|
||||
const executorOptions: ServerLogActionTypeExecutorOptions = {
|
||||
actionId,
|
||||
services: actionsMock.createServices(),
|
||||
params: { message: 'message text here', level: 'info' },
|
||||
config: {},
|
||||
secrets: {},
|
||||
});
|
||||
};
|
||||
await actionType.executor(executorOptions);
|
||||
expect(mockedLogger.info).toHaveBeenCalledWith('Server log: message text here');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -12,6 +12,13 @@ import { Logger } from '../../../../../src/core/server';
|
|||
import { ActionType, ActionTypeExecutorOptions, ActionTypeExecutorResult } from '../types';
|
||||
import { withoutControlCharacters } from './lib/string_utils';
|
||||
|
||||
export type ServerLogActionType = ActionType<{}, {}, ActionParamsType>;
|
||||
export type ServerLogActionTypeExecutorOptions = ActionTypeExecutorOptions<
|
||||
{},
|
||||
{},
|
||||
ActionParamsType
|
||||
>;
|
||||
|
||||
// params definition
|
||||
|
||||
export type ActionParamsType = TypeOf<typeof ParamsSchema>;
|
||||
|
@ -32,7 +39,7 @@ const ParamsSchema = schema.object({
|
|||
});
|
||||
|
||||
// action type definition
|
||||
export function getActionType({ logger }: { logger: Logger }): ActionType {
|
||||
export function getActionType({ logger }: { logger: Logger }): ServerLogActionType {
|
||||
return {
|
||||
id: '.server-log',
|
||||
minimumLicenseRequired: 'basic',
|
||||
|
@ -50,10 +57,10 @@ export function getActionType({ logger }: { logger: Logger }): ActionType {
|
|||
|
||||
async function executor(
|
||||
{ logger }: { logger: Logger },
|
||||
execOptions: ActionTypeExecutorOptions
|
||||
): Promise<ActionTypeExecutorResult> {
|
||||
execOptions: ServerLogActionTypeExecutorOptions
|
||||
): Promise<ActionTypeExecutorResult<void>> {
|
||||
const actionId = execOptions.actionId;
|
||||
const params = execOptions.params as ActionParamsType;
|
||||
const params = execOptions.params;
|
||||
|
||||
const sanitizedMessage = withoutControlCharacters(params.message);
|
||||
try {
|
||||
|
|
|
@ -17,9 +17,14 @@ import { ActionsConfigurationUtilities } from '../../actions_config';
|
|||
import { ActionType, ActionTypeExecutorOptions, ActionTypeExecutorResult } from '../../types';
|
||||
import { createExternalService } from './service';
|
||||
import { api } from './api';
|
||||
import { ExecutorParams, ExecutorSubActionPushParams } from './types';
|
||||
import * as i18n from './translations';
|
||||
import { Logger } from '../../../../../../src/core/server';
|
||||
import {
|
||||
ExecutorParams,
|
||||
ExecutorSubActionPushParams,
|
||||
ServiceNowPublicConfigurationType,
|
||||
ServiceNowSecretConfigurationType,
|
||||
} from './types';
|
||||
|
||||
// TODO: to remove, need to support Case
|
||||
import { buildMap, mapParams } from '../case/utils';
|
||||
|
@ -31,7 +36,14 @@ interface GetActionTypeParams {
|
|||
}
|
||||
|
||||
// action type definition
|
||||
export function getActionType(params: GetActionTypeParams): ActionType {
|
||||
export function getActionType(
|
||||
params: GetActionTypeParams
|
||||
): ActionType<
|
||||
ServiceNowPublicConfigurationType,
|
||||
ServiceNowSecretConfigurationType,
|
||||
ExecutorParams,
|
||||
PushToServiceResponse | {}
|
||||
> {
|
||||
const { logger, configurationUtilities } = params;
|
||||
return {
|
||||
id: '.servicenow',
|
||||
|
@ -54,10 +66,14 @@ export function getActionType(params: GetActionTypeParams): ActionType {
|
|||
|
||||
async function executor(
|
||||
{ logger }: { logger: Logger },
|
||||
execOptions: ActionTypeExecutorOptions
|
||||
): Promise<ActionTypeExecutorResult> {
|
||||
execOptions: ActionTypeExecutorOptions<
|
||||
ServiceNowPublicConfigurationType,
|
||||
ServiceNowSecretConfigurationType,
|
||||
ExecutorParams
|
||||
>
|
||||
): Promise<ActionTypeExecutorResult<PushToServiceResponse | {}>> {
|
||||
const { actionId, config, params, secrets } = execOptions;
|
||||
const { subAction, subActionParams } = params as ExecutorParams;
|
||||
const { subAction, subActionParams } = params;
|
||||
let data: PushToServiceResponse | null = null;
|
||||
|
||||
const externalService = createExternalService({
|
||||
|
@ -81,9 +97,8 @@ async function executor(
|
|||
const pushToServiceParams = subActionParams as ExecutorSubActionPushParams;
|
||||
|
||||
const { comments, externalId, ...restParams } = pushToServiceParams;
|
||||
const mapping = config.incidentConfiguration
|
||||
? buildMap(config.incidentConfiguration.mapping)
|
||||
: null;
|
||||
const incidentConfiguration = config.incidentConfiguration;
|
||||
const mapping = incidentConfiguration ? buildMap(incidentConfiguration.mapping) : null;
|
||||
const externalObject =
|
||||
config.incidentConfiguration && mapping ? mapParams(restParams, mapping) : {};
|
||||
|
||||
|
|
|
@ -4,14 +4,9 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import {
|
||||
ActionType,
|
||||
Services,
|
||||
ActionTypeExecutorOptions,
|
||||
ActionTypeExecutorResult,
|
||||
} from '../types';
|
||||
import { Services, ActionTypeExecutorResult } from '../types';
|
||||
import { validateParams, validateSecrets } from '../lib';
|
||||
import { getActionType } from './slack';
|
||||
import { getActionType, SlackActionType, SlackActionTypeExecutorOptions } from './slack';
|
||||
import { actionsConfigMock } from '../actions_config.mock';
|
||||
import { actionsMock } from '../mocks';
|
||||
|
||||
|
@ -19,11 +14,13 @@ const ACTION_TYPE_ID = '.slack';
|
|||
|
||||
const services: Services = actionsMock.createServices();
|
||||
|
||||
let actionType: ActionType;
|
||||
let actionType: SlackActionType;
|
||||
|
||||
beforeAll(() => {
|
||||
actionType = getActionType({
|
||||
async executor() {},
|
||||
async executor(options) {
|
||||
return { status: 'ok', actionId: options.actionId };
|
||||
},
|
||||
configurationUtilities: actionsConfigMock.create(),
|
||||
});
|
||||
});
|
||||
|
@ -119,7 +116,7 @@ describe('validateActionTypeSecrets()', () => {
|
|||
|
||||
describe('execute()', () => {
|
||||
beforeAll(() => {
|
||||
async function mockSlackExecutor(options: ActionTypeExecutorOptions) {
|
||||
async function mockSlackExecutor(options: SlackActionTypeExecutorOptions) {
|
||||
const { params } = options;
|
||||
const { message } = params;
|
||||
if (message == null) throw new Error('message property required in parameter');
|
||||
|
@ -134,7 +131,7 @@ describe('execute()', () => {
|
|||
text: `slack mockExecutor success: ${message}`,
|
||||
actionId: '',
|
||||
status: 'ok',
|
||||
} as ActionTypeExecutorResult;
|
||||
} as ActionTypeExecutorResult<void>;
|
||||
}
|
||||
|
||||
actionType = getActionType({
|
||||
|
|
|
@ -21,6 +21,13 @@ import {
|
|||
} from '../types';
|
||||
import { ActionsConfigurationUtilities } from '../actions_config';
|
||||
|
||||
export type SlackActionType = ActionType<{}, ActionTypeSecretsType, ActionParamsType, unknown>;
|
||||
export type SlackActionTypeExecutorOptions = ActionTypeExecutorOptions<
|
||||
{},
|
||||
ActionTypeSecretsType,
|
||||
ActionParamsType
|
||||
>;
|
||||
|
||||
// secrets definition
|
||||
|
||||
export type ActionTypeSecretsType = TypeOf<typeof SecretsSchema>;
|
||||
|
@ -46,8 +53,8 @@ export function getActionType({
|
|||
executor = slackExecutor,
|
||||
}: {
|
||||
configurationUtilities: ActionsConfigurationUtilities;
|
||||
executor?: ExecutorType;
|
||||
}): ActionType {
|
||||
executor?: ExecutorType<{}, ActionTypeSecretsType, ActionParamsType, unknown>;
|
||||
}): SlackActionType {
|
||||
return {
|
||||
id: '.slack',
|
||||
minimumLicenseRequired: 'gold',
|
||||
|
@ -92,11 +99,11 @@ function valdiateActionTypeConfig(
|
|||
// action executor
|
||||
|
||||
async function slackExecutor(
|
||||
execOptions: ActionTypeExecutorOptions
|
||||
): Promise<ActionTypeExecutorResult> {
|
||||
execOptions: SlackActionTypeExecutorOptions
|
||||
): Promise<ActionTypeExecutorResult<unknown>> {
|
||||
const actionId = execOptions.actionId;
|
||||
const secrets = execOptions.secrets as ActionTypeSecretsType;
|
||||
const params = execOptions.params as ActionParamsType;
|
||||
const secrets = execOptions.secrets;
|
||||
const params = execOptions.params;
|
||||
|
||||
let result: IncomingWebhookResult;
|
||||
const { webhookUrl } = secrets;
|
||||
|
@ -156,18 +163,21 @@ async function slackExecutor(
|
|||
return successResult(actionId, result);
|
||||
}
|
||||
|
||||
function successResult(actionId: string, data: unknown): ActionTypeExecutorResult {
|
||||
function successResult(actionId: string, data: unknown): ActionTypeExecutorResult<unknown> {
|
||||
return { status: 'ok', data, actionId };
|
||||
}
|
||||
|
||||
function errorResult(actionId: string, message: string): ActionTypeExecutorResult {
|
||||
function errorResult(actionId: string, message: string): ActionTypeExecutorResult<void> {
|
||||
return {
|
||||
status: 'error',
|
||||
message,
|
||||
actionId,
|
||||
};
|
||||
}
|
||||
function serviceErrorResult(actionId: string, serviceMessage: string): ActionTypeExecutorResult {
|
||||
function serviceErrorResult(
|
||||
actionId: string,
|
||||
serviceMessage: string
|
||||
): ActionTypeExecutorResult<void> {
|
||||
const errMessage = i18n.translate('xpack.actions.builtin.slack.errorPostingErrorMessage', {
|
||||
defaultMessage: 'error posting slack message',
|
||||
});
|
||||
|
@ -179,7 +189,7 @@ function serviceErrorResult(actionId: string, serviceMessage: string): ActionTyp
|
|||
};
|
||||
}
|
||||
|
||||
function retryResult(actionId: string, message: string): ActionTypeExecutorResult {
|
||||
function retryResult(actionId: string, message: string): ActionTypeExecutorResult<void> {
|
||||
const errMessage = i18n.translate(
|
||||
'xpack.actions.builtin.slack.errorPostingRetryLaterErrorMessage',
|
||||
{
|
||||
|
@ -198,7 +208,7 @@ function retryResultSeconds(
|
|||
actionId: string,
|
||||
message: string,
|
||||
retryAfter: number
|
||||
): ActionTypeExecutorResult {
|
||||
): ActionTypeExecutorResult<void> {
|
||||
const retryEpoch = Date.now() + retryAfter * 1000;
|
||||
const retry = new Date(retryEpoch);
|
||||
const retryString = retry.toISOString();
|
||||
|
|
|
@ -8,14 +8,21 @@ jest.mock('axios', () => ({
|
|||
request: jest.fn(),
|
||||
}));
|
||||
|
||||
import { getActionType } from './webhook';
|
||||
import { ActionType, Services } from '../types';
|
||||
import { Services } from '../types';
|
||||
import { validateConfig, validateSecrets, validateParams } from '../lib';
|
||||
import { actionsConfigMock } from '../actions_config.mock';
|
||||
import { createActionTypeRegistry } from './index.test';
|
||||
import { Logger } from '../../../../../src/core/server';
|
||||
import { actionsMock } from '../mocks';
|
||||
import axios from 'axios';
|
||||
import {
|
||||
ActionParamsType,
|
||||
ActionTypeConfigType,
|
||||
ActionTypeSecretsType,
|
||||
getActionType,
|
||||
WebhookActionType,
|
||||
WebhookMethods,
|
||||
} from './webhook';
|
||||
|
||||
const axiosRequestMock = axios.request as jest.Mock;
|
||||
|
||||
|
@ -23,12 +30,16 @@ const ACTION_TYPE_ID = '.webhook';
|
|||
|
||||
const services: Services = actionsMock.createServices();
|
||||
|
||||
let actionType: ActionType;
|
||||
let actionType: WebhookActionType;
|
||||
let mockedLogger: jest.Mocked<Logger>;
|
||||
|
||||
beforeAll(() => {
|
||||
const { logger, actionTypeRegistry } = createActionTypeRegistry();
|
||||
actionType = actionTypeRegistry.get(ACTION_TYPE_ID);
|
||||
actionType = actionTypeRegistry.get<
|
||||
ActionTypeConfigType,
|
||||
ActionTypeSecretsType,
|
||||
ActionParamsType
|
||||
>(ACTION_TYPE_ID);
|
||||
mockedLogger = logger;
|
||||
});
|
||||
|
||||
|
@ -235,16 +246,17 @@ describe('execute()', () => {
|
|||
});
|
||||
|
||||
test('execute with username/password sends request with basic auth', async () => {
|
||||
const config: ActionTypeConfigType = {
|
||||
url: 'https://abc.def/my-webhook',
|
||||
method: WebhookMethods.POST,
|
||||
headers: {
|
||||
aheader: 'a value',
|
||||
},
|
||||
};
|
||||
await actionType.executor({
|
||||
actionId: 'some-id',
|
||||
services,
|
||||
config: {
|
||||
url: 'https://abc.def/my-webhook',
|
||||
method: 'post',
|
||||
headers: {
|
||||
aheader: 'a value',
|
||||
},
|
||||
},
|
||||
config,
|
||||
secrets: { user: 'abc', password: '123' },
|
||||
params: { body: 'some data' },
|
||||
});
|
||||
|
@ -266,17 +278,19 @@ describe('execute()', () => {
|
|||
});
|
||||
|
||||
test('execute without username/password sends request without basic auth', async () => {
|
||||
const config: ActionTypeConfigType = {
|
||||
url: 'https://abc.def/my-webhook',
|
||||
method: WebhookMethods.POST,
|
||||
headers: {
|
||||
aheader: 'a value',
|
||||
},
|
||||
};
|
||||
const secrets: ActionTypeSecretsType = { user: null, password: null };
|
||||
await actionType.executor({
|
||||
actionId: 'some-id',
|
||||
services,
|
||||
config: {
|
||||
url: 'https://abc.def/my-webhook',
|
||||
method: 'post',
|
||||
headers: {
|
||||
aheader: 'a value',
|
||||
},
|
||||
},
|
||||
secrets: {},
|
||||
config,
|
||||
secrets,
|
||||
params: { body: 'some data' },
|
||||
});
|
||||
|
||||
|
|
|
@ -17,11 +17,23 @@ import { ActionsConfigurationUtilities } from '../actions_config';
|
|||
import { Logger } from '../../../../../src/core/server';
|
||||
|
||||
// config definition
|
||||
enum WebhookMethods {
|
||||
export enum WebhookMethods {
|
||||
POST = 'post',
|
||||
PUT = 'put',
|
||||
}
|
||||
|
||||
export type WebhookActionType = ActionType<
|
||||
ActionTypeConfigType,
|
||||
ActionTypeSecretsType,
|
||||
ActionParamsType,
|
||||
unknown
|
||||
>;
|
||||
export type WebhookActionTypeExecutorOptions = ActionTypeExecutorOptions<
|
||||
ActionTypeConfigType,
|
||||
ActionTypeSecretsType,
|
||||
ActionParamsType
|
||||
>;
|
||||
|
||||
const HeadersSchema = schema.recordOf(schema.string(), schema.string());
|
||||
const configSchemaProps = {
|
||||
url: schema.string(),
|
||||
|
@ -31,7 +43,7 @@ const configSchemaProps = {
|
|||
headers: nullableType(HeadersSchema),
|
||||
};
|
||||
const ConfigSchema = schema.object(configSchemaProps);
|
||||
type ActionTypeConfigType = TypeOf<typeof ConfigSchema>;
|
||||
export type ActionTypeConfigType = TypeOf<typeof ConfigSchema>;
|
||||
|
||||
// secrets definition
|
||||
export type ActionTypeSecretsType = TypeOf<typeof SecretsSchema>;
|
||||
|
@ -51,7 +63,7 @@ const SecretsSchema = schema.object(secretSchemaProps, {
|
|||
});
|
||||
|
||||
// params definition
|
||||
type ActionParamsType = TypeOf<typeof ParamsSchema>;
|
||||
export type ActionParamsType = TypeOf<typeof ParamsSchema>;
|
||||
const ParamsSchema = schema.object({
|
||||
body: schema.maybe(schema.string()),
|
||||
});
|
||||
|
@ -63,7 +75,7 @@ export function getActionType({
|
|||
}: {
|
||||
logger: Logger;
|
||||
configurationUtilities: ActionsConfigurationUtilities;
|
||||
}): ActionType {
|
||||
}): WebhookActionType {
|
||||
return {
|
||||
id: '.webhook',
|
||||
minimumLicenseRequired: 'gold',
|
||||
|
@ -112,13 +124,13 @@ function validateActionTypeConfig(
|
|||
// action executor
|
||||
export async function executor(
|
||||
{ logger }: { logger: Logger },
|
||||
execOptions: ActionTypeExecutorOptions
|
||||
): Promise<ActionTypeExecutorResult> {
|
||||
execOptions: WebhookActionTypeExecutorOptions
|
||||
): Promise<ActionTypeExecutorResult<unknown>> {
|
||||
const actionId = execOptions.actionId;
|
||||
const { method, url, headers = {} } = execOptions.config as ActionTypeConfigType;
|
||||
const { body: data } = execOptions.params as ActionParamsType;
|
||||
const { method, url, headers = {} } = execOptions.config;
|
||||
const { body: data } = execOptions.params;
|
||||
|
||||
const secrets: ActionTypeSecretsType = execOptions.secrets as ActionTypeSecretsType;
|
||||
const secrets: ActionTypeSecretsType = execOptions.secrets;
|
||||
const basicAuth =
|
||||
isString(secrets.user) && isString(secrets.password)
|
||||
? { auth: { username: secrets.user, password: secrets.password } }
|
||||
|
@ -172,11 +184,14 @@ export async function executor(
|
|||
}
|
||||
|
||||
// Action Executor Result w/ internationalisation
|
||||
function successResult(actionId: string, data: unknown): ActionTypeExecutorResult {
|
||||
function successResult(actionId: string, data: unknown): ActionTypeExecutorResult<unknown> {
|
||||
return { status: 'ok', data, actionId };
|
||||
}
|
||||
|
||||
function errorResultInvalid(actionId: string, serviceMessage: string): ActionTypeExecutorResult {
|
||||
function errorResultInvalid(
|
||||
actionId: string,
|
||||
serviceMessage: string
|
||||
): ActionTypeExecutorResult<void> {
|
||||
const errMessage = i18n.translate('xpack.actions.builtin.webhook.invalidResponseErrorMessage', {
|
||||
defaultMessage: 'error calling webhook, invalid response',
|
||||
});
|
||||
|
@ -188,7 +203,7 @@ function errorResultInvalid(actionId: string, serviceMessage: string): ActionTyp
|
|||
};
|
||||
}
|
||||
|
||||
function errorResultUnexpectedError(actionId: string): ActionTypeExecutorResult {
|
||||
function errorResultUnexpectedError(actionId: string): ActionTypeExecutorResult<void> {
|
||||
const errMessage = i18n.translate('xpack.actions.builtin.webhook.unreachableErrorMessage', {
|
||||
defaultMessage: 'error calling webhook, unexpected error',
|
||||
});
|
||||
|
@ -199,7 +214,7 @@ function errorResultUnexpectedError(actionId: string): ActionTypeExecutorResult
|
|||
};
|
||||
}
|
||||
|
||||
function retryResult(actionId: string, serviceMessage: string): ActionTypeExecutorResult {
|
||||
function retryResult(actionId: string, serviceMessage: string): ActionTypeExecutorResult<void> {
|
||||
const errMessage = i18n.translate(
|
||||
'xpack.actions.builtin.webhook.invalidResponseRetryLaterErrorMessage',
|
||||
{
|
||||
|
@ -220,7 +235,7 @@ function retryResultSeconds(
|
|||
serviceMessage: string,
|
||||
|
||||
retryAfter: number
|
||||
): ActionTypeExecutorResult {
|
||||
): ActionTypeExecutorResult<void> {
|
||||
const retryEpoch = Date.now() + retryAfter * 1000;
|
||||
const retry = new Date(retryEpoch);
|
||||
const retryString = retry.toISOString();
|
||||
|
|
|
@ -59,7 +59,7 @@ export class ActionExecutor {
|
|||
actionId,
|
||||
params,
|
||||
request,
|
||||
}: ExecuteOptions): Promise<ActionTypeExecutorResult> {
|
||||
}: ExecuteOptions): Promise<ActionTypeExecutorResult<unknown>> {
|
||||
if (!this.isInitialized) {
|
||||
throw new Error('ActionExecutor not initialized');
|
||||
}
|
||||
|
@ -125,7 +125,7 @@ export class ActionExecutor {
|
|||
};
|
||||
|
||||
eventLogger.startTiming(event);
|
||||
let rawResult: ActionTypeExecutorResult | null | undefined | void;
|
||||
let rawResult: ActionTypeExecutorResult<unknown>;
|
||||
try {
|
||||
rawResult = await actionType.executor({
|
||||
actionId,
|
||||
|
@ -173,7 +173,7 @@ export class ActionExecutor {
|
|||
}
|
||||
}
|
||||
|
||||
function actionErrorToMessage(result: ActionTypeExecutorResult): string {
|
||||
function actionErrorToMessage(result: ActionTypeExecutorResult<unknown>): string {
|
||||
let message = result.message || 'unknown error running action';
|
||||
|
||||
if (result.serviceMessage) {
|
||||
|
|
|
@ -59,7 +59,9 @@ describe('isLicenseValidForActionType', () => {
|
|||
id: 'foo',
|
||||
name: 'Foo',
|
||||
minimumLicenseRequired: 'gold',
|
||||
executor: async () => {},
|
||||
executor: async (options) => {
|
||||
return { status: 'ok', actionId: options.actionId };
|
||||
},
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
|
@ -120,7 +122,9 @@ describe('ensureLicenseForActionType()', () => {
|
|||
id: 'foo',
|
||||
name: 'Foo',
|
||||
minimumLicenseRequired: 'gold',
|
||||
executor: async () => {},
|
||||
executor: async (options) => {
|
||||
return { status: 'ok', actionId: options.actionId };
|
||||
},
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
|
|
|
@ -94,7 +94,7 @@ export class TaskRunnerFactory {
|
|||
},
|
||||
} as unknown) as KibanaRequest;
|
||||
|
||||
let executorResult: ActionTypeExecutorResult;
|
||||
let executorResult: ActionTypeExecutorResult<unknown>;
|
||||
try {
|
||||
executorResult = await actionExecutor.execute({
|
||||
params,
|
||||
|
|
|
@ -9,7 +9,7 @@ import { schema } from '@kbn/config-schema';
|
|||
import { validateParams, validateConfig, validateSecrets } from './validate_with_schema';
|
||||
import { ActionType, ExecutorType } from '../types';
|
||||
|
||||
const executor: ExecutorType = async (options) => {
|
||||
const executor: ExecutorType<{}, {}, {}, void> = async (options) => {
|
||||
return { status: 'ok', actionId: options.actionId };
|
||||
};
|
||||
|
||||
|
|
|
@ -5,24 +5,44 @@
|
|||
*/
|
||||
|
||||
import Boom from 'boom';
|
||||
import { ActionType } from '../types';
|
||||
import { ActionType, ActionTypeConfig, ActionTypeSecrets, ActionTypeParams } from '../types';
|
||||
|
||||
export function validateParams(actionType: ActionType, value: unknown) {
|
||||
export function validateParams<
|
||||
Config extends ActionTypeConfig = ActionTypeConfig,
|
||||
Secrets extends ActionTypeSecrets = ActionTypeSecrets,
|
||||
Params extends ActionTypeParams = ActionTypeParams,
|
||||
ExecutorResultData = void
|
||||
>(actionType: ActionType<Config, Secrets, Params, ExecutorResultData>, value: unknown) {
|
||||
return validateWithSchema(actionType, 'params', value);
|
||||
}
|
||||
|
||||
export function validateConfig(actionType: ActionType, value: unknown) {
|
||||
export function validateConfig<
|
||||
Config extends ActionTypeConfig = ActionTypeConfig,
|
||||
Secrets extends ActionTypeSecrets = ActionTypeSecrets,
|
||||
Params extends ActionTypeParams = ActionTypeParams,
|
||||
ExecutorResultData = void
|
||||
>(actionType: ActionType<Config, Secrets, Params, ExecutorResultData>, value: unknown) {
|
||||
return validateWithSchema(actionType, 'config', value);
|
||||
}
|
||||
|
||||
export function validateSecrets(actionType: ActionType, value: unknown) {
|
||||
export function validateSecrets<
|
||||
Config extends ActionTypeConfig = ActionTypeConfig,
|
||||
Secrets extends ActionTypeSecrets = ActionTypeSecrets,
|
||||
Params extends ActionTypeParams = ActionTypeParams,
|
||||
ExecutorResultData = void
|
||||
>(actionType: ActionType<Config, Secrets, Params, ExecutorResultData>, value: unknown) {
|
||||
return validateWithSchema(actionType, 'secrets', value);
|
||||
}
|
||||
|
||||
type ValidKeys = 'params' | 'config' | 'secrets';
|
||||
|
||||
function validateWithSchema(
|
||||
actionType: ActionType,
|
||||
function validateWithSchema<
|
||||
Config extends ActionTypeConfig = ActionTypeConfig,
|
||||
Secrets extends ActionTypeSecrets = ActionTypeSecrets,
|
||||
Params extends ActionTypeParams = ActionTypeParams,
|
||||
ExecutorResultData = void
|
||||
>(
|
||||
actionType: ActionType<Config, Secrets, Params, ExecutorResultData>,
|
||||
key: ValidKeys,
|
||||
value: unknown
|
||||
): Record<string, unknown> {
|
||||
|
|
|
@ -125,7 +125,9 @@ describe('Actions Plugin', () => {
|
|||
id: 'test',
|
||||
name: 'test',
|
||||
minimumLicenseRequired: 'basic',
|
||||
async executor() {},
|
||||
async executor(options) {
|
||||
return { status: 'ok', actionId: options.actionId };
|
||||
},
|
||||
};
|
||||
|
||||
beforeEach(async () => {
|
||||
|
|
|
@ -33,13 +33,20 @@ import { PluginSetupContract as FeaturesPluginSetup } from '../../features/serve
|
|||
import { SecurityPluginSetup } from '../../security/server';
|
||||
|
||||
import { ActionsConfig } from './config';
|
||||
import { Services, ActionType, PreConfiguredAction } from './types';
|
||||
import { ActionExecutor, TaskRunnerFactory, LicenseState, ILicenseState } from './lib';
|
||||
import { ActionsClient } from './actions_client';
|
||||
import { ActionTypeRegistry } from './action_type_registry';
|
||||
import { createExecutionEnqueuerFunction } from './create_execute_function';
|
||||
import { registerBuiltInActionTypes } from './builtin_action_types';
|
||||
import { registerActionsUsageCollector } from './usage';
|
||||
import {
|
||||
Services,
|
||||
ActionType,
|
||||
PreConfiguredAction,
|
||||
ActionTypeConfig,
|
||||
ActionTypeSecrets,
|
||||
ActionTypeParams,
|
||||
} from './types';
|
||||
|
||||
import { getActionsConfigurationUtilities } from './actions_config';
|
||||
|
||||
|
@ -70,7 +77,13 @@ export const EVENT_LOG_ACTIONS = {
|
|||
};
|
||||
|
||||
export interface PluginSetupContract {
|
||||
registerType: (actionType: ActionType) => void;
|
||||
registerType<
|
||||
Config extends ActionTypeConfig = ActionTypeConfig,
|
||||
Secrets extends ActionTypeSecrets = ActionTypeSecrets,
|
||||
Params extends ActionTypeParams = ActionTypeParams
|
||||
>(
|
||||
actionType: ActionType<Config, Secrets, Params>
|
||||
): void;
|
||||
}
|
||||
|
||||
export interface PluginStartContract {
|
||||
|
@ -219,7 +232,13 @@ export class ActionsPlugin implements Plugin<Promise<PluginSetupContract>, Plugi
|
|||
executeActionRoute(router, this.licenseState);
|
||||
|
||||
return {
|
||||
registerType: (actionType: ActionType) => {
|
||||
registerType: <
|
||||
Config extends ActionTypeConfig = ActionTypeConfig,
|
||||
Secrets extends ActionTypeSecrets = ActionTypeSecrets,
|
||||
Params extends ActionTypeParams = ActionTypeParams
|
||||
>(
|
||||
actionType: ActionType<Config, Secrets, Params>
|
||||
) => {
|
||||
if (!(actionType.minimumLicenseRequired in LICENSE_TYPE)) {
|
||||
throw new Error(`"${actionType.minimumLicenseRequired}" is not a valid license type`);
|
||||
}
|
||||
|
|
|
@ -71,7 +71,9 @@ describe('executeActionRoute', () => {
|
|||
const router = httpServiceMock.createRouter();
|
||||
|
||||
const actionsClient = actionsClientMock.create();
|
||||
actionsClient.execute.mockResolvedValueOnce((null as unknown) as ActionTypeExecutorResult);
|
||||
actionsClient.execute.mockResolvedValueOnce(
|
||||
(null as unknown) as ActionTypeExecutorResult<void>
|
||||
);
|
||||
|
||||
const [context, req, res] = mockHandlerArguments(
|
||||
{ actionsClient },
|
||||
|
|
|
@ -48,7 +48,7 @@ export const executeActionRoute = (router: IRouter, licenseState: ILicenseState)
|
|||
const { params } = req.body;
|
||||
const { id } = req.params;
|
||||
try {
|
||||
const body: ActionTypeExecutorResult = await actionsClient.execute({
|
||||
const body: ActionTypeExecutorResult<unknown> = await actionsClient.execute({
|
||||
params,
|
||||
actionId: id,
|
||||
});
|
||||
|
|
|
@ -21,6 +21,9 @@ export type GetServicesFunction = (request: KibanaRequest) => Services;
|
|||
export type ActionTypeRegistryContract = PublicMethodsOf<ActionTypeRegistry>;
|
||||
export type GetBasePathFunction = (spaceId?: string) => string;
|
||||
export type SpaceIdToNamespaceFunction = (spaceId?: string) => string | undefined;
|
||||
export type ActionTypeConfig = Record<string, unknown>;
|
||||
export type ActionTypeSecrets = Record<string, unknown>;
|
||||
export type ActionTypeParams = Record<string, unknown>;
|
||||
|
||||
export interface Services {
|
||||
callCluster: ILegacyScopedClusterClient['callAsCurrentUser'];
|
||||
|
@ -49,32 +52,27 @@ export interface ActionsConfigType {
|
|||
}
|
||||
|
||||
// the parameters passed to an action type executor function
|
||||
export interface ActionTypeExecutorOptions {
|
||||
export interface ActionTypeExecutorOptions<Config, Secrets, Params> {
|
||||
actionId: string;
|
||||
services: Services;
|
||||
// This will have to remain `any` until we can extend Action Executors with generics
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
config: Record<string, any>;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
secrets: Record<string, any>;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
params: Record<string, any>;
|
||||
config: Config;
|
||||
secrets: Secrets;
|
||||
params: Params;
|
||||
}
|
||||
|
||||
export interface ActionResult {
|
||||
export interface ActionResult<Config extends ActionTypeConfig = ActionTypeConfig> {
|
||||
id: string;
|
||||
actionTypeId: string;
|
||||
name: string;
|
||||
// This will have to remain `any` until we can extend Action Executors with generics
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
config?: Record<string, any>;
|
||||
config?: Config;
|
||||
isPreconfigured: boolean;
|
||||
}
|
||||
|
||||
export interface PreConfiguredAction extends ActionResult {
|
||||
// This will have to remain `any` until we can extend Action Executors with generics
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
secrets: Record<string, any>;
|
||||
export interface PreConfiguredAction<
|
||||
Config extends ActionTypeConfig = ActionTypeConfig,
|
||||
Secrets extends ActionTypeSecrets = ActionTypeSecrets
|
||||
> extends ActionResult<Config> {
|
||||
secrets: Secrets;
|
||||
}
|
||||
|
||||
export interface FindActionResult extends ActionResult {
|
||||
|
@ -82,38 +80,45 @@ export interface FindActionResult extends ActionResult {
|
|||
}
|
||||
|
||||
// the result returned from an action type executor function
|
||||
export interface ActionTypeExecutorResult {
|
||||
export interface ActionTypeExecutorResult<Data> {
|
||||
actionId: string;
|
||||
status: 'ok' | 'error';
|
||||
message?: string;
|
||||
serviceMessage?: string;
|
||||
// This will have to remain `any` until we can extend Action Executors with generics
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
data?: any;
|
||||
data?: Data;
|
||||
retry?: null | boolean | Date;
|
||||
}
|
||||
|
||||
// signature of the action type executor function
|
||||
export type ExecutorType = (
|
||||
options: ActionTypeExecutorOptions
|
||||
) => Promise<ActionTypeExecutorResult | null | undefined | void>;
|
||||
export type ExecutorType<Config, Secrets, Params, ResultData> = (
|
||||
options: ActionTypeExecutorOptions<Config, Secrets, Params>
|
||||
) => Promise<ActionTypeExecutorResult<ResultData>>;
|
||||
|
||||
interface ValidatorType {
|
||||
validate(value: unknown): Record<string, unknown>;
|
||||
interface ValidatorType<Type> {
|
||||
validate(value: unknown): Type;
|
||||
}
|
||||
|
||||
export type ActionTypeCreator = (config?: ActionsConfigType) => ActionType;
|
||||
export interface ActionType {
|
||||
export interface ActionValidationService {
|
||||
isWhitelistedHostname(hostname: string): boolean;
|
||||
isWhitelistedUri(uri: string): boolean;
|
||||
}
|
||||
|
||||
export interface ActionType<
|
||||
Config extends ActionTypeConfig = ActionTypeConfig,
|
||||
Secrets extends ActionTypeSecrets = ActionTypeSecrets,
|
||||
Params extends ActionTypeParams = ActionTypeParams,
|
||||
ExecutorResultData = void
|
||||
> {
|
||||
id: string;
|
||||
name: string;
|
||||
maxAttempts?: number;
|
||||
minimumLicenseRequired: LicenseType;
|
||||
validate?: {
|
||||
params?: ValidatorType;
|
||||
config?: ValidatorType;
|
||||
secrets?: ValidatorType;
|
||||
params?: ValidatorType<Params>;
|
||||
config?: ValidatorType<Config>;
|
||||
secrets?: ValidatorType<Secrets>;
|
||||
};
|
||||
executor: ExecutorType;
|
||||
executor: ExecutorType<Config, Secrets, Params, ExecutorResultData>;
|
||||
}
|
||||
|
||||
export interface RawAction extends SavedObjectAttributes {
|
||||
|
|
|
@ -241,16 +241,15 @@ export const pushToService = async (
|
|||
casePushParams: ServiceConnectorCaseParams,
|
||||
signal: AbortSignal
|
||||
): Promise<ServiceConnectorCaseResponse> => {
|
||||
const response = await KibanaServices.get().http.fetch<ActionTypeExecutorResult>(
|
||||
`${ACTION_URL}/action/${connectorId}/_execute`,
|
||||
{
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
params: { subAction: 'pushToService', subActionParams: casePushParams },
|
||||
}),
|
||||
signal,
|
||||
}
|
||||
);
|
||||
const response = await KibanaServices.get().http.fetch<
|
||||
ActionTypeExecutorResult<ReturnType<typeof decodeServiceConnectorCaseResponse>>
|
||||
>(`${ACTION_URL}/action/${connectorId}/_execute`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
params: { subAction: 'pushToService', subActionParams: casePushParams },
|
||||
}),
|
||||
signal,
|
||||
});
|
||||
|
||||
if (response.status === 'error') {
|
||||
throw new Error(response.serviceMessage ?? response.message ?? i18n.ERROR_PUSH_TO_SERVICE);
|
||||
|
|
|
@ -5,16 +5,14 @@
|
|||
*/
|
||||
|
||||
import { CoreSetup } from 'src/core/server';
|
||||
import { schema } from '@kbn/config-schema';
|
||||
import { schema, TypeOf } from '@kbn/config-schema';
|
||||
import { FixtureStartDeps, FixtureSetupDeps } from './plugin';
|
||||
import { ActionType, ActionTypeExecutorOptions } from '../../../../../../../plugins/actions/server';
|
||||
import { ActionType } from '../../../../../../../plugins/actions/server';
|
||||
|
||||
export function defineActionTypes(
|
||||
core: CoreSetup<FixtureStartDeps>,
|
||||
{ actions }: Pick<FixtureSetupDeps, 'actions'>
|
||||
) {
|
||||
const clusterClient = core.elasticsearch.legacy.client;
|
||||
|
||||
// Action types
|
||||
const noopActionType: ActionType = {
|
||||
id: 'test.noop',
|
||||
|
@ -32,24 +30,39 @@ export function defineActionTypes(
|
|||
throw new Error('this action is intended to fail');
|
||||
},
|
||||
};
|
||||
const indexRecordActionType: ActionType = {
|
||||
actions.registerType(noopActionType);
|
||||
actions.registerType(throwActionType);
|
||||
actions.registerType(getIndexRecordActionType());
|
||||
actions.registerType(getFailingActionType());
|
||||
actions.registerType(getRateLimitedActionType());
|
||||
actions.registerType(getAuthorizationActionType(core));
|
||||
}
|
||||
|
||||
function getIndexRecordActionType() {
|
||||
const paramsSchema = schema.object({
|
||||
index: schema.string(),
|
||||
reference: schema.string(),
|
||||
message: schema.string(),
|
||||
});
|
||||
type ParamsType = TypeOf<typeof paramsSchema>;
|
||||
const configSchema = schema.object({
|
||||
unencrypted: schema.string(),
|
||||
});
|
||||
type ConfigType = TypeOf<typeof configSchema>;
|
||||
const secretsSchema = schema.object({
|
||||
encrypted: schema.string(),
|
||||
});
|
||||
type SecretsType = TypeOf<typeof secretsSchema>;
|
||||
const result: ActionType<ConfigType, SecretsType, ParamsType> = {
|
||||
id: 'test.index-record',
|
||||
name: 'Test: Index Record',
|
||||
minimumLicenseRequired: 'gold',
|
||||
validate: {
|
||||
params: schema.object({
|
||||
index: schema.string(),
|
||||
reference: schema.string(),
|
||||
message: schema.string(),
|
||||
}),
|
||||
config: schema.object({
|
||||
unencrypted: schema.string(),
|
||||
}),
|
||||
secrets: schema.object({
|
||||
encrypted: schema.string(),
|
||||
}),
|
||||
params: paramsSchema,
|
||||
config: configSchema,
|
||||
secrets: secretsSchema,
|
||||
},
|
||||
async executor({ config, secrets, params, services, actionId }: ActionTypeExecutorOptions) {
|
||||
async executor({ config, secrets, params, services, actionId }) {
|
||||
await services.callCluster('index', {
|
||||
index: params.index,
|
||||
refresh: 'wait_for',
|
||||
|
@ -64,17 +77,23 @@ export function defineActionTypes(
|
|||
return { status: 'ok', actionId };
|
||||
},
|
||||
};
|
||||
const failingActionType: ActionType = {
|
||||
return result;
|
||||
}
|
||||
|
||||
function getFailingActionType() {
|
||||
const paramsSchema = schema.object({
|
||||
index: schema.string(),
|
||||
reference: schema.string(),
|
||||
});
|
||||
type ParamsType = TypeOf<typeof paramsSchema>;
|
||||
const result: ActionType<{}, {}, ParamsType> = {
|
||||
id: 'test.failing',
|
||||
name: 'Test: Failing',
|
||||
minimumLicenseRequired: 'gold',
|
||||
validate: {
|
||||
params: schema.object({
|
||||
index: schema.string(),
|
||||
reference: schema.string(),
|
||||
}),
|
||||
params: paramsSchema,
|
||||
},
|
||||
async executor({ config, secrets, params, services }: ActionTypeExecutorOptions) {
|
||||
async executor({ config, secrets, params, services }) {
|
||||
await services.callCluster('index', {
|
||||
index: params.index,
|
||||
refresh: 'wait_for',
|
||||
|
@ -89,19 +108,25 @@ export function defineActionTypes(
|
|||
throw new Error(`expected failure for ${params.index} ${params.reference}`);
|
||||
},
|
||||
};
|
||||
const rateLimitedActionType: ActionType = {
|
||||
return result;
|
||||
}
|
||||
|
||||
function getRateLimitedActionType() {
|
||||
const paramsSchema = schema.object({
|
||||
index: schema.string(),
|
||||
reference: schema.string(),
|
||||
retryAt: schema.number(),
|
||||
});
|
||||
type ParamsType = TypeOf<typeof paramsSchema>;
|
||||
const result: ActionType<{}, {}, ParamsType> = {
|
||||
id: 'test.rate-limit',
|
||||
name: 'Test: Rate Limit',
|
||||
minimumLicenseRequired: 'gold',
|
||||
maxAttempts: 2,
|
||||
validate: {
|
||||
params: schema.object({
|
||||
index: schema.string(),
|
||||
reference: schema.string(),
|
||||
retryAt: schema.number(),
|
||||
}),
|
||||
params: paramsSchema,
|
||||
},
|
||||
async executor({ config, params, services }: ActionTypeExecutorOptions) {
|
||||
async executor({ config, params, services }) {
|
||||
await services.callCluster('index', {
|
||||
index: params.index,
|
||||
refresh: 'wait_for',
|
||||
|
@ -119,20 +144,27 @@ export function defineActionTypes(
|
|||
};
|
||||
},
|
||||
};
|
||||
const authorizationActionType: ActionType = {
|
||||
return result;
|
||||
}
|
||||
|
||||
function getAuthorizationActionType(core: CoreSetup<FixtureStartDeps>) {
|
||||
const clusterClient = core.elasticsearch.legacy.client;
|
||||
const paramsSchema = schema.object({
|
||||
callClusterAuthorizationIndex: schema.string(),
|
||||
savedObjectsClientType: schema.string(),
|
||||
savedObjectsClientId: schema.string(),
|
||||
index: schema.string(),
|
||||
reference: schema.string(),
|
||||
});
|
||||
type ParamsType = TypeOf<typeof paramsSchema>;
|
||||
const result: ActionType<{}, {}, ParamsType> = {
|
||||
id: 'test.authorization',
|
||||
name: 'Test: Authorization',
|
||||
minimumLicenseRequired: 'gold',
|
||||
validate: {
|
||||
params: schema.object({
|
||||
callClusterAuthorizationIndex: schema.string(),
|
||||
savedObjectsClientType: schema.string(),
|
||||
savedObjectsClientId: schema.string(),
|
||||
index: schema.string(),
|
||||
reference: schema.string(),
|
||||
}),
|
||||
params: paramsSchema,
|
||||
},
|
||||
async executor({ params, services, actionId }: ActionTypeExecutorOptions) {
|
||||
async executor({ params, services, actionId }) {
|
||||
// Call cluster
|
||||
let callClusterSuccess = false;
|
||||
let callClusterError;
|
||||
|
@ -200,10 +232,5 @@ export function defineActionTypes(
|
|||
};
|
||||
},
|
||||
};
|
||||
actions.registerType(noopActionType);
|
||||
actions.registerType(throwActionType);
|
||||
actions.registerType(indexRecordActionType);
|
||||
actions.registerType(failingActionType);
|
||||
actions.registerType(rateLimitedActionType);
|
||||
actions.registerType(authorizationActionType);
|
||||
return result;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue