[ML] Add endpoints and service for ML filters (#20406) (#20462)

* [ML] Add endpoints and service for ML filters

* [ML] Replace getFilter(s) with single filters function
This commit is contained in:
Pete Harverson 2018-07-05 12:08:42 +01:00 committed by GitHub
parent 9a974c9479
commit d967c5d0eb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 344 additions and 2 deletions

View file

@ -20,6 +20,7 @@ import { dataRecognizer } from './server/routes/modules';
import { dataVisualizerRoutes } from './server/routes/data_visualizer';
import { calendars } from './server/routes/calendars';
import { fieldsService } from './server/routes/fields_service';
import { filtersRoutes } from './server/routes/filters';
import { resultsServiceRoutes } from './server/routes/results_service';
import { jobServiceRoutes } from './server/routes/job_service';
import { jobAuditMessagesRoutes } from './server/routes/job_audit_messages';
@ -85,6 +86,7 @@ export const ml = (kibana) => {
dataVisualizerRoutes(server, commonRouteConfig);
calendars(server, commonRouteConfig);
fieldsService(server, commonRouteConfig);
filtersRoutes(server, commonRouteConfig);
resultsServiceRoutes(server, commonRouteConfig);
jobServiceRoutes(server, commonRouteConfig);
jobAuditMessagesRoutes(server, commonRouteConfig);

View file

@ -0,0 +1,65 @@
/*
* 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.
*/
// Service for querying filters, which hold lists of entities,
// for example a list of known safe URL domains.
import chrome from 'ui/chrome';
import { http } from 'plugins/ml/services/http_service';
const basePath = chrome.addBasePath('/api/ml');
export const filters = {
filters(obj) {
const filterId = (obj && obj.filterId) ? `/${obj.filterId}` : '';
return http({
url: `${basePath}/filters${filterId}`,
method: 'GET'
});
},
addFilter(
filterId,
description,
items) {
return http({
url: `${basePath}/filters`,
method: 'PUT',
data: {
filterId,
description,
items
}
});
},
updateFilter(
filterId,
description,
addItems,
deleteItems
) {
return http({
url: `${basePath}/filters/${filterId}`,
method: 'PUT',
data: {
description,
addItems,
deleteItems
}
});
},
deleteFilter(filterId) {
return http({
url: `${basePath}/filters/${filterId}`,
method: 'DELETE'
});
},
};

View file

@ -11,6 +11,7 @@ import chrome from 'ui/chrome';
import { http } from 'plugins/ml/services/http_service';
import { filters } from './filters';
import { results } from './results';
import { jobs } from './jobs';
@ -407,6 +408,7 @@ export const ml = {
});
},
filters,
results,
jobs,
};

View file

@ -9,7 +9,7 @@
import expect from 'expect.js';
import {
elasticsearchJsPlugin
} from '../elasticsearch-ml';
} from '../elasticsearch_ml';
describe('ML - Endpoints', () => {

View file

@ -7,7 +7,7 @@
import { once } from 'lodash';
import { elasticsearchJsPlugin } from './elasticsearch-ml';
import { elasticsearchJsPlugin } from './elasticsearch_ml';
const callWithRequest = once((server) => {
const config = {

View file

@ -502,6 +502,63 @@ export const elasticsearchJsPlugin = (Client, config, components) => {
method: 'DELETE'
});
ml.filters = ca({
urls: [
{
fmt: '/_xpack/ml/filters/<%=filterId%>',
req: {
filterId: {
type: 'string'
}
}
},
{
fmt: '/_xpack/ml/filters/',
}
],
method: 'GET'
});
ml.addFilter = ca({
url: {
fmt: '/_xpack/ml/filters/<%=filterId%>',
req: {
filterId: {
type: 'string'
}
}
},
needBody: true,
method: 'PUT'
});
ml.updateFilter = ca({
urls: [
{
fmt: '/_xpack/ml/filters/<%=filterId%>/_update',
req: {
jobId: {
type: 'string'
}
}
}
],
needBody: true,
method: 'POST'
});
ml.deleteFilter = ca({
url: {
fmt: '/_xpack/ml/filters/<%=filterId%>',
req: {
filterId: {
type: 'string'
}
}
},
method: 'DELETE'
});
ml.info = ca({
url: {
fmt: '/_xpack/ml/info'

View file

@ -0,0 +1,78 @@
/*
* 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 Boom from 'boom';
export class FilterManager {
constructor(callWithRequest) {
this.callWithRequest = callWithRequest;
}
async getFilter(filterId) {
try {
const resp = await this.callWithRequest('ml.filters', { filterId });
const filters = resp.filters;
if (filters.length) {
return filters[0];
} else {
return Boom.notFound(`Filter with the id "${filterId}" not found`);
}
} catch (error) {
throw Boom.badRequest(error);
}
}
async getAllFilters() {
try {
const filtersResp = await this.callWithRequest('ml.filters');
return filtersResp.filters;
} catch (error) {
throw Boom.badRequest(error);
}
}
async newFilter(filter) {
const filterId = filter.filterId;
delete filter.filterId;
try {
await this.callWithRequest('ml.addFilter', { filterId, body: filter });
// Return the newly created filter.
return await this.getFilter(filterId);
} catch (error) {
return Boom.badRequest(error);
}
}
async updateFilter(filterId,
description,
addItems,
deleteItems) {
try {
await this.callWithRequest('ml.updateFilter', {
filterId,
body: {
description,
add_items: addItems,
delete_items: deleteItems
}
});
// Return the newly updated filter.
return await this.getFilter(filterId);
} catch (error) {
return Boom.badRequest(error);
}
}
async deleteFilter(filterId) {
return this.callWithRequest('ml.deleteFilter', { filterId });
}
}

View file

@ -0,0 +1,9 @@
/*
* 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.
*/
export { FilterManager } from './filter_manager';

View file

@ -0,0 +1,129 @@
/*
* 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 { callWithRequestFactory } from '../client/call_with_request_factory';
import { wrapError } from '../client/errors';
import { FilterManager } from '../models/filter';
// TODO - add function for returning a list of just the filter IDs.
// TODO - add function for returning a list of filter IDs plus item count.
function getAllFilters(callWithRequest) {
const mgr = new FilterManager(callWithRequest);
return mgr.getAllFilters();
}
function getFilter(callWithRequest, filterId) {
const mgr = new FilterManager(callWithRequest);
return mgr.getFilter(filterId);
}
function newFilter(callWithRequest, filter) {
const mgr = new FilterManager(callWithRequest);
return mgr.newFilter(filter);
}
function updateFilter(
callWithRequest,
filterId,
description,
addItems,
deleteItems) {
const mgr = new FilterManager(callWithRequest);
return mgr.updateFilter(filterId, description, addItems, deleteItems);
}
function deleteFilter(callWithRequest, filterId) {
const mgr = new FilterManager(callWithRequest);
return mgr.deleteFilter(filterId);
}
export function filtersRoutes(server, commonRouteConfig) {
server.route({
method: 'GET',
path: '/api/ml/filters',
handler(request, reply) {
const callWithRequest = callWithRequestFactory(server, request);
return getAllFilters(callWithRequest)
.then(resp => reply(resp))
.catch(resp => reply(wrapError(resp)));
},
config: {
...commonRouteConfig
}
});
server.route({
method: 'GET',
path: '/api/ml/filters/{filterId}',
handler(request, reply) {
const callWithRequest = callWithRequestFactory(server, request);
const filterId = request.params.filterId;
return getFilter(callWithRequest, filterId)
.then(resp => reply(resp))
.catch(resp => reply(wrapError(resp)));
},
config: {
...commonRouteConfig
}
});
server.route({
method: 'PUT',
path: '/api/ml/filters',
handler(request, reply) {
const callWithRequest = callWithRequestFactory(server, request);
const body = request.payload;
return newFilter(callWithRequest, body)
.then(resp => reply(resp))
.catch(resp => reply(wrapError(resp)));
},
config: {
...commonRouteConfig
}
});
server.route({
method: 'PUT',
path: '/api/ml/filters/{filterId}',
handler(request, reply) {
const callWithRequest = callWithRequestFactory(server, request);
const filterId = request.params.filterId;
const payload = request.payload;
return updateFilter(
callWithRequest,
filterId,
payload.description,
payload.addItems,
payload.deleteItems)
.then(resp => reply(resp))
.catch(resp => reply(wrapError(resp)));
},
config: {
...commonRouteConfig
}
});
server.route({
method: 'DELETE',
path: '/api/ml/filters/{filterId}',
handler(request, reply) {
const callWithRequest = callWithRequestFactory(server, request);
const filterId = request.params.filterId;
return deleteFilter(callWithRequest, filterId)
.then(resp => reply(resp))
.catch(resp => reply(wrapError(resp)));
},
config: {
...commonRouteConfig
}
});
}