Skip to content

Commit 5ff4f93

Browse files
authored
Adds explain lifecycle API to the Rest Client (#32606)
1 parent 2fc3f1d commit 5ff4f93

File tree

18 files changed

+628
-284
lines changed

18 files changed

+628
-284
lines changed

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

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

2222
import org.elasticsearch.action.ActionListener;
23+
import org.elasticsearch.protocol.xpack.indexlifecycle.ExplainLifecycleRequest;
24+
import org.elasticsearch.protocol.xpack.indexlifecycle.ExplainLifecycleResponse;
2325
import org.elasticsearch.protocol.xpack.indexlifecycle.SetIndexLifecyclePolicyRequest;
2426
import org.elasticsearch.protocol.xpack.indexlifecycle.SetIndexLifecyclePolicyResponse;
2527

@@ -62,4 +64,32 @@ public void setIndexLifecyclePolicyAsync(SetIndexLifecyclePolicyRequest request,
6264
restHighLevelClient.performRequestAsyncAndParseEntity(request, RequestConverters::setIndexLifecyclePolicy, options,
6365
SetIndexLifecyclePolicyResponse::fromXContent, listener, emptySet());
6466
}
67+
68+
/**
69+
* Explain the lifecycle state for an index
70+
* See <a href="https://fix-me-when-we-have-docs.com">
71+
* the docs</a> for more.
72+
* @param request the request
73+
* @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
74+
* @return the response
75+
* @throws IOException in case there is a problem sending the request or parsing back the response
76+
*/
77+
public ExplainLifecycleResponse explainLifecycle(ExplainLifecycleRequest request,RequestOptions options) throws IOException {
78+
return restHighLevelClient.performRequestAndParseEntity(request, RequestConverters::explainLifecycle, options,
79+
ExplainLifecycleResponse::fromXContent, emptySet());
80+
}
81+
82+
/**
83+
* Asynchronously explain the lifecycle state for an index
84+
* See <a href="https://fix-me-when-we-have-docs.com">
85+
* the docs</a> for more.
86+
* @param request the request
87+
* @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
88+
* @param listener the listener to be notified upon request completion
89+
*/
90+
public void explainLifecycleAsync(ExplainLifecycleRequest request, RequestOptions options,
91+
ActionListener<ExplainLifecycleResponse> listener) {
92+
restHighLevelClient.performRequestAsyncAndParseEntity(request, RequestConverters::explainLifecycle, options,
93+
ExplainLifecycleResponse::fromXContent, listener, emptySet());
94+
}
6595
}

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@
109109
import org.elasticsearch.protocol.xpack.XPackInfoRequest;
110110
import org.elasticsearch.protocol.xpack.license.GetLicenseRequest;
111111
import org.elasticsearch.protocol.xpack.XPackUsageRequest;
112+
import org.elasticsearch.protocol.xpack.indexlifecycle.ExplainLifecycleRequest;
112113
import org.elasticsearch.protocol.xpack.indexlifecycle.SetIndexLifecyclePolicyRequest;
113114
import org.elasticsearch.protocol.xpack.license.PutLicenseRequest;
114115
import org.elasticsearch.protocol.xpack.watcher.DeleteWatchRequest;
@@ -1169,6 +1170,20 @@ static Request setIndexLifecyclePolicy(SetIndexLifecyclePolicyRequest setPolicyR
11691170
return request;
11701171
}
11711172

1173+
static Request explainLifecycle(ExplainLifecycleRequest explainLifecycleRequest) {
1174+
String[] indices = explainLifecycleRequest.indices() == null ? Strings.EMPTY_ARRAY : explainLifecycleRequest.indices();
1175+
Request request = new Request(HttpGet.METHOD_NAME,
1176+
new EndpointBuilder()
1177+
.addCommaSeparatedPathParts(indices)
1178+
.addPathPartAsIs("_ilm")
1179+
.addPathPartAsIs("explain")
1180+
.build());
1181+
Params params = new Params(request);
1182+
params.withIndicesOptions(explainLifecycleRequest.indicesOptions());
1183+
params.withMasterTimeout(explainLifecycleRequest.masterNodeTimeout());
1184+
return request;
1185+
}
1186+
11721187
static Request putLicense(PutLicenseRequest putLicenseRequest) {
11731188
String endpoint = new EndpointBuilder()
11741189
.addPathPartAsIs("_xpack")

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

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,14 @@
2525
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsRequest;
2626
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsResponse;
2727
import org.elasticsearch.common.settings.Settings;
28+
import org.elasticsearch.protocol.xpack.indexlifecycle.ExplainLifecycleRequest;
29+
import org.elasticsearch.protocol.xpack.indexlifecycle.ExplainLifecycleResponse;
30+
import org.elasticsearch.protocol.xpack.indexlifecycle.IndexLifecycleExplainResponse;
2831
import org.elasticsearch.protocol.xpack.indexlifecycle.SetIndexLifecyclePolicyRequest;
2932
import org.elasticsearch.protocol.xpack.indexlifecycle.SetIndexLifecyclePolicyResponse;
3033

34+
import java.util.Map;
35+
3136
import static org.hamcrest.Matchers.equalTo;
3237
import static org.hamcrest.Matchers.is;
3338

@@ -100,4 +105,95 @@ public void testSetIndexLifecyclePolicy() throws Exception {
100105
assertThat(settingsResponse.getSetting("foo", "index.lifecycle.name"), equalTo(policy));
101106
assertThat(settingsResponse.getSetting("baz", "index.lifecycle.name"), equalTo(policy));
102107
}
108+
109+
public void testExplainLifecycle() throws Exception {
110+
String policy = randomAlphaOfLength(10);
111+
112+
// TODO: NORELEASE convert this to using the high level client once there are APIs for it
113+
String jsonString = "{\n" +
114+
" \"policy\": {\n" +
115+
" \"type\": \"timeseries\",\n" +
116+
" \"phases\": {\n" +
117+
" \"hot\": {\n" +
118+
" \"actions\": {\n" +
119+
" \"rollover\": {\n" +
120+
" \"max_age\": \"50d\"\n" +
121+
" } \n" +
122+
" }\n" +
123+
" },\n" +
124+
" \"warm\": {\n" +
125+
" \"after\": \"1000s\",\n" +
126+
" \"actions\": {\n" +
127+
" \"allocate\": {\n" +
128+
" \"require\": { \"_name\": \"node-1\" },\n" +
129+
" \"include\": {},\n" +
130+
" \"exclude\": {}\n" +
131+
" },\n" +
132+
" \"shrink\": {\n" +
133+
" \"number_of_shards\": 1\n" +
134+
" },\n" +
135+
" \"forcemerge\": {\n" +
136+
" \"max_num_segments\": 1000\n" +
137+
" }\n" +
138+
" }\n" +
139+
" },\n" +
140+
" \"cold\": {\n" +
141+
" \"after\": \"2000s\",\n" +
142+
" \"actions\": {\n" +
143+
" \"replicas\": {\n" +
144+
" \"number_of_replicas\": 0\n" +
145+
" }\n" +
146+
" }\n" +
147+
" },\n" +
148+
" \"delete\": {\n" +
149+
" \"after\": \"3000s\",\n" +
150+
" \"actions\": {\n" +
151+
" \"delete\": {}\n" +
152+
" }\n" +
153+
" }\n" +
154+
" }\n" +
155+
" }\n" +
156+
"}";
157+
HttpEntity entity = new NStringEntity(jsonString, ContentType.APPLICATION_JSON);
158+
Request request = new Request("PUT", "/_ilm/" + policy);
159+
request.setEntity(entity);
160+
client().performRequest(request);
161+
162+
createIndex("foo", Settings.builder().put("index.lifecycle.name", policy).build());
163+
createIndex("baz", Settings.builder().put("index.lifecycle.name", policy).build());
164+
createIndex("squash", Settings.EMPTY);
165+
assertBusy(() -> {
166+
GetSettingsRequest getSettingsRequest = new GetSettingsRequest().indices("foo", "baz");
167+
GetSettingsResponse settingsResponse = highLevelClient().indices().getSettings(getSettingsRequest, RequestOptions.DEFAULT);
168+
assertThat(settingsResponse.getSetting("foo", "index.lifecycle.name"), equalTo(policy));
169+
assertThat(settingsResponse.getSetting("baz", "index.lifecycle.name"), equalTo(policy));
170+
assertThat(settingsResponse.getSetting("foo", "index.lifecycle.phase"), equalTo("hot"));
171+
assertThat(settingsResponse.getSetting("baz", "index.lifecycle.phase"), equalTo("hot"));
172+
});
173+
174+
ExplainLifecycleRequest req = new ExplainLifecycleRequest();
175+
req.indices("foo", "baz", "squash");
176+
ExplainLifecycleResponse response = execute(req, highLevelClient().indexLifecycle()::explainLifecycle,
177+
highLevelClient().indexLifecycle()::explainLifecycleAsync);
178+
Map<String, IndexLifecycleExplainResponse> indexResponses = response.getIndexResponses();
179+
assertEquals(3, indexResponses.size());
180+
IndexLifecycleExplainResponse fooResponse = indexResponses.get("foo");
181+
assertNotNull(fooResponse);
182+
assertTrue(fooResponse.managedByILM());
183+
assertEquals("foo", fooResponse.getIndex());
184+
assertEquals("hot", fooResponse.getPhase());
185+
assertEquals("rollover", fooResponse.getAction());
186+
assertEquals("attempt_rollover", fooResponse.getStep());
187+
IndexLifecycleExplainResponse bazResponse = indexResponses.get("baz");
188+
assertNotNull(bazResponse);
189+
assertTrue(bazResponse.managedByILM());
190+
assertEquals("baz", bazResponse.getIndex());
191+
assertEquals("hot", bazResponse.getPhase());
192+
assertEquals("rollover", bazResponse.getAction());
193+
assertEquals("attempt_rollover", bazResponse.getStep());
194+
IndexLifecycleExplainResponse squashResponse = indexResponses.get("squash");
195+
assertNotNull(squashResponse);
196+
assertFalse(squashResponse.managedByILM());
197+
assertEquals("squash", squashResponse.getIndex());
198+
}
103199
}

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@
126126
import org.elasticsearch.index.rankeval.RatedRequest;
127127
import org.elasticsearch.index.rankeval.RestRankEvalAction;
128128
import org.elasticsearch.protocol.xpack.XPackInfoRequest;
129+
import org.elasticsearch.protocol.xpack.indexlifecycle.ExplainLifecycleRequest;
129130
import org.elasticsearch.protocol.xpack.indexlifecycle.SetIndexLifecyclePolicyRequest;
130131
import org.elasticsearch.protocol.xpack.watcher.DeleteWatchRequest;
131132
import org.elasticsearch.protocol.xpack.watcher.PutWatchRequest;
@@ -2601,6 +2602,21 @@ public void testSetIndexLifecyclePolicy() throws Exception {
26012602
assertThat(request.getParameters(), equalTo(expectedParams));
26022603
}
26032604

2605+
public void testExplainLifecycle() throws Exception {
2606+
ExplainLifecycleRequest req = new ExplainLifecycleRequest();
2607+
String[] indices = rarely() ? null : randomIndicesNames(0, 10);
2608+
req.indices(indices);
2609+
Map<String, String> expectedParams = new HashMap<>();
2610+
setRandomMasterTimeout(req, expectedParams);
2611+
setRandomIndicesOptions(req::indicesOptions, req::indicesOptions, expectedParams);
2612+
2613+
Request request = RequestConverters.explainLifecycle(req);
2614+
assertThat(request.getMethod(), equalTo(HttpGet.METHOD_NAME));
2615+
String idxString = Strings.arrayToCommaDelimitedString(indices);
2616+
assertThat(request.getEndpoint(), equalTo("/" + (idxString.isEmpty() ? "" : (idxString + "/")) + "_ilm/explain"));
2617+
assertThat(request.getParameters(), equalTo(expectedParams));
2618+
}
2619+
26042620
public void testXPackDeleteWatch() {
26052621
DeleteWatchRequest deleteWatchRequest = new DeleteWatchRequest();
26062622
String watchId = randomAlphaOfLength(10);

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

Lines changed: 4 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,9 @@
77
package org.elasticsearch.xpack.core.indexlifecycle.action;
88

99
import org.elasticsearch.action.Action;
10-
import org.elasticsearch.action.ActionRequestValidationException;
11-
import org.elasticsearch.action.ActionResponse;
12-
import org.elasticsearch.action.support.master.info.ClusterInfoRequest;
13-
import org.elasticsearch.common.Strings;
14-
import org.elasticsearch.common.io.stream.StreamInput;
15-
import org.elasticsearch.common.io.stream.StreamOutput;
16-
import org.elasticsearch.common.xcontent.ToXContentObject;
17-
import org.elasticsearch.common.xcontent.XContentBuilder;
10+
import org.elasticsearch.protocol.xpack.indexlifecycle.ExplainLifecycleResponse;
1811

19-
import java.io.IOException;
20-
import java.util.Arrays;
21-
import java.util.List;
22-
import java.util.Objects;
23-
24-
public class ExplainLifecycleAction extends Action<ExplainLifecycleAction.Response> {
12+
public class ExplainLifecycleAction extends Action<ExplainLifecycleResponse> {
2513
public static final ExplainLifecycleAction INSTANCE = new ExplainLifecycleAction();
2614
public static final String NAME = "indices:admin/ilm/explain";
2715

@@ -30,107 +18,8 @@ protected ExplainLifecycleAction() {
3018
}
3119

3220
@Override
33-
public Response newResponse() {
34-
return new Response();
35-
}
36-
37-
public static class Response extends ActionResponse implements ToXContentObject {
38-
39-
private List<IndexLifecycleExplainResponse> indexResponses;
40-
41-
public Response() {
42-
}
43-
44-
public Response(List<IndexLifecycleExplainResponse> indexResponses) {
45-
this.indexResponses = indexResponses;
46-
}
47-
48-
public List<IndexLifecycleExplainResponse> getIndexResponses() {
49-
return indexResponses;
50-
}
51-
52-
@Override
53-
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
54-
builder.startObject();
55-
for (IndexLifecycleExplainResponse indexResponse : indexResponses) {
56-
builder.field(indexResponse.getIndex(), indexResponse);
57-
}
58-
builder.endObject();
59-
return builder;
60-
}
61-
62-
@Override
63-
public void readFrom(StreamInput in) throws IOException {
64-
indexResponses = in.readList(IndexLifecycleExplainResponse::new);
65-
}
66-
67-
@Override
68-
public void writeTo(StreamOutput out) throws IOException {
69-
out.writeList(indexResponses);
70-
}
71-
72-
@Override
73-
public int hashCode() {
74-
return Objects.hash(indexResponses);
75-
}
76-
77-
@Override
78-
public boolean equals(Object obj) {
79-
if (obj == null) {
80-
return false;
81-
}
82-
if (obj.getClass() != getClass()) {
83-
return false;
84-
}
85-
Response other = (Response) obj;
86-
return Objects.equals(indexResponses, other.indexResponses);
87-
}
88-
89-
@Override
90-
public String toString() {
91-
return Strings.toString(this, true, true);
92-
}
93-
94-
}
95-
96-
public static class Request extends ClusterInfoRequest<Request> {
97-
98-
public Request() {
99-
super();
100-
}
101-
102-
public Request(StreamInput in) throws IOException {
103-
super(in);
104-
}
105-
106-
@Override
107-
public ActionRequestValidationException validate() {
108-
return null;
109-
}
110-
111-
@Override
112-
public int hashCode() {
113-
return Objects.hash(Arrays.hashCode(indices()), indicesOptions());
114-
}
115-
116-
@Override
117-
public boolean equals(Object obj) {
118-
if (obj == null) {
119-
return false;
120-
}
121-
if (obj.getClass() != getClass()) {
122-
return false;
123-
}
124-
Request other = (Request) obj;
125-
return Objects.deepEquals(indices(), other.indices()) &&
126-
Objects.equals(indicesOptions(), other.indicesOptions());
127-
}
128-
129-
@Override
130-
public String toString() {
131-
return "Request [indices()=" + Arrays.toString(indices()) + ", indicesOptions()=" + indicesOptions() + "]";
132-
}
133-
21+
public ExplainLifecycleResponse newResponse() {
22+
return new ExplainLifecycleResponse();
13423
}
13524

13625
}

0 commit comments

Comments
 (0)