[Ingest Manager] Support registration of server side callbacks for Create Datasource API (#69428)

* Ingest: Expose `registerExternalCallback()` method out of Ingest server `start` lifecycle
* Ingest: Add support for External Callbacks on REST `createDatasourceHandler()`
* Ingest: expose DatasourceServices to Plugin start interface
* Endpoint: Added Endpoint Ingest handler for Create Datasources
  - Also moved the temporary logic from the middleware
    to the handler (still temporary)

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
Paul Tavares 2020-06-24 15:16:15 -04:00 committed by GitHub
parent 904be0249b
commit a104e5ab0e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 553 additions and 48 deletions

View file

@ -11,6 +11,7 @@ export {
IngestManagerSetupContract,
IngestManagerSetupDeps,
IngestManagerStartContract,
ExternalCallback,
} from './plugin';
export const config = {
@ -42,6 +43,8 @@ export const config = {
export type IngestManagerConfigType = TypeOf<typeof config.schema>;
export { DatasourceServiceInterface } from './services/datasource';
export const plugin = (initializerContext: PluginInitializerContext) => {
return new IngestManagerPlugin(initializerContext);
};

View file

@ -0,0 +1,36 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { loggingSystemMock, savedObjectsServiceMock } from 'src/core/server/mocks';
import { IngestManagerAppContext } from './plugin';
import { encryptedSavedObjectsMock } from '../../encrypted_saved_objects/server/mocks';
import { securityMock } from '../../security/server/mocks';
import { DatasourceServiceInterface } from './services/datasource';
export const createAppContextStartContractMock = (): IngestManagerAppContext => {
return {
encryptedSavedObjectsStart: encryptedSavedObjectsMock.createStart(),
savedObjects: savedObjectsServiceMock.createStartContract(),
security: securityMock.createSetup(),
logger: loggingSystemMock.create().get(),
isProductionMode: true,
kibanaVersion: '8.0.0',
};
};
export const createDatasourceServiceMock = () => {
return {
assignPackageStream: jest.fn(),
buildDatasourceFromPackage: jest.fn(),
bulkCreate: jest.fn(),
create: jest.fn(),
delete: jest.fn(),
get: jest.fn(),
getByIDs: jest.fn(),
list: jest.fn(),
update: jest.fn(),
} as jest.Mocked<DatasourceServiceInterface>;
};

View file

@ -45,13 +45,14 @@ import {
registerSettingsRoutes,
registerAppRoutes,
} from './routes';
import { IngestManagerConfigType } from '../common';
import { IngestManagerConfigType, NewDatasource } from '../common';
import {
appContextService,
licenseService,
ESIndexPatternSavedObjectService,
ESIndexPatternService,
AgentService,
datasourceService,
} from './services';
import { getAgentStatusById } from './services/agents';
import { CloudSetup } from '../../cloud/server';
@ -92,12 +93,31 @@ const allSavedObjectTypes = [
ENROLLMENT_API_KEYS_SAVED_OBJECT_TYPE,
];
/**
* Callbacks supported by the Ingest plugin
*/
export type ExternalCallback = [
'datasourceCreate',
(newDatasource: NewDatasource) => Promise<NewDatasource>
];
export type ExternalCallbacksStorage = Map<ExternalCallback[0], Set<ExternalCallback[1]>>;
/**
* Describes public IngestManager plugin contract returned at the `startup` stage.
*/
export interface IngestManagerStartContract {
esIndexPatternService: ESIndexPatternService;
agentService: AgentService;
/**
* Services for Ingest's Datasources
*/
datasourceService: typeof datasourceService;
/**
* Register callbacks for inclusion in ingest API processing
* @param args
*/
registerExternalCallback: (...args: ExternalCallback) => void;
}
export class IngestManagerPlugin
@ -237,6 +257,10 @@ export class IngestManagerPlugin
agentService: {
getAgentStatusById,
},
datasourceService,
registerExternalCallback: (...args: ExternalCallback) => {
return appContextService.addExternalCallback(...args);
},
};
}

View file

@ -0,0 +1,332 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { httpServerMock, httpServiceMock } from 'src/core/server/mocks';
import { IRouter, KibanaRequest, Logger, RequestHandler, RouteConfig } from 'kibana/server';
import { registerRoutes } from './index';
import { DATASOURCE_API_ROUTES } from '../../../common/constants';
import { xpackMocks } from '../../../../../mocks';
import { appContextService } from '../../services';
import { createAppContextStartContractMock } from '../../mocks';
import { DatasourceServiceInterface, ExternalCallback } from '../..';
import { CreateDatasourceRequestSchema } from '../../types/rest_spec';
import { datasourceService } from '../../services';
const datasourceServiceMock = datasourceService as jest.Mocked<DatasourceServiceInterface>;
jest.mock('../../services/datasource', (): {
datasourceService: jest.Mocked<DatasourceServiceInterface>;
} => {
return {
datasourceService: {
assignPackageStream: jest.fn((packageInfo, dataInputs) => Promise.resolve(dataInputs)),
buildDatasourceFromPackage: jest.fn(),
bulkCreate: jest.fn(),
create: jest.fn((soClient, newData) =>
Promise.resolve({
...newData,
id: '1',
revision: 1,
updated_at: new Date().toISOString(),
updated_by: 'elastic',
created_at: new Date().toISOString(),
created_by: 'elastic',
})
),
delete: jest.fn(),
get: jest.fn(),
getByIDs: jest.fn(),
list: jest.fn(),
update: jest.fn(),
},
};
});
jest.mock('../../services/epm/packages', () => {
return {
ensureInstalledPackage: jest.fn(() => Promise.resolve()),
getPackageInfo: jest.fn(() => Promise.resolve()),
};
});
describe('When calling datasource', () => {
let routerMock: jest.Mocked<IRouter>;
let routeHandler: RequestHandler<any, any, any>;
let routeConfig: RouteConfig<any, any, any, any>;
let context: ReturnType<typeof xpackMocks.createRequestHandlerContext>;
let response: ReturnType<typeof httpServerMock.createResponseFactory>;
beforeAll(() => {
routerMock = httpServiceMock.createRouter();
registerRoutes(routerMock);
});
beforeEach(() => {
appContextService.start(createAppContextStartContractMock());
context = xpackMocks.createRequestHandlerContext();
response = httpServerMock.createResponseFactory();
});
afterEach(() => {
jest.clearAllMocks();
appContextService.stop();
});
describe('create api handler', () => {
const getCreateKibanaRequest = (
newData?: typeof CreateDatasourceRequestSchema.body
): KibanaRequest<undefined, undefined, typeof CreateDatasourceRequestSchema.body> => {
return httpServerMock.createKibanaRequest<
undefined,
undefined,
typeof CreateDatasourceRequestSchema.body
>({
path: routeConfig.path,
method: 'post',
body: newData || {
name: 'endpoint-1',
description: '',
config_id: 'a5ca00c0-b30c-11ea-9732-1bb05811278c',
enabled: true,
output_id: '',
inputs: [],
namespace: 'default',
package: { name: 'endpoint', title: 'Elastic Endpoint', version: '0.5.0' },
},
});
};
// Set the routeConfig and routeHandler to the Create API
beforeAll(() => {
[routeConfig, routeHandler] = routerMock.post.mock.calls.find(([{ path }]) =>
path.startsWith(DATASOURCE_API_ROUTES.CREATE_PATTERN)
)!;
});
describe('and external callbacks are registered', () => {
const callbackCallingOrder: string[] = [];
// Callback one adds an input that includes a `config` property
const callbackOne: ExternalCallback[1] = jest.fn(async (ds) => {
callbackCallingOrder.push('one');
const newDs = {
...ds,
inputs: [
{
type: 'endpoint',
enabled: true,
streams: [],
config: {
one: {
value: 'inserted by callbackOne',
},
},
},
],
};
return newDs;
});
// Callback two adds an additional `input[0].config` property
const callbackTwo: ExternalCallback[1] = jest.fn(async (ds) => {
callbackCallingOrder.push('two');
const newDs = {
...ds,
inputs: [
{
...ds.inputs[0],
config: {
...ds.inputs[0].config,
two: {
value: 'inserted by callbackTwo',
},
},
},
],
};
return newDs;
});
beforeEach(() => {
appContextService.addExternalCallback('datasourceCreate', callbackOne);
appContextService.addExternalCallback('datasourceCreate', callbackTwo);
});
afterEach(() => (callbackCallingOrder.length = 0));
it('should call external callbacks in expected order', async () => {
const request = getCreateKibanaRequest();
await routeHandler(context, request, response);
expect(response.ok).toHaveBeenCalled();
expect(callbackCallingOrder).toEqual(['one', 'two']);
});
it('should feed datasource returned by last callback', async () => {
const request = getCreateKibanaRequest();
await routeHandler(context, request, response);
expect(response.ok).toHaveBeenCalled();
expect(callbackOne).toHaveBeenCalledWith({
config_id: 'a5ca00c0-b30c-11ea-9732-1bb05811278c',
description: '',
enabled: true,
inputs: [],
name: 'endpoint-1',
namespace: 'default',
output_id: '',
package: {
name: 'endpoint',
title: 'Elastic Endpoint',
version: '0.5.0',
},
});
expect(callbackTwo).toHaveBeenCalledWith({
config_id: 'a5ca00c0-b30c-11ea-9732-1bb05811278c',
description: '',
enabled: true,
inputs: [
{
type: 'endpoint',
enabled: true,
streams: [],
config: {
one: {
value: 'inserted by callbackOne',
},
},
},
],
name: 'endpoint-1',
namespace: 'default',
output_id: '',
package: {
name: 'endpoint',
title: 'Elastic Endpoint',
version: '0.5.0',
},
});
});
it('should create with data from callback', async () => {
const request = getCreateKibanaRequest();
await routeHandler(context, request, response);
expect(response.ok).toHaveBeenCalled();
expect(datasourceServiceMock.create.mock.calls[0][1]).toEqual({
config_id: 'a5ca00c0-b30c-11ea-9732-1bb05811278c',
description: '',
enabled: true,
inputs: [
{
config: {
one: {
value: 'inserted by callbackOne',
},
two: {
value: 'inserted by callbackTwo',
},
},
enabled: true,
streams: [],
type: 'endpoint',
},
],
name: 'endpoint-1',
namespace: 'default',
output_id: '',
package: {
name: 'endpoint',
title: 'Elastic Endpoint',
version: '0.5.0',
},
});
});
describe('and a callback throws an exception', () => {
const callbackThree: ExternalCallback[1] = jest.fn(async (ds) => {
callbackCallingOrder.push('three');
throw new Error('callbackThree threw error on purpose');
});
const callbackFour: ExternalCallback[1] = jest.fn(async (ds) => {
callbackCallingOrder.push('four');
return {
...ds,
inputs: [
{
...ds.inputs[0],
config: {
...ds.inputs[0].config,
four: {
value: 'inserted by callbackFour',
},
},
},
],
};
});
beforeEach(() => {
appContextService.addExternalCallback('datasourceCreate', callbackThree);
appContextService.addExternalCallback('datasourceCreate', callbackFour);
});
it('should skip over callback exceptions and still execute other callbacks', async () => {
const request = getCreateKibanaRequest();
await routeHandler(context, request, response);
expect(response.ok).toHaveBeenCalled();
expect(callbackCallingOrder).toEqual(['one', 'two', 'three', 'four']);
});
it('should log errors', async () => {
const errorLogger = (appContextService.getLogger() as jest.Mocked<Logger>).error;
const request = getCreateKibanaRequest();
await routeHandler(context, request, response);
expect(response.ok).toHaveBeenCalled();
expect(errorLogger.mock.calls).toEqual([
['An external registered [datasourceCreate] callback failed when executed'],
[new Error('callbackThree threw error on purpose')],
]);
});
it('should create datasource with last successful returned datasource', async () => {
const request = getCreateKibanaRequest();
await routeHandler(context, request, response);
expect(response.ok).toHaveBeenCalled();
expect(datasourceServiceMock.create.mock.calls[0][1]).toEqual({
config_id: 'a5ca00c0-b30c-11ea-9732-1bb05811278c',
description: '',
enabled: true,
inputs: [
{
config: {
one: {
value: 'inserted by callbackOne',
},
two: {
value: 'inserted by callbackTwo',
},
four: {
value: 'inserted by callbackFour',
},
},
enabled: true,
streams: [],
type: 'endpoint',
},
],
name: 'endpoint-1',
namespace: 'default',
output_id: '',
package: {
name: 'endpoint',
title: 'Elastic Endpoint',
version: '0.5.0',
},
});
});
});
});
});
});

View file

@ -14,6 +14,7 @@ import {
CreateDatasourceRequestSchema,
UpdateDatasourceRequestSchema,
DeleteDatasourcesRequestSchema,
NewDatasource,
} from '../../types';
import { CreateDatasourceResponse, DeleteDatasourcesResponse } from '../../../common';
@ -76,23 +77,50 @@ export const createDatasourceHandler: RequestHandler<
const soClient = context.core.savedObjects.client;
const callCluster = context.core.elasticsearch.legacy.client.callAsCurrentUser;
const user = (await appContextService.getSecurity()?.authc.getCurrentUser(request)) || undefined;
const newData = { ...request.body };
const logger = appContextService.getLogger();
let newData = { ...request.body };
try {
// If we have external callbacks, then process those now before creating the actual datasource
const externalCallbacks = appContextService.getExternalCallbacks('datasourceCreate');
if (externalCallbacks && externalCallbacks.size > 0) {
let updatedNewData: NewDatasource = newData;
for (const callback of externalCallbacks) {
try {
// ensure that the returned value by the callback passes schema validation
updatedNewData = CreateDatasourceRequestSchema.body.validate(
await callback(updatedNewData)
);
} catch (error) {
// Log the error, but keep going and process the other callbacks
logger.error('An external registered [datasourceCreate] callback failed when executed');
logger.error(error);
}
}
// The type `NewDatasource` and the `DatasourceBaseSchema` are incompatible.
// `NewDatasrouce` defines `namespace` as optional string, which means that `undefined` is a
// valid value, however, the schema defines it as string with a minimum length of 1.
// Here, we need to cast the value back to the schema type and ignore the TS error.
// @ts-ignore
newData = updatedNewData as typeof CreateDatasourceRequestSchema.body;
}
// Make sure the datasource package is installed
if (request.body.package?.name) {
if (newData.package?.name) {
await ensureInstalledPackage({
savedObjectsClient: soClient,
pkgName: request.body.package.name,
pkgName: newData.package.name,
callCluster,
});
const pkgInfo = await getPackageInfo({
savedObjectsClient: soClient,
pkgName: request.body.package.name,
pkgVersion: request.body.package.version,
pkgName: newData.package.name,
pkgVersion: newData.package.version,
});
newData.inputs = (await datasourceService.assignPackageStream(
pkgInfo,
request.body.inputs
newData.inputs
)) as TypeOf<typeof CreateDatasourceRequestSchema.body>['inputs'];
}
@ -103,6 +131,7 @@ export const createDatasourceHandler: RequestHandler<
body,
});
} catch (e) {
logger.error(e);
return response.customError({
statusCode: 500,
body: { message: e.message },

View file

@ -12,7 +12,7 @@ import {
} from '../../../encrypted_saved_objects/server';
import { SecurityPluginSetup } from '../../../security/server';
import { IngestManagerConfigType } from '../../common';
import { IngestManagerAppContext } from '../plugin';
import { ExternalCallback, ExternalCallbacksStorage, IngestManagerAppContext } from '../plugin';
import { CloudSetup } from '../../../cloud/server';
class AppContextService {
@ -27,6 +27,7 @@ class AppContextService {
private cloud?: CloudSetup;
private logger: Logger | undefined;
private httpSetup?: HttpServiceSetup;
private externalCallbacks: ExternalCallbacksStorage = new Map();
public async start(appContext: IngestManagerAppContext) {
this.encryptedSavedObjects = appContext.encryptedSavedObjectsStart?.getClient();
@ -47,7 +48,9 @@ class AppContextService {
}
}
public stop() {}
public stop() {
this.externalCallbacks.clear();
}
public getEncryptedSavedObjects() {
if (!this.encryptedSavedObjects) {
@ -121,6 +124,19 @@ class AppContextService {
}
return this.kibanaVersion;
}
public addExternalCallback(type: ExternalCallback[0], callback: ExternalCallback[1]) {
if (!this.externalCallbacks.has(type)) {
this.externalCallbacks.set(type, new Set());
}
this.externalCallbacks.get(type)!.add(callback);
}
public getExternalCallbacks(type: ExternalCallback[0]) {
if (this.externalCallbacks) {
return this.externalCallbacks.get(type);
}
}
}
export const appContextService = new AppContextService();

View file

@ -307,4 +307,5 @@ async function _assignPackageStreamToStream(
return { ...stream };
}
export type DatasourceServiceInterface = DatasourceService;
export const datasourceService = new DatasourceService();

View file

@ -17,7 +17,6 @@ import {
sendPutDatasource,
} from '../policy_list/services/ingest';
import { NewPolicyData, PolicyData } from '../../../../../../common/endpoint/types';
import { factory as policyConfigFactory } from '../../../../../../common/endpoint/models/policy_config';
import { ImmutableMiddlewareFactory } from '../../../../../common/store';
export const policyDetailsMiddlewareFactory: ImmutableMiddlewareFactory<PolicyDetailsState> = (
@ -43,23 +42,6 @@ export const policyDetailsMiddlewareFactory: ImmutableMiddlewareFactory<PolicyDe
return;
}
// Until we get the Default configuration into the Endpoint package so that the datasource has
// the expected data structure, we will add it here manually.
if (!policyItem.inputs.length) {
policyItem.inputs = [
{
type: 'endpoint',
enabled: true,
streams: [],
config: {
policy: {
value: policyConfigFactory(),
},
},
},
];
}
dispatch({
type: 'serverReturnedPolicyDetailsData',
payload: {

View file

@ -11,7 +11,7 @@ import {
} from '../../../../../../../src/core/server/mocks';
import { registerAlertRoutes } from '../routes';
import { alertingIndexGetQuerySchema } from '../../../../common/endpoint_alerts/schema/alert_index';
import { createMockAgentService } from '../../mocks';
import { createMockEndpointAppContextServiceStartContract } from '../../mocks';
import { EndpointAppContextService } from '../../endpoint_app_context_services';
import { createMockConfig } from '../../../lib/detection_engine/routes/__mocks__';
@ -28,9 +28,7 @@ describe('test alerts route', () => {
routerMock = httpServiceMock.createRouter();
endpointAppContextService = new EndpointAppContextService();
endpointAppContextService.start({
agentService: createMockAgentService(),
});
endpointAppContextService.start(createMockEndpointAppContextServiceStartContract());
registerAlertRoutes(routerMock, {
logFactory: loggingSystemMock.create(),

View file

@ -3,7 +3,15 @@
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { AgentService } from '../../../ingest_manager/server';
import { AgentService, IngestManagerStartContract } from '../../../ingest_manager/server';
import { handleDatasourceCreate } from './ingest_integration';
export type EndpointAppContextServiceStartContract = Pick<
IngestManagerStartContract,
'agentService'
> & {
registerIngestCallback: IngestManagerStartContract['registerExternalCallback'];
};
/**
* A singleton that holds shared services that are initialized during the start up phase
@ -12,8 +20,9 @@ import { AgentService } from '../../../ingest_manager/server';
export class EndpointAppContextService {
private agentService: AgentService | undefined;
public start(dependencies: { agentService: AgentService }) {
public start(dependencies: EndpointAppContextServiceStartContract) {
this.agentService = dependencies.agentService;
dependencies.registerIngestCallback('datasourceCreate', handleDatasourceCreate);
}
public stop() {}

View file

@ -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;
* you may not use this file except in compliance with the Elastic License.
*/
import { factory as policyConfigFactory } from '../../common/endpoint/models/policy_config';
import { NewPolicyData } from '../../common/endpoint/types';
import { NewDatasource } from '../../../ingest_manager/common/types/models';
/**
* Callback to handle creation of Datasources in Ingest Manager
* @param newDatasource
*/
export const handleDatasourceCreate = async (
newDatasource: NewDatasource
): Promise<NewDatasource> => {
// We only care about Endpoint datasources
if (newDatasource.package?.name !== 'endpoint') {
return newDatasource;
}
// We cast the type here so that any changes to the Endpoint specific data
// follow the types/schema expected
let updatedDatasource = newDatasource as NewPolicyData;
// Until we get the Default Policy Configuration in the Endpoint package,
// we will add it here manually at creation time.
// @ts-ignore
if (newDatasource.inputs.length === 0) {
updatedDatasource = {
...newDatasource,
inputs: [
{
type: 'endpoint',
enabled: true,
streams: [],
config: {
policy: {
value: policyConfigFactory(),
},
},
},
],
};
}
return updatedDatasource;
};

View file

@ -6,7 +6,28 @@
import { IScopedClusterClient, SavedObjectsClientContract } from 'kibana/server';
import { xpackMocks } from '../../../../mocks';
import { AgentService, IngestManagerStartContract } from '../../../ingest_manager/server';
import {
AgentService,
IngestManagerStartContract,
ExternalCallback,
} from '../../../ingest_manager/server';
import { EndpointAppContextServiceStartContract } from './endpoint_app_context_services';
import { createDatasourceServiceMock } from '../../../ingest_manager/server/mocks';
/**
* Crates a mocked input contract for the `EndpointAppContextService#start()` method
*/
export const createMockEndpointAppContextServiceStartContract = (): jest.Mocked<
EndpointAppContextServiceStartContract
> => {
return {
agentService: createMockAgentService(),
registerIngestCallback: jest.fn<
ReturnType<IngestManagerStartContract['registerExternalCallback']>,
Parameters<IngestManagerStartContract['registerExternalCallback']>
>(),
};
};
/**
* Creates a mock AgentService
@ -32,6 +53,8 @@ export const createMockIngestManagerStartContract = (
getESIndexPattern: jest.fn().mockResolvedValue(indexPattern),
},
agentService: createMockAgentService(),
registerExternalCallback: jest.fn((...args: ExternalCallback) => {}),
datasourceService: createDatasourceServiceMock(),
};
};

View file

@ -27,8 +27,10 @@ import {
} from '../../../../common/endpoint/types';
import { SearchResponse } from 'elasticsearch';
import { registerEndpointRoutes } from './index';
import { createMockAgentService, createRouteHandlerContext } from '../../mocks';
import { AgentService } from '../../../../../ingest_manager/server';
import {
createMockEndpointAppContextServiceStartContract,
createRouteHandlerContext,
} from '../../mocks';
import Boom from 'boom';
import { EndpointAppContextService } from '../../endpoint_app_context_services';
import { createMockConfig } from '../../../lib/detection_engine/routes/__mocks__';
@ -44,7 +46,9 @@ describe('test endpoint route', () => {
let routeHandler: RequestHandler<any, any, any>;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let routeConfig: RouteConfig<any, any, any, any>;
let mockAgentService: jest.Mocked<AgentService>;
let mockAgentService: ReturnType<
typeof createMockEndpointAppContextServiceStartContract
>['agentService'];
let endpointAppContextService: EndpointAppContextService;
beforeEach(() => {
@ -56,11 +60,10 @@ describe('test endpoint route', () => {
mockClusterClient.asScoped.mockReturnValue(mockScopedClient);
routerMock = httpServiceMock.createRouter();
mockResponse = httpServerMock.createResponseFactory();
mockAgentService = createMockAgentService();
endpointAppContextService = new EndpointAppContextService();
endpointAppContextService.start({
agentService: mockAgentService,
});
const startContract = createMockEndpointAppContextServiceStartContract();
endpointAppContextService.start(startContract);
mockAgentService = startContract.agentService;
registerEndpointRoutes(routerMock, {
logFactory: loggingSystemMock.create(),

View file

@ -4,7 +4,10 @@
* you may not use this file except in compliance with the Elastic License.
*/
import { EndpointAppContextService } from '../../endpoint_app_context_services';
import { createMockAgentService, createRouteHandlerContext } from '../../mocks';
import {
createMockEndpointAppContextServiceStartContract,
createRouteHandlerContext,
} from '../../mocks';
import { getHostPolicyResponseHandler } from './handlers';
import {
IScopedClusterClient,
@ -17,7 +20,6 @@ import {
loggingSystemMock,
savedObjectsClientMock,
} from '../../../../../../../src/core/server/mocks';
import { AgentService } from '../../../../../ingest_manager/server/services';
import { SearchResponse } from 'elasticsearch';
import { GetHostPolicyResponse, HostPolicyResponse } from '../../../../common/endpoint/types';
import { EndpointDocGenerator } from '../../../../common/endpoint/generate_data';
@ -28,17 +30,13 @@ describe('test policy response handler', () => {
let mockScopedClient: jest.Mocked<IScopedClusterClient>;
let mockSavedObjectClient: jest.Mocked<SavedObjectsClientContract>;
let mockResponse: jest.Mocked<KibanaResponseFactory>;
let mockAgentService: jest.Mocked<AgentService>;
beforeEach(() => {
mockScopedClient = elasticsearchServiceMock.createScopedClusterClient();
mockSavedObjectClient = savedObjectsClientMock.create();
mockResponse = httpServerMock.createResponseFactory();
endpointAppContextService = new EndpointAppContextService();
mockAgentService = createMockAgentService();
endpointAppContextService.start({
agentService: mockAgentService,
});
endpointAppContextService.start(createMockEndpointAppContextServiceStartContract());
});
afterEach(() => endpointAppContextService.stop());

View file

@ -219,7 +219,9 @@ export class Plugin implements IPlugin<PluginSetup, PluginStart, SetupPlugins, S
public start(core: CoreStart, plugins: StartPlugins) {
this.endpointAppContextService.start({
agentService: plugins.ingestManager.agentService,
registerIngestCallback: plugins.ingestManager.registerExternalCallback,
});
return {};
}