-
Notifications
You must be signed in to change notification settings - Fork 24.9k
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
REST client: introduce a strict deprecation mode #33708
Conversation
Minimal change that marks a rest request as failed if a deprecation warning has been issued by the server. This is valuable for internal tests and documentation snippets so that only non-deprecated code is used. This also minimizes possible divergence of the high level REST client from the server. `off` (default): the warning is logged at WARN level. As before the response is returned to the caller for further analysis. The caller still can retrieve all warnings from the response. `on`: the warning is logged at WARN level but the response is marked as failed. The caller can retrieve all warnings from the ResponseException.
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 left a question. I'm super thankful that you picked this up and at a high-level it looks sane. We'll take a closer review after understanding why you opted for a system property instead of a more direct constructor parameter.
@@ -119,6 +120,7 @@ | |||
this.failureListener = failureListener; | |||
this.pathPrefix = pathPrefix; | |||
this.nodeSelector = nodeSelector; | |||
this.strictDeprecationMode = System.getProperty("es.deprecation.mode.strict", "off").equals("on"); |
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 have one question and it's why you opted for a flag here instead of a constructor parameter?
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.
Initially I also considered a ctor param, but changed my mind ;)
Remember: I originally started looking into this as the High level REST client integration tests did not fail once I deprecated a url parameter. So for me the strict mode is extremely useful for testing in general. Having a flag that a CI environment (elastic's or otherwise) can enforce is a kind of a must. And with the current approach the community can help without the need to understand and modify the way the HLRC initiates the low level client or the impressive test infrastructure for that matter;) This way the clean up can be done step by step: start cleaning the high level REST client (by fixing warning by warning), then flip the flag in the CI for the project; tackle the next project. And once all projects are cleaned, then flip it globally.
Basically I consider this a test-only parameter, which must not leak into production under any circumstances. Perhaps the name of the variable should be changed; any naming suggestions welcomed!
On the other hand the RestClient ctor already has a "few" positional parameters (currently 7). And if a tester or a CI needs to be able to set the mode as well, the discussion of whether the ctor setting or the system one should have the priority, is always a tricky one (I do not know what is the ES "common" approach in such a case). Also if it is implemented as a ctor param, then any subprojects will need to create a rest client with the appropriate setting and be cleaned in a single go.
Basically it boiled down to the fact that this approach gives the minimal viable solution, a proof of concept if you like. And it makes it easier for small isolated PRs. Changing it to a ctor param instead or having a combination of both is trivial to implement (as part of this PR or a separate one). But incredibly difficult to migrate to/adopt.
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 idea behind having the builder for the rest client was so that we could add more parameters to ctor without bothering anyone. I admit there are a bunch though. I think I'd prefer to pass in a boolean or to make an interface that the client can implement to handle deprecations over a system property.
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.
Thanks for explaining your reasoning @lipsill. I think that I would rather see a constructor parameter here. We can use the builder to reduce the pain on users. I am not concerned about our tests as we already fail test cases that have unexpected warning headers through our test infrastructure.
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 am not concerned about our tests as we already fail test cases that have unexpected warning headers through our test infrastructure.
I think that only works on the YAML tests. If so this'd be the right hook to use to implement it for the other rest tests. That'd be a super useful followup if I'm right.
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 don't think that warnings that come back over the low level rest client always get checked. I know we check them in the yaml test cases but I don't think that we push them into the thread context. So subclasses of ESRestTestCase
that do not subclass ESClientYamlTestSuiteTestCase
likely don't check for deprecations.
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.
@nik9000 I am not sure that I understood you correctly. Is the idea here to always push any warnings from the REST tests to the thread context? So that the checks in the ESTestCase
can be reused (the one that @jasontedor pointed out)? This way any internal test causing a warning fails.
Basically in test mode any warning is pushed to the thread context regardless of the strict mode setting? The strict mode setting is for the clients, so that they can check if they are using deprecated functionality.
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.
Ah, you're right. Thanks for clarifying.
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 honestly don't know what the right thing to do for tests is at this point, but I figure it is right to solve that problem after you introduce the strict mode. For the most part, tests should just use that.
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.
Or, rather, for the most part, I expect tests not to get deprecations. So maybe, most tests should use strict mode and not worry about the thread context stuff. But we can think about that after this PR.
I think that we should also adapt the existing code that intended to print out the warnings here. I guess it does not work anymore given that the warnings format has changed and this code hasn't been updated. Would have been better to have an integration test maybe to test it with real warnings. |
As far as I can tell, this simply 'dumps' all
containing the warning I decided to leave the logging as is for now and not to parse the warning message from the http header. But it could be easily changed ;) |
Ok cool I misunderstood where the regex is used. Glad to hear that the log lines are still printed. I thought it's related to this PR as the original issue mentions logging with strict mode disabled, so I thought that the current logging may need some adjustments, but maybe it's ok as-is. |
Pinging @elastic/es-core-infra |
deprecation mode for the REST client
@jasontedor @nik9000 I just pushed a commit that replaces the system property with a ctor parameter for the strict mode. Can you have a look if this is what you had in mind? Thanks! |
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.
@lipsill, could you change a few small things? I left notes inline. Otherwise this is great!
In particular, I'd like to split how we integrate this into the testing framework as a follow up change. If you are interested in working on that as well as this that'd be wonderful. If not I'll have a look at it.
@@ -96,6 +100,40 @@ public HttpEntity getEntity() { | |||
return response.getEntity(); | |||
} | |||
|
|||
private static Pattern WARNING_HEADER_PATTERN = Pattern.compile( | |||
"299 " + // warn code |
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.
Could you line all of these up vertically?
@@ -58,6 +58,10 @@ private static String buildMessage(Response response) throws IOException { | |||
response.getStatusLine().toString() | |||
); | |||
|
|||
if (response.hasWarnings()) { | |||
message += "\n" + "Warnings: " + response.getWarnings(); |
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.
👍
@@ -82,6 +82,7 @@ | |||
public static final String CLIENT_RETRY_TIMEOUT = "client.retry.timeout"; | |||
public static final String CLIENT_SOCKET_TIMEOUT = "client.socket.timeout"; | |||
public static final String CLIENT_PATH_PREFIX = "client.path.prefix"; | |||
public static final String STRICT_DEPRECATION_MODE = "strict.deprecation.mode"; |
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'd save this for a follow up change. I suspect we'll want to control this some other way in tests. We might be able to get away with a method on ESRestTestCase
that returns the default for it but I'm not sure. Either way, I think it should wait.
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.
OK, I am removing it. My thinking here was to introduce the hook even if not used ;)
A method could be a way to go, I was following the way other tests are defining their settings (i.e. socket time out). But let's table this till the next PR ;)
"\""); // closing quote | ||
|
||
|
||
public List<String> getWarnings() { |
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.
Could you add javadoc for this?
return warnings; | ||
} | ||
|
||
public boolean hasWarnings() { |
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.
And could you add javadoc for this too?
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 to me. I'll try and merge and backport this this afternoon.
@elasticmachine test this please |
@nik9000 Thanks for the review! I just went ahead and merged
Can you trigger another CI? |
@elasticmachine test this please |
I just had a look at the CI failure
After bisect it seems like the issue is caused by ba3ceea. There is already an issue about it (#34098, #34046) and the test has already been muted (2b730d1, cb4cdf1). As the failing test has been muted after the last time I merged, I will go ahead and merge again ;) |
@elaticmachine, test this please. Again. |
Thanks again @lipsill! I've merged and will backport to 6.x. Would you like to work on turning this on in the testing framework? |
* master: Use more precise does S3 bucket exist method (elastic#34123) LLREST: Introduce a strict mode (elastic#33708) [CCR] Adjust list retryable errors (elastic#33985) Fix AggregationFactories.Builder equality and hash regarding order (elastic#34005) MINOR: Remove some deadcode in NodeEnv and Related (elastic#34133) Rest-Api-Spec: Correct spelling in filter_path description (elastic#33154) Core: Don't rely on java time for epoch seconds formatting (elastic#34086) Retry errors when fetching follower global checkpoint. (elastic#34019) Watcher: Reenable watcher stats REST tests (elastic#34107) Remove special-casing of Synonym filters in AnalysisRegistry (elastic#34034) Rename CCR APIs (elastic#34027) Fixed CCR stats api serialization issues and (elastic#33983) Support 'string'-style queries on metadata fields when reasonable. (elastic#34089) Logging: Drop Settings from security logger get calls (elastic#33940) SQL: Internal refactoring of operators as functions (elastic#34097)
es.deprecation.mode.strict
Add tests for the Low Level REST Client's strict deprecation hangling. Relates to elastic#33708
Yes, I'd like to take a stab at it ;) |
Introduces `RestClientBuilder#setStrictDeprecationMode` which defaults to false but when set to true, causes a rest request to fail if a deprecation warning header comes back in the response from Elasticsearch. This should be valueable to Elasticsearch's tests, especially those of the High Level REST Client where they will help catch divergence between the client and the server.
Add tests for the Low Level REST Client's strict deprecation handling. Relates to #33708
Add tests for the Low Level REST Client's strict deprecation handling. Relates to #33708
There are things, but it genuinely takes a long time because there is a lot going on. You could do |
#33708 introduced a strict deprecation mode that makes a REST request fail if there is a warning header in the response returned by Elasticsearch (usually a deprecation message signaling that a feature or a field has been deprecated). This change adds the strict deprecation mode into the REST integration tests, and makes the tests fail if a deprecated feature is used. Also any test using a deprecated feature has been modified to pass the build. The YAML integration tests already analyzed HTTP warnings so they do not use this mode, keeping their "expected vs actual" behavior.
@nik9000 the backport is done here right? |
Thanks for the ping @colings86! Yes, it is backported. Sorry for the mess! |
Introduces `RestClientBuilder#setStrictDeprecationMode` which defaults to false but when set to true, causes a rest request to fail if a deprecation warning header comes back in the response from Elasticsearch. This should be valueable to Elasticsearch's tests, especially those of the High Level REST Client where they will help catch divergence between the client and the server.
Add tests for the Low Level REST Client's strict deprecation handling. Relates to #33708
#33708 introduced a strict deprecation mode that makes a REST request fail if there is a warning header in the response returned by Elasticsearch (usually a deprecation message signaling that a feature or a field has been deprecated). This change adds the strict deprecation mode into the REST integration tests, and makes the tests fail if a deprecated feature is used. Also any test using a deprecated feature has been modified to pass the build. The YAML integration tests already analyzed HTTP warnings so they do not use this mode, keeping their "expected vs actual" behavior.
Minimal change that marks a rest request as failed if a deprecation
warning has been issued by the server. This is valuable for internal
tests and documentation snippets so that only non-deprecated code is
used.
This also minimizes possible divergence of the high level REST client
from the server.
off
(default): the warning is logged at WARN level. As before theresponse is returned to the caller for further analysis. The caller
still can retrieve all warnings from the response.
on
: the warning is logged at WARN level but the response is marked asfailed. The caller can retrieve all warnings from the ResponseException.
Fixes #33534