Skip to content

Commit 8750d62

Browse files
authored
Adds REST client support for starting and stopping ILM (#32609)
* Adds REST client support for PutOperationMode in ILM * Corrects licence headers * iter * add request converter test * Fixes tests * Creates start and stop actions for controlling ILM operation * Addresses review comments
1 parent 2305cb8 commit 8750d62

30 files changed

+609
-147
lines changed

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

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,13 @@
2020
package org.elasticsearch.client;
2121

2222
import org.elasticsearch.action.ActionListener;
23+
import org.elasticsearch.action.support.master.AcknowledgedResponse;
2324
import org.elasticsearch.protocol.xpack.indexlifecycle.ExplainLifecycleRequest;
2425
import org.elasticsearch.protocol.xpack.indexlifecycle.ExplainLifecycleResponse;
2526
import org.elasticsearch.protocol.xpack.indexlifecycle.SetIndexLifecyclePolicyRequest;
2627
import org.elasticsearch.protocol.xpack.indexlifecycle.SetIndexLifecyclePolicyResponse;
28+
import org.elasticsearch.protocol.xpack.indexlifecycle.StartILMRequest;
29+
import org.elasticsearch.protocol.xpack.indexlifecycle.StopILMRequest;
2730

2831
import java.io.IOException;
2932

@@ -65,6 +68,60 @@ public void setIndexLifecyclePolicyAsync(SetIndexLifecyclePolicyRequest request,
6568
SetIndexLifecyclePolicyResponse::fromXContent, listener, emptySet());
6669
}
6770

71+
/**
72+
* Start the Index Lifecycle Management feature.
73+
* See <a href="https://fix-me-when-we-have-docs.com">
74+
* the docs</a> for more.
75+
* @param request the request
76+
* @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
77+
* @return the response
78+
* @throws IOException in case there is a problem sending the request or parsing back the response
79+
*/
80+
public AcknowledgedResponse startILM(StartILMRequest request, RequestOptions options) throws IOException {
81+
return restHighLevelClient.performRequestAndParseEntity(request, RequestConverters::startILM, options,
82+
AcknowledgedResponse::fromXContent, emptySet());
83+
}
84+
85+
/**
86+
* Asynchronously start the Index Lifecycle Management feature.
87+
* See <a href="https://fix-me-when-we-have-docs.com">
88+
* the docs</a> for more.
89+
* @param request the request
90+
* @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
91+
* @param listener the listener to be notified upon request completion
92+
*/
93+
public void startILMAsync(StartILMRequest request, RequestOptions options, ActionListener<AcknowledgedResponse> listener) {
94+
restHighLevelClient.performRequestAsyncAndParseEntity(request, RequestConverters::startILM, options,
95+
AcknowledgedResponse::fromXContent, listener, emptySet());
96+
}
97+
98+
/**
99+
* Stop the Index Lifecycle Management feature.
100+
* See <a href="https://fix-me-when-we-have-docs.com">
101+
* the docs</a> for more.
102+
* @param request the request
103+
* @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
104+
* @return the response
105+
* @throws IOException in case there is a problem sending the request or parsing back the response
106+
*/
107+
public AcknowledgedResponse stopILM(StopILMRequest request, RequestOptions options) throws IOException {
108+
return restHighLevelClient.performRequestAndParseEntity(request, RequestConverters::stopILM, options,
109+
AcknowledgedResponse::fromXContent, emptySet());
110+
}
111+
112+
/**
113+
* Asynchronously stop the Index Lifecycle Management feature.
114+
* See <a href="https://fix-me-when-we-have-docs.com">
115+
* the docs</a> for more.
116+
* @param request the request
117+
* @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
118+
* @param listener the listener to be notified upon request completion
119+
*/
120+
public void stopILMAsync(StopILMRequest request, RequestOptions options, ActionListener<AcknowledgedResponse> listener) {
121+
restHighLevelClient.performRequestAsyncAndParseEntity(request, RequestConverters::stopILM, options,
122+
AcknowledgedResponse::fromXContent, listener, emptySet());
123+
}
124+
68125
/**
69126
* Explain the lifecycle state for an index
70127
* See <a href="https://fix-me-when-we-have-docs.com">

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

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,12 @@
107107
import org.elasticsearch.index.VersionType;
108108
import org.elasticsearch.index.rankeval.RankEvalRequest;
109109
import org.elasticsearch.protocol.xpack.XPackInfoRequest;
110-
import org.elasticsearch.protocol.xpack.license.GetLicenseRequest;
111110
import org.elasticsearch.protocol.xpack.XPackUsageRequest;
112111
import org.elasticsearch.protocol.xpack.indexlifecycle.ExplainLifecycleRequest;
113112
import org.elasticsearch.protocol.xpack.indexlifecycle.SetIndexLifecyclePolicyRequest;
113+
import org.elasticsearch.protocol.xpack.indexlifecycle.StartILMRequest;
114+
import org.elasticsearch.protocol.xpack.indexlifecycle.StopILMRequest;
115+
import org.elasticsearch.protocol.xpack.license.GetLicenseRequest;
114116
import org.elasticsearch.protocol.xpack.license.PutLicenseRequest;
115117
import org.elasticsearch.protocol.xpack.watcher.DeleteWatchRequest;
116118
import org.elasticsearch.protocol.xpack.watcher.PutWatchRequest;
@@ -1170,6 +1172,30 @@ static Request setIndexLifecyclePolicy(SetIndexLifecyclePolicyRequest setPolicyR
11701172
return request;
11711173
}
11721174

1175+
static Request startILM(StartILMRequest startILMRequest) {
1176+
Request request = new Request(HttpPost.METHOD_NAME,
1177+
new EndpointBuilder()
1178+
.addPathPartAsIs("_ilm")
1179+
.addPathPartAsIs("start")
1180+
.build());
1181+
Params params = new Params(request);
1182+
params.withMasterTimeout(startILMRequest.masterNodeTimeout());
1183+
params.withTimeout(startILMRequest.timeout());
1184+
return request;
1185+
}
1186+
1187+
static Request stopILM(StopILMRequest stopILMRequest) {
1188+
Request request = new Request(HttpPost.METHOD_NAME,
1189+
new EndpointBuilder()
1190+
.addPathPartAsIs("_ilm")
1191+
.addPathPartAsIs("stop")
1192+
.build());
1193+
Params params = new Params(request);
1194+
params.withMasterTimeout(stopILMRequest.masterNodeTimeout());
1195+
params.withTimeout(stopILMRequest.timeout());
1196+
return request;
1197+
}
1198+
11731199
static Request explainLifecycle(ExplainLifecycleRequest explainLifecycleRequest) {
11741200
String[] indices = explainLifecycleRequest.indices() == null ? Strings.EMPTY_ARRAY : explainLifecycleRequest.indices();
11751201
Request request = new Request(HttpGet.METHOD_NAME,

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

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,19 @@
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;
2526
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsRequest;
2627
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsResponse;
28+
import org.elasticsearch.action.support.master.AcknowledgedResponse;
2729
import org.elasticsearch.common.settings.Settings;
2830
import org.elasticsearch.protocol.xpack.indexlifecycle.ExplainLifecycleRequest;
2931
import org.elasticsearch.protocol.xpack.indexlifecycle.ExplainLifecycleResponse;
3032
import org.elasticsearch.protocol.xpack.indexlifecycle.IndexLifecycleExplainResponse;
3133
import org.elasticsearch.protocol.xpack.indexlifecycle.SetIndexLifecyclePolicyRequest;
3234
import org.elasticsearch.protocol.xpack.indexlifecycle.SetIndexLifecyclePolicyResponse;
35+
import org.elasticsearch.protocol.xpack.indexlifecycle.StartILMRequest;
36+
import org.elasticsearch.protocol.xpack.indexlifecycle.StopILMRequest;
37+
import org.hamcrest.Matchers;
3338

3439
import java.util.Map;
3540

@@ -106,6 +111,94 @@ public void testSetIndexLifecyclePolicy() throws Exception {
106111
assertThat(settingsResponse.getSetting("baz", "index.lifecycle.name"), equalTo(policy));
107112
}
108113

114+
public void testStartStopILM() throws Exception {
115+
String policy = randomAlphaOfLength(10);
116+
117+
// TODO: NORELEASE convert this to using the high level client once there are APIs for it
118+
String jsonString = "{\n" +
119+
" \"policy\": {\n" +
120+
" \"type\": \"timeseries\",\n" +
121+
" \"phases\": {\n" +
122+
" \"hot\": {\n" +
123+
" \"actions\": {\n" +
124+
" \"rollover\": {\n" +
125+
" \"max_age\": \"50d\"\n" +
126+
" } \n" +
127+
" }\n" +
128+
" },\n" +
129+
" \"warm\": {\n" +
130+
" \"after\": \"1000s\",\n" +
131+
" \"actions\": {\n" +
132+
" \"allocate\": {\n" +
133+
" \"require\": { \"_name\": \"node-1\" },\n" +
134+
" \"include\": {},\n" +
135+
" \"exclude\": {}\n" +
136+
" },\n" +
137+
" \"shrink\": {\n" +
138+
" \"number_of_shards\": 1\n" +
139+
" },\n" +
140+
" \"forcemerge\": {\n" +
141+
" \"max_num_segments\": 1000\n" +
142+
" }\n" +
143+
" }\n" +
144+
" },\n" +
145+
" \"cold\": {\n" +
146+
" \"after\": \"2000s\",\n" +
147+
" \"actions\": {\n" +
148+
" \"allocate\": {\n" +
149+
" \"number_of_replicas\": 0\n" +
150+
" }\n" +
151+
" }\n" +
152+
" },\n" +
153+
" \"delete\": {\n" +
154+
" \"after\": \"3000s\",\n" +
155+
" \"actions\": {\n" +
156+
" \"delete\": {}\n" +
157+
" }\n" +
158+
" }\n" +
159+
" }\n" +
160+
" }\n" +
161+
"}";
162+
HttpEntity entity = new NStringEntity(jsonString, ContentType.APPLICATION_JSON);
163+
Request request = new Request("PUT", "/_ilm/" + policy);
164+
request.setEntity(entity);
165+
client().performRequest(request);
166+
167+
createIndex("foo", Settings.builder().put("index.lifecycle.name", "bar").build());
168+
createIndex("baz", Settings.builder().put("index.lifecycle.name", "eggplant").build());
169+
createIndex("squash", Settings.EMPTY);
170+
171+
// TODO: NORELEASE convert this to using the high level client once
172+
// there are APIs for it
173+
Request statusReq = new Request("GET", "/_ilm/status");
174+
Response statusResponse = client().performRequest(statusReq);
175+
String statusResponseString = EntityUtils.toString(statusResponse.getEntity());
176+
assertEquals("{\"operation_mode\":\"RUNNING\"}", statusResponseString);
177+
178+
StopILMRequest stopReq = new StopILMRequest();
179+
AcknowledgedResponse stopResponse = execute(stopReq, highLevelClient().indexLifecycle()::stopILM,
180+
highLevelClient().indexLifecycle()::stopILMAsync);
181+
assertTrue(stopResponse.isAcknowledged());
182+
183+
// TODO: NORELEASE convert this to using the high level client once there are APIs for it
184+
statusReq = new Request("GET", "/_ilm/status");
185+
statusResponse = client().performRequest(statusReq);
186+
statusResponseString = EntityUtils.toString(statusResponse.getEntity());
187+
assertThat(statusResponseString,
188+
Matchers.anyOf(equalTo("{\"operation_mode\":\"STOPPING\"}"), equalTo("{\"operation_mode\":\"STOPPED\"}")));
189+
190+
StartILMRequest startReq = new StartILMRequest();
191+
AcknowledgedResponse startResponse = execute(startReq, highLevelClient().indexLifecycle()::startILM,
192+
highLevelClient().indexLifecycle()::startILMAsync);
193+
assertTrue(startResponse.isAcknowledged());
194+
195+
// TODO: NORELEASE convert this to using the high level client once there are APIs for it
196+
statusReq = new Request("GET", "/_ilm/status");
197+
statusResponse = client().performRequest(statusReq);
198+
statusResponseString = EntityUtils.toString(statusResponse.getEntity());
199+
assertEquals("{\"operation_mode\":\"RUNNING\"}", statusResponseString);
200+
}
201+
109202
public void testExplainLifecycle() throws Exception {
110203
String policy = randomAlphaOfLength(10);
111204

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

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,8 @@
128128
import org.elasticsearch.protocol.xpack.XPackInfoRequest;
129129
import org.elasticsearch.protocol.xpack.indexlifecycle.ExplainLifecycleRequest;
130130
import org.elasticsearch.protocol.xpack.indexlifecycle.SetIndexLifecyclePolicyRequest;
131+
import org.elasticsearch.protocol.xpack.indexlifecycle.StartILMRequest;
132+
import org.elasticsearch.protocol.xpack.indexlifecycle.StopILMRequest;
131133
import org.elasticsearch.protocol.xpack.watcher.DeleteWatchRequest;
132134
import org.elasticsearch.protocol.xpack.watcher.PutWatchRequest;
133135
import org.elasticsearch.repositories.fs.FsRepository;
@@ -2602,6 +2604,30 @@ public void testSetIndexLifecyclePolicy() throws Exception {
26022604
assertThat(request.getParameters(), equalTo(expectedParams));
26032605
}
26042606

2607+
public void testStartILM() throws Exception {
2608+
StartILMRequest req = new StartILMRequest();
2609+
Map<String, String> expectedParams = new HashMap<>();
2610+
setRandomMasterTimeout(req, expectedParams);
2611+
setRandomTimeout(req::timeout, AcknowledgedRequest.DEFAULT_ACK_TIMEOUT, expectedParams);
2612+
2613+
Request request = RequestConverters.startILM(req);
2614+
assertThat(request.getMethod(), equalTo(HttpPost.METHOD_NAME));
2615+
assertThat(request.getEndpoint(), equalTo("/_ilm/start"));
2616+
assertThat(request.getParameters(), equalTo(expectedParams));
2617+
}
2618+
2619+
public void testStopILM() throws Exception {
2620+
StopILMRequest req = new StopILMRequest();
2621+
Map<String, String> expectedParams = new HashMap<>();
2622+
setRandomMasterTimeout(req, expectedParams);
2623+
setRandomTimeout(req::timeout, AcknowledgedRequest.DEFAULT_ACK_TIMEOUT, expectedParams);
2624+
2625+
Request request = RequestConverters.stopILM(req);
2626+
assertThat(request.getMethod(), equalTo(HttpPost.METHOD_NAME));
2627+
assertThat(request.getEndpoint(), equalTo("/_ilm/stop"));
2628+
assertThat(request.getParameters(), equalTo(expectedParams));
2629+
}
2630+
26052631
public void testExplainLifecycle() throws Exception {
26062632
ExplainLifecycleRequest req = new ExplainLifecycleRequest();
26072633
String[] indices = rarely() ? null : randomIndicesNames(0, 10);

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/IndexLifecycleMetadata.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import org.elasticsearch.common.io.stream.StreamOutput;
1919
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
2020
import org.elasticsearch.common.xcontent.XContentBuilder;
21+
import org.elasticsearch.protocol.xpack.indexlifecycle.OperationMode;
2122
import org.elasticsearch.xpack.core.XPackPlugin.XPackMetaDataCustom;
2223

2324
import java.io.IOException;

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/action/GetStatusAction.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
import org.elasticsearch.common.io.stream.StreamOutput;
1616
import org.elasticsearch.common.xcontent.ToXContentObject;
1717
import org.elasticsearch.common.xcontent.XContentBuilder;
18-
import org.elasticsearch.xpack.core.indexlifecycle.OperationMode;
18+
import org.elasticsearch.protocol.xpack.indexlifecycle.OperationMode;
1919

2020
import java.io.IOException;
2121
import java.util.Objects;

x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/action/PutOperationModeAction.java

Lines changed: 0 additions & 99 deletions
This file was deleted.

0 commit comments

Comments
 (0)