-
Notifications
You must be signed in to change notification settings - Fork 25.3k
Add Path Parameters to Cluster Allocation Explain API #129342
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
base: main
Are you sure you want to change the base?
Add Path Parameters to Cluster Allocation Explain API #129342
Conversation
The cluster allocation explain API now accepts parameters via the request body, via path parameters passed in the URL, but not via both. Issue: elastic#127028
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.
Sorry got called away mid-review. I left a couple of comments, will come back to this.
@@ -44,6 +44,7 @@ | |||
import static org.mockito.Mockito.when; | |||
|
|||
public class RestRequestTests extends ESTestCase { | |||
private static final String PARAMETER_KEY = "PARAMETER_KEY"; |
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.
This indicates to me that this literal parameter name is important in these tests, but I think that's not the case. Instead, we should use randomIdentifier()
(within each test, it won't work in static context) to indicate to readers that the parameter name doesn't matter as long as it's equal in all the places it needs to be.
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.
Updated in 77080cb
if (hasAnyParameterBeenPassed(request)) { | ||
throw new IllegalArgumentException("Parameters cannot be passed in both the URL and the request body"); | ||
} |
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.
Is this needed? I would expect that if the request contains a parameter which isn't consumed in this method then that'll automatically throw an IAE - see org.elasticsearch.rest.BaseRestHandler#handleRequest
, particularly unconsumedParams
.
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.
You are correct, but this terminates the flow early before the body is parsed. In the case where parameters are passed alongside a request body and the request body contains an incorrect type, then the user would get the parsing exception thrown first. If they fixed that, then they would get the error about having parameters in the URL. I felt it more logical to be told: 1) you can't have parameters in both the body and the URL so pick one, and then 2) iterate through the errors found in the request body / parameters, whichever route selected. If this goes against conventions found in other APIs then happy to maintain consistency and remove this
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 there's a convention for this, at least not a very widely-implemented one. I doubt a user would ever really make these multiple mistakes in practice, and really doubt that they would care about having to solve the problems one-by-one; in contrast we're definitely going to be re-reading this code in future, so this is somewhere that we should prioritise simplicity of the implementation.
"description": "Specifies the index within which we would like to describe the shard" | ||
}, | ||
"shard": { | ||
"type": "number", | ||
"description": "Specifies the ID of the shard that you would like an explanation for" |
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.
Grammar nit: "we" or "you"? Tho other similar docs write this without needing these pronouns, maybe we can rephrase this.
Also (and this is really nitpicking to the max) avoid the dangling preposition: "the ID of the shard that you would like an explanation for" -> "the ID of the shard for which you would like an explanation"
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 coped the description for shard
verbatim from the existing API docs, here. I made up the description for index
so will update 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.
Updated in 84817db
@@ -5,7 +5,105 @@ | |||
cluster.allocation_explain: {} | |||
|
|||
--- | |||
"cluster shard allocation explanation 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.
I'd suggest keeping this test - it's not doing any harm IMO and without it the diff is awful.
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 renamed this test to cluster shard allocation explanation test with 3 valid body parameters
but I added tests above and below it, copying parts of this test as a template, and git has made a horrible diff of it.
To summarise my changes in this file:
- I kept all existing tests, but I may have renamed them to specify exactly what they were testing.
- I added extensive testing to the old functionality including:
2.1 Insufficient parameters passed in thebody
request sinceindex
,shard
andprimary
are required despite not being explicitly stated in the API docs.
2.2 Parameters of invalid types passed and throwing errors - I added tests for path parameter support, including:
3.1 Insufficient parameters passed
3.2 Parameters of invalid types passed
For 2.1 and 2.2, if this is tested elsewhere then please point me to it! I felt this an appropriate place to add these tests, and increased test coverage is always good, even if I've added hundreds of line of very similar, repetitive tests. If this can be parameterized somehow, then again I'm happy to do so.
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 see the new tests, they seem very thorough, I just recommend keeping this test as-is (including its name). Clean diffs are valuable when digging back through history looking for bugs. If you feel strongly about the naming then that can happen in a separate PR (maybe to go in first).
@@ -478,6 +478,18 @@ public int paramAsInt(String key, int defaultValue) { | |||
} | |||
} | |||
|
|||
public Integer paramAsInt(String key, Integer defaultValue) { |
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.
Naming nit: paramAsInteger
?
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.
Updated in 84817db
); | ||
} | ||
|
||
// This checks for optionally provided query parameters |
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.
This is correct, but it is the common pattern across all REST handlers (without needing comments elsewhere) so this sort of comment may actually cause more confusion: why is it called out here when this is just the common pattern? Is something different going 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.
Updated in 84817db
This comment was marked as off-topic.
This comment was marked as off-topic.
@elasticmachine update branch |
I think your yaml tests are failing on older ES versions where the parameters are not supported. You'd need to mark your yaml tests so they're skipped on older versions. See this doc. |
last time I did this, it was all version-based. It seems now we don't do that anymore and skipping yaml tests need to use the other options in the doc I linked above. From the looks of it, the capabilities/parameters one is related to what you do. I found one example where this is used that you can use as an example. |
47e5479
to
a8042af
Compare
- is_true: rebalance_explanation | ||
|
||
--- | ||
# Is this incorrect behaviour? Should an InvalidArgumentException be returned here? |
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'll call attention to this since this is current, production behaviour but I wasn't sure if it was correct
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.
ShardNotFoundException
extends ElasticsearchException
which according to the ExceptionHelper
here, does not return a RestStatus.BAD_REQUEST
, which may mean it's not converted to IAE which I would expect. Happy to be corrected
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.
ShardNotFoundException
is a ResourceNotFoundException
and ResourceNotFoundException#status
returns RestStatus#NOT_FOUND
which maps onto a 404 Not Found
response code. That sounds correct to me.
- match: { acknowledged: true } | ||
|
||
- do: | ||
# Numerical values passed here are implicitly supported by RestRequest parsing all parameters as strings |
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.
Calling this out since the API claims to only support strings for this field, but the way we parse the parameters means we can support integer values as strings, such as "1"
. Worth adding to the API documentation?
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.
This is a convention across the whole API surface, documented here.
- is_true: rebalance_explanation | ||
|
||
--- | ||
# When a float is passed in the body, a ShardNotFoundException is thrown. This behaviour is corrected when passed via a path 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.
Related to a comment above about potential incorrect behaviour when a float is passed. I have changed the behaviour when one is passed as a path parameter since I assumed this to be logical to throw an IAE
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 think I'd rather this were consistent. You're right, IllegalArgumentException
seems preferable if shard
isn't an integer. If that's a change in behaviour for the body-params case, let's fix that up first (in a separate PR) and then there's no concerns here.
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.
You've used the phrase "path parameters" in several places (including the PR title) but in fact these are query parameters. See e.g. RFC 3986 §3:
URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
Could you fix that? Other replies inline.
@@ -5,7 +5,105 @@ | |||
cluster.allocation_explain: {} | |||
|
|||
--- | |||
"cluster shard allocation explanation 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 I see the new tests, they seem very thorough, I just recommend keeping this test as-is (including its name). Clean diffs are valuable when digging back through history looking for bugs. If you feel strongly about the naming then that can happen in a separate PR (maybe to go in first).
- is_true: rebalance_explanation | ||
|
||
--- | ||
# Is this incorrect behaviour? Should an InvalidArgumentException be returned here? |
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.
ShardNotFoundException
is a ResourceNotFoundException
and ResourceNotFoundException#status
returns RestStatus#NOT_FOUND
which maps onto a 404 Not Found
response code. That sounds correct to me.
- match: { acknowledged: true } | ||
|
||
- do: | ||
# Numerical values passed here are implicitly supported by RestRequest parsing all parameters as strings |
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.
This is a convention across the whole API surface, documented here.
- is_true: rebalance_explanation | ||
|
||
--- | ||
# When a float is passed in the body, a ShardNotFoundException is thrown. This behaviour is corrected when passed via a path 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.
I think I'd rather this were consistent. You're right, IllegalArgumentException
seems preferable if shard
isn't an integer. If that's a change in behaviour for the body-params case, let's fix that up first (in a separate PR) and then there's no concerns here.
if (hasAnyParameterBeenPassed(request)) { | ||
throw new IllegalArgumentException("Parameters cannot be passed in both the URL and the request body"); | ||
} |
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 there's a convention for this, at least not a very widely-implemented one. I doubt a user would ever really make these multiple mistakes in practice, and really doubt that they would care about having to solve the problems one-by-one; in contrast we're definitely going to be re-reading this code in future, so this is somewhere that we should prioritise simplicity of the implementation.
The cluster allocation explain API now accepts parameters via the request body, via path parameters passed in the URL, but not via both.
#127028