Skip to content

Commit f5918db

Browse files
committed
HLRC: Add ILM Status to HLRC
Adds support for the Index Lifecycle Management Status to the Java High-Level Rest Client. Relates to elastic#33100
1 parent ba8d4eb commit f5918db

File tree

8 files changed

+273
-19
lines changed

8 files changed

+273
-19
lines changed

client/rest-high-level/src/main/java/org/elasticsearch/client/IndexLifecycleClient.java

+29
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.elasticsearch.action.ActionListener;
2323
import org.elasticsearch.action.support.master.AcknowledgedResponse;
2424
import org.elasticsearch.client.indexlifecycle.DeleteLifecyclePolicyRequest;
25+
import org.elasticsearch.client.indexlifecycle.StatusILMResponse;
2526
import org.elasticsearch.protocol.xpack.indexlifecycle.ExplainLifecycleRequest;
2627
import org.elasticsearch.protocol.xpack.indexlifecycle.ExplainLifecycleResponse;
2728
import org.elasticsearch.protocol.xpack.indexlifecycle.SetIndexLifecyclePolicyRequest;
@@ -139,6 +140,34 @@ public AcknowledgedResponse stopILM(StopILMRequest request, RequestOptions optio
139140
AcknowledgedResponse::fromXContent, emptySet());
140141
}
141142

143+
/**
144+
* Get the status of index lifecycle management
145+
* See <a href="https://fix-me-when-we-have-docs.com">
146+
* the docs</a> for more.
147+
*
148+
* @param request the request with user defined timeouts.
149+
* @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
150+
*/
151+
public StatusILMResponse StatusILM(TimedRequest request, RequestOptions options) throws IOException {
152+
return restHighLevelClient.performRequestAndParseEntity(request, RequestConverters::statusILM, options,
153+
StatusILMResponse::fromXContent, emptySet());
154+
}
155+
156+
/**
157+
* Asynchronously get the status of index lifecycle management
158+
* See <a href="https://fix-me-when-we-have-docs.com">
159+
* the docs</a> for more.
160+
*
161+
* @param request the request with user defined timeouts.
162+
* @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
163+
* @param listener the listener to be notified upon request completion
164+
*/
165+
public void StatusILMAsync(TimedRequest request, RequestOptions options,
166+
ActionListener<StatusILMResponse> listener) {
167+
restHighLevelClient.performRequestAsyncAndParseEntity(request, RequestConverters::statusILM, options,
168+
StatusILMResponse::fromXContent, listener, emptySet());
169+
}
170+
142171
/**
143172
* Asynchronously stop the Index Lifecycle Management feature.
144173
* See <a href="https://fix-me-when-we-have-docs.com">

client/rest-high-level/src/main/java/org/elasticsearch/client/RequestConverters.java

+12
Original file line numberDiff line numberDiff line change
@@ -1241,6 +1241,18 @@ static Request stopILM(StopILMRequest stopILMRequest) {
12411241
return request;
12421242
}
12431243

1244+
static Request statusILM(TimedRequest ilmStatusRequest){
1245+
Request request = new Request(HttpGet.METHOD_NAME,
1246+
new EndpointBuilder()
1247+
.addPathPartAsIs("_ilm")
1248+
.addPathPartAsIs("status")
1249+
.build());
1250+
Params params = new Params(request);
1251+
params.withMasterTimeout(ilmStatusRequest.masterNodeTimeout());
1252+
params.withTimeout(ilmStatusRequest.timeout());
1253+
return request;
1254+
}
1255+
12441256
static Request explainLifecycle(ExplainLifecycleRequest explainLifecycleRequest) {
12451257
String[] indices = explainLifecycleRequest.indices() == null ? Strings.EMPTY_ARRAY : explainLifecycleRequest.indices();
12461258
Request request = new Request(HttpGet.METHOD_NAME,

client/rest-high-level/src/main/java/org/elasticsearch/client/TimedRequest.java

-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ public class TimedRequest implements Validatable {
3636

3737
public void setTimeout(TimeValue timeout) {
3838
this.timeout = timeout;
39-
4039
}
4140

4241
public void setMasterTimeout(TimeValue masterTimeout) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
/*
2+
* Licensed to Elasticsearch under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.elasticsearch.client.indexlifecycle;
21+
22+
import org.elasticsearch.action.admin.indices.shrink.ShrinkAction;
23+
import org.elasticsearch.common.ParseField;
24+
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
25+
import org.elasticsearch.common.xcontent.XContentParser;
26+
27+
import java.util.EnumSet;
28+
import java.util.Locale;
29+
import java.util.Objects;
30+
31+
/**
32+
* The current status of index lifecycle management. See {@link OperationMode} for available statuses.
33+
*/
34+
public class StatusILMResponse {
35+
36+
private final OperationMode operationMode;
37+
@SuppressWarnings("unchecked")
38+
private static final ConstructingObjectParser<StatusILMResponse, Void> PARSER = new ConstructingObjectParser<>(
39+
"operation_mode", a -> new StatusILMResponse((String) a[0]));
40+
41+
static {
42+
PARSER.declareString(ConstructingObjectParser.constructorArg(), new ParseField("operation_mode"));
43+
}
44+
45+
//package private for testing
46+
StatusILMResponse(String operationMode) {
47+
this.operationMode = OperationMode.fromString(operationMode);
48+
}
49+
50+
public OperationMode getOperationMode() {
51+
return operationMode;
52+
}
53+
54+
public static StatusILMResponse fromXContent(XContentParser parser) {
55+
return PARSER.apply(parser, null);
56+
}
57+
58+
/**
59+
* Enum representing the different modes that Index Lifecycle Service can operate in.
60+
*/
61+
public enum OperationMode {
62+
/**
63+
* This represents a state where no policies are executed
64+
*/
65+
STOPPED,
66+
67+
/**
68+
* this represents a state where only sensitive actions (like {@link ShrinkAction}) will be executed
69+
* until they finish, at which point the operation mode will move to <code>STOPPED</code>.
70+
*/
71+
STOPPING,
72+
73+
/**
74+
* Normal operation where all policies are executed as normal.
75+
*/
76+
RUNNING;
77+
78+
static OperationMode fromString(String string) {
79+
return EnumSet.allOf(OperationMode.class).stream()
80+
.filter(e -> string.equalsIgnoreCase(e.name())).findFirst()
81+
.orElseThrow(() -> new IllegalArgumentException(String.format(Locale.ENGLISH, "%s is not a valid operation_mode", string)));
82+
}
83+
}
84+
85+
// generated
86+
@Override
87+
public boolean equals(Object o) {
88+
if (this == o) return true;
89+
if (o == null || getClass() != o.getClass()) return false;
90+
StatusILMResponse that = (StatusILMResponse) o;
91+
return operationMode == that.operationMode;
92+
}
93+
94+
// generated
95+
@Override
96+
public int hashCode() {
97+
return Objects.hash(operationMode);
98+
}
99+
}

client/rest-high-level/src/test/java/org/elasticsearch/client/IndexLifecycleIT.java

+13-18
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@
2222
import org.apache.http.HttpEntity;
2323
import org.apache.http.entity.ContentType;
2424
import org.apache.http.nio.entity.NStringEntity;
25-
import org.apache.http.util.EntityUtils;
2625
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsRequest;
2726
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsResponse;
2827
import org.elasticsearch.action.support.master.AcknowledgedResponse;
2928
import org.elasticsearch.client.indexlifecycle.DeleteLifecyclePolicyRequest;
29+
import org.elasticsearch.client.indexlifecycle.StatusILMResponse;
3030
import org.elasticsearch.common.settings.Settings;
3131
import org.elasticsearch.protocol.xpack.indexlifecycle.ExplainLifecycleRequest;
3232
import org.elasticsearch.protocol.xpack.indexlifecycle.ExplainLifecycleResponse;
@@ -169,35 +169,30 @@ public void testStartStopILM() throws Exception {
169169
createIndex("baz", Settings.builder().put("index.lifecycle.name", "eggplant").build());
170170
createIndex("squash", Settings.EMPTY);
171171

172-
// TODO: NORELEASE convert this to using the high level client once
173-
// there are APIs for it
174-
Request statusReq = new Request("GET", "/_ilm/status");
175-
Response statusResponse = client().performRequest(statusReq);
176-
String statusResponseString = EntityUtils.toString(statusResponse.getEntity());
177-
assertEquals("{\"operation_mode\":\"RUNNING\"}", statusResponseString);
172+
TimedRequest statusRequest = new TimedRequest();
173+
StatusILMResponse statusResponse = execute(statusRequest, highLevelClient().indexLifecycle()::StatusILM,
174+
highLevelClient().indexLifecycle()::StatusILMAsync);
175+
assertEquals(statusResponse.getOperationMode(), StatusILMResponse.OperationMode.RUNNING);
178176

179177
StopILMRequest stopReq = new StopILMRequest();
180178
AcknowledgedResponse stopResponse = execute(stopReq, highLevelClient().indexLifecycle()::stopILM,
181179
highLevelClient().indexLifecycle()::stopILMAsync);
182180
assertTrue(stopResponse.isAcknowledged());
183181

184-
// TODO: NORELEASE convert this to using the high level client once there are APIs for it
185-
statusReq = new Request("GET", "/_ilm/status");
186-
statusResponse = client().performRequest(statusReq);
187-
statusResponseString = EntityUtils.toString(statusResponse.getEntity());
188-
assertThat(statusResponseString,
189-
Matchers.anyOf(equalTo("{\"operation_mode\":\"STOPPING\"}"), equalTo("{\"operation_mode\":\"STOPPED\"}")));
182+
183+
statusResponse = execute(statusRequest, highLevelClient().indexLifecycle()::StatusILM,
184+
highLevelClient().indexLifecycle()::StatusILMAsync);
185+
assertThat(statusResponse.getOperationMode(),
186+
Matchers.anyOf(equalTo(StatusILMResponse.OperationMode.STOPPING), equalTo(StatusILMResponse.OperationMode.STOPPED)));
190187

191188
StartILMRequest startReq = new StartILMRequest();
192189
AcknowledgedResponse startResponse = execute(startReq, highLevelClient().indexLifecycle()::startILM,
193190
highLevelClient().indexLifecycle()::startILMAsync);
194191
assertTrue(startResponse.isAcknowledged());
195192

196-
// TODO: NORELEASE convert this to using the high level client once there are APIs for it
197-
statusReq = new Request("GET", "/_ilm/status");
198-
statusResponse = client().performRequest(statusReq);
199-
statusResponseString = EntityUtils.toString(statusResponse.getEntity());
200-
assertEquals("{\"operation_mode\":\"RUNNING\"}", statusResponseString);
193+
statusResponse = execute(statusRequest, highLevelClient().indexLifecycle()::StatusILM,
194+
highLevelClient().indexLifecycle()::StatusILMAsync);
195+
assertEquals(statusResponse.getOperationMode(), StatusILMResponse.OperationMode.RUNNING);
201196
}
202197

203198
public void testExplainLifecycle() throws Exception {

client/rest-high-level/src/test/java/org/elasticsearch/client/RequestConvertersTests.java

+12
Original file line numberDiff line numberDiff line change
@@ -2755,6 +2755,18 @@ public void testStopILM() throws Exception {
27552755
assertThat(request.getParameters(), equalTo(expectedParams));
27562756
}
27572757

2758+
public void testStatusILM() throws Exception {
2759+
TimedRequest req = new TimedRequest();
2760+
Map<String, String> expectedParams = new HashMap<>();
2761+
setRandomMasterTimeout(req::setMasterTimeout, TimedRequest.DEFAULT_TIMEOUT, expectedParams);
2762+
setRandomTimeoutTimeValue(req::setTimeout, TimedRequest.DEFAULT_MASTER_TIMEOUT, expectedParams);
2763+
2764+
Request request = RequestConverters.statusILM(req);
2765+
assertThat(request.getMethod(), equalTo(HttpGet.METHOD_NAME));
2766+
assertThat(request.getEndpoint(), equalTo("/_ilm/status"));
2767+
assertThat(request.getParameters(), equalTo(expectedParams));
2768+
}
2769+
27582770
public void testExplainLifecycle() throws Exception {
27592771
ExplainLifecycleRequest req = new ExplainLifecycleRequest();
27602772
String[] indices = rarely() ? null : randomIndicesNames(0, 10);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Licensed to Elasticsearch under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.elasticsearch.client;
21+
22+
import org.elasticsearch.common.unit.TimeValue;
23+
import org.elasticsearch.test.ESTestCase;
24+
25+
public class TimedRequestTests extends ESTestCase {
26+
27+
public void testDefaults() {
28+
TimedRequest timedRequest = new TimedRequest();
29+
assertEquals(timedRequest.timeout(), TimedRequest.DEFAULT_TIMEOUT);
30+
assertEquals(timedRequest.masterNodeTimeout(), TimedRequest.DEFAULT_MASTER_TIMEOUT);
31+
}
32+
33+
public void testNonDefaults() {
34+
TimedRequest timedRequest = new TimedRequest();
35+
TimeValue timeout = TimeValue.timeValueSeconds(randomIntBetween(0, 1000));
36+
TimeValue masterTimeout = TimeValue.timeValueSeconds(randomIntBetween(0,1000));
37+
timedRequest.setTimeout(timeout);
38+
timedRequest.setMasterTimeout(masterTimeout);
39+
assertEquals(timedRequest.timeout(), timeout);
40+
assertEquals(timedRequest.masterNodeTimeout(), masterTimeout);
41+
}
42+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
* Licensed to Elasticsearch under one or more contributor
3+
* license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright
5+
* ownership. Elasticsearch licenses this file to you under
6+
* the Apache License, Version 2.0 (the "License"); you may
7+
* not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
20+
package org.elasticsearch.client.indexlifecycle;
21+
22+
import org.elasticsearch.common.xcontent.DeprecationHandler;
23+
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
24+
import org.elasticsearch.common.xcontent.XContentParser;
25+
import org.elasticsearch.common.xcontent.XContentType;
26+
import org.elasticsearch.protocol.xpack.indexlifecycle.OperationMode;
27+
import org.elasticsearch.test.ESTestCase;
28+
import org.hamcrest.CoreMatchers;
29+
30+
import java.io.IOException;
31+
import java.util.EnumSet;
32+
import java.util.stream.Collectors;
33+
34+
public class StatusILMResponseTests extends ESTestCase {
35+
36+
public void testClientServerStatuses() {
37+
assertEquals(
38+
EnumSet.allOf(StatusILMResponse.OperationMode.class).stream().map(Enum::name).collect(Collectors.toSet()),
39+
EnumSet.allOf(OperationMode.class).stream().map(Enum::name).collect(Collectors.toSet()));
40+
}
41+
42+
public void testFromName() {
43+
EnumSet.allOf(StatusILMResponse.OperationMode.class)
44+
.forEach(e -> assertEquals(StatusILMResponse.OperationMode.fromString(e.name()), e));
45+
}
46+
47+
public void testInvalidStatus() {
48+
String invalidName = randomAlphaOfLength(10);
49+
Exception e = expectThrows(IllegalArgumentException.class, () -> StatusILMResponse.OperationMode.fromString(invalidName));
50+
assertThat(e.getMessage(), CoreMatchers.containsString(invalidName + " is not a valid operation_mode"));
51+
}
52+
53+
public void testValidStatuses() {
54+
EnumSet.allOf(StatusILMResponse.OperationMode.class)
55+
.forEach(e -> assertEquals(new StatusILMResponse(e.name()).getOperationMode(), e));
56+
}
57+
58+
public void testXContent() throws IOException {
59+
XContentType xContentType = XContentType.JSON;
60+
String mode = randomFrom(EnumSet.allOf(StatusILMResponse.OperationMode.class)
61+
.stream().map(Enum::name).collect(Collectors.toList()));
62+
XContentParser parser = xContentType.xContent().createParser(NamedXContentRegistry.EMPTY,
63+
DeprecationHandler.THROW_UNSUPPORTED_OPERATION, "{\"operation_mode\" : \"" + mode + "\"}");
64+
assertEquals(StatusILMResponse.fromXContent(parser).getOperationMode(), StatusILMResponse.OperationMode.fromString(mode));
65+
}
66+
}

0 commit comments

Comments
 (0)