diff --git a/x-pack/legacy/plugins/actions/README.md b/x-pack/legacy/plugins/actions/README.md
index 3ac4741b6f061..f17456d6ea393 100644
--- a/x-pack/legacy/plugins/actions/README.md
+++ b/x-pack/legacy/plugins/actions/README.md
@@ -145,8 +145,7 @@ The following table describes the properties of the `options` object.
|---|---|---|
|id|The id of the action you want to fire.|string|
|params|The `params` value to give the action type executor.|object|
-|namespace|The saved object namespace the action exists within.|string|
-|basePath|This is a temporary parameter, but we need to capture and track the value of `request.getBasePath()` until future changes are made.
In most cases this can be `undefined` unless you need cross spaces support.|string|
+|spaceId|The space id the action is within.|string|
### Example
@@ -155,14 +154,13 @@ This example makes action `3c5b2bd4-5424-4e4b-8cf5-c0a58c762cc5` fire an email.
```
server.plugins.actions.fire({
id: '3c5b2bd4-5424-4e4b-8cf5-c0a58c762cc5',
+ spaceId: 'default', // The spaceId of the action
params: {
from: 'example@elastic.co',
to: ['destination@elastic.co'],
subject: 'My email subject',
body: 'My email body',
},
- namespace: undefined, // The namespace the action exists within
- basePath: undefined, // Usually `request.getBasePath();` or `undefined`
});
```
diff --git a/x-pack/legacy/plugins/actions/server/action_type_registry.test.ts b/x-pack/legacy/plugins/actions/server/action_type_registry.test.ts
index 7e181ff1ca4ef..dcb8b8b299d1a 100644
--- a/x-pack/legacy/plugins/actions/server/action_type_registry.test.ts
+++ b/x-pack/legacy/plugins/actions/server/action_type_registry.test.ts
@@ -28,6 +28,8 @@ const actionTypeRegistryParams = {
getServices,
taskManager: mockTaskManager,
encryptedSavedObjectsPlugin: encryptedSavedObjectsMock.create(),
+ spaceIdToNamespace: jest.fn().mockReturnValue(undefined),
+ getBasePath: jest.fn().mockReturnValue(undefined),
};
beforeEach(() => jest.resetAllMocks());
diff --git a/x-pack/legacy/plugins/actions/server/action_type_registry.ts b/x-pack/legacy/plugins/actions/server/action_type_registry.ts
index 72ba36c402bf9..635d618878260 100644
--- a/x-pack/legacy/plugins/actions/server/action_type_registry.ts
+++ b/x-pack/legacy/plugins/actions/server/action_type_registry.ts
@@ -10,28 +10,35 @@ import { ActionType, GetServicesFunction } from './types';
import { TaskManager, TaskRunCreatorFunction } from '../../task_manager';
import { getCreateTaskRunnerFunction, ExecutorError } from './lib';
import { EncryptedSavedObjectsPlugin } from '../../encrypted_saved_objects';
+import { SpacesPlugin } from '../../spaces';
interface ConstructorOptions {
taskManager: TaskManager;
getServices: GetServicesFunction;
encryptedSavedObjectsPlugin: EncryptedSavedObjectsPlugin;
+ spaceIdToNamespace: SpacesPlugin['spaceIdToNamespace'];
+ getBasePath: SpacesPlugin['getBasePath'];
}
export class ActionTypeRegistry {
private readonly taskRunCreatorFunction: TaskRunCreatorFunction;
- private readonly getServices: GetServicesFunction;
private readonly taskManager: TaskManager;
private readonly actionTypes: Map = new Map();
- private readonly encryptedSavedObjectsPlugin: EncryptedSavedObjectsPlugin;
- constructor({ getServices, taskManager, encryptedSavedObjectsPlugin }: ConstructorOptions) {
- this.getServices = getServices;
+ constructor({
+ getServices,
+ taskManager,
+ encryptedSavedObjectsPlugin,
+ spaceIdToNamespace,
+ getBasePath,
+ }: ConstructorOptions) {
this.taskManager = taskManager;
- this.encryptedSavedObjectsPlugin = encryptedSavedObjectsPlugin;
this.taskRunCreatorFunction = getCreateTaskRunnerFunction({
+ getServices,
actionTypeRegistry: this,
- getServices: this.getServices,
- encryptedSavedObjectsPlugin: this.encryptedSavedObjectsPlugin,
+ encryptedSavedObjectsPlugin,
+ spaceIdToNamespace,
+ getBasePath,
});
}
diff --git a/x-pack/legacy/plugins/actions/server/actions_client.test.ts b/x-pack/legacy/plugins/actions/server/actions_client.test.ts
index 25a26f2093267..d724c28d72ea5 100644
--- a/x-pack/legacy/plugins/actions/server/actions_client.test.ts
+++ b/x-pack/legacy/plugins/actions/server/actions_client.test.ts
@@ -10,16 +10,14 @@ import { ActionTypeRegistry } from './action_type_registry';
import { ActionsClient } from './actions_client';
import { ExecutorType } from './types';
import { taskManagerMock } from '../../task_manager/task_manager.mock';
-import { EncryptedSavedObjectsPlugin } from '../../encrypted_saved_objects';
import { SavedObjectsClientMock } from '../../../../../src/core/server/mocks';
+import { encryptedSavedObjectsMock } from '../../encrypted_saved_objects/server/plugin.mock';
const savedObjectsClient = SavedObjectsClientMock.create();
const mockTaskManager = taskManagerMock.create();
-const mockEncryptedSavedObjectsPlugin = {
- getDecryptedAsInternalUser: jest.fn() as EncryptedSavedObjectsPlugin['getDecryptedAsInternalUser'],
-} as EncryptedSavedObjectsPlugin;
+const mockEncryptedSavedObjectsPlugin = encryptedSavedObjectsMock.create();
function getServices() {
return {
@@ -33,6 +31,8 @@ const actionTypeRegistryParams = {
getServices,
taskManager: mockTaskManager,
encryptedSavedObjectsPlugin: mockEncryptedSavedObjectsPlugin,
+ spaceIdToNamespace: jest.fn().mockReturnValue(undefined),
+ getBasePath: jest.fn().mockReturnValue(undefined),
};
const executor: ExecutorType = async options => {
diff --git a/x-pack/legacy/plugins/actions/server/builtin_action_types/email.test.ts b/x-pack/legacy/plugins/actions/server/builtin_action_types/email.test.ts
index a8416f469ce1c..7ebb1ff943750 100644
--- a/x-pack/legacy/plugins/actions/server/builtin_action_types/email.test.ts
+++ b/x-pack/legacy/plugins/actions/server/builtin_action_types/email.test.ts
@@ -43,6 +43,8 @@ beforeAll(() => {
getServices,
taskManager: taskManagerMock.create(),
encryptedSavedObjectsPlugin: mockEncryptedSavedObjectsPlugin,
+ spaceIdToNamespace: jest.fn().mockReturnValue(undefined),
+ getBasePath: jest.fn().mockReturnValue(undefined),
});
registerBuiltInActionTypes(actionTypeRegistry);
diff --git a/x-pack/legacy/plugins/actions/server/builtin_action_types/es_index.test.ts b/x-pack/legacy/plugins/actions/server/builtin_action_types/es_index.test.ts
index 03829815c0bdf..301f6613bcfa6 100644
--- a/x-pack/legacy/plugins/actions/server/builtin_action_types/es_index.test.ts
+++ b/x-pack/legacy/plugins/actions/server/builtin_action_types/es_index.test.ts
@@ -40,6 +40,8 @@ beforeAll(() => {
getServices,
taskManager: taskManagerMock.create(),
encryptedSavedObjectsPlugin: mockEncryptedSavedObjectsPlugin,
+ spaceIdToNamespace: jest.fn().mockReturnValue(undefined),
+ getBasePath: jest.fn().mockReturnValue(undefined),
});
registerBuiltInActionTypes(actionTypeRegistry);
diff --git a/x-pack/legacy/plugins/actions/server/builtin_action_types/server_log.test.ts b/x-pack/legacy/plugins/actions/server/builtin_action_types/server_log.test.ts
index a852752784a3c..ef38c5b910627 100644
--- a/x-pack/legacy/plugins/actions/server/builtin_action_types/server_log.test.ts
+++ b/x-pack/legacy/plugins/actions/server/builtin_action_types/server_log.test.ts
@@ -35,6 +35,8 @@ beforeAll(() => {
getServices,
taskManager: taskManagerMock.create(),
encryptedSavedObjectsPlugin: mockEncryptedSavedObjectsPlugin,
+ spaceIdToNamespace: jest.fn().mockReturnValue(undefined),
+ getBasePath: jest.fn().mockReturnValue(undefined),
});
registerBuiltInActionTypes(actionTypeRegistry);
});
diff --git a/x-pack/legacy/plugins/actions/server/builtin_action_types/slack.test.ts b/x-pack/legacy/plugins/actions/server/builtin_action_types/slack.test.ts
index 71e307721e51a..c2cc2d04d4f37 100644
--- a/x-pack/legacy/plugins/actions/server/builtin_action_types/slack.test.ts
+++ b/x-pack/legacy/plugins/actions/server/builtin_action_types/slack.test.ts
@@ -52,6 +52,8 @@ beforeAll(() => {
getServices,
taskManager: taskManagerMock.create(),
encryptedSavedObjectsPlugin: mockEncryptedSavedObjectsPlugin,
+ spaceIdToNamespace: jest.fn().mockReturnValue(undefined),
+ getBasePath: jest.fn().mockReturnValue(undefined),
});
actionTypeRegistry.register(getActionType({ executor: mockSlackExecutor }));
actionType = actionTypeRegistry.get(ACTION_TYPE_ID);
diff --git a/x-pack/legacy/plugins/actions/server/create_fire_function.test.ts b/x-pack/legacy/plugins/actions/server/create_fire_function.test.ts
index 2f56a7f7a943e..1f286d371e633 100644
--- a/x-pack/legacy/plugins/actions/server/create_fire_function.test.ts
+++ b/x-pack/legacy/plugins/actions/server/create_fire_function.test.ts
@@ -10,6 +10,7 @@ import { SavedObjectsClientMock } from '../../../../../src/core/server/mocks';
const mockTaskManager = taskManagerMock.create();
const savedObjectsClient = SavedObjectsClientMock.create();
+const spaceIdToNamespace = jest.fn();
beforeEach(() => jest.resetAllMocks());
@@ -18,6 +19,7 @@ describe('fire()', () => {
const fireFn = createFireFunction({
taskManager: mockTaskManager,
internalSavedObjectsRepository: savedObjectsClient,
+ spaceIdToNamespace,
});
savedObjectsClient.get.mockResolvedValueOnce({
id: '123',
@@ -27,41 +29,41 @@ describe('fire()', () => {
},
references: [],
});
+ spaceIdToNamespace.mockReturnValueOnce('namespace1');
await fireFn({
id: '123',
params: { baz: false },
- namespace: 'abc',
- basePath: '/s/default',
+ spaceId: 'default',
});
expect(mockTaskManager.schedule).toHaveBeenCalledTimes(1);
expect(mockTaskManager.schedule.mock.calls[0]).toMatchInlineSnapshot(`
-Array [
- Object {
- "params": Object {
- "basePath": "/s/default",
- "id": "123",
- "namespace": "abc",
- "params": Object {
- "baz": false,
- },
- },
- "scope": Array [
- "actions",
- ],
- "state": Object {},
- "taskType": "actions:mock-action",
- },
-]
-`);
+ Array [
+ Object {
+ "params": Object {
+ "id": "123",
+ "params": Object {
+ "baz": false,
+ },
+ "spaceId": "default",
+ },
+ "scope": Array [
+ "actions",
+ ],
+ "state": Object {},
+ "taskType": "actions:mock-action",
+ },
+ ]
+ `);
expect(savedObjectsClient.get).toHaveBeenCalledTimes(1);
expect(savedObjectsClient.get.mock.calls[0]).toMatchInlineSnapshot(`
-Array [
- "action",
- "123",
- Object {
- "namespace": "abc",
- },
-]
-`);
+ Array [
+ "action",
+ "123",
+ Object {
+ "namespace": "namespace1",
+ },
+ ]
+ `);
+ expect(spaceIdToNamespace).toHaveBeenCalledWith('default');
});
});
diff --git a/x-pack/legacy/plugins/actions/server/create_fire_function.ts b/x-pack/legacy/plugins/actions/server/create_fire_function.ts
index a00744aa329c3..0bf11cbf5dd40 100644
--- a/x-pack/legacy/plugins/actions/server/create_fire_function.ts
+++ b/x-pack/legacy/plugins/actions/server/create_fire_function.ts
@@ -6,31 +6,33 @@
import { SavedObjectsClientContract } from 'src/core/server';
import { TaskManager } from '../../task_manager';
+import { SpacesPlugin } from '../../spaces';
interface CreateFireFunctionOptions {
taskManager: TaskManager;
internalSavedObjectsRepository: SavedObjectsClientContract;
+ spaceIdToNamespace: SpacesPlugin['spaceIdToNamespace'];
}
-interface FireOptions {
+export interface FireOptions {
id: string;
params: Record;
- namespace?: string;
- basePath: string;
+ spaceId: string;
}
export function createFireFunction({
taskManager,
internalSavedObjectsRepository,
+ spaceIdToNamespace,
}: CreateFireFunctionOptions) {
- return async function fire({ id, params, namespace, basePath }: FireOptions) {
+ return async function fire({ id, params, spaceId }: FireOptions) {
+ const namespace = spaceIdToNamespace(spaceId);
const actionSavedObject = await internalSavedObjectsRepository.get('action', id, { namespace });
await taskManager.schedule({
taskType: `actions:${actionSavedObject.attributes.actionTypeId}`,
params: {
id,
- basePath,
- namespace,
+ spaceId,
params,
},
state: {},
diff --git a/x-pack/legacy/plugins/actions/server/init.ts b/x-pack/legacy/plugins/actions/server/init.ts
index c046979aca0a9..27cff53bb97d1 100644
--- a/x-pack/legacy/plugins/actions/server/init.ts
+++ b/x-pack/legacy/plugins/actions/server/init.ts
@@ -18,10 +18,19 @@ import {
listActionTypesRoute,
fireRoute,
} from './routes';
-
import { registerBuiltInActionTypes } from './builtin_action_types';
+import { SpacesPlugin } from '../../spaces';
+import { createOptionalPlugin } from '../../../server/lib/optional_plugin';
export function init(server: Legacy.Server) {
+ const config = server.config();
+ const spaces = createOptionalPlugin(
+ config,
+ 'xpack.spaces',
+ server.plugins,
+ 'spaces'
+ );
+
const { callWithInternalUser } = server.plugins.elasticsearch.getCluster('admin');
const savedObjectsRepositoryWithInternalUser = server.savedObjects.getSavedObjectsRepository(
callWithInternalUser
@@ -58,6 +67,14 @@ export function init(server: Legacy.Server) {
getServices,
taskManager: taskManager!,
encryptedSavedObjectsPlugin: server.plugins.encrypted_saved_objects!,
+ getBasePath(...args) {
+ return spaces.isEnabled
+ ? spaces.getBasePath(...args)
+ : server.config().get('server.basePath');
+ },
+ spaceIdToNamespace(...args) {
+ return spaces.isEnabled ? spaces.spaceIdToNamespace(...args) : undefined;
+ },
});
registerBuiltInActionTypes(actionTypeRegistry);
@@ -78,6 +95,9 @@ export function init(server: Legacy.Server) {
const fireFn = createFireFunction({
taskManager: taskManager!,
internalSavedObjectsRepository: savedObjectsRepositoryWithInternalUser,
+ spaceIdToNamespace(...args) {
+ return spaces.isEnabled ? spaces.spaceIdToNamespace(...args) : undefined;
+ },
});
// Expose functions to server
diff --git a/x-pack/legacy/plugins/actions/server/lib/execute.ts b/x-pack/legacy/plugins/actions/server/lib/execute.ts
index 04e4ae156d337..95c4f17dd922e 100644
--- a/x-pack/legacy/plugins/actions/server/lib/execute.ts
+++ b/x-pack/legacy/plugins/actions/server/lib/execute.ts
@@ -10,7 +10,7 @@ import { EncryptedSavedObjectsPlugin } from '../../../encrypted_saved_objects';
interface ExecuteOptions {
actionId: string;
- namespace: string;
+ namespace?: string;
services: Services;
params: Record;
encryptedSavedObjectsPlugin: EncryptedSavedObjectsPlugin;
diff --git a/x-pack/legacy/plugins/actions/server/lib/get_create_task_runner_function.test.ts b/x-pack/legacy/plugins/actions/server/lib/get_create_task_runner_function.test.ts
index e870330e95e2f..4f732afc3ec7f 100644
--- a/x-pack/legacy/plugins/actions/server/lib/get_create_task_runner_function.test.ts
+++ b/x-pack/legacy/plugins/actions/server/lib/get_create_task_runner_function.test.ts
@@ -14,6 +14,7 @@ import { SavedObjectsClientMock } from '../../../../../../src/core/server/mocks'
import { actionTypeRegistryMock } from '../action_type_registry.mock';
import { ExecutorError } from './executor_error';
+const spaceIdToNamespace = jest.fn();
const actionTypeRegistry = actionTypeRegistryMock.create();
const mockedEncryptedSavedObjectsPlugin = encryptedSavedObjectsMock.create();
@@ -34,7 +35,9 @@ const getCreateTaskRunnerFunctionParams = {
};
},
actionTypeRegistry,
+ spaceIdToNamespace,
encryptedSavedObjectsPlugin: mockedEncryptedSavedObjectsPlugin,
+ getBasePath: jest.fn().mockReturnValue(undefined),
};
const taskInstanceMock = {
@@ -43,7 +46,7 @@ const taskInstanceMock = {
params: {
id: '2',
params: { baz: true },
- namespace: 'test',
+ spaceId: 'test',
},
taskType: 'actions:1',
};
@@ -56,12 +59,14 @@ test('executes the task by calling the executor with proper parameters', async (
const runner = createTaskRunner({ taskInstance: taskInstanceMock });
mockExecute.mockResolvedValueOnce({ status: 'ok' });
+ spaceIdToNamespace.mockReturnValueOnce('namespace-test');
const runnerResult = await runner.run();
expect(runnerResult).toBeUndefined();
+ expect(spaceIdToNamespace).toHaveBeenCalledWith('test');
expect(mockExecute).toHaveBeenCalledWith({
- namespace: 'test',
+ namespace: 'namespace-test',
actionId: '2',
actionTypeRegistry,
encryptedSavedObjectsPlugin: mockedEncryptedSavedObjectsPlugin,
diff --git a/x-pack/legacy/plugins/actions/server/lib/get_create_task_runner_function.ts b/x-pack/legacy/plugins/actions/server/lib/get_create_task_runner_function.ts
index 366bf057c846b..f9398f25ff7ff 100644
--- a/x-pack/legacy/plugins/actions/server/lib/get_create_task_runner_function.ts
+++ b/x-pack/legacy/plugins/actions/server/lib/get_create_task_runner_function.ts
@@ -9,11 +9,14 @@ import { ExecutorError } from './executor_error';
import { ActionTypeRegistryContract, GetServicesFunction } from '../types';
import { TaskInstance } from '../../../task_manager';
import { EncryptedSavedObjectsPlugin } from '../../../encrypted_saved_objects';
+import { SpacesPlugin } from '../../../spaces';
interface CreateTaskRunnerFunctionOptions {
getServices: GetServicesFunction;
actionTypeRegistry: ActionTypeRegistryContract;
encryptedSavedObjectsPlugin: EncryptedSavedObjectsPlugin;
+ spaceIdToNamespace: SpacesPlugin['spaceIdToNamespace'];
+ getBasePath: SpacesPlugin['getBasePath'];
}
interface TaskRunnerOptions {
@@ -24,17 +27,21 @@ export function getCreateTaskRunnerFunction({
getServices,
actionTypeRegistry,
encryptedSavedObjectsPlugin,
+ spaceIdToNamespace,
+ getBasePath,
}: CreateTaskRunnerFunctionOptions) {
return ({ taskInstance }: TaskRunnerOptions) => {
return {
run: async () => {
- const { namespace, id, params } = taskInstance.params;
+ const { spaceId, id, params } = taskInstance.params;
+ const namespace = spaceIdToNamespace(spaceId);
+ const basePath = getBasePath(spaceId);
const executorResult = await execute({
namespace,
actionTypeRegistry,
encryptedSavedObjectsPlugin,
actionId: id,
- services: getServices(taskInstance.params.basePath),
+ services: getServices(basePath),
params,
});
if (executorResult.status === 'error') {
diff --git a/x-pack/legacy/plugins/actions/server/types.ts b/x-pack/legacy/plugins/actions/server/types.ts
index 56f895bbaa778..a3134b4cd4d1f 100644
--- a/x-pack/legacy/plugins/actions/server/types.ts
+++ b/x-pack/legacy/plugins/actions/server/types.ts
@@ -6,6 +6,7 @@
import { SavedObjectsClientContract } from 'src/core/server';
import { ActionTypeRegistry } from './action_type_registry';
+import { FireOptions } from './create_fire_function';
export type WithoutQueryAndParams = Pick>;
export type GetServicesFunction = (basePath: string, overwrites?: Partial) => Services;
@@ -20,7 +21,7 @@ export interface Services {
export interface ActionsPlugin {
registerType: ActionTypeRegistry['register'];
listTypes: ActionTypeRegistry['list'];
- fire(options: { id: string; params: Record; basePath: string }): Promise;
+ fire(options: FireOptions): Promise;
}
// the parameters passed to an action type executor function
diff --git a/x-pack/legacy/plugins/alerting/server/alert_type_registry.test.ts b/x-pack/legacy/plugins/alerting/server/alert_type_registry.test.ts
index 442023951714e..f14da9e9ed83d 100644
--- a/x-pack/legacy/plugins/alerting/server/alert_type_registry.test.ts
+++ b/x-pack/legacy/plugins/alerting/server/alert_type_registry.test.ts
@@ -25,6 +25,8 @@ const alertTypeRegistryParams = {
taskManager,
fireAction: jest.fn(),
internalSavedObjectsRepository: SavedObjectsClientMock.create(),
+ spaceIdToNamespace: jest.fn().mockReturnValue(undefined),
+ getBasePath: jest.fn().mockReturnValue(undefined),
};
beforeEach(() => jest.resetAllMocks());
@@ -46,7 +48,7 @@ describe('has()', () => {
});
});
-describe('registry()', () => {
+describe('register()', () => {
test('registers the executor with the task manager', () => {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const { getCreateTaskRunnerFunction } = require('./lib/get_create_task_runner_function');
@@ -79,6 +81,8 @@ Object {
}
`);
expect(firstCall.internalSavedObjectsRepository).toBeTruthy();
+ expect(firstCall.getBasePath).toBeTruthy();
+ expect(firstCall.spaceIdToNamespace).toBeTruthy();
expect(firstCall.fireAction).toMatchInlineSnapshot(`[MockFunction]`);
});
diff --git a/x-pack/legacy/plugins/alerting/server/alert_type_registry.ts b/x-pack/legacy/plugins/alerting/server/alert_type_registry.ts
index 61a358473ef46..7e763858fd20e 100644
--- a/x-pack/legacy/plugins/alerting/server/alert_type_registry.ts
+++ b/x-pack/legacy/plugins/alerting/server/alert_type_registry.ts
@@ -11,12 +11,15 @@ import { AlertType, Services } from './types';
import { TaskManager } from '../../task_manager';
import { getCreateTaskRunnerFunction } from './lib';
import { ActionsPlugin } from '../../actions';
+import { SpacesPlugin } from '../../spaces';
interface ConstructorOptions {
getServices: (basePath: string) => Services;
taskManager: TaskManager;
fireAction: ActionsPlugin['fire'];
internalSavedObjectsRepository: SavedObjectsClientContract;
+ spaceIdToNamespace: SpacesPlugin['spaceIdToNamespace'];
+ getBasePath: SpacesPlugin['getBasePath'];
}
export class AlertTypeRegistry {
@@ -25,17 +28,23 @@ export class AlertTypeRegistry {
private readonly fireAction: ActionsPlugin['fire'];
private readonly alertTypes: Map = new Map();
private readonly internalSavedObjectsRepository: SavedObjectsClientContract;
+ private readonly spaceIdToNamespace: SpacesPlugin['spaceIdToNamespace'];
+ private readonly getBasePath: SpacesPlugin['getBasePath'];
constructor({
internalSavedObjectsRepository,
fireAction,
taskManager,
getServices,
+ spaceIdToNamespace,
+ getBasePath,
}: ConstructorOptions) {
this.taskManager = taskManager;
this.fireAction = fireAction;
this.internalSavedObjectsRepository = internalSavedObjectsRepository;
this.getServices = getServices;
+ this.getBasePath = getBasePath;
+ this.spaceIdToNamespace = spaceIdToNamespace;
}
public has(id: string) {
@@ -63,6 +72,8 @@ export class AlertTypeRegistry {
getServices: this.getServices,
fireAction: this.fireAction,
internalSavedObjectsRepository: this.internalSavedObjectsRepository,
+ getBasePath: this.getBasePath,
+ spaceIdToNamespace: this.spaceIdToNamespace,
}),
},
});
diff --git a/x-pack/legacy/plugins/alerting/server/alerts_client.test.ts b/x-pack/legacy/plugins/alerting/server/alerts_client.test.ts
index aba51e82c6677..c6eae114e725a 100644
--- a/x-pack/legacy/plugins/alerting/server/alerts_client.test.ts
+++ b/x-pack/legacy/plugins/alerting/server/alerts_client.test.ts
@@ -19,7 +19,7 @@ const alertsClientParams = {
taskManager,
alertTypeRegistry,
savedObjectsClient,
- basePath: '/s/default',
+ spaceId: 'default',
};
beforeEach(() => jest.resetAllMocks());
@@ -119,98 +119,98 @@ describe('create()', () => {
});
const result = await alertsClient.create({ data });
expect(result).toMatchInlineSnapshot(`
- Object {
- "actions": Array [
- Object {
- "group": "default",
- "id": "1",
- "params": Object {
- "foo": true,
- },
- },
- ],
- "alertTypeId": "123",
- "alertTypeParams": Object {
- "bar": true,
- },
- "id": "1",
- "interval": "10s",
- "scheduledTaskId": "task-123",
- }
- `);
+ Object {
+ "actions": Array [
+ Object {
+ "group": "default",
+ "id": "1",
+ "params": Object {
+ "foo": true,
+ },
+ },
+ ],
+ "alertTypeId": "123",
+ "alertTypeParams": Object {
+ "bar": true,
+ },
+ "id": "1",
+ "interval": "10s",
+ "scheduledTaskId": "task-123",
+ }
+ `);
expect(savedObjectsClient.create).toHaveBeenCalledTimes(1);
expect(savedObjectsClient.create.mock.calls[0]).toHaveLength(3);
expect(savedObjectsClient.create.mock.calls[0][0]).toEqual('alert');
expect(savedObjectsClient.create.mock.calls[0][1]).toMatchInlineSnapshot(`
- Object {
- "actions": Array [
- Object {
- "actionRef": "action_0",
- "group": "default",
- "params": Object {
- "foo": true,
- },
- },
- ],
- "alertTypeId": "123",
- "alertTypeParams": Object {
- "bar": true,
- },
- "enabled": true,
- "interval": "10s",
- }
- `);
+ Object {
+ "actions": Array [
+ Object {
+ "actionRef": "action_0",
+ "group": "default",
+ "params": Object {
+ "foo": true,
+ },
+ },
+ ],
+ "alertTypeId": "123",
+ "alertTypeParams": Object {
+ "bar": true,
+ },
+ "enabled": true,
+ "interval": "10s",
+ }
+ `);
expect(savedObjectsClient.create.mock.calls[0][2]).toMatchInlineSnapshot(`
- Object {
- "references": Array [
- Object {
- "id": "1",
- "name": "action_0",
- "type": "action",
- },
- ],
- }
- `);
+ Object {
+ "references": Array [
+ Object {
+ "id": "1",
+ "name": "action_0",
+ "type": "action",
+ },
+ ],
+ }
+ `);
expect(taskManager.schedule).toHaveBeenCalledTimes(1);
expect(taskManager.schedule.mock.calls[0]).toMatchInlineSnapshot(`
- Array [
- Object {
- "params": Object {
- "alertId": "1",
- "basePath": "/s/default",
- },
- "scope": Array [
- "alerting",
- ],
- "state": Object {
- "alertInstances": Object {},
- "alertTypeState": Object {},
- "previousStartedAt": null,
- },
- "taskType": "alerting:123",
- },
- ]
- `);
+ Array [
+ Object {
+ "params": Object {
+ "alertId": "1",
+ "spaceId": "default",
+ },
+ "scope": Array [
+ "alerting",
+ ],
+ "state": Object {
+ "alertInstances": Object {},
+ "alertTypeState": Object {},
+ "previousStartedAt": null,
+ },
+ "taskType": "alerting:123",
+ },
+ ]
+ `);
expect(savedObjectsClient.update).toHaveBeenCalledTimes(1);
expect(savedObjectsClient.update.mock.calls[0]).toHaveLength(4);
expect(savedObjectsClient.update.mock.calls[0][0]).toEqual('alert');
expect(savedObjectsClient.update.mock.calls[0][1]).toEqual('1');
expect(savedObjectsClient.update.mock.calls[0][2]).toMatchInlineSnapshot(`
- Object {
- "scheduledTaskId": "task-123",
- }
- `);
+ Object {
+ "scheduledTaskId": "task-123",
+ }
+ `);
expect(savedObjectsClient.update.mock.calls[0][3]).toMatchInlineSnapshot(`
- Object {
- "references": Array [
- Object {
- "id": "1",
- "name": "action_0",
- "type": "action",
- },
- ],
- }
- `);
+ Object {
+ "references": Array [
+ Object {
+ "id": "1",
+ "name": "action_0",
+ "type": "action",
+ },
+ ],
+ }
+ `);
});
test('creates a disabled alert', async () => {
@@ -251,25 +251,25 @@ describe('create()', () => {
});
const result = await alertsClient.create({ data });
expect(result).toMatchInlineSnapshot(`
- Object {
- "actions": Array [
- Object {
- "group": "default",
- "id": "1",
- "params": Object {
- "foo": true,
- },
- },
- ],
- "alertTypeId": "123",
- "alertTypeParams": Object {
- "bar": true,
- },
- "enabled": false,
- "id": "1",
- "interval": 10000,
- }
- `);
+ Object {
+ "actions": Array [
+ Object {
+ "group": "default",
+ "id": "1",
+ "params": Object {
+ "foo": true,
+ },
+ },
+ ],
+ "alertTypeId": "123",
+ "alertTypeParams": Object {
+ "bar": true,
+ },
+ "enabled": false,
+ "id": "1",
+ "interval": 10000,
+ }
+ `);
expect(savedObjectsClient.create).toHaveBeenCalledTimes(1);
expect(taskManager.schedule).toHaveBeenCalledTimes(0);
});
@@ -350,11 +350,11 @@ describe('create()', () => {
);
expect(savedObjectsClient.delete).toHaveBeenCalledTimes(1);
expect(savedObjectsClient.delete.mock.calls[0]).toMatchInlineSnapshot(`
- Array [
- "alert",
- "1",
- ]
- `);
+ Array [
+ "alert",
+ "1",
+ ]
+ `);
});
test('returns task manager error if cleanup fails, logs to console', async () => {
@@ -399,14 +399,14 @@ describe('create()', () => {
);
expect(alertsClientParams.log).toHaveBeenCalledTimes(1);
expect(alertsClientParams.log.mock.calls[0]).toMatchInlineSnapshot(`
- Array [
- Array [
- "alerting",
- "error",
- ],
- "Failed to cleanup alert \\"1\\" after scheduling task failed. Error: Saved object delete error",
- ]
- `);
+ Array [
+ Array [
+ "alerting",
+ "error",
+ ],
+ "Failed to cleanup alert \\"1\\" after scheduling task failed. Error: Saved object delete error",
+ ]
+ `);
});
test('throws an error if alert type not registerd', async () => {
@@ -463,7 +463,7 @@ describe('enable()', () => {
taskType: `alerting:2`,
params: {
alertId: '1',
- basePath: '/s/default',
+ spaceId: 'default',
},
state: {
alertInstances: {},
@@ -575,31 +575,31 @@ describe('get()', () => {
});
const result = await alertsClient.get({ id: '1' });
expect(result).toMatchInlineSnapshot(`
- Object {
- "actions": Array [
- Object {
- "group": "default",
- "id": "1",
- "params": Object {
- "foo": true,
- },
- },
- ],
- "alertTypeId": "123",
- "alertTypeParams": Object {
- "bar": true,
- },
- "id": "1",
- "interval": "10s",
- }
- `);
+ Object {
+ "actions": Array [
+ Object {
+ "group": "default",
+ "id": "1",
+ "params": Object {
+ "foo": true,
+ },
+ },
+ ],
+ "alertTypeId": "123",
+ "alertTypeParams": Object {
+ "bar": true,
+ },
+ "id": "1",
+ "interval": "10s",
+ }
+ `);
expect(savedObjectsClient.get).toHaveBeenCalledTimes(1);
expect(savedObjectsClient.get.mock.calls[0]).toMatchInlineSnapshot(`
- Array [
- "alert",
- "1",
- ]
- `);
+ Array [
+ "alert",
+ "1",
+ ]
+ `);
});
test(`throws an error when references aren't found`, async () => {
@@ -670,39 +670,39 @@ describe('find()', () => {
});
const result = await alertsClient.find();
expect(result).toMatchInlineSnapshot(`
- Object {
- "data": Array [
- Object {
- "actions": Array [
- Object {
- "group": "default",
- "id": "1",
- "params": Object {
- "foo": true,
+ Object {
+ "data": Array [
+ Object {
+ "actions": Array [
+ Object {
+ "group": "default",
+ "id": "1",
+ "params": Object {
+ "foo": true,
+ },
+ },
+ ],
+ "alertTypeId": "123",
+ "alertTypeParams": Object {
+ "bar": true,
+ },
+ "id": "1",
+ "interval": "10s",
},
- },
- ],
- "alertTypeId": "123",
- "alertTypeParams": Object {
- "bar": true,
- },
- "id": "1",
- "interval": "10s",
- },
- ],
- "page": 1,
- "perPage": 10,
- "total": 1,
- }
- `);
+ ],
+ "page": 1,
+ "perPage": 10,
+ "total": 1,
+ }
+ `);
expect(savedObjectsClient.find).toHaveBeenCalledTimes(1);
expect(savedObjectsClient.find.mock.calls[0]).toMatchInlineSnapshot(`
- Array [
- Object {
- "type": "alert",
- },
- ]
- `);
+ Array [
+ Object {
+ "type": "alert",
+ },
+ ]
+ `);
});
});
@@ -744,17 +744,17 @@ describe('delete()', () => {
expect(result).toEqual({ success: true });
expect(savedObjectsClient.delete).toHaveBeenCalledTimes(1);
expect(savedObjectsClient.delete.mock.calls[0]).toMatchInlineSnapshot(`
- Array [
- "alert",
- "1",
- ]
- `);
+ Array [
+ "alert",
+ "1",
+ ]
+ `);
expect(taskManager.remove).toHaveBeenCalledTimes(1);
expect(taskManager.remove.mock.calls[0]).toMatchInlineSnapshot(`
- Array [
- "task-123",
- ]
- `);
+ Array [
+ "task-123",
+ ]
+ `);
});
});
@@ -826,58 +826,58 @@ describe('update()', () => {
},
});
expect(result).toMatchInlineSnapshot(`
- Object {
- "actions": Array [
- Object {
- "group": "default",
- "id": "1",
- "params": Object {
- "foo": true,
- },
- },
- ],
- "alertTypeParams": Object {
- "bar": true,
- },
- "enabled": true,
- "id": "1",
- "interval": "10s",
- "scheduledTaskId": "task-123",
- }
- `);
+ Object {
+ "actions": Array [
+ Object {
+ "group": "default",
+ "id": "1",
+ "params": Object {
+ "foo": true,
+ },
+ },
+ ],
+ "alertTypeParams": Object {
+ "bar": true,
+ },
+ "enabled": true,
+ "id": "1",
+ "interval": "10s",
+ "scheduledTaskId": "task-123",
+ }
+ `);
expect(savedObjectsClient.update).toHaveBeenCalledTimes(1);
expect(savedObjectsClient.update.mock.calls[0]).toHaveLength(4);
expect(savedObjectsClient.update.mock.calls[0][0]).toEqual('alert');
expect(savedObjectsClient.update.mock.calls[0][1]).toEqual('1');
expect(savedObjectsClient.update.mock.calls[0][2]).toMatchInlineSnapshot(`
- Object {
- "actions": Array [
- Object {
- "actionRef": "action_0",
- "group": "default",
- "params": Object {
- "foo": true,
- },
- },
- ],
- "alertTypeParams": Object {
- "bar": true,
- },
- "interval": "10s",
- }
- `);
+ Object {
+ "actions": Array [
+ Object {
+ "actionRef": "action_0",
+ "group": "default",
+ "params": Object {
+ "foo": true,
+ },
+ },
+ ],
+ "alertTypeParams": Object {
+ "bar": true,
+ },
+ "interval": "10s",
+ }
+ `);
expect(savedObjectsClient.update.mock.calls[0][3]).toMatchInlineSnapshot(`
- Object {
- "references": Array [
- Object {
- "id": "1",
- "name": "action_0",
- "type": "action",
- },
- ],
- "version": "123",
- }
- `);
+ Object {
+ "references": Array [
+ Object {
+ "id": "1",
+ "name": "action_0",
+ "type": "action",
+ },
+ ],
+ "version": "123",
+ }
+ `);
});
it('should validate alertTypeParams', async () => {
diff --git a/x-pack/legacy/plugins/alerting/server/alerts_client.ts b/x-pack/legacy/plugins/alerting/server/alerts_client.ts
index 2c5dd49a9e2a7..cbd1ba3eab53e 100644
--- a/x-pack/legacy/plugins/alerting/server/alerts_client.ts
+++ b/x-pack/legacy/plugins/alerting/server/alerts_client.ts
@@ -15,7 +15,7 @@ interface ConstructorOptions {
taskManager: TaskManager;
savedObjectsClient: SavedObjectsClientContract;
alertTypeRegistry: AlertTypeRegistry;
- basePath: string;
+ spaceId?: string;
}
interface FindOptions {
@@ -60,7 +60,7 @@ interface UpdateOptions {
export class AlertsClient {
private readonly log: Log;
- private readonly basePath: string;
+ private readonly spaceId?: string;
private readonly taskManager: TaskManager;
private readonly savedObjectsClient: SavedObjectsClientContract;
private readonly alertTypeRegistry: AlertTypeRegistry;
@@ -70,10 +70,10 @@ export class AlertsClient {
savedObjectsClient,
taskManager,
log,
- basePath,
+ spaceId,
}: ConstructorOptions) {
this.log = log;
- this.basePath = basePath;
+ this.spaceId = spaceId;
this.taskManager = taskManager;
this.alertTypeRegistry = alertTypeRegistry;
this.savedObjectsClient = savedObjectsClient;
@@ -97,8 +97,7 @@ export class AlertsClient {
scheduledTask = await this.scheduleAlert(
createdAlert.id,
rawAlert.alertTypeId,
- rawAlert.interval,
- this.basePath
+ rawAlert.interval
);
} catch (e) {
// Cleanup data, something went wrong scheduling the task
@@ -189,8 +188,7 @@ export class AlertsClient {
const scheduledTask = await this.scheduleAlert(
id,
existingObject.attributes.alertTypeId,
- existingObject.attributes.interval,
- this.basePath
+ existingObject.attributes.interval
);
await this.savedObjectsClient.update(
'alert',
@@ -220,12 +218,12 @@ export class AlertsClient {
}
}
- private async scheduleAlert(id: string, alertTypeId: string, interval: string, basePath: string) {
+ private async scheduleAlert(id: string, alertTypeId: string, interval: string) {
return await this.taskManager.schedule({
taskType: `alerting:${alertTypeId}`,
params: {
alertId: id,
- basePath,
+ spaceId: this.spaceId,
},
state: {
previousStartedAt: null,
diff --git a/x-pack/legacy/plugins/alerting/server/init.ts b/x-pack/legacy/plugins/alerting/server/init.ts
index ec1255cc5ac20..bf7b4b8009b97 100644
--- a/x-pack/legacy/plugins/alerting/server/init.ts
+++ b/x-pack/legacy/plugins/alerting/server/init.ts
@@ -18,8 +18,18 @@ import {
import { AlertingPlugin, Services } from './types';
import { AlertTypeRegistry } from './alert_type_registry';
import { AlertsClient } from './alerts_client';
+import { SpacesPlugin } from '../../spaces';
+import { createOptionalPlugin } from '../../../server/lib/optional_plugin';
export function init(server: Legacy.Server) {
+ const config = server.config();
+ const spaces = createOptionalPlugin(
+ config,
+ 'xpack.spaces',
+ server.plugins,
+ 'spaces'
+ );
+
const { callWithInternalUser } = server.plugins.elasticsearch.getCluster('admin');
const savedObjectsRepositoryWithInternalUser = server.savedObjects.getSavedObjectsRepository(
callWithInternalUser
@@ -43,6 +53,14 @@ export function init(server: Legacy.Server) {
taskManager: taskManager!,
fireAction: server.plugins.actions!.fire,
internalSavedObjectsRepository: savedObjectsRepositoryWithInternalUser,
+ getBasePath(...args) {
+ return spaces.isEnabled
+ ? spaces.getBasePath(...args)
+ : server.config().get('server.basePath');
+ },
+ spaceIdToNamespace(...args) {
+ return spaces.isEnabled ? spaces.spaceIdToNamespace(...args) : undefined;
+ },
});
// Register routes
@@ -64,7 +82,7 @@ export function init(server: Legacy.Server) {
savedObjectsClient,
alertTypeRegistry,
taskManager: taskManager!,
- basePath: request.getBasePath(),
+ spaceId: spaces.isEnabled ? spaces.getSpaceId(request) : undefined,
});
return alertsClient;
});
diff --git a/x-pack/legacy/plugins/alerting/server/lib/create_fire_handler.test.ts b/x-pack/legacy/plugins/alerting/server/lib/create_fire_handler.test.ts
index ba8e35dbd7ba9..bbafd60cdbc64 100644
--- a/x-pack/legacy/plugins/alerting/server/lib/create_fire_handler.test.ts
+++ b/x-pack/legacy/plugins/alerting/server/lib/create_fire_handler.test.ts
@@ -7,8 +7,10 @@
import { createFireHandler } from './create_fire_handler';
const createFireHandlerParams = {
- basePath: '/s/default',
fireAction: jest.fn(),
+ spaceId: 'default',
+ spaceIdToNamespace: jest.fn().mockReturnValue(undefined),
+ getBasePath: jest.fn().mockReturnValue(undefined),
alertSavedObject: {
id: '1',
type: 'alert',
@@ -47,18 +49,18 @@ test('calls fireAction per selected action', async () => {
await fireHandler('default', {}, {});
expect(createFireHandlerParams.fireAction).toHaveBeenCalledTimes(1);
expect(createFireHandlerParams.fireAction.mock.calls[0]).toMatchInlineSnapshot(`
-Array [
- Object {
- "basePath": "/s/default",
- "id": "1",
- "params": Object {
- "contextVal": "My goes here",
- "foo": true,
- "stateVal": "My goes here",
- },
- },
-]
-`);
+ Array [
+ Object {
+ "id": "1",
+ "params": Object {
+ "contextVal": "My goes here",
+ "foo": true,
+ "stateVal": "My goes here",
+ },
+ "spaceId": "default",
+ },
+ ]
+ `);
});
test('limits fireAction per action group', async () => {
@@ -72,18 +74,18 @@ test('context attribute gets parameterized', async () => {
await fireHandler('default', { value: 'context-val' }, {});
expect(createFireHandlerParams.fireAction).toHaveBeenCalledTimes(1);
expect(createFireHandlerParams.fireAction.mock.calls[0]).toMatchInlineSnapshot(`
-Array [
- Object {
- "basePath": "/s/default",
- "id": "1",
- "params": Object {
- "contextVal": "My context-val goes here",
- "foo": true,
- "stateVal": "My goes here",
- },
- },
-]
-`);
+ Array [
+ Object {
+ "id": "1",
+ "params": Object {
+ "contextVal": "My context-val goes here",
+ "foo": true,
+ "stateVal": "My goes here",
+ },
+ "spaceId": "default",
+ },
+ ]
+ `);
});
test('state attribute gets parameterized', async () => {
@@ -91,23 +93,23 @@ test('state attribute gets parameterized', async () => {
await fireHandler('default', {}, { value: 'state-val' });
expect(createFireHandlerParams.fireAction).toHaveBeenCalledTimes(1);
expect(createFireHandlerParams.fireAction.mock.calls[0]).toMatchInlineSnapshot(`
-Array [
- Object {
- "basePath": "/s/default",
- "id": "1",
- "params": Object {
- "contextVal": "My goes here",
- "foo": true,
- "stateVal": "My state-val goes here",
- },
- },
-]
-`);
+ Array [
+ Object {
+ "id": "1",
+ "params": Object {
+ "contextVal": "My goes here",
+ "foo": true,
+ "stateVal": "My state-val goes here",
+ },
+ "spaceId": "default",
+ },
+ ]
+ `);
});
test('throws error if reference not found', async () => {
const params = {
- basePath: '/s/default',
+ spaceId: 'default',
fireAction: jest.fn(),
alertSavedObject: {
id: '1',
diff --git a/x-pack/legacy/plugins/alerting/server/lib/create_fire_handler.ts b/x-pack/legacy/plugins/alerting/server/lib/create_fire_handler.ts
index 3a271365105c7..f51b374298a07 100644
--- a/x-pack/legacy/plugins/alerting/server/lib/create_fire_handler.ts
+++ b/x-pack/legacy/plugins/alerting/server/lib/create_fire_handler.ts
@@ -12,13 +12,13 @@ import { transformActionParams } from './transform_action_params';
interface CreateFireHandlerOptions {
fireAction: ActionsPlugin['fire'];
alertSavedObject: SavedObject;
- basePath: string;
+ spaceId: string;
}
export function createFireHandler({
fireAction,
alertSavedObject,
- basePath,
+ spaceId,
}: CreateFireHandlerOptions) {
return async (actionGroup: string, context: Context, state: State) => {
const alertActions: RawAlertAction[] = alertSavedObject.attributes.actions;
@@ -43,7 +43,7 @@ export function createFireHandler({
await fireAction({
id: action.id,
params: action.params,
- basePath,
+ spaceId,
});
}
};
diff --git a/x-pack/legacy/plugins/alerting/server/lib/get_create_task_runner_function.test.ts b/x-pack/legacy/plugins/alerting/server/lib/get_create_task_runner_function.test.ts
index f12751e2288dd..95969d3d9a17c 100644
--- a/x-pack/legacy/plugins/alerting/server/lib/get_create_task_runner_function.test.ts
+++ b/x-pack/legacy/plugins/alerting/server/lib/get_create_task_runner_function.test.ts
@@ -54,6 +54,8 @@ const getCreateTaskRunnerFunctionParams = {
},
fireAction: jest.fn(),
internalSavedObjectsRepository: savedObjectsClient,
+ spaceIdToNamespace: jest.fn().mockReturnValue(undefined),
+ getBasePath: jest.fn().mockReturnValue(undefined),
};
const mockedAlertTypeSavedObject = {
@@ -93,22 +95,22 @@ test('successfully executes the task', async () => {
const runner = createTaskRunner({ taskInstance: mockedTaskInstance });
const runnerResult = await runner.run();
expect(runnerResult).toMatchInlineSnapshot(`
- Object {
- "runAt": 1970-01-01T00:00:10.000Z,
- "state": Object {
- "alertInstances": Object {},
- "alertTypeState": undefined,
- "previousStartedAt": 1970-01-01T00:00:00.000Z,
- },
- }
- `);
- expect(getCreateTaskRunnerFunctionParams.alertType.executor).toHaveBeenCalledTimes(1);
- const call = getCreateTaskRunnerFunctionParams.alertType.executor.mock.calls[0][0];
- expect(call.params).toMatchInlineSnapshot(`
Object {
- "bar": true,
+ "runAt": 1970-01-01T00:00:10.000Z,
+ "state": Object {
+ "alertInstances": Object {},
+ "alertTypeState": undefined,
+ "previousStartedAt": 1970-01-01T00:00:00.000Z,
+ },
}
`);
+ expect(getCreateTaskRunnerFunctionParams.alertType.executor).toHaveBeenCalledTimes(1);
+ const call = getCreateTaskRunnerFunctionParams.alertType.executor.mock.calls[0][0];
+ expect(call.params).toMatchInlineSnapshot(`
+ Object {
+ "bar": true,
+ }
+ `);
expect(call.startedAt).toMatchInlineSnapshot(`1970-01-01T00:00:00.000Z`);
expect(call.state).toMatchInlineSnapshot(`Object {}`);
expect(call.services.alertInstanceFactory).toBeTruthy();
@@ -128,16 +130,16 @@ test('fireAction is called per alert instance that fired', async () => {
await runner.run();
expect(getCreateTaskRunnerFunctionParams.fireAction).toHaveBeenCalledTimes(1);
expect(getCreateTaskRunnerFunctionParams.fireAction.mock.calls[0]).toMatchInlineSnapshot(`
- Array [
- Object {
- "basePath": undefined,
- "id": "1",
- "params": Object {
- "foo": true,
- },
- },
- ]
- `);
+ Array [
+ Object {
+ "id": "1",
+ "params": Object {
+ "foo": true,
+ },
+ "spaceId": undefined,
+ },
+ ]
+ `);
});
test('persists alertInstances passed in from state, only if they fire', async () => {
@@ -162,17 +164,17 @@ test('persists alertInstances passed in from state, only if they fire', async ()
});
const runnerResult = await runner.run();
expect(runnerResult.state.alertInstances).toMatchInlineSnapshot(`
- Object {
- "1": Object {
- "meta": Object {
- "lastFired": 0,
- },
- "state": Object {
- "bar": false,
- },
- },
- }
- `);
+ Object {
+ "1": Object {
+ "meta": Object {
+ "lastFired": 0,
+ },
+ "state": Object {
+ "bar": false,
+ },
+ },
+ }
+ `);
});
test('validates params before executing the alert type', async () => {
diff --git a/x-pack/legacy/plugins/alerting/server/lib/get_create_task_runner_function.ts b/x-pack/legacy/plugins/alerting/server/lib/get_create_task_runner_function.ts
index 5591b63188b35..2ac3023a2079c 100644
--- a/x-pack/legacy/plugins/alerting/server/lib/get_create_task_runner_function.ts
+++ b/x-pack/legacy/plugins/alerting/server/lib/get_create_task_runner_function.ts
@@ -13,12 +13,15 @@ import { createAlertInstanceFactory } from './create_alert_instance_factory';
import { AlertInstance } from './alert_instance';
import { getNextRunAt } from './get_next_run_at';
import { validateAlertTypeParams } from './validate_alert_type_params';
+import { SpacesPlugin } from '../../../spaces';
interface CreateTaskRunnerFunctionOptions {
getServices: (basePath: string) => Services;
alertType: AlertType;
fireAction: ActionsPlugin['fire'];
internalSavedObjectsRepository: SavedObjectsClientContract;
+ spaceIdToNamespace: SpacesPlugin['spaceIdToNamespace'];
+ getBasePath: SpacesPlugin['getBasePath'];
}
interface TaskRunnerOptions {
@@ -30,13 +33,17 @@ export function getCreateTaskRunnerFunction({
alertType,
fireAction,
internalSavedObjectsRepository,
+ spaceIdToNamespace,
+ getBasePath,
}: CreateTaskRunnerFunctionOptions) {
return ({ taskInstance }: TaskRunnerOptions) => {
return {
run: async () => {
+ const namespace = spaceIdToNamespace(taskInstance.params.spaceId);
const alertSavedObject = await internalSavedObjectsRepository.get(
'alert',
- taskInstance.params.alertId
+ taskInstance.params.alertId,
+ { namespace }
);
// Validate
@@ -48,7 +55,7 @@ export function getCreateTaskRunnerFunction({
const fireHandler = createFireHandler({
alertSavedObject,
fireAction,
- basePath: taskInstance.params.basePath,
+ spaceId: taskInstance.params.spaceId,
});
const alertInstances: Record = {};
const alertInstancesData = taskInstance.state.alertInstances || {};
diff --git a/x-pack/test/api_integration/apis/actions/constants.ts b/x-pack/test/api_integration/apis/actions/constants.ts
index f79a63072be79..b7c391507dcc2 100644
--- a/x-pack/test/api_integration/apis/actions/constants.ts
+++ b/x-pack/test/api_integration/apis/actions/constants.ts
@@ -5,3 +5,4 @@
*/
export const ES_ARCHIVER_ACTION_ID = '60071910-1ef1-4a72-9a68-b94af6a836a7';
+export const SPACE_1_ES_ARCHIVER_ACTION_ID = '6c7d0f6b-2fb5-4821-b182-624fc3ccc7a3';
diff --git a/x-pack/test/api_integration/apis/actions/create.ts b/x-pack/test/api_integration/apis/actions/create.ts
index d76166316d87a..d7df3fd97c696 100644
--- a/x-pack/test/api_integration/apis/actions/create.ts
+++ b/x-pack/test/api_integration/apis/actions/create.ts
@@ -38,6 +38,29 @@ export default function createActionTests({ getService }: KibanaFunctionalTestDe
});
});
+ it('should return 200 when creating an action inside a space and to not be accessible from another space', async () => {
+ const { body: createdAction } = await supertest
+ .post('/s/space_1/api/action')
+ .set('kbn-xsrf', 'foo')
+ .send({
+ description: 'My action',
+ actionTypeId: 'test.index-record',
+ config: {
+ unencrypted: `This value shouldn't get encrypted`,
+ },
+ secrets: {
+ encrypted: 'This value should be encrypted',
+ },
+ })
+ .expect(200);
+ expect(createdAction).to.eql({
+ id: createdAction.id,
+ });
+ expect(typeof createdAction.id).to.be('string');
+ await supertest.get(`/s/space_1/api/action/${createdAction.id}`).expect(200);
+ await supertest.get(`/api/action/${createdAction.id}`).expect(404);
+ });
+
it(`should return 400 when action type isn't registered`, async () => {
await supertest
.post('/api/action')
diff --git a/x-pack/test/api_integration/apis/actions/delete.ts b/x-pack/test/api_integration/apis/actions/delete.ts
index 92e513ea6f2b6..68f8924010cce 100644
--- a/x-pack/test/api_integration/apis/actions/delete.ts
+++ b/x-pack/test/api_integration/apis/actions/delete.ts
@@ -6,7 +6,7 @@
import expect from '@kbn/expect';
-import { ES_ARCHIVER_ACTION_ID } from './constants';
+import { ES_ARCHIVER_ACTION_ID, SPACE_1_ES_ARCHIVER_ACTION_ID } from './constants';
import { KibanaFunctionalTestDefaultProviders } from '../../../types/providers';
// eslint-disable-next-line import/no-default-export
@@ -25,6 +25,20 @@ export default function deleteActionTests({ getService }: KibanaFunctionalTestDe
.expect(204, '');
});
+ it('should return 204 when deleting an action in a space', async () => {
+ await supertest
+ .delete(`/s/space_1/api/action/${SPACE_1_ES_ARCHIVER_ACTION_ID}`)
+ .set('kbn-xsrf', 'foo')
+ .expect(204, '');
+ });
+
+ it('should return 404 when deleting an action in another space', async () => {
+ await supertest
+ .delete(`/api/action/${SPACE_1_ES_ARCHIVER_ACTION_ID}`)
+ .set('kbn-xsrf', 'foo')
+ .expect(404);
+ });
+
it(`should return 404 when action doesn't exist`, async () => {
await supertest
.delete('/api/action/2')
diff --git a/x-pack/test/api_integration/apis/actions/find.ts b/x-pack/test/api_integration/apis/actions/find.ts
index 6bf863737735c..66a5e956db919 100644
--- a/x-pack/test/api_integration/apis/actions/find.ts
+++ b/x-pack/test/api_integration/apis/actions/find.ts
@@ -5,7 +5,7 @@
*/
import expect from '@kbn/expect';
-import { ES_ARCHIVER_ACTION_ID } from './constants';
+import { ES_ARCHIVER_ACTION_ID, SPACE_1_ES_ARCHIVER_ACTION_ID } from './constants';
import { KibanaFunctionalTestDefaultProviders } from '../../../types/providers';
// eslint-disable-next-line import/no-default-export
@@ -38,6 +38,27 @@ export default function findActionTests({ getService }: KibanaFunctionalTestDefa
});
});
+ it('should return 200 with individual responses in a space', async () => {
+ await supertest
+ .get(
+ '/s/space_1/api/action/_find?search=test.index-record&search_fields=actionTypeId&fields=description'
+ )
+ .expect(200)
+ .then((resp: any) => {
+ expect(resp.body).to.eql({
+ page: 1,
+ perPage: 20,
+ total: 1,
+ data: [
+ {
+ id: SPACE_1_ES_ARCHIVER_ACTION_ID,
+ description: 'My action',
+ },
+ ],
+ });
+ });
+ });
+
it('should not return encrypted attributes', async () => {
await supertest
.get('/api/action/_find?search=test.index-record&search_fields=actionTypeId')
diff --git a/x-pack/test/api_integration/apis/actions/fire.ts b/x-pack/test/api_integration/apis/actions/fire.ts
index e1d659f356efb..60fe0d5f3dc61 100644
--- a/x-pack/test/api_integration/apis/actions/fire.ts
+++ b/x-pack/test/api_integration/apis/actions/fire.ts
@@ -5,7 +5,7 @@
*/
import expect from '@kbn/expect';
-import { ES_ARCHIVER_ACTION_ID } from './constants';
+import { ES_ARCHIVER_ACTION_ID, SPACE_1_ES_ARCHIVER_ACTION_ID } from './constants';
import { KibanaFunctionalTestDefaultProviders } from '../../../types/providers';
// eslint-disable-next-line import/no-default-export
@@ -110,6 +110,77 @@ export default function({ getService }: KibanaFunctionalTestDefaultProviders) {
});
});
+ it(`can't fire from another space`, async () => {
+ await supertest
+ .post(`/api/action/${SPACE_1_ES_ARCHIVER_ACTION_ID}/_fire`)
+ .set('kbn-xsrf', 'foo')
+ .send({
+ params: {
+ index: esTestIndexName,
+ reference: 'actions-fire-2',
+ message: 'Testing 123',
+ },
+ })
+ .expect(404);
+ });
+
+ it('fire works in a space', async () => {
+ await supertest
+ .post(`/s/space_1/api/action/${SPACE_1_ES_ARCHIVER_ACTION_ID}/_fire`)
+ .set('kbn-xsrf', 'foo')
+ .send({
+ params: {
+ index: esTestIndexName,
+ reference: 'actions-fire-3',
+ message: 'Testing 123',
+ },
+ })
+ .expect(200)
+ .then((resp: any) => {
+ expect(resp.body).to.be.an('object');
+ });
+ const indexedRecord = await retry.tryForTime(15000, async () => {
+ const searchResult = await es.search({
+ index: esTestIndexName,
+ body: {
+ query: {
+ bool: {
+ must: [
+ {
+ term: {
+ source: 'action:test.index-record',
+ },
+ },
+ {
+ term: {
+ reference: 'actions-fire-3',
+ },
+ },
+ ],
+ },
+ },
+ },
+ });
+ expect(searchResult.hits.total.value).to.eql(1);
+ return searchResult.hits.hits[0];
+ });
+ expect(indexedRecord._source).to.eql({
+ params: {
+ index: esTestIndexName,
+ reference: 'actions-fire-3',
+ message: 'Testing 123',
+ },
+ config: {
+ unencrypted: `This value shouldn't get encrypted`,
+ },
+ secrets: {
+ encrypted: 'This value should be encrypted',
+ },
+ reference: 'actions-fire-3',
+ source: 'action:test.index-record',
+ });
+ });
+
it('fire still works with encrypted attributes after updating an action', async () => {
const { body: updatedAction } = await supertest
.put(`/api/action/${ES_ARCHIVER_ACTION_ID}`)
@@ -133,7 +204,7 @@ export default function({ getService }: KibanaFunctionalTestDefaultProviders) {
.send({
params: {
index: esTestIndexName,
- reference: 'actions-fire-2',
+ reference: 'actions-fire-4',
message: 'Testing 123',
},
})
@@ -155,7 +226,7 @@ export default function({ getService }: KibanaFunctionalTestDefaultProviders) {
},
{
term: {
- reference: 'actions-fire-2',
+ reference: 'actions-fire-4',
},
},
],
@@ -169,7 +240,7 @@ export default function({ getService }: KibanaFunctionalTestDefaultProviders) {
expect(indexedRecord._source).to.eql({
params: {
index: esTestIndexName,
- reference: 'actions-fire-2',
+ reference: 'actions-fire-4',
message: 'Testing 123',
},
config: {
@@ -178,7 +249,7 @@ export default function({ getService }: KibanaFunctionalTestDefaultProviders) {
secrets: {
encrypted: 'This value should be encrypted',
},
- reference: 'actions-fire-2',
+ reference: 'actions-fire-4',
source: 'action:test.index-record',
});
});
diff --git a/x-pack/test/api_integration/apis/actions/get.ts b/x-pack/test/api_integration/apis/actions/get.ts
index 427e7d5df32d2..1b34b16c0ea07 100644
--- a/x-pack/test/api_integration/apis/actions/get.ts
+++ b/x-pack/test/api_integration/apis/actions/get.ts
@@ -5,7 +5,7 @@
*/
import expect from '@kbn/expect';
-import { ES_ARCHIVER_ACTION_ID } from './constants';
+import { ES_ARCHIVER_ACTION_ID, SPACE_1_ES_ARCHIVER_ACTION_ID } from './constants';
import { KibanaFunctionalTestDefaultProviders } from '../../../types/providers';
// eslint-disable-next-line import/no-default-export
@@ -33,6 +33,26 @@ export default function getActionTests({ getService }: KibanaFunctionalTestDefau
});
});
+ it('should return 404 when finding a record in another space', async () => {
+ await supertest.get(`/api/action/${SPACE_1_ES_ARCHIVER_ACTION_ID}`).expect(404);
+ });
+
+ it('should return 200 when finding a record in a space', async () => {
+ await supertest
+ .get(`/s/space_1/api/action/${SPACE_1_ES_ARCHIVER_ACTION_ID}`)
+ .expect(200)
+ .then((resp: any) => {
+ expect(resp.body).to.eql({
+ id: SPACE_1_ES_ARCHIVER_ACTION_ID,
+ actionTypeId: 'test.index-record',
+ description: 'My action',
+ config: {
+ unencrypted: `This value shouldn't get encrypted`,
+ },
+ });
+ });
+ });
+
it('should return 404 when not finding a record', async () => {
await supertest
.get('/api/action/2')
diff --git a/x-pack/test/api_integration/apis/actions/update.ts b/x-pack/test/api_integration/apis/actions/update.ts
index fad9fed7aabd0..24b73ab723d98 100644
--- a/x-pack/test/api_integration/apis/actions/update.ts
+++ b/x-pack/test/api_integration/apis/actions/update.ts
@@ -5,7 +5,7 @@
*/
import expect from '@kbn/expect';
-import { ES_ARCHIVER_ACTION_ID } from './constants';
+import { ES_ARCHIVER_ACTION_ID, SPACE_1_ES_ARCHIVER_ACTION_ID } from './constants';
import { KibanaFunctionalTestDefaultProviders } from '../../../types/providers';
// eslint-disable-next-line import/no-default-export
@@ -38,6 +38,41 @@ export default function updateActionTests({ getService }: KibanaFunctionalTestDe
});
});
+ it('should return 200 when updating a document in a space', async () => {
+ await supertest
+ .put(`/s/space_1/api/action/${SPACE_1_ES_ARCHIVER_ACTION_ID}`)
+ .set('kbn-xsrf', 'foo')
+ .send({
+ description: 'My action updated',
+ config: {
+ unencrypted: `This value shouldn't get encrypted`,
+ },
+ secrets: {
+ encrypted: 'This value should be encrypted',
+ },
+ })
+ .expect(200)
+ .then((resp: any) => {
+ expect(resp.body).to.eql({
+ id: SPACE_1_ES_ARCHIVER_ACTION_ID,
+ });
+ });
+ });
+
+ it('should return 404 when updating a document in another space', async () => {
+ await supertest
+ .put(`/api/action/${SPACE_1_ES_ARCHIVER_ACTION_ID}`)
+ .set('kbn-xsrf', 'foo')
+ .send({
+ description: 'My action updated',
+ config: {
+ unencrypted: `This value shouldn't get encrypted`,
+ encrypted: 'This value should be encrypted',
+ },
+ })
+ .expect(404);
+ });
+
it('should not be able to pass null config', async () => {
await supertest
.put(`/api/action/${ES_ARCHIVER_ACTION_ID}`)
diff --git a/x-pack/test/api_integration/apis/alerting/alerts.ts b/x-pack/test/api_integration/apis/alerting/alerts.ts
index e2376c364b9e2..7b4232f266e20 100644
--- a/x-pack/test/api_integration/apis/alerting/alerts.ts
+++ b/x-pack/test/api_integration/apis/alerting/alerts.ts
@@ -7,7 +7,7 @@
import expect from '@kbn/expect';
import { getTestAlertData, setupEsTestIndex, destroyEsTestIndex } from './utils';
import { KibanaFunctionalTestDefaultProviders } from '../../../types/providers';
-import { ES_ARCHIVER_ACTION_ID } from './constants';
+import { ES_ARCHIVER_ACTION_ID, SPACE_1_ES_ARCHIVER_ACTION_ID } from './constants';
// eslint-disable-next-line import/no-default-export
export default function alertTests({ getService }: KibanaFunctionalTestDefaultProviders) {
@@ -18,7 +18,7 @@ export default function alertTests({ getService }: KibanaFunctionalTestDefaultPr
describe('alerts', () => {
let esTestIndexName: string;
- const createdAlertIds: string[] = [];
+ const createdAlertIds: Array<{ space: string; id: string }> = [];
before(async () => {
await destroyEsTestIndex(es);
@@ -27,9 +27,10 @@ export default function alertTests({ getService }: KibanaFunctionalTestDefaultPr
});
after(async () => {
await Promise.all(
- createdAlertIds.map(id => {
+ createdAlertIds.map(({ space, id }) => {
+ const urlPrefix = space !== 'default' ? `/s/${space}` : '';
return supertest
- .delete(`/api/alert/${id}`)
+ .delete(`${urlPrefix}/api/alert/${id}`)
.set('kbn-xsrf', 'foo')
.expect(204, '');
})
@@ -66,7 +67,7 @@ export default function alertTests({ getService }: KibanaFunctionalTestDefaultPr
)
.expect(200)
.then((resp: any) => {
- createdAlertIds.push(resp.body.id);
+ createdAlertIds.push({ space: 'default', id: resp.body.id });
});
const alertTestRecord = await retry.tryForTime(15000, async () => {
const searchResult = await es.search({
@@ -144,6 +145,111 @@ export default function alertTests({ getService }: KibanaFunctionalTestDefaultPr
});
});
+ it('should schedule task, run alert and fire actions in a space', async () => {
+ const { body: createdAlert } = await supertest
+ .post('/s/space_1/api/alert')
+ .set('kbn-xsrf', 'foo')
+ .send(
+ getTestAlertData({
+ interval: '1s',
+ alertTypeId: 'test.always-firing',
+ alertTypeParams: {
+ index: esTestIndexName,
+ reference: 'create-test-2',
+ },
+ actions: [
+ {
+ group: 'default',
+ id: SPACE_1_ES_ARCHIVER_ACTION_ID,
+ params: {
+ index: esTestIndexName,
+ reference: 'create-test-2',
+ message:
+ 'instanceContextValue: {{context.instanceContextValue}}, instanceStateValue: {{state.instanceStateValue}}',
+ },
+ },
+ ],
+ })
+ )
+ .expect(200);
+ createdAlertIds.push({ space: 'space_1', id: createdAlert.id });
+
+ const alertTestRecord = await retry.tryForTime(15000, async () => {
+ const searchResult = await es.search({
+ index: esTestIndexName,
+ body: {
+ query: {
+ bool: {
+ must: [
+ {
+ term: {
+ source: 'alert:test.always-firing',
+ },
+ },
+ {
+ term: {
+ reference: 'create-test-2',
+ },
+ },
+ ],
+ },
+ },
+ },
+ });
+ expect(searchResult.hits.total.value).to.eql(1);
+ return searchResult.hits.hits[0];
+ });
+ expect(alertTestRecord._source).to.eql({
+ source: 'alert:test.always-firing',
+ reference: 'create-test-2',
+ state: {},
+ params: {
+ index: esTestIndexName,
+ reference: 'create-test-2',
+ },
+ });
+ const actionTestRecord = await retry.tryForTime(15000, async () => {
+ const searchResult = await es.search({
+ index: esTestIndexName,
+ body: {
+ query: {
+ bool: {
+ must: [
+ {
+ term: {
+ source: 'action:test.index-record',
+ },
+ },
+ {
+ term: {
+ reference: 'create-test-2',
+ },
+ },
+ ],
+ },
+ },
+ },
+ });
+ expect(searchResult.hits.total.value).to.eql(1);
+ return searchResult.hits.hits[0];
+ });
+ expect(actionTestRecord._source).to.eql({
+ config: {
+ unencrypted: `This value shouldn't get encrypted`,
+ },
+ secrets: {
+ encrypted: 'This value should be encrypted',
+ },
+ params: {
+ index: esTestIndexName,
+ reference: 'create-test-2',
+ message: 'instanceContextValue: true, instanceStateValue: true',
+ },
+ reference: 'create-test-2',
+ source: 'action:test.index-record',
+ });
+ });
+
it('should handle custom retry logic', async () => {
// We'll use this start time to query tasks created after this point
const testStart = new Date();
@@ -175,7 +281,7 @@ export default function alertTests({ getService }: KibanaFunctionalTestDefaultPr
})
)
.expect(200);
- createdAlertIds.push(createdAlert.id);
+ createdAlertIds.push({ space: 'default', id: createdAlert.id });
const scheduledActionTask = await retry.tryForTime(15000, async () => {
const searchResult = await es.search({
diff --git a/x-pack/test/api_integration/apis/alerting/constants.ts b/x-pack/test/api_integration/apis/alerting/constants.ts
index d946111ae8bbb..8289111072b38 100644
--- a/x-pack/test/api_integration/apis/alerting/constants.ts
+++ b/x-pack/test/api_integration/apis/alerting/constants.ts
@@ -4,6 +4,10 @@
* you may not use this file except in compliance with the Elastic License.
*/
-import { ES_ARCHIVER_ACTION_ID as ActionArchiverActionId } from '../actions/constants';
+import {
+ ES_ARCHIVER_ACTION_ID as ActionArchiverActionId,
+ SPACE_1_ES_ARCHIVER_ACTION_ID as ActionArchiverSpace1ActionId,
+} from '../actions/constants';
export const ES_ARCHIVER_ACTION_ID = ActionArchiverActionId;
+export const SPACE_1_ES_ARCHIVER_ACTION_ID = ActionArchiverSpace1ActionId;
diff --git a/x-pack/test/api_integration/apis/alerting/create.ts b/x-pack/test/api_integration/apis/alerting/create.ts
index 4d9bceaee0d29..5923081a5f137 100644
--- a/x-pack/test/api_integration/apis/alerting/create.ts
+++ b/x-pack/test/api_integration/apis/alerting/create.ts
@@ -16,14 +16,15 @@ export default function createAlertTests({ getService }: KibanaFunctionalTestDef
const es = getService('es');
describe('create', () => {
- const createdAlertIds: string[] = [];
+ const createdAlertIds: Array<{ space: string; id: string }> = [];
before(() => esArchiver.load('actions/basic'));
after(async () => {
await Promise.all(
- createdAlertIds.map(id => {
+ createdAlertIds.map(({ space, id }) => {
+ const urlPrefix = space !== 'default' ? `/s/${space}` : '';
return supertest
- .delete(`/api/alert/${id}`)
+ .delete(`${urlPrefix}/api/alert/${id}`)
.set('kbn-xsrf', 'foo')
.expect(204, '');
})
@@ -45,7 +46,7 @@ export default function createAlertTests({ getService }: KibanaFunctionalTestDef
.send(getTestAlertData())
.expect(200)
.then(async (resp: any) => {
- createdAlertIds.push(resp.body.id);
+ createdAlertIds.push({ space: 'default', id: resp.body.id });
expect(resp.body).to.eql({
id: resp.body.id,
actions: [
@@ -70,11 +71,46 @@ export default function createAlertTests({ getService }: KibanaFunctionalTestDef
expect(taskRecord.task.taskType).to.eql('alerting:test.noop');
expect(JSON.parse(taskRecord.task.params)).to.eql({
alertId: resp.body.id,
- basePath: '',
+ spaceId: 'default',
});
});
});
+ it('should return 200 when creating an alert in a space', async () => {
+ const { body: createdAlert } = await supertest
+ .post('/s/space_1/api/alert')
+ .set('kbn-xsrf', 'foo')
+ .send(getTestAlertData())
+ .expect(200);
+ createdAlertIds.push({ space: 'space_1', id: createdAlert.id });
+ expect(createdAlert).to.eql({
+ id: createdAlert.id,
+ actions: [
+ {
+ group: 'default',
+ id: ES_ARCHIVER_ACTION_ID,
+ params: {
+ message:
+ 'instanceContextValue: {{context.instanceContextValue}}, instanceStateValue: {{state.instanceStateValue}}',
+ },
+ },
+ ],
+ enabled: true,
+ alertTypeId: 'test.noop',
+ alertTypeParams: {},
+ interval: '10s',
+ scheduledTaskId: createdAlert.scheduledTaskId,
+ });
+ expect(typeof createdAlert.scheduledTaskId).to.be('string');
+ const { _source: taskRecord } = await getScheduledTask(createdAlert.scheduledTaskId);
+ expect(taskRecord.type).to.eql('task');
+ expect(taskRecord.task.taskType).to.eql('alerting:test.noop');
+ expect(JSON.parse(taskRecord.task.params)).to.eql({
+ alertId: createdAlert.id,
+ spaceId: 'space_1',
+ });
+ });
+
it('should not schedule a task when creating a disabled alert', async () => {
const { body: createdAlert } = await supertest
.post('/api/alert')
diff --git a/x-pack/test/api_integration/apis/alerting/delete.ts b/x-pack/test/api_integration/apis/alerting/delete.ts
index a287d75c85d4c..52e8ee4a9d8a5 100644
--- a/x-pack/test/api_integration/apis/alerting/delete.ts
+++ b/x-pack/test/api_integration/apis/alerting/delete.ts
@@ -17,6 +17,8 @@ export default function createDeleteTests({ getService }: KibanaFunctionalTestDe
describe('delete', () => {
let alertId: string;
let scheduledTaskId: string;
+ let space1AlertId: string;
+ let space1ScheduledTaskId: string;
before(async () => {
await esArchiver.load('actions/basic');
@@ -29,6 +31,15 @@ export default function createDeleteTests({ getService }: KibanaFunctionalTestDe
alertId = resp.body.id;
scheduledTaskId = resp.body.scheduledTaskId;
});
+ await supertest
+ .post('/s/space_1/api/alert')
+ .set('kbn-xsrf', 'foo')
+ .send(getTestAlertData())
+ .expect(200)
+ .then((resp: any) => {
+ space1AlertId = resp.body.id;
+ space1ScheduledTaskId = resp.body.scheduledTaskId;
+ });
});
after(() => esArchiver.unload('actions/basic'));
@@ -53,5 +64,27 @@ export default function createDeleteTests({ getService }: KibanaFunctionalTestDe
}
expect(hasThrownError).to.eql(true);
});
+
+ it('should return 404 when deleting an alert from another space', async () => {
+ await supertest
+ .delete(`/api/alert/${space1AlertId}`)
+ .set('kbn-xsrf', 'foo')
+ .expect(404);
+ });
+
+ it('should return 204 when deleting an alert in a space', async () => {
+ await supertest
+ .delete(`/s/space_1/api/alert/${space1AlertId}`)
+ .set('kbn-xsrf', 'foo')
+ .expect(204, '');
+ let hasThrownError = false;
+ try {
+ await getScheduledTask(space1ScheduledTaskId);
+ } catch (e) {
+ hasThrownError = true;
+ expect(e.status).to.eql(404);
+ }
+ expect(hasThrownError).to.eql(true);
+ });
});
}
diff --git a/x-pack/test/api_integration/apis/alerting/disable.ts b/x-pack/test/api_integration/apis/alerting/disable.ts
index 44e49f3c2d1b6..a1dae1efa5bbe 100644
--- a/x-pack/test/api_integration/apis/alerting/disable.ts
+++ b/x-pack/test/api_integration/apis/alerting/disable.ts
@@ -15,7 +15,8 @@ export default function createDisableAlertTests({
const esArchiver = getService('esArchiver');
describe('disable', () => {
- let createdAlert: any;
+ let alertId: string;
+ let space1AlertId: string;
before(async () => {
await esArchiver.load('actions/basic');
@@ -25,13 +26,25 @@ export default function createDisableAlertTests({
.send(getTestAlertData({ enabled: true }))
.expect(200)
.then((resp: any) => {
- createdAlert = resp.body;
+ alertId = resp.body.id;
+ });
+ await supertest
+ .post('/s/space_1/api/alert')
+ .set('kbn-xsrf', 'foo')
+ .send(getTestAlertData({ enabled: true }))
+ .expect(200)
+ .then((resp: any) => {
+ space1AlertId = resp.body.id;
});
});
after(async () => {
await supertest
- .delete(`/api/alert/${createdAlert.id}`)
+ .delete(`/api/alert/${alertId}`)
+ .set('kbn-xsrf', 'foo')
+ .expect(204, '');
+ await supertest
+ .delete(`/s/space_1/api/alert/${space1AlertId}`)
.set('kbn-xsrf', 'foo')
.expect(204, '');
await esArchiver.unload('actions/basic');
@@ -39,7 +52,21 @@ export default function createDisableAlertTests({
it('should return 204 when disabling an alert', async () => {
await supertest
- .post(`/api/alert/${createdAlert.id}/_disable`)
+ .post(`/api/alert/${alertId}/_disable`)
+ .set('kbn-xsrf', 'foo')
+ .expect(204);
+ });
+
+ it('should return 404 when disabling an alert from another space', async () => {
+ await supertest
+ .post(`/api/alert/${space1AlertId}/_disable`)
+ .set('kbn-xsrf', 'foo')
+ .expect(404);
+ });
+
+ it('should return 204 when disabling an alert in a space', async () => {
+ await supertest
+ .post(`/s/space_1/api/alert/${space1AlertId}/_disable`)
.set('kbn-xsrf', 'foo')
.expect(204);
});
diff --git a/x-pack/test/api_integration/apis/alerting/enable.ts b/x-pack/test/api_integration/apis/alerting/enable.ts
index 5222ea14b28e7..b91084aaa854d 100644
--- a/x-pack/test/api_integration/apis/alerting/enable.ts
+++ b/x-pack/test/api_integration/apis/alerting/enable.ts
@@ -15,7 +15,8 @@ export default function createEnableAlertTests({
const esArchiver = getService('esArchiver');
describe('enable', () => {
- let createdAlert: any;
+ let alertId: string;
+ let space1AlertId: string;
before(async () => {
await esArchiver.load('actions/basic');
@@ -25,13 +26,25 @@ export default function createEnableAlertTests({
.send(getTestAlertData({ enabled: false }))
.expect(200)
.then((resp: any) => {
- createdAlert = resp.body;
+ alertId = resp.body.id;
+ });
+ await supertest
+ .post('/s/space_1/api/alert')
+ .set('kbn-xsrf', 'foo')
+ .send(getTestAlertData({ enabled: false }))
+ .expect(200)
+ .then((resp: any) => {
+ space1AlertId = resp.body.id;
});
});
after(async () => {
await supertest
- .delete(`/api/alert/${createdAlert.id}`)
+ .delete(`/api/alert/${alertId}`)
+ .set('kbn-xsrf', 'foo')
+ .expect(204, '');
+ await supertest
+ .delete(`/s/space_1/api/alert/${space1AlertId}`)
.set('kbn-xsrf', 'foo')
.expect(204, '');
await esArchiver.unload('actions/basic');
@@ -39,7 +52,21 @@ export default function createEnableAlertTests({
it('should return 204 when enabling an alert', async () => {
await supertest
- .post(`/api/alert/${createdAlert.id}/_enable`)
+ .post(`/api/alert/${alertId}/_enable`)
+ .set('kbn-xsrf', 'foo')
+ .expect(204);
+ });
+
+ it('should return 404 when enabling an alert from another space', async () => {
+ await supertest
+ .post(`/api/alert/${space1AlertId}/_enable`)
+ .set('kbn-xsrf', 'foo')
+ .expect(404);
+ });
+
+ it('should return 204 when enabling an alert in a space', async () => {
+ await supertest
+ .post(`/s/space_1/api/alert/${space1AlertId}/_enable`)
.set('kbn-xsrf', 'foo')
.expect(204);
});
diff --git a/x-pack/test/api_integration/apis/alerting/find.ts b/x-pack/test/api_integration/apis/alerting/find.ts
index 14b207db001b6..d438291ee212e 100644
--- a/x-pack/test/api_integration/apis/alerting/find.ts
+++ b/x-pack/test/api_integration/apis/alerting/find.ts
@@ -16,6 +16,7 @@ export default function createFindTests({ getService }: KibanaFunctionalTestDefa
describe('find', () => {
let alertId: string;
+ let space1AlertId: string;
before(async () => {
await esArchiver.load('actions/basic');
@@ -27,12 +28,24 @@ export default function createFindTests({ getService }: KibanaFunctionalTestDefa
.then((resp: any) => {
alertId = resp.body.id;
});
+ await supertest
+ .post('/s/space_1/api/alert')
+ .set('kbn-xsrf', 'foo')
+ .send(getTestAlertData())
+ .expect(200)
+ .then((resp: any) => {
+ space1AlertId = resp.body.id;
+ });
});
after(async () => {
await supertest
.delete(`/api/alert/${alertId}`)
.set('kbn-xsrf', 'foo')
.expect(204, '');
+ await supertest
+ .delete(`/s/space_1/api/alert/${space1AlertId}`)
+ .set('kbn-xsrf', 'foo')
+ .expect(204, '');
await esArchiver.unload('actions/basic');
});
@@ -66,5 +79,32 @@ export default function createFindTests({ getService }: KibanaFunctionalTestDefa
});
});
});
+
+ it('should return 200 when finding alerts in a space', async () => {
+ await supertest
+ .get('/s/space_1/api/alert/_find')
+ .expect(200)
+ .then((resp: any) => {
+ const match = resp.body.data.find((obj: any) => obj.id === space1AlertId);
+ expect(match).to.eql({
+ id: space1AlertId,
+ alertTypeId: 'test.noop',
+ interval: '10s',
+ enabled: true,
+ actions: [
+ {
+ group: 'default',
+ id: ES_ARCHIVER_ACTION_ID,
+ params: {
+ message:
+ 'instanceContextValue: {{context.instanceContextValue}}, instanceStateValue: {{state.instanceStateValue}}',
+ },
+ },
+ ],
+ alertTypeParams: {},
+ scheduledTaskId: match.scheduledTaskId,
+ });
+ });
+ });
});
}
diff --git a/x-pack/test/api_integration/apis/alerting/get.ts b/x-pack/test/api_integration/apis/alerting/get.ts
index d201307949f57..bb39c38a64e21 100644
--- a/x-pack/test/api_integration/apis/alerting/get.ts
+++ b/x-pack/test/api_integration/apis/alerting/get.ts
@@ -16,6 +16,7 @@ export default function createGetTests({ getService }: KibanaFunctionalTestDefau
describe('get', () => {
let alertId: string;
+ let space1AlertId: string;
before(async () => {
await esArchiver.load('actions/basic');
@@ -27,12 +28,24 @@ export default function createGetTests({ getService }: KibanaFunctionalTestDefau
.then((resp: any) => {
alertId = resp.body.id;
});
+ await supertest
+ .post('/s/space_1/api/alert')
+ .set('kbn-xsrf', 'foo')
+ .send(getTestAlertData())
+ .expect(200)
+ .then((resp: any) => {
+ space1AlertId = resp.body.id;
+ });
});
after(async () => {
await supertest
.delete(`/api/alert/${alertId}`)
.set('kbn-xsrf', 'foo')
.expect(204, '');
+ await supertest
+ .delete(`/s/space_1/api/alert/${space1AlertId}`)
+ .set('kbn-xsrf', 'foo')
+ .expect(204, '');
await esArchiver.unload('actions/basic');
});
@@ -61,5 +74,35 @@ export default function createGetTests({ getService }: KibanaFunctionalTestDefau
});
});
});
+
+ it('should return 404 when gettin an alert in another space', async () => {
+ await supertest.get(`/api/alert/${space1AlertId}`).expect(404);
+ });
+
+ it('should return 200 when getting an alert in a space', async () => {
+ await supertest
+ .get(`/s/space_1/api/alert/${space1AlertId}`)
+ .expect(200)
+ .then((resp: any) => {
+ expect(resp.body).to.eql({
+ id: space1AlertId,
+ alertTypeId: 'test.noop',
+ interval: '10s',
+ enabled: true,
+ actions: [
+ {
+ group: 'default',
+ id: ES_ARCHIVER_ACTION_ID,
+ params: {
+ message:
+ 'instanceContextValue: {{context.instanceContextValue}}, instanceStateValue: {{state.instanceStateValue}}',
+ },
+ },
+ ],
+ alertTypeParams: {},
+ scheduledTaskId: resp.body.scheduledTaskId,
+ });
+ });
+ });
});
}
diff --git a/x-pack/test/api_integration/apis/alerting/update.ts b/x-pack/test/api_integration/apis/alerting/update.ts
index 4c50f48244133..b08489fcef3b7 100644
--- a/x-pack/test/api_integration/apis/alerting/update.ts
+++ b/x-pack/test/api_integration/apis/alerting/update.ts
@@ -6,7 +6,7 @@
import expect from '@kbn/expect';
import { getTestAlertData } from './utils';
-import { ES_ARCHIVER_ACTION_ID } from './constants';
+import { ES_ARCHIVER_ACTION_ID, SPACE_1_ES_ARCHIVER_ACTION_ID } from './constants';
import { KibanaFunctionalTestDefaultProviders } from '../../../types/providers';
// eslint-disable-next-line import/no-default-export
@@ -15,7 +15,8 @@ export default function createUpdateTests({ getService }: KibanaFunctionalTestDe
const esArchiver = getService('esArchiver');
describe('update', () => {
- let createdAlert: any;
+ let alertId: string;
+ let space1AlertId: string;
before(async () => {
await esArchiver.load('actions/basic');
@@ -25,20 +26,62 @@ export default function createUpdateTests({ getService }: KibanaFunctionalTestDe
.send(getTestAlertData())
.expect(200)
.then((resp: any) => {
- createdAlert = resp.body;
+ alertId = resp.body.id;
+ });
+ await supertest
+ .post('/s/space_1/api/alert')
+ .set('kbn-xsrf', 'foo')
+ .send(getTestAlertData())
+ .expect(200)
+ .then((resp: any) => {
+ space1AlertId = resp.body.id;
});
});
after(async () => {
await supertest
- .delete(`/api/alert/${createdAlert.id}`)
+ .delete(`/api/alert/${alertId}`)
+ .set('kbn-xsrf', 'foo')
+ .expect(204, '');
+ await supertest
+ .delete(`/s/space_1/api/alert/${space1AlertId}`)
.set('kbn-xsrf', 'foo')
.expect(204, '');
await esArchiver.unload('actions/basic');
});
it('should return 200 when updating an alert', async () => {
+ const alert = {
+ alertTypeParams: {
+ foo: true,
+ },
+ interval: '12s',
+ actions: [
+ {
+ group: 'default',
+ id: ES_ARCHIVER_ACTION_ID,
+ params: {
+ message:
+ 'UPDATED: instanceContextValue: {{context.instanceContextValue}}, instanceStateValue: {{state.instanceStateValue}}',
+ },
+ },
+ ],
+ };
await supertest
- .put(`/api/alert/${createdAlert.id}`)
+ .put(`/api/alert/${alertId}`)
+ .set('kbn-xsrf', 'foo')
+ .send(alert)
+ .expect(200)
+ .then((resp: any) => {
+ expect(resp.body).to.eql({
+ ...alert,
+ id: alertId,
+ });
+ });
+ });
+
+ it('should return 404 when updating an alert from another space', async () => {
+ await supertest
+ .put(`/api/alert/${space1AlertId}`)
.set('kbn-xsrf', 'foo')
.send({
alertTypeParams: {
@@ -56,31 +99,42 @@ export default function createUpdateTests({ getService }: KibanaFunctionalTestDe
},
],
})
+ .expect(404);
+ });
+
+ it('should return 200 when updating an alert in a space', async () => {
+ const alert = {
+ alertTypeParams: {
+ foo: true,
+ },
+ interval: '12s',
+ actions: [
+ {
+ group: 'default',
+ id: SPACE_1_ES_ARCHIVER_ACTION_ID,
+ params: {
+ message:
+ 'UPDATED: instanceContextValue: {{context.instanceContextValue}}, instanceStateValue: {{state.instanceStateValue}}',
+ },
+ },
+ ],
+ };
+ await supertest
+ .put(`/s/space_1/api/alert/${space1AlertId}`)
+ .set('kbn-xsrf', 'foo')
+ .send(alert)
.expect(200)
.then((resp: any) => {
expect(resp.body).to.eql({
- id: createdAlert.id,
- alertTypeParams: {
- foo: true,
- },
- interval: '12s',
- actions: [
- {
- group: 'default',
- id: ES_ARCHIVER_ACTION_ID,
- params: {
- message:
- 'UPDATED: instanceContextValue: {{context.instanceContextValue}}, instanceStateValue: {{state.instanceStateValue}}',
- },
- },
- ],
+ ...alert,
+ id: space1AlertId,
});
});
});
it('should return 400 when attempting to change alert type', async () => {
await supertest
- .put(`/api/alert/${createdAlert.id}`)
+ .put(`/api/alert/${alertId}`)
.set('kbn-xsrf', 'foo')
.send({
alertTypeId: '1',
@@ -115,7 +169,7 @@ export default function createUpdateTests({ getService }: KibanaFunctionalTestDe
it('should return 400 when payload is empty and invalid', async () => {
await supertest
- .put(`/api/alert/${createdAlert.id}`)
+ .put(`/api/alert/${alertId}`)
.set('kbn-xsrf', 'foo')
.send({})
.expect(400)
@@ -167,7 +221,7 @@ export default function createUpdateTests({ getService }: KibanaFunctionalTestDe
it(`should return 400 when interval is wrong syntax`, async () => {
const { body: error } = await supertest
- .put(`/api/alert/${createdAlert.id}`)
+ .put(`/api/alert/${alertId}`)
.set('kbn-xsrf', 'foo')
.send(getTestAlertData({ interval: '10x', enabled: undefined }))
.expect(400);
diff --git a/x-pack/test/functional/es_archives/actions/basic/data.json b/x-pack/test/functional/es_archives/actions/basic/data.json
index 2049fcd3f1b8c..b8dc9e307ee9e 100644
--- a/x-pack/test/functional/es_archives/actions/basic/data.json
+++ b/x-pack/test/functional/es_archives/actions/basic/data.json
@@ -48,3 +48,22 @@
}
}
}
+
+{
+ "value": {
+ "id" : "space_1:action:6c7d0f6b-2fb5-4821-b182-624fc3ccc7a3",
+ "index" : ".kibana",
+ "source" : {
+ "action" : {
+ "description" : "My action",
+ "actionTypeId" : "test.index-record",
+ "config" : {
+ "unencrypted" : "This value shouldn't get encrypted"
+ },
+ "secrets" : "LEepwqGVUSkkAZSYCGDz3Y0DGoRgBGPRnu+Ta0jmEz+TiGUj3SBYWL6t2jqncBhsWgzSzwCusY+z5B/k+4wjaXW5t/KxNZP7bGpLQK0hL9IwKxqmRzRbEvX0nzeExxgfSaMRjjn2SnrE21MTw6qyBwGNqnuvmN7ILde4ZUbR9Jyjl8A6Y0GDcWvN"
+ },
+ "type": "action",
+ "namespace": "space_1"
+ }
+ }
+}