[Uptime] Monitor management stub crud routes (#119800) (#119865)

* fix uptime config key

* crud routes

* prefix

* test wip

* add tests

* revert

* fixed path

Co-authored-by: Shahzad <shahzad.muhammad@elastic.co>
This commit is contained in:
Kibana Machine 2021-11-29 13:49:14 -05:00 committed by GitHub
parent b605837bcf
commit 386835778e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 317 additions and 2 deletions

View file

@ -36,7 +36,7 @@ export const config: PluginConfigDescriptor = {
username: schema.string(),
password: schema.string(),
manifestUrl: schema.string(),
hosts: schema.arrayOf(schema.string()),
hosts: schema.maybe(schema.arrayOf(schema.string())),
})
),
})

View file

@ -37,5 +37,6 @@ export enum API_URLS {
CONNECTOR_TYPES = '/api/actions/connector_types',
// Service end points
INDEX_TEMPLATES = '/api/uptime/service/index_templates',
INDEX_TEMPLATES = '/internal/uptime/service/index_templates',
SYNTHETICS_MONITORS = '/internal/uptime/service/monitors',
}

View file

@ -20,6 +20,7 @@ export class UMKibanaBackendFrameworkAdapter implements UMBackendFrameworkAdapte
validate,
options,
};
switch (method) {
case 'GET':
this.server.router.get(routeDefinition, handler);
@ -27,6 +28,12 @@ export class UMKibanaBackendFrameworkAdapter implements UMBackendFrameworkAdapte
case 'POST':
this.server.router.post(routeDefinition, handler);
break;
case 'PUT':
this.server.router.put(routeDefinition, handler);
break;
case 'DELETE':
this.server.router.delete(routeDefinition, handler);
break;
default:
throw new Error(`Handler for method ${method} is not defined`);
}

View file

@ -28,6 +28,13 @@ import { createNetworkEventsRoute } from './network_events';
import { createJourneyFailedStepsRoute } from './pings/journeys';
import { createLastSuccessfulStepRoute } from './synthetics/last_successful_step';
import { installIndexTemplatesRoute } from './synthetics_service/install_index_templates';
import {
getAllSyntheticsMonitorRoute,
getSyntheticsMonitorRoute,
} from './synthetics_service/get_monitors';
import { addSyntheticsMonitorRoute } from './synthetics_service/add_monitor';
import { editSyntheticsMonitorRoute } from './synthetics_service/edit_monitor';
import { deleteSyntheticsMonitorRoute } from './synthetics_service/delete_monitor';
export * from './types';
export { createRouteWithAuth } from './create_route_with_auth';
@ -53,4 +60,9 @@ export const restApiRoutes: UMRestApiRouteFactory[] = [
createLastSuccessfulStepRoute,
createJourneyScreenshotBlocksRoute,
installIndexTemplatesRoute,
getSyntheticsMonitorRoute,
getAllSyntheticsMonitorRoute,
addSyntheticsMonitorRoute,
editSyntheticsMonitorRoute,
deleteSyntheticsMonitorRoute,
];

View file

@ -0,0 +1,26 @@
/*
* 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 { schema } from '@kbn/config-schema';
import { UMRestApiRouteFactory } from '../types';
import { API_URLS } from '../../../common/constants';
import { SyntheticsMonitorSavedObject } from '../../../common/types';
import { syntheticsMonitorType } from '../../lib/saved_objects/synthetics_monitor';
export const addSyntheticsMonitorRoute: UMRestApiRouteFactory = () => ({
method: 'POST',
path: API_URLS.SYNTHETICS_MONITORS,
validate: {
body: schema.any(),
},
handler: async ({ request, savedObjectsClient }): Promise<any> => {
const monitor = request.body as SyntheticsMonitorSavedObject;
const newMonitor = await savedObjectsClient.create(syntheticsMonitorType, monitor);
// TODO: call to service sync
return newMonitor;
},
});

View file

@ -0,0 +1,34 @@
/*
* 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 { schema } from '@kbn/config-schema';
import { SavedObjectsErrorHelpers } from '../../../../../../src/core/server';
import { UMRestApiRouteFactory } from '../types';
import { API_URLS } from '../../../common/constants';
import { syntheticsMonitorType } from '../../lib/saved_objects/synthetics_monitor';
export const deleteSyntheticsMonitorRoute: UMRestApiRouteFactory = () => ({
method: 'DELETE',
path: API_URLS.SYNTHETICS_MONITORS + '/{monitorId}',
validate: {
params: schema.object({
monitorId: schema.string(),
}),
},
handler: async ({ request, savedObjectsClient }): Promise<any> => {
const { monitorId } = request.params;
try {
await savedObjectsClient.delete(syntheticsMonitorType, monitorId);
// TODO: call to service sync
return monitorId;
} catch (getErr) {
if (SavedObjectsErrorHelpers.isNotFoundError(getErr)) {
return 'Not found';
}
}
},
});

View file

@ -0,0 +1,31 @@
/*
* 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 { schema } from '@kbn/config-schema';
import { UMRestApiRouteFactory } from '../types';
import { API_URLS } from '../../../common/constants';
import { SyntheticsMonitorSavedObject } from '../../../common/types';
import { syntheticsMonitorType } from '../../lib/saved_objects/synthetics_monitor';
export const editSyntheticsMonitorRoute: UMRestApiRouteFactory = () => ({
method: 'PUT',
path: API_URLS.SYNTHETICS_MONITORS + '/{monitorId}',
validate: {
params: schema.object({
monitorId: schema.string(),
}),
body: schema.any(),
},
handler: async ({ request, savedObjectsClient }): Promise<any> => {
const monitor = request.body as SyntheticsMonitorSavedObject['attributes'];
const { monitorId } = request.params;
const editMonitor = await savedObjectsClient.update(syntheticsMonitorType, monitorId, monitor);
// TODO: call to service sync
return editMonitor;
},
});

View file

@ -0,0 +1,40 @@
/*
* 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 { schema } from '@kbn/config-schema';
import { UMRestApiRouteFactory } from '../types';
import { API_URLS } from '../../../common/constants';
import { syntheticsMonitorType } from '../../lib/saved_objects/synthetics_monitor';
export const getSyntheticsMonitorRoute: UMRestApiRouteFactory = () => ({
method: 'GET',
path: API_URLS.SYNTHETICS_MONITORS + '/{monitorId}',
validate: {
params: schema.object({
monitorId: schema.string(),
}),
},
handler: async ({ request, savedObjectsClient }): Promise<any> => {
const { monitorId } = request.params;
return await savedObjectsClient.get(syntheticsMonitorType, monitorId);
},
});
export const getAllSyntheticsMonitorRoute: UMRestApiRouteFactory = () => ({
method: 'GET',
path: API_URLS.SYNTHETICS_MONITORS,
validate: {
query: schema.object({
page: schema.maybe(schema.number()),
perPage: schema.maybe(schema.number()),
}),
},
handler: async ({ request, savedObjectsClient }): Promise<any> => {
const { perPage = 50, page } = request.query;
// TODO: add query/filtering params
return await savedObjectsClient.find({ type: syntheticsMonitorType, perPage, page });
},
});

View file

@ -0,0 +1,29 @@
/*
* 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 '../../../ftr_provider_context';
import { API_URLS } from '../../../../../plugins/uptime/common/constants';
export default function ({ getService }: FtrProviderContext) {
describe('add synthetics monitor', () => {
const supertest = getService('supertest');
const newMonitor = {
type: 'http',
name: 'Test monitor',
urls: 'https://www.elastic.co',
};
it('returns the newly added monitor', async () => {
const apiResponse = await supertest
.post(API_URLS.SYNTHETICS_MONITORS)
.set('kbn-xsrf', 'true')
.send(newMonitor);
expect(apiResponse.body.attributes).eql(newMonitor);
});
});
}

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
* 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 '../../../ftr_provider_context';
import { API_URLS } from '../../../../../plugins/uptime/common/constants';
export default function ({ getService }: FtrProviderContext) {
describe('delete synthetics monitor', () => {
const supertest = getService('supertest');
const newMonitor = {
type: 'http',
name: 'Test monitor',
urls: 'https://www.elastic.co',
};
it('deleted monitor by id', async () => {
const apiResponse = await supertest
.post(API_URLS.SYNTHETICS_MONITORS)
.set('kbn-xsrf', 'true')
.send(newMonitor);
const monitorId = apiResponse.body.id;
const deleteResponse = await supertest
.delete(API_URLS.SYNTHETICS_MONITORS + '/' + monitorId)
.set('kbn-xsrf', 'true');
//
expect(deleteResponse.body).eql(monitorId);
});
});
}

View file

@ -0,0 +1,37 @@
/*
* 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 '../../../ftr_provider_context';
import { API_URLS } from '../../../../../plugins/uptime/common/constants';
export default function ({ getService }: FtrProviderContext) {
describe('edit synthetics monitor', () => {
const supertest = getService('supertest');
const newMonitor = {
type: 'http',
name: 'Test monitor',
urls: 'https://www.elastic.co',
};
it('edits the monitor', async () => {
const apiResponse = await supertest
.post(API_URLS.SYNTHETICS_MONITORS)
.set('kbn-xsrf', 'true')
.send(newMonitor);
const monitorId = apiResponse.body.id;
expect(apiResponse.body.attributes).eql(newMonitor);
const editResponse = await supertest
.put(API_URLS.SYNTHETICS_MONITORS + '/' + monitorId)
.set('kbn-xsrf', 'true')
.send({ ...newMonitor, name: 'New name' });
expect(editResponse.body.attributes.name).eql('New name');
});
});
}

View file

@ -0,0 +1,51 @@
/*
* 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 '../../../ftr_provider_context';
import { API_URLS } from '../../../../../plugins/uptime/common/constants';
export default function ({ getService }: FtrProviderContext) {
describe('get synthetics monitor', () => {
const newMonitor = {
type: 'http',
name: 'Test monitor',
urls: 'https://www.elastic.co',
};
const addMonitor = async () => {
const res = await supertest
.post(API_URLS.SYNTHETICS_MONITORS)
.set('kbn-xsrf', 'true')
.send(newMonitor);
return res.body.id;
};
const supertest = getService('supertest');
it('get all monitors', async () => {
const id1 = await addMonitor();
const id2 = await addMonitor();
const apiResponse = await supertest.get(API_URLS.SYNTHETICS_MONITORS);
const monitor1 = apiResponse.body.saved_objects.find((obj: any) => obj.id === id1);
const monitor2 = apiResponse.body.saved_objects.find((obj: any) => obj.id === id2);
expect(monitor1.id).eql(id1);
expect(monitor2.id).eql(id2);
});
it('get monitor by id', async () => {
const monitorId = await addMonitor();
const apiResponse = await supertest.get(API_URLS.SYNTHETICS_MONITORS + '/' + monitorId);
expect(apiResponse.body.id).eql(monitorId);
});
});
}

View file

@ -71,5 +71,12 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) {
loadTestFile(require.resolve('./index_status'));
loadTestFile(require.resolve('./monitor_states_real_data'));
});
describe('uptime CRUD routes', () => {
loadTestFile(require.resolve('./get_monitor'));
loadTestFile(require.resolve('./add_monitor'));
loadTestFile(require.resolve('./edit_monitor'));
loadTestFile(require.resolve('./delete_monitor'));
});
});
}

View file

@ -35,6 +35,10 @@ export async function getApiIntegrationConfig({ readConfigFile }: FtrConfigProvi
'--xpack.ruleRegistry.write.enabled=true',
'--xpack.ruleRegistry.write.enabled=true',
'--xpack.ruleRegistry.write.cache.enabled=false',
'--xpack.uptime.unsafe.service.enabled=true',
'--xpack.uptime.unsafe.service.password=test',
'--xpack.uptime.unsafe.service.manifestUrl=http://test.com',
'--xpack.uptime.unsafe.service.username=user',
`--xpack.securitySolution.enableExperimental=${JSON.stringify(['ruleRegistryEnabled'])}`,
],
},