mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
Ping the response-ops team whenever a new connector type is registered (#144736)
Similar to https://github.com/elastic/kibana/pull/144196 and https://github.com/elastic/kibana/pull/144424. In this PR, I'm making the Response Ops team get pinged whenever a new connector type is added. I also renamed two connector types in our test suite to keep the array I'm asserting clean (from test connectors). - `.test-sub-action-connector` -> `test.sub-action-connector` - `.test-sub-action-connector-without-sub-actions` -> `test.sub-action-connector-without-sub-actions` Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
a7fdac4564
commit
08eb63af67
12 changed files with 116 additions and 12 deletions
|
@ -13,6 +13,7 @@ const createActionTypeRegistryMock = () => {
|
|||
register: jest.fn(),
|
||||
get: jest.fn(),
|
||||
list: jest.fn(),
|
||||
getAllTypes: jest.fn(),
|
||||
ensureActionTypeEnabled: jest.fn(),
|
||||
isActionTypeEnabled: jest.fn(),
|
||||
isActionExecutable: jest.fn(),
|
||||
|
|
|
@ -474,3 +474,27 @@ describe('isActionExecutable()', () => {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('getAllTypes()', () => {
|
||||
test('should return empty when notihing is registered', () => {
|
||||
const registry = new ActionTypeRegistry(actionTypeRegistryParams);
|
||||
const result = registry.getAllTypes();
|
||||
expect(result).toEqual([]);
|
||||
});
|
||||
|
||||
test('should return list of registered type ids', () => {
|
||||
mockedLicenseState.isLicenseValidForActionType.mockReturnValue({ isValid: true });
|
||||
const registry = new ActionTypeRegistry(actionTypeRegistryParams);
|
||||
registry.register({
|
||||
id: 'foo',
|
||||
name: 'Foo',
|
||||
minimumLicenseRequired: 'basic',
|
||||
supportedFeatureIds: ['alerting'],
|
||||
executor: async (options) => {
|
||||
return { status: 'ok', actionId: options.actionId };
|
||||
},
|
||||
});
|
||||
const result = registry.getAllTypes();
|
||||
expect(result).toEqual(['foo']);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -221,4 +221,8 @@ export class ActionTypeRegistry {
|
|||
public getUtils(): ActionsConfigurationUtilities {
|
||||
return this.actionsConfigUtils;
|
||||
}
|
||||
|
||||
public getAllTypes(): string[] {
|
||||
return [...this.list().map(({ id }) => id)];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ const createStartMock = () => {
|
|||
const mock: jest.Mocked<PluginStartContract> = {
|
||||
isActionTypeEnabled: jest.fn(),
|
||||
isActionExecutable: jest.fn(),
|
||||
getAllTypes: jest.fn(),
|
||||
getActionsClientWithRequest: jest.fn().mockResolvedValue(actionsClientMock.create()),
|
||||
getUnsecuredActionsClient: jest.fn().mockReturnValue(unsecuredActionsClientMock.create()),
|
||||
getActionsAuthorizationWithRequest: jest
|
||||
|
|
|
@ -137,6 +137,8 @@ export interface PluginStartContract {
|
|||
options?: { notifyUsage: boolean }
|
||||
): boolean;
|
||||
|
||||
getAllTypes: ActionTypeRegistry['getAllTypes'];
|
||||
|
||||
getActionsClientWithRequest(request: KibanaRequest): Promise<PublicMethodsOf<ActionsClient>>;
|
||||
|
||||
getActionsAuthorizationWithRequest(request: KibanaRequest): PublicMethodsOf<ActionsAuthorization>;
|
||||
|
@ -551,6 +553,7 @@ export class ActionsPlugin implements Plugin<PluginSetupContract, PluginStartCon
|
|||
) => {
|
||||
return this.actionTypeRegistry!.isActionExecutable(actionId, actionTypeId, options);
|
||||
},
|
||||
getAllTypes: actionTypeRegistry!.getAllTypes.bind(actionTypeRegistry),
|
||||
getActionsAuthorizationWithRequest(request: KibanaRequest) {
|
||||
return instantiateAuthorization(request);
|
||||
},
|
||||
|
|
|
@ -346,7 +346,7 @@ The actions framework exports the `registerSubActionConnectorType` to register s
|
|||
|
||||
```
|
||||
plugins.actions.registerSubActionConnectorType({
|
||||
id: '.test-sub-action-connector',
|
||||
id: 'test.sub-action-connector',
|
||||
name: 'Test: Sub action connector',
|
||||
minimumLicenseRequired: 'platinum' as const,
|
||||
schema: { config: TestConfigSchema, secrets: TestSecretsSchema },
|
||||
|
@ -363,7 +363,7 @@ The sub actions framework allows custom validators during registration of the co
|
|||
|
||||
```typescript
|
||||
plugins.actions.registerSubActionConnectorType({
|
||||
id: '.test-sub-action-connector',
|
||||
id: 'test.sub-action-connector',
|
||||
name: 'Test: Sub action connector',
|
||||
minimumLicenseRequired: 'platinum' as const,
|
||||
schema: { config: TestConfigSchema, secrets: TestSecretsSchema },
|
||||
|
|
|
@ -46,8 +46,8 @@ const enabledActionTypes = [
|
|||
'.slack',
|
||||
'.webhook',
|
||||
'.xmatters',
|
||||
'.test-sub-action-connector',
|
||||
'.test-sub-action-connector-without-sub-actions',
|
||||
'test.sub-action-connector',
|
||||
'test.sub-action-connector-without-sub-actions',
|
||||
'test.authorization',
|
||||
'test.failing',
|
||||
'test.index-record',
|
||||
|
|
|
@ -427,4 +427,25 @@ export function defineRoutes(
|
|||
}
|
||||
}
|
||||
);
|
||||
|
||||
router.get(
|
||||
{
|
||||
path: '/api/alerts_fixture/registered_connector_types',
|
||||
validate: {},
|
||||
},
|
||||
async (
|
||||
context: RequestHandlerContext,
|
||||
req: KibanaRequest<any, any, any, any>,
|
||||
res: KibanaResponseFactory
|
||||
): Promise<IKibanaResponse<any>> => {
|
||||
try {
|
||||
const [_, { actions }] = await core.getStartServices();
|
||||
return res.ok({
|
||||
body: actions.getAllTypes(),
|
||||
});
|
||||
} catch (e) {
|
||||
return res.badRequest({ body: e });
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
@ -80,7 +80,7 @@ export const getTestSubActionConnector = (
|
|||
public async noData() {}
|
||||
}
|
||||
return {
|
||||
id: '.test-sub-action-connector',
|
||||
id: 'test.sub-action-connector',
|
||||
name: 'Test: Sub action connector',
|
||||
minimumLicenseRequired: 'platinum' as const,
|
||||
supportedFeatureIds: ['alerting'],
|
||||
|
@ -101,7 +101,7 @@ export const getTestSubActionConnectorWithoutSubActions = (
|
|||
}
|
||||
|
||||
return {
|
||||
id: '.test-sub-action-connector-without-sub-actions',
|
||||
id: 'test.sub-action-connector-without-sub-actions',
|
||||
name: 'Test: Sub action connector',
|
||||
minimumLicenseRequired: 'platinum' as const,
|
||||
supportedFeatureIds: ['alerting'],
|
||||
|
|
|
@ -18,7 +18,7 @@ const createSubActionConnector = async ({
|
|||
supertest,
|
||||
config,
|
||||
secrets,
|
||||
connectorTypeId = '.test-sub-action-connector',
|
||||
connectorTypeId = 'test.sub-action-connector',
|
||||
expectedHttpCode = 200,
|
||||
}: {
|
||||
supertest: SuperTest.SuperTest<SuperTest.Test>;
|
||||
|
@ -94,7 +94,7 @@ export default function createActionTests({ getService }: FtrProviderContext) {
|
|||
is_deprecated: false,
|
||||
is_missing_secrets: false,
|
||||
name: 'My sub connector',
|
||||
connector_type_id: '.test-sub-action-connector',
|
||||
connector_type_id: 'test.sub-action-connector',
|
||||
config: {
|
||||
url: 'https://example.com',
|
||||
},
|
||||
|
@ -247,7 +247,7 @@ export default function createActionTests({ getService }: FtrProviderContext) {
|
|||
message: 'an error occurred while running the action',
|
||||
retry: true,
|
||||
connector_id: res.body.id,
|
||||
service_message: `Sub action \"notRegistered\" is not registered. Connector id: ${res.body.id}. Connector name: Test: Sub action connector. Connector type: .test-sub-action-connector`,
|
||||
service_message: `Sub action \"notRegistered\" is not registered. Connector id: ${res.body.id}. Connector name: Test: Sub action connector. Connector type: test.sub-action-connector`,
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -267,7 +267,7 @@ export default function createActionTests({ getService }: FtrProviderContext) {
|
|||
message: 'an error occurred while running the action',
|
||||
retry: true,
|
||||
connector_id: res.body.id,
|
||||
service_message: `Method \"notAFunction\" does not exists in service. Sub action: \"notAFunction\". Connector id: ${res.body.id}. Connector name: Test: Sub action connector. Connector type: .test-sub-action-connector`,
|
||||
service_message: `Method \"notAFunction\" does not exists in service. Sub action: \"notAFunction\". Connector id: ${res.body.id}. Connector name: Test: Sub action connector. Connector type: test.sub-action-connector`,
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -287,14 +287,14 @@ export default function createActionTests({ getService }: FtrProviderContext) {
|
|||
message: 'an error occurred while running the action',
|
||||
retry: true,
|
||||
connector_id: res.body.id,
|
||||
service_message: `Method \"notExist\" does not exists in service. Sub action: \"notExist\". Connector id: ${res.body.id}. Connector name: Test: Sub action connector. Connector type: .test-sub-action-connector`,
|
||||
service_message: `Method \"notExist\" does not exists in service. Sub action: \"notExist\". Connector id: ${res.body.id}. Connector name: Test: Sub action connector. Connector type: test.sub-action-connector`,
|
||||
});
|
||||
});
|
||||
|
||||
it('should return an error if there are no sub actions registered', async () => {
|
||||
const res = await createSubActionConnector({
|
||||
supertest,
|
||||
connectorTypeId: '.test-sub-action-connector-without-sub-actions',
|
||||
connectorTypeId: 'test.sub-action-connector-without-sub-actions',
|
||||
});
|
||||
objectRemover.add('default', res.body.id, 'action', 'actions');
|
||||
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License
|
||||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import expect from '@kbn/expect';
|
||||
import { FtrProviderContext } from '../../../common/ftr_provider_context';
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default function createRegisteredConnectorTypeTests({ getService }: FtrProviderContext) {
|
||||
const supertest = getService('supertest');
|
||||
|
||||
// This test is intended to fail when new connector types are registered.
|
||||
// To resolve, add the new connector type ID to this list. This will trigger
|
||||
// a CODEOWNERS review by Response Ops.
|
||||
describe('check registered connector types', () => {
|
||||
it('should list all registered connector types', async () => {
|
||||
const registeredConnectorTypes = await supertest
|
||||
.get('/api/alerts_fixture/registered_connector_types')
|
||||
.expect(200)
|
||||
.then((response) => response.body);
|
||||
|
||||
expect(
|
||||
registeredConnectorTypes.filter(
|
||||
(connectorType: string) => !connectorType.startsWith('test.')
|
||||
)
|
||||
).to.eql([
|
||||
'.email',
|
||||
'.index',
|
||||
'.pagerduty',
|
||||
'.swimlane',
|
||||
'.server-log',
|
||||
'.slack',
|
||||
'.webhook',
|
||||
'.cases-webhook',
|
||||
'.xmatters',
|
||||
'.servicenow',
|
||||
'.servicenow-sir',
|
||||
'.servicenow-itom',
|
||||
'.jira',
|
||||
'.resilient',
|
||||
'.teams',
|
||||
'.opsgenie',
|
||||
]);
|
||||
});
|
||||
});
|
||||
}
|
|
@ -29,6 +29,7 @@ export default function actionsTests({ loadTestFile, getService }: FtrProviderCo
|
|||
loadTestFile(require.resolve('./connector_types/stack/preconfigured_alert_history_connector'));
|
||||
loadTestFile(require.resolve('./type_not_enabled'));
|
||||
loadTestFile(require.resolve('./schedule_unsecured_action'));
|
||||
loadTestFile(require.resolve('./check_registered_connector_types'));
|
||||
|
||||
// note that this test will destroy existing spaces
|
||||
loadTestFile(require.resolve('./migrations'));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue