Skip to content

Commit

Permalink
Crude and incomplete impl of Space-Aware Saved Objects Client
Browse files Browse the repository at this point in the history
  • Loading branch information
legrego committed May 7, 2018
1 parent 4cbfe51 commit f208d3c
Show file tree
Hide file tree
Showing 4 changed files with 203 additions and 7 deletions.
40 changes: 33 additions & 7 deletions src/server/saved_objects/client/saved_objects_client.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ export class SavedObjectsClient {
async create(type, attributes = {}, options = {}) {
const {
id,
extraBodyProperties = {},
overwrite = false
} = options;

Expand All @@ -122,7 +123,8 @@ export class SavedObjectsClient {
body: {
type,
updated_at: time,
[type]: attributes
[type]: attributes,
...extraBodyProperties
},
});

Expand Down Expand Up @@ -169,7 +171,8 @@ export class SavedObjectsClient {
{
type: object.type,
updated_at: time,
[object.type]: object.attributes
[object.type]: object.attributes,
...object.extraBodyProperties
}
];
};
Expand Down Expand Up @@ -272,6 +275,7 @@ export class SavedObjectsClient {
sortField,
sortOrder,
fields,
queryDecorator,
} = options;

if (searchFields && !Array.isArray(searchFields)) {
Expand Down Expand Up @@ -300,6 +304,10 @@ export class SavedObjectsClient {
}
};

if (esOptions.body.query && typeof queryDecorator === 'function') {
esOptions.body.query = queryDecorator(esOptions.body.query);
}

const response = await this._callCluster('search', esOptions);

if (response.status === 404) {
Expand Down Expand Up @@ -342,7 +350,7 @@ export class SavedObjectsClient {
* { id: 'foo', type: 'index-pattern' }
* ])
*/
async bulkGet(objects = []) {
async bulkGet(objects = [], options = {}) {
if (objects.length === 0) {
return { saved_objects: [] };
}
Expand All @@ -357,8 +365,15 @@ export class SavedObjectsClient {
}
});

const { docs } = response;

let docsToReturn = docs;
if (typeof options.documentFilter === 'function') {
docsToReturn = docs.filter(options.documentFilter);
}

return {
saved_objects: response.docs.map((doc, i) => {
saved_objects: docsToReturn.map((doc, i) => {
const { id, type } = objects[i];

if (!doc.found) {
Expand All @@ -370,13 +385,19 @@ export class SavedObjectsClient {
}

const time = doc._source.updated_at;
return {
const savedObject = {
id,
type,
...time && { updated_at: time },
version: doc._version,
attributes: doc._source[type]
};

if (typeof options.resultDecorator === 'function') {
return options.resultDecorator(savedObject, doc);
}

return savedObject;
})
};
}
Expand All @@ -388,14 +409,18 @@ export class SavedObjectsClient {
* @param {string} id
* @returns {promise} - { id, type, version, attributes }
*/
async get(type, id) {
async get(type, id, options = {}) {
const response = await this._callCluster('get', {
id: this._generateEsId(type, id),
type: this._type,
index: this._index,
ignore: [404]
});

if (typeof options.responseInterceptor === 'function') {
options.responseInterceptor(response);
}

const docNotFound = response.found === false;
const indexNotFound = response.status === 404;
if (docNotFound || indexNotFound) {
Expand Down Expand Up @@ -435,7 +460,8 @@ export class SavedObjectsClient {
body: {
doc: {
updated_at: time,
[type]: attributes
[type]: attributes,
...options.extraBodyProperties
}
},
});
Expand Down
4 changes: 4 additions & 0 deletions x-pack/plugins/spaces/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { initSpacesApi } from './server/routes/api/v1/spaces';
import { initSpacesRequestInterceptors } from './server/lib/space_request_interceptors';
import { mirrorPluginStatus } from '../../server/lib/mirror_plugin_status';
import mappings from './mappings.json';
import { spacesSavedObjectsClientWrapper } from './server/lib/saved_objects_client/saved_objects_client_wrapper';

export const spaces = (kibana) => new kibana.Plugin({
id: 'spaces',
Expand Down Expand Up @@ -55,6 +56,9 @@ export const spaces = (kibana) => new kibana.Plugin({
const config = server.config();
validateConfig(config, message => server.log(['spaces', 'warning'], message));

const savedObjectsClientProvider = server.getSavedObjectsClientProvider();
savedObjectsClientProvider.addClientWrapper(spacesSavedObjectsClientWrapper);

initSpacesApi(server);

initSpacesRequestInterceptors(server);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
* 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 { SpacesSavedObjectsClient } from './spaces_saved_objects_client';

export function spacesSavedObjectsClientWrapper(baseClient, options) {
return new SpacesSavedObjectsClient({
baseClient,
...options
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
/*
* 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 class SpacesSavedObjectsClient {
constructor(options) {
const {
request,
baseClient,
spaceUrlContext,
} = options;

this.errors = baseClient.errors;

this._client = baseClient;
this._request = request;

this._spaceUrlContext = spaceUrlContext;
}

async create(type, attributes = {}, options = {}) {

if (this._isTypeSpaceAware(type)) {
options.extraBodyProperties = {
...options.extraBodyProperties,
spaceId: await this._getSpaceId()
};
}

return await this._client.create(type, attributes, options);
}

async bulkCreate(objects, options = {}) {
options.extraBodyProperties = {
...options.extraBodyProperties,
spaceId: await this._getSpaceId()
};

return await this._client.bulkCreate(objects, options);
}

async delete(type, id) {
return await this._client.delete(type, id);
}

async find(options = {}) {
const spaceOptions = {};

if (this._isTypeSpaceAware(options.type)) {
const spaceId = await this._getSpaceId();

spaceOptions.queryDecorator = (query) => {
const { bool = {} } = query;

if (!Array.isArray(bool.filter)) {
bool.filter = [];
}

bool.filter.push({
term: {
spaceId
}
});

return query;
};
}

return await this._client.find({ ...options, ...spaceOptions });
}

async bulkGet(objects = []) {
// ES 'mget' does not support queries, so we have to filter results after the fact.
const thisSpaceId = await this._getSpaceId();

return await this._client.bulkGet(objects, {
documentFilter: (doc) => {
if (!doc.found) return true;

const { type, spaceId } = doc._source;

if (this._isTypeSpaceAware(type)) {
return spaceId === thisSpaceId;
}

return true;
},
resultDecorator(savedObject, doc) {
savedObject.attributes = {
...savedObject.attributes,
spaceId: doc._source.spaceId
};
return savedObject;
}
});
}

async get(type, id) {
// ES 'get' does not support queries, so we have to filter results after the fact.
let thisSpaceId;

if (this._isTypeSpaceAware(type)) {
thisSpaceId = await this._getSpaceId();
}

return await this._client.get(type, id, {
responseInterceptor: (response) => {
if (!this._isTypeSpaceAware(type)) {
return response;
}

if (response.found && response.status !== 404) {
const { spaceId } = response._source;
if (spaceId !== thisSpaceId) {
response.found = false;
response._source = {};
}
}

return response;
}
});
}

async update(type, id, attributes, options = {}) {
return await this._client.update(type, id, attributes, options);
}

_isTypeSpaceAware(type) {
return type !== 'space';
}

async _getSpaceId() {
if (!this._spaceId) {
const {
saved_objects: spaces = []
} = await this.find({
type: 'space',
search: `"${this._spaceUrlContext}"`,
search_fields: ['urlContext'],
});

if (spaces.length > 0) {
this._spaceId = spaces[0].id;
}
}

return this._spaceId;
}
}

0 comments on commit f208d3c

Please sign in to comment.