Skip to content

Commit 286505f

Browse files
Cluster Allocation Explain API Throws IAE
Throws an Illegal Argument Exception when a non-integer value is passed as the `shard` parameter. The legacy behaviour of allowing strings to be passed, providing they are strings containing integers, is maintained.
1 parent 1e6473a commit 286505f

File tree

2 files changed

+90
-16
lines changed

2 files changed

+90
-16
lines changed

rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/cluster.allocation_explain/10_basic.yml

Lines changed: 62 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
body: { "index": "test", "shard": 2147483647, "primary": true }
4040

4141
---
42-
"cluster shard allocation explanation test with long shard value":
42+
"cluster shard allocation explanation test with an invalid, string shard parameter in the body":
4343
- do:
4444
indices.create:
4545
index: test
@@ -49,31 +49,72 @@
4949
- do:
5050
catch: /x_content_parse_exception/
5151
cluster.allocation_explain:
52-
body: { "index": "test", "shard": 214748364777, "primary": true }
52+
body: { "index": "test", "shard": "wrong", "primary": true }
5353

5454
---
55-
"cluster shard allocation explanation test with float shard value":
55+
"cluster shard allocation explanation test with a valid, string shard parameter in the body":
5656
- do:
5757
indices.create:
5858
index: test
59-
body: { "settings": { "index.number_of_shards": 2, "index.number_of_replicas": 0 } }
6059

6160
- match: { acknowledged: true }
6261

6362
- do:
6463
cluster.allocation_explain:
65-
body: { "index": "test", "shard": 1.0, "primary": true }
64+
body: { "index": "test", "shard": "0", "primary": true }
6665

6766
- match: { current_state: "started" }
6867
- is_true: current_node.id
6968
- match: { index: "test" }
70-
- match: { shard: 1 }
69+
- match: { shard: 0 }
7170
- match: { primary: true }
7271
- is_true: can_remain_on_current_node
7372
- is_true: can_rebalance_cluster
7473
- is_true: can_rebalance_to_other_node
7574
- is_true: rebalance_explanation
7675

76+
---
77+
"cluster shard allocation explanation test with long shard value":
78+
- do:
79+
indices.create:
80+
index: test
81+
82+
- match: { acknowledged: true }
83+
84+
- do:
85+
catch: /x_content_parse_exception/
86+
cluster.allocation_explain:
87+
body: { "index": "test", "shard": 214748364777, "primary": true }
88+
89+
---
90+
"cluster shard allocation explanation test with float shard value":
91+
- do:
92+
indices.create:
93+
index: test
94+
body: { "settings": { "index.number_of_shards": 2, "index.number_of_replicas": 0 } }
95+
96+
- match: { acknowledged: true }
97+
98+
- do:
99+
catch: /illegal_argument_exception/
100+
cluster.allocation_explain:
101+
body: { "index": "test", "shard": 1.0, "primary": true }
102+
103+
---
104+
"cluster shard allocation explanation test with stringified float shard value":
105+
- do:
106+
indices.create:
107+
index: test
108+
body: { "settings": { "index.number_of_shards": 2, "index.number_of_replicas": 0 } }
109+
110+
- match: { acknowledged: true }
111+
112+
- do:
113+
catch: /illegal_argument_exception/
114+
cluster.allocation_explain:
115+
body: { "index": "test", "shard": "1.0", "primary": true }
116+
117+
77118
---
78119
"cluster shard allocation explanation test with double shard value":
79120
- do:
@@ -84,18 +125,24 @@
84125
- match: { acknowledged: true }
85126

86127
- do:
128+
catch: /x_content_parse_exception/
87129
cluster.allocation_explain:
88130
body: { "index": "test", "shard": 1.1234567891234567, "primary": true }
89131

90-
- match: { current_state: "started" }
91-
- is_true: current_node.id
92-
- match: { index: "test" }
93-
- match: { shard: 1 }
94-
- match: { primary: true }
95-
- is_true: can_remain_on_current_node
96-
- is_true: can_rebalance_cluster
97-
- is_true: can_rebalance_to_other_node
98-
- is_true: rebalance_explanation
132+
---
133+
"cluster shard allocation explanation test with stringified double shard value":
134+
- do:
135+
indices.create:
136+
index: test
137+
body: { "settings": { "index.number_of_shards": 2, "index.number_of_replicas": 0 } }
138+
139+
- match: { acknowledged: true }
140+
141+
- do:
142+
catch: /x_content_parse_exception/
143+
cluster.allocation_explain:
144+
body: { "index": "test", "shard": "1.1234567891234567", "primary": true }
145+
99146

100147
---
101148
"cluster shard allocation explanation test with three valid body parameters":

server/src/main/java/org/elasticsearch/action/admin/cluster/allocation/ClusterAllocationExplainRequest.java

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,34 @@ public class ClusterAllocationExplainRequest extends MasterNodeRequest<ClusterAl
3131
private static final ObjectParser<ClusterAllocationExplainRequest, Void> PARSER = new ObjectParser<>("cluster/allocation/explain");
3232
static {
3333
PARSER.declareString(ClusterAllocationExplainRequest::setIndex, new ParseField("index"));
34-
PARSER.declareInt(ClusterAllocationExplainRequest::setShard, new ParseField("shard"));
34+
PARSER.declareField(
35+
ClusterAllocationExplainRequest::setShard,
36+
(xContentParser) -> {
37+
if (xContentParser.currentToken() == XContentParser.Token.VALUE_NUMBER) {
38+
if (xContentParser.numberType() == XContentParser.NumberType.INT) {
39+
return xContentParser.intValue();
40+
} else {
41+
throw new IllegalArgumentException("Expected an integer value for [shard]");
42+
}
43+
} else if (xContentParser.currentToken() == XContentParser.Token.VALUE_STRING) {
44+
String text = xContentParser.text();
45+
try {
46+
// Only accept if the string is a valid integer representation
47+
if (text.matches("[-+]?\\d+")) {
48+
return Integer.parseInt(text);
49+
} else {
50+
throw new IllegalArgumentException("String value for [shard] must be an integer, but was: " + text);
51+
}
52+
} catch (NumberFormatException e) {
53+
throw new IllegalArgumentException("Invalid integer value for [shard]: " + text, e);
54+
}
55+
} else {
56+
throw new IllegalArgumentException("Expected an integer for [shard]");
57+
}
58+
},
59+
new ParseField("shard"),
60+
ObjectParser.ValueType.INT
61+
);
3562
PARSER.declareBoolean(ClusterAllocationExplainRequest::setPrimary, new ParseField("primary"));
3663
PARSER.declareString(ClusterAllocationExplainRequest::setCurrentNode, new ParseField("current_node"));
3764
}

0 commit comments

Comments
 (0)