-
Notifications
You must be signed in to change notification settings - Fork 8.3k
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
[savedObjects] fix error handling when Kibana index is missing #14141
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a couple nitpicks, but I'm good with merging as-is. LGTM
} | ||
|
||
// 404 might be because document is missing or index is missing, | ||
// don't leak that implementation detail to the user |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be great if we could add an explanation here. (Basically answering the question: Why don't we want to leak this to the user?)
We've got this same comment in multiple places. Not sure if we should add an explanation in one place and "link" there, but it feels like we should make it clear here, at least.
.expect(200) | ||
.then(resp => { | ||
expect(resp.body).to.eql({ | ||
saved_objects: [ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would be 🎉 to have snapshot tests for these, but that's of course not possible yet
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are basically snapshot tests, no? What would be different with a snapshot test?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
++ Yeah, it's basically the same (I just prefer working with snapshots over large objects, e.g. when changing code etc)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shit, I totally meant to delete my comment, thought it failed, and accidentally deleted yours 😿
}); | ||
}); | ||
|
||
describe('unkown id', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo, unknown
@@ -25,6 +24,62 @@ export class SavedObjectsClient { | |||
this._unwrappedCallCluster = callCluster; | |||
} | |||
|
|||
/** | |||
* ## SavedObjectsClient errors |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright, you asked for some docs @kjbekkelund :) I don't think it's bad to have some of these thought written down but let me know if you think I went overboard
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❤️ I like this! It gives tons of context and makes it way easier to understand why we do what we do.
const indexNotFound = response.error && response.error.type === 'index_not_found_exception'; | ||
if (docNotFound || indexNotFound) { | ||
// see "404s from missing index" above | ||
throw errors.createGenericNotFoundError(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also fixed the lib/errors
module. Including a decorateNotFoundError
contradicts the goal of not exposing where NotFound errors come from, so now it has a createGenericNotFoundError()
that does the same thing these lines were doing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
@epixa any more feedback? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, just few nits.
* by the decorators in `./lib/errors` | ||
* | ||
* Type 1 errors are inevitable, but since all expected/handle-able errors | ||
* should be Type 2 the `isXYZError()` helpers exposed at `SavedObjectsClient.errors` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo: is this a typo (double mentioning of SavedObjectsClient.errors
)?
* ### 404s from missing index | ||
* | ||
* From the perspective of application code and APIs the SavedObjectsClient is | ||
* a black box that persists objects. One of the internal details that the client |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question: just for my understanding, that the client has no control over
- the client
here is the consumer of SavedObjectsClient
or the SavedObjectsClient
itself?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I use client here to mean SavedObjectsClient and browser/user client. I'll more clearly distinguish those.
* | ||
* At the time of writing we are in the process of transitioning away from the | ||
* operating assumption that the SavedObjects index is always available. Part of | ||
* this transition is handling errors resulting from an index missing. These use |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo: these use to trigger
--> these used to trigger
?
expect(error.output.payload).to.have.property('message', 'biz: foobar'); | ||
it('Uses "Not Found" message', () => { | ||
const error = createGenericNotFoundError(); | ||
expect(error.output.payload).to.have.property('message', 'Not Found'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question: there is no need to change anything here, just wondering why not to use to.be
?
expect(error.output.payload.message).to.be('Not Found')
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the error message shows the properties that do exist, that is all
callAdminCluster.returns({}); | ||
callAdminCluster.returns({ | ||
result: 'deleted' | ||
}); | ||
await savedObjectsClient.delete('index-pattern', 'logstash-*'); | ||
|
||
expect(callAdminCluster.calledOnce).to.be(true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: since you're here already :)
sinon.assert.calledOnce(onBeforeWrite);
sinon.assert.calledOnce(callAdminCluster);
sinon.assert.calledWithExactly(callAdminCluster, 'delete', {
type: 'doc',
id: 'index-pattern:logstash-*',
refresh: 'wait_for',
index: '.kibana-test',
ignore: [404],
});
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a lot of that in this file, but if you like!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pretty sure I'm falling in love with sinon's matcher API. I'm going to merge if the tests pass, but if you wouldn't mind double checking this commit @azasypkin, I would appreciate it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, thanks!
tasks/config/run.js
Outdated
@@ -55,6 +55,7 @@ module.exports = function (grunt) { | |||
...stdDevArgs, | |||
'--optimize.enabled=false', | |||
'--elasticsearch.url=' + esTestConfig.getUrl(), | |||
'--elasticsearch.healthCheck.delay=360000', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question: just curious, why exactly 6 minutes? :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Haha, I'm horrible at math
|
||
it('returns generic 404 when kibana index is missing', async () => ( | ||
await supertest | ||
.delete(`/api/saved_objects/dashboard/not-a-real-id`) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: maybe not-a-real-id
---> be3733a0-9efe-11e7-acb3-3dab96693fab
just to be sure we get 404
because of missing index and not because of non-existing id.
@spalger I don't have anything new to add beyond @azasypkin's latest round of comments. |
6852b15
to
f98c009
Compare
* [savedObjects/delete+bulk_get] add failing tests * [savedObjects/delete+bulk_get] improve 404 handling * [savedObjects/client] fix mocha tests * [savedObjects/tests] remove extra test wrapper * [apiIntegration/kbnServer] basically disable es healthcheck * [savedObjects/create] add integration test * [savedObjects/find] add failing integration tests * [savedObjects/find] fix failing test * [savedObjects/client] explain reason for generic 404s * [savedObjects/get] add integration tests * [savedObjects/find] test request with unkown type * [savedObjects/find] add some more weird param tests * [savedObjects/find] test that weird params pass when no index * [savedObjects/update] use generic 404 * fix typos * [savedObjects/update] add integration tests * remove debugging uncomment * [savedObjects/tests] move backup kibana index delete out of tests * [savedObjects/tests/esArchives] remove logstash data * [savedObjects] update test * [uiSettings] remove detailed previously leaked from API * [functional/dashboard] wrap check that is only failing on Jenkins * [savedObjects/error] replace decorateNotFound with createGenericNotFound * fix typo * [savedObjectsClient/errors] fix decorateEsError() test * [savedObjectsClient] fix typos * [savedObjects/tests/functional] delete document that would normally exist * [savedObjectsClient/tests] use sinon assertions * [savedObjects/apiTests] create without index responds with 503 after #14202
6.x: ddc1d9c |
Currently when the Kibana index is missing the savedObjectsClient and APIs produce unexpected results. This PR tests and formalizes the following behaviors:
For those unfamiliar, run the API integration tests and dependencies in one go with:
To run the server/runner combo and for debugging run the following two commands in separate tabs: