Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Uses uuid for auto-generated ids and prepends type #12834

Merged
merged 1 commit into from
Jul 14, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,7 @@ const { BadRequest } = elasticsearch.errors;
describe('SavedObjectsClient', () => {
let callAdminCluster;
let savedObjectsClient;
const illegalArgumentException = {
type: 'illegal_argument_exception',
reason: 'Rejecting mapping update to [.kibana-v6] as the final mapping would have more than 1 type: [doc, foo]'
};
const illegalArgumentException = { type: 'type_missing_exception' };

describe('mapping', () => {
beforeEach(() => {
Expand All @@ -25,7 +22,7 @@ describe('SavedObjectsClient', () => {


describe('#create', () => {
it('falls back to v6 mapping', async () => {
it('falls back to single-type mapping', async () => {
const error = new BadRequest('[illegal_argument_exception] Rejecting mapping update to [.kibana-v6]', {
body: {
error: illegalArgumentException
Expand All @@ -49,48 +46,66 @@ describe('SavedObjectsClient', () => {
}
});
});

it('prepends id for single-type', async () => {
const id = 'foo';
const error = new BadRequest('[illegal_argument_exception] Rejecting mapping update to [.kibana-v6]', {
body: {
error: illegalArgumentException
}
});

callAdminCluster
.onFirstCall().throws(error)
.onSecondCall().returns(Promise.resolve());

await savedObjectsClient.create('index-pattern', {}, { id });

const [, args] = callAdminCluster.getCall(1).args;
expect(args.id).to.eql('index-pattern:foo');
});
});

describe('#bulkCreate', () => {
it('falls back to v6 mappings', async () => {
const firstResponse = {
errors: true,
items: [{
create: {
_type: 'config',
_id: 'one',
_version: 2,
status: 400,
error: illegalArgumentException
}
}, {
create: {
_type: 'index-pattern',
_id: 'two',
_version: 2,
status: 400,
error: illegalArgumentException
}
}]
};

const secondResponse = {
errors: false,
items: [{
create: {
_type: 'config',
_id: 'one',
_version: 2
}
}, {
create: {
_type: 'index-pattern',
_id: 'two',
_version: 2
}
}]
};
const firstResponse = {
errors: true,
items: [{
create: {
_type: 'config',
_id: 'one',
_version: 2,
status: 400,
error: illegalArgumentException
}
}, {
create: {
_type: 'index-pattern',
_id: 'two',
_version: 2,
status: 400,
error: illegalArgumentException
}
}]
};

const secondResponse = {
errors: false,
items: [{
create: {
_type: 'config',
_id: 'one',
_version: 2
}
}, {
create: {
_type: 'index-pattern',
_id: 'two',
_version: 2
}
}]
};

it('falls back to single-type mappings', async () => {
callAdminCluster
.onFirstCall().returns(Promise.resolve(firstResponse))
.onSecondCall().returns(Promise.resolve(secondResponse));
Expand All @@ -116,23 +131,38 @@ describe('SavedObjectsClient', () => {
}
]);
});

it('prepends id for single-type', async () => {
callAdminCluster
.onFirstCall().returns(Promise.resolve(firstResponse))
.onSecondCall().returns(Promise.resolve(secondResponse));

await savedObjectsClient.bulkCreate([
{ type: 'config', id: 'one', attributes: { title: 'Test One' } },
{ type: 'index-pattern', id: 'two', attributes: { title: 'Test Two' } }
]);

const [, { body }] = callAdminCluster.getCall(1).args;
expect(body[0].create._id).to.eql('config:one');
expect(body[2].create._id).to.eql('index-pattern:two');
// expect(args.id).to.eql('index-pattern:foo');
});
});

describe('update', () => {
it('falls back to v6 mappings', async () => {
const id = 'logstash-*';
const type = 'index-pattern';
const version = 2;
const attributes = { title: 'Testing' };

const error = new BadRequest('[document_missing_exception] [config][logstash-*]: document missing', {
body: {
error: {
type: 'document_missing_exception'
}
const id = 'logstash-*';
const type = 'index-pattern';
const version = 2;
const attributes = { title: 'Testing' };
const error = new BadRequest('[document_missing_exception] [config][logstash-*]: document missing', {
body: {
error: {
type: 'document_missing_exception'
}
});
}
});

beforeEach(() => {
callAdminCluster
.onFirstCall().throws(error)
.onSecondCall().returns(Promise.resolve({
Expand All @@ -141,7 +171,10 @@ describe('SavedObjectsClient', () => {
_version: version,
result: 'updated'
}));
});


it('falls back to single-type mappings', async () => {
const response = await savedObjectsClient.update('index-pattern', 'logstash-*', attributes);
expect(response).to.eql({
id,
Expand All @@ -150,6 +183,13 @@ describe('SavedObjectsClient', () => {
attributes
});
});

it('prepends id for single-type', async () => {
await savedObjectsClient.update('index-pattern', 'logstash-*', attributes);

const [, args] = callAdminCluster.getCall(1).args;
expect(args.id).to.eql('index-pattern:logstash-*');
});
});
});
});
3 changes: 2 additions & 1 deletion src/server/saved_objects/client/lib/compatibility.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import uuid from 'uuid';
import { V6_TYPE } from '../saved_objects_client';

/**
Expand Down Expand Up @@ -29,7 +30,7 @@ export function v6BulkCreate(objects, options = {}) {

acc.push({ [method]: {
_type: V6_TYPE,
_id: object.id ? `${object.type}:${object.id}` : undefined
_id: `${object.type}:${object.id || uuid.v1()}`,
} });

acc.push(Object.assign({},
Expand Down
11 changes: 0 additions & 11 deletions src/server/saved_objects/client/lib/handle_es_error.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,6 @@ const {
BadRequest
} = elasticsearch.errors;

export function isSingleTypeError(error) {
if (!error) return;

return error.type === 'illegal_argument_exception' &&
error.reason.match(/the final mapping would have more than 1 type/);
}

export function handleEsError(error) {
if (!(error instanceof Error)) {
throw new Error('Expected an instance of Error');
Expand Down Expand Up @@ -50,10 +43,6 @@ export function handleEsError(error) {
}

if (error instanceof BadRequest) {
if (isSingleTypeError(get(error, 'body.error'))) {
details.type = 'is_single_type';
}

throw Boom.badRequest(reason, details);
}

Expand Down
15 changes: 8 additions & 7 deletions src/server/saved_objects/client/saved_objects_client.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import Boom from 'boom';
import uuid from 'uuid';
import { get } from 'lodash';

import {
createFindQuery,
createIdQuery,
handleEsError,
isSingleTypeError,
v5BulkCreate,
v6BulkCreate,
normalizeEsDoc,
Expand Down Expand Up @@ -40,7 +40,7 @@ export class SavedObjectsClient {
refresh: 'wait_for'
}, {
type: V6_TYPE,
id: options.id ? `${type}:${options.id}` : undefined,
id: `${type}:${options.id || uuid.v1()}`,
body: {
type,
[type]: attributes
Expand Down Expand Up @@ -71,7 +71,7 @@ export class SavedObjectsClient {
const items = get(response, 'items', []);
const missingTypesCount = items.filter(item => {
const method = Object.keys(item)[0];
return isSingleTypeError(get(item, `${method}.error`));
return get(item, `${method}.error.type`) === 'type_missing_exception';
}).length;

const formatFallback = format === 'v5' && items.length > 0 && items.length === missingTypesCount;
Expand All @@ -82,10 +82,10 @@ export class SavedObjectsClient {

return get(response, 'items', []).map((resp, i) => {
const method = Object.keys(resp)[0];
const { id, type, attributes } = objects[i];
const { type, attributes } = objects[i];

return normalizeEsDoc(resp[method], {
id,
id: resp[method]._id,
type,
attributes,
error: resp[method].error ? { message: get(resp[method], 'error.reason') } : undefined
Expand Down Expand Up @@ -233,6 +233,7 @@ export class SavedObjectsClient {
}
}, {
type: V6_TYPE,
id: `${type}:${id}`,
body: {
doc: {
[type]: attributes
Expand All @@ -245,8 +246,8 @@ export class SavedObjectsClient {

_withKibanaIndexAndMappingFallback(method, params, fallbackParams) {
const fallbacks = {
'create': ['is_single_type'],
'index': ['is_single_type'],
'create': ['type_missing_exception'],
'index': ['type_missing_exception'],
'update': ['document_missing_exception']
};

Expand Down