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

[fix/UiSettings] ignore certain errors #13079

Merged
merged 27 commits into from
Aug 9, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
8871956
[SavedObjectClient] emit detectable errors
spalger Jul 24, 2017
a5892fc
[uiSettingsService] consume new SavedObjectsClient errors
spalger Jul 24, 2017
e4a7f81
[SavedObjectsClient] expose errorTypeHelpers as such
spalger Jul 25, 2017
b299ec5
[elasticsearch/tests] recreate error for each test
spalger Jul 25, 2017
fce5916
[http] wait for elasticsearch plugin to be ready
spalger Jul 25, 2017
cbdbe2a
[shortUrl/tests] ensure that create request responds with 200
spalger Jul 25, 2017
e1e835a
[shortUrl] use errorTypeHelpers to filter errors
spalger Jul 25, 2017
f378cd1
[uiSettings/savedObjectsClientStub] stub errorTypeHelpers
spalger Jul 25, 2017
5431bdc
[SavedObjectsClient/errors] expose error module so tests can make errors
spalger Jul 25, 2017
7c81e7a
[shortUrl/tests] use actual SavedObjectsClient errors
spalger Jul 25, 2017
304fd9e
[uiSettings/savedObjectsClientStub] use actual errors lib
spalger Jul 25, 2017
28f9c7e
Merge branch 'master' of github.com:elastic/kibana into fix/ui-settin…
spalger Jul 25, 2017
2e1fec2
[SavedObjectsClient] use decorate instead of "wrap"
spalger Jul 25, 2017
624cb20
Merge branch 'master' of github.com:elastic/kibana into fix/ui-settin…
spalger Jul 27, 2017
fbb9639
[server/routes/uiSettings] refactor routes to forward Boom errors fro…
spalger Jul 27, 2017
b817071
Merge branch 'master' of github.com:elastic/kibana into fix/ui-settin…
spalger Jul 28, 2017
a8e59b3
[uiSettings] colocate routes and service
spalger Jul 28, 2017
b6d7334
Merge branch 'master' of github.com:elastic/kibana into fix/ui-settin…
spalger Jul 28, 2017
66316d9
[testUtils/esTestCluster] use more standard api style
spalger Jul 28, 2017
3e7324b
Merge branch 'refactor/create-es-test-cluster' into fix/ui-settings/i…
spalger Jul 28, 2017
e1a91e0
[testUtils/es] add createCallCluster util
spalger Jul 28, 2017
4c8bb8b
[testUtils/esTestCluster] add getters for client/callCluster
spalger Jul 28, 2017
2205697
[es/healthcheck] ensure that healtcheck stops when server is stopped
spalger Jul 28, 2017
1fe6c37
Merge branch 'master' of github.com:elastic/kibana into fix/ui-settin…
spalger Jul 28, 2017
a6aa832
Merge branch 'fix/es/stop-healthcheck-on-shutdown' into fix/ui-settin…
spalger Jul 28, 2017
e902cd6
[uiSettings/routes] add param/payload validation
spalger Jul 29, 2017
256a0b2
[uiSettings/routes] add tests that verify error behaviors
spalger Jul 29, 2017
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
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@
"babel-register": "6.18.0",
"bluebird": "2.9.34",
"body-parser": "1.12.0",
"boom": "2.8.0",
"boom": "5.2.0",
"brace": "0.5.1",
"bunyan": "1.7.1",
"check-hash": "1.0.1",
Expand Down
6 changes: 4 additions & 2 deletions src/core_plugins/elasticsearch/lib/__tests__/cluster.js
Original file line number Diff line number Diff line change
Expand Up @@ -104,10 +104,12 @@ describe('plugins/elasticsearch', function () {

describe('wrap401Errors', () => {
let handler;
const error = new Error('Authentication required');
error.statusCode = 401;
let error;

beforeEach(() => {
error = new Error('Authentication required');
error.statusCode = 401;

handler = sinon.stub();
});

Expand Down
32 changes: 30 additions & 2 deletions src/core_plugins/elasticsearch/lib/__tests__/health_check.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,13 @@ describe('plugins/elasticsearch', () => {
let health;
let plugin;
let cluster;
let server;
const sandbox = sinon.sandbox.create();

function getTimerCount() {
return Object.keys(sandbox.clock.timers || {}).length;
}

beforeEach(() => {
const COMPATIBLE_VERSION_NUMBER = '5.0.0';

Expand Down Expand Up @@ -66,7 +71,7 @@ describe('plugins/elasticsearch', () => {
const set = sinon.stub();

// Setup the server mock
const server = {
server = {
log: sinon.stub(),
info: { port: 5601 },
config: function () { return { get, set }; },
Expand All @@ -77,14 +82,37 @@ describe('plugins/elasticsearch', () => {
},
getKibanaIndexMappingsDsl() {
return mappings;
}
},
ext: sinon.stub()
};

health = healthCheck(plugin, server);
});

afterEach(() => sandbox.restore());

it('should stop when cluster is shutdown', () => {
sandbox.useFakeTimers();

// ensure that health.start() is responsible for the timer we are observing
expect(getTimerCount()).to.be(0);
health.start();
expect(getTimerCount()).to.be(1);

// ensure that a server extension was registered
sinon.assert.calledOnce(server.ext);
sinon.assert.calledWithExactly(server.ext, sinon.match.string, sinon.match.func);

// call the server extension
const reply = sinon.stub();
const [,handler] = server.ext.firstCall.args;
handler({}, reply);

// ensure that the handler called reply and unregistered the time
sinon.assert.calledOnce(reply);
expect(getTimerCount()).to.be(0);
});

it('should set the cluster green if everything is ready', function () {
cluster.callWithInternalUser.withArgs('ping').returns(Promise.resolve());
cluster.callWithInternalUser.withArgs('cluster.health', sinon.match.any).returns(
Expand Down
5 changes: 5 additions & 0 deletions src/core_plugins/elasticsearch/lib/health_check.js
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,11 @@ export default function (plugin, server) {
return true;
}

server.ext('onPreStop', (request, reply) => {
stopChecking();
reply();
});

return {
waitUntilReady: waitUntilReady,
run: check,
Expand Down
2 changes: 0 additions & 2 deletions src/core_plugins/kibana/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { mkdirp as mkdirpNode } from 'mkdirp';

import manageUuid from './server/lib/manage_uuid';
import search from './server/routes/api/search';
import settings from './server/routes/api/settings';
import { scrollSearchApi } from './server/routes/api/scroll_search';
import { importApi } from './server/routes/api/import';
import { exportApi } from './server/routes/api/export';
Expand Down Expand Up @@ -142,7 +141,6 @@ export default function (kibana) {
manageUuid(server);
// routes
search(server);
settings(server);
scripts(server);
scrollSearchApi(server);
importApi(server);
Expand Down
2 changes: 1 addition & 1 deletion src/core_plugins/kibana/server/lib/handle_es_error.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export default function handleESError(error) {
error instanceof esErrors.ServiceUnavailable ||
error instanceof esErrors.NoConnections ||
error instanceof esErrors.RequestTimeout) {
return Boom.serverTimeout(error);
return Boom.serverUnavailable(error);
} else if (error instanceof esErrors.Conflict || _.contains(error.message, 'index_template_already_exists')) {
return Boom.conflict(error);
} else if (error instanceof esErrors[403]) {
Expand Down
6 changes: 0 additions & 6 deletions src/core_plugins/kibana/server/routes/api/settings/index.js

This file was deleted.

This file was deleted.

15 changes: 0 additions & 15 deletions src/core_plugins/kibana/server/routes/api/settings/register_get.js

This file was deleted.

21 changes: 0 additions & 21 deletions src/core_plugins/kibana/server/routes/api/settings/register_set.js

This file was deleted.

This file was deleted.

2 changes: 2 additions & 0 deletions src/server/http/__tests__/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ describe('routes', () => {

it('redirects shortened urls', (done) => {
kbnTestServer.makeRequest(kbnServer, shortenOptions, (res) => {
expect(res).to.have.property('statusCode', 200);

const gotoOptions = {
method: 'GET',
url: '/goto/' + res.payload
Expand Down
8 changes: 4 additions & 4 deletions src/server/http/__tests__/short_url_lookup.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import expect from 'expect.js';
import sinon from 'sinon';
import shortUrlLookupProvider from '../short_url_lookup';
import { SavedObjectsClient } from '../../saved_objects/client';

describe('shortUrlLookupProvider', () => {
const ID = 'bf00ad16941fc51420f91a93428b27a0';
Expand All @@ -17,7 +18,8 @@ describe('shortUrlLookupProvider', () => {
savedObjectsClient = {
get: sandbox.stub(),
create: sandbox.stub().returns(Promise.resolve({ id: ID })),
update: sandbox.stub()
update: sandbox.stub(),
errors: SavedObjectsClient.errors
};

req = { getSavedObjectsClient: () => savedObjectsClient };
Expand Down Expand Up @@ -58,10 +60,8 @@ describe('shortUrlLookupProvider', () => {
});

it('gracefully handles version conflict', async () => {
const error = new Error('version conflict');
error.data = { type: 'version_conflict_engine_exception' };
const error = savedObjectsClient.errors.decorateConflictError(new Error());
savedObjectsClient.create.throws(error);

const id = await shortUrl.generateUrlId(URL, req);
expect(id).to.eql(ID);
});
Expand Down
10 changes: 6 additions & 4 deletions src/server/http/short_url_lookup.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,24 @@ export default function (server) {
return {
async generateUrlId(url, req) {
const id = crypto.createHash('md5').update(url).digest('hex');
const savedObjectsClient = req.getSavedObjectsClient();
const { isConflictError } = savedObjectsClient.errors;

try {
const doc = await req.getSavedObjectsClient().create('url', {
const doc = await savedObjectsClient.create('url', {
url,
accessCount: 0,
createDate: new Date(),
accessDate: new Date()
}, { id });

return doc.id;
} catch(e) {
if (get(e, 'data.type') === 'version_conflict_engine_exception') {
} catch (error) {
if (isConflictError(error)) {
return id;
}

throw e;
throw error;
}
},

Expand Down
89 changes: 89 additions & 0 deletions src/server/saved_objects/client/lib/__tests__/decorate_es_error.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
import expect from 'expect.js';
import { errors as esErrors } from 'elasticsearch';

import { decorateEsError } from '../decorate_es_error';
import {
isEsUnavailableError,
isConflictError,
isNotAuthorizedError,
isForbiddenError,
isNotFoundError,
isBadRequestError,
} from '../errors';

describe('savedObjectsClient/decorateEsError', () => {
it('always returns the same error it receives', () => {
const error = new Error();
expect(decorateEsError(error)).to.be(error);
});

it('makes es.ConnectionFault a SavedObjectsClient/EsUnavailable error', () => {
const error = new esErrors.ConnectionFault();
expect(isEsUnavailableError(error)).to.be(false);
expect(decorateEsError(error)).to.be(error);
expect(isEsUnavailableError(error)).to.be(true);
});

it('makes es.ServiceUnavailable a SavedObjectsClient/EsUnavailable error', () => {
const error = new esErrors.ServiceUnavailable();
expect(isEsUnavailableError(error)).to.be(false);
expect(decorateEsError(error)).to.be(error);
expect(isEsUnavailableError(error)).to.be(true);
});

it('makes es.NoConnections a SavedObjectsClient/EsUnavailable error', () => {
const error = new esErrors.NoConnections();
expect(isEsUnavailableError(error)).to.be(false);
expect(decorateEsError(error)).to.be(error);
expect(isEsUnavailableError(error)).to.be(true);
});

it('makes es.RequestTimeout a SavedObjectsClient/EsUnavailable error', () => {
const error = new esErrors.RequestTimeout();
expect(isEsUnavailableError(error)).to.be(false);
expect(decorateEsError(error)).to.be(error);
expect(isEsUnavailableError(error)).to.be(true);
});

it('makes es.Conflict a SavedObjectsClient/Conflict error', () => {
const error = new esErrors.Conflict();
expect(isConflictError(error)).to.be(false);
expect(decorateEsError(error)).to.be(error);
expect(isConflictError(error)).to.be(true);
});

it('makes es.AuthenticationException a SavedObjectsClient/NotAuthorized error', () => {
const error = new esErrors.AuthenticationException();
expect(isNotAuthorizedError(error)).to.be(false);
expect(decorateEsError(error)).to.be(error);
expect(isNotAuthorizedError(error)).to.be(true);
});

it('makes es.Forbidden a SavedObjectsClient/Forbidden error', () => {
const error = new esErrors.Forbidden();
expect(isForbiddenError(error)).to.be(false);
expect(decorateEsError(error)).to.be(error);
expect(isForbiddenError(error)).to.be(true);
});

it('makes es.NotFound a SavedObjectsClient/NotFound error', () => {
const error = new esErrors.NotFound();
expect(isNotFoundError(error)).to.be(false);
expect(decorateEsError(error)).to.be(error);
expect(isNotFoundError(error)).to.be(true);
});

it('makes es.BadRequest a SavedObjectsClient/BadRequest error', () => {
const error = new esErrors.BadRequest();
expect(isBadRequestError(error)).to.be(false);
expect(decorateEsError(error)).to.be(error);
expect(isBadRequestError(error)).to.be(true);
});

it('returns other errors as Boom errors', () => {
const error = new Error();
expect(error).to.not.have.property('isBoom');
expect(decorateEsError(error)).to.be(error);
expect(error).to.have.property('isBoom');
});
});
Loading