Skip to content

Adds explain lifecycle API to the Rest Client #32606

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

Merged
merged 10 commits into from
Aug 9, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
package org.elasticsearch.client;

import org.elasticsearch.action.ActionListener;
import org.elasticsearch.protocol.xpack.indexlifecycle.ExplainLifecycleRequest;
import org.elasticsearch.protocol.xpack.indexlifecycle.ExplainLifecycleResponse;
import org.elasticsearch.protocol.xpack.indexlifecycle.SetIndexLifecyclePolicyRequest;
import org.elasticsearch.protocol.xpack.indexlifecycle.SetIndexLifecyclePolicyResponse;

Expand Down Expand Up @@ -62,4 +64,32 @@ public void setIndexLifecyclePolicyAsync(SetIndexLifecyclePolicyRequest request,
restHighLevelClient.performRequestAsyncAndParseEntity(request, RequestConverters::setIndexLifecyclePolicy, options,
SetIndexLifecyclePolicyResponse::fromXContent, listener, emptySet());
}

/**
* Explain the lifecycle state for an index
* See <a href="https://fix-me-when-we-have-docs.com">
* the docs</a> for more.
* @param request the request
* @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
* @return the response
* @throws IOException in case there is a problem sending the request or parsing back the response
*/
public ExplainLifecycleResponse explainLifecycle(ExplainLifecycleRequest request,RequestOptions options) throws IOException {
return restHighLevelClient.performRequestAndParseEntity(request, RequestConverters::explainLifecycle, options,
ExplainLifecycleResponse::fromXContent, emptySet());
}

/**
* Asynchronously explain the lifecycle state for an index
* See <a href="https://fix-me-when-we-have-docs.com">
* the docs</a> for more.
* @param request the request
* @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
* @param listener the listener to be notified upon request completion
*/
public void explainLifecycleAsync(ExplainLifecycleRequest request, RequestOptions options,
ActionListener<ExplainLifecycleResponse> listener) {
restHighLevelClient.performRequestAsyncAndParseEntity(request, RequestConverters::explainLifecycle, options,
ExplainLifecycleResponse::fromXContent, listener, emptySet());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@
import org.elasticsearch.protocol.xpack.XPackInfoRequest;
import org.elasticsearch.protocol.xpack.license.GetLicenseRequest;
import org.elasticsearch.protocol.xpack.XPackUsageRequest;
import org.elasticsearch.protocol.xpack.indexlifecycle.ExplainLifecycleRequest;
import org.elasticsearch.protocol.xpack.indexlifecycle.SetIndexLifecyclePolicyRequest;
import org.elasticsearch.protocol.xpack.license.PutLicenseRequest;
import org.elasticsearch.protocol.xpack.watcher.DeleteWatchRequest;
Expand Down Expand Up @@ -1169,6 +1170,20 @@ static Request setIndexLifecyclePolicy(SetIndexLifecyclePolicyRequest setPolicyR
return request;
}

static Request explainLifecycle(ExplainLifecycleRequest explainLifecycleRequest) {
String[] indices = explainLifecycleRequest.indices() == null ? Strings.EMPTY_ARRAY : explainLifecycleRequest.indices();
Request request = new Request(HttpGet.METHOD_NAME,
new EndpointBuilder()
.addCommaSeparatedPathParts(indices)
.addPathPartAsIs("_ilm")
.addPathPartAsIs("explain")
.build());
Params params = new Params(request);
params.withIndicesOptions(explainLifecycleRequest.indicesOptions());
params.withMasterTimeout(explainLifecycleRequest.masterNodeTimeout());
return request;
}

static Request putLicense(PutLicenseRequest putLicenseRequest) {
String endpoint = new EndpointBuilder()
.addPathPartAsIs("_xpack")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,14 @@
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsRequest;
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsResponse;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.protocol.xpack.indexlifecycle.ExplainLifecycleRequest;
import org.elasticsearch.protocol.xpack.indexlifecycle.ExplainLifecycleResponse;
import org.elasticsearch.protocol.xpack.indexlifecycle.IndexLifecycleExplainResponse;
import org.elasticsearch.protocol.xpack.indexlifecycle.SetIndexLifecyclePolicyRequest;
import org.elasticsearch.protocol.xpack.indexlifecycle.SetIndexLifecyclePolicyResponse;

import java.util.Map;

import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;

Expand Down Expand Up @@ -100,4 +105,95 @@ public void testSetIndexLifecyclePolicy() throws Exception {
assertThat(settingsResponse.getSetting("foo", "index.lifecycle.name"), equalTo(policy));
assertThat(settingsResponse.getSetting("baz", "index.lifecycle.name"), equalTo(policy));
}

public void testExplainLifecycle() throws Exception {
String policy = randomAlphaOfLength(10);

// TODO: NORELEASE convert this to using the high level client once there are APIs for it
String jsonString = "{\n" +
" \"policy\": {\n" +
" \"type\": \"timeseries\",\n" +
" \"phases\": {\n" +
" \"hot\": {\n" +
" \"actions\": {\n" +
" \"rollover\": {\n" +
" \"max_age\": \"50d\"\n" +
" } \n" +
" }\n" +
" },\n" +
" \"warm\": {\n" +
" \"after\": \"1000s\",\n" +
" \"actions\": {\n" +
" \"allocate\": {\n" +
" \"require\": { \"_name\": \"node-1\" },\n" +
" \"include\": {},\n" +
" \"exclude\": {}\n" +
" },\n" +
" \"shrink\": {\n" +
" \"number_of_shards\": 1\n" +
" },\n" +
" \"forcemerge\": {\n" +
" \"max_num_segments\": 1000\n" +
" }\n" +
" }\n" +
" },\n" +
" \"cold\": {\n" +
" \"after\": \"2000s\",\n" +
" \"actions\": {\n" +
" \"replicas\": {\n" +
" \"number_of_replicas\": 0\n" +
" }\n" +
" }\n" +
" },\n" +
" \"delete\": {\n" +
" \"after\": \"3000s\",\n" +
" \"actions\": {\n" +
" \"delete\": {}\n" +
" }\n" +
" }\n" +
" }\n" +
" }\n" +
"}";
HttpEntity entity = new NStringEntity(jsonString, ContentType.APPLICATION_JSON);
Request request = new Request("PUT", "/_ilm/" + policy);
request.setEntity(entity);
client().performRequest(request);

createIndex("foo", Settings.builder().put("index.lifecycle.name", policy).build());
createIndex("baz", Settings.builder().put("index.lifecycle.name", policy).build());
createIndex("squash", Settings.EMPTY);
assertBusy(() -> {
GetSettingsRequest getSettingsRequest = new GetSettingsRequest().indices("foo", "baz");
GetSettingsResponse settingsResponse = highLevelClient().indices().getSettings(getSettingsRequest, RequestOptions.DEFAULT);
assertThat(settingsResponse.getSetting("foo", "index.lifecycle.name"), equalTo(policy));
assertThat(settingsResponse.getSetting("baz", "index.lifecycle.name"), equalTo(policy));
assertThat(settingsResponse.getSetting("foo", "index.lifecycle.phase"), equalTo("hot"));
assertThat(settingsResponse.getSetting("baz", "index.lifecycle.phase"), equalTo("hot"));
});

ExplainLifecycleRequest req = new ExplainLifecycleRequest();
req.indices("foo", "baz", "squash");
ExplainLifecycleResponse response = execute(req, highLevelClient().indexLifecycle()::explainLifecycle,
highLevelClient().indexLifecycle()::explainLifecycleAsync);
Map<String, IndexLifecycleExplainResponse> indexResponses = response.getIndexResponses();
assertEquals(3, indexResponses.size());
IndexLifecycleExplainResponse fooResponse = indexResponses.get("foo");
assertNotNull(fooResponse);
assertTrue(fooResponse.managedByILM());
assertEquals("foo", fooResponse.getIndex());
assertEquals("hot", fooResponse.getPhase());
assertEquals("rollover", fooResponse.getAction());
assertEquals("attempt_rollover", fooResponse.getStep());
IndexLifecycleExplainResponse bazResponse = indexResponses.get("baz");
assertNotNull(bazResponse);
assertTrue(bazResponse.managedByILM());
assertEquals("baz", bazResponse.getIndex());
assertEquals("hot", bazResponse.getPhase());
assertEquals("rollover", bazResponse.getAction());
assertEquals("attempt_rollover", bazResponse.getStep());
IndexLifecycleExplainResponse squashResponse = indexResponses.get("squash");
assertNotNull(squashResponse);
assertFalse(squashResponse.managedByILM());
assertEquals("squash", squashResponse.getIndex());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@
import org.elasticsearch.index.rankeval.RatedRequest;
import org.elasticsearch.index.rankeval.RestRankEvalAction;
import org.elasticsearch.protocol.xpack.XPackInfoRequest;
import org.elasticsearch.protocol.xpack.indexlifecycle.ExplainLifecycleRequest;
import org.elasticsearch.protocol.xpack.indexlifecycle.SetIndexLifecyclePolicyRequest;
import org.elasticsearch.protocol.xpack.watcher.DeleteWatchRequest;
import org.elasticsearch.protocol.xpack.watcher.PutWatchRequest;
Expand Down Expand Up @@ -2601,6 +2602,21 @@ public void testSetIndexLifecyclePolicy() throws Exception {
assertThat(request.getParameters(), equalTo(expectedParams));
}

public void testExplainLifecycle() throws Exception {
ExplainLifecycleRequest req = new ExplainLifecycleRequest();
String[] indices = rarely() ? null : randomIndicesNames(0, 10);
req.indices(indices);
Map<String, String> expectedParams = new HashMap<>();
setRandomMasterTimeout(req, expectedParams);
setRandomIndicesOptions(req::indicesOptions, req::indicesOptions, expectedParams);

Request request = RequestConverters.explainLifecycle(req);
assertThat(request.getMethod(), equalTo(HttpGet.METHOD_NAME));
String idxString = Strings.arrayToCommaDelimitedString(indices);
assertThat(request.getEndpoint(), equalTo("/" + (idxString.isEmpty() ? "" : (idxString + "/")) + "_ilm/explain"));
assertThat(request.getParameters(), equalTo(expectedParams));
}

public void testXPackDeleteWatch() {
DeleteWatchRequest deleteWatchRequest = new DeleteWatchRequest();
String watchId = randomAlphaOfLength(10);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,9 @@
package org.elasticsearch.xpack.core.indexlifecycle.action;

import org.elasticsearch.action.Action;
import org.elasticsearch.action.ActionRequestValidationException;
import org.elasticsearch.action.ActionResponse;
import org.elasticsearch.action.support.master.info.ClusterInfoRequest;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.ToXContentObject;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.protocol.xpack.indexlifecycle.ExplainLifecycleResponse;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

public class ExplainLifecycleAction extends Action<ExplainLifecycleAction.Response> {
public class ExplainLifecycleAction extends Action<ExplainLifecycleResponse> {
public static final ExplainLifecycleAction INSTANCE = new ExplainLifecycleAction();
public static final String NAME = "indices:admin/ilm/explain";

Expand All @@ -30,107 +18,8 @@ protected ExplainLifecycleAction() {
}

@Override
public Response newResponse() {
return new Response();
}

public static class Response extends ActionResponse implements ToXContentObject {

private List<IndexLifecycleExplainResponse> indexResponses;

public Response() {
}

public Response(List<IndexLifecycleExplainResponse> indexResponses) {
this.indexResponses = indexResponses;
}

public List<IndexLifecycleExplainResponse> getIndexResponses() {
return indexResponses;
}

@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject();
for (IndexLifecycleExplainResponse indexResponse : indexResponses) {
builder.field(indexResponse.getIndex(), indexResponse);
}
builder.endObject();
return builder;
}

@Override
public void readFrom(StreamInput in) throws IOException {
indexResponses = in.readList(IndexLifecycleExplainResponse::new);
}

@Override
public void writeTo(StreamOutput out) throws IOException {
out.writeList(indexResponses);
}

@Override
public int hashCode() {
return Objects.hash(indexResponses);
}

@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (obj.getClass() != getClass()) {
return false;
}
Response other = (Response) obj;
return Objects.equals(indexResponses, other.indexResponses);
}

@Override
public String toString() {
return Strings.toString(this, true, true);
}

}

public static class Request extends ClusterInfoRequest<Request> {

public Request() {
super();
}

public Request(StreamInput in) throws IOException {
super(in);
}

@Override
public ActionRequestValidationException validate() {
return null;
}

@Override
public int hashCode() {
return Objects.hash(Arrays.hashCode(indices()), indicesOptions());
}

@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (obj.getClass() != getClass()) {
return false;
}
Request other = (Request) obj;
return Objects.deepEquals(indices(), other.indices()) &&
Objects.equals(indicesOptions(), other.indicesOptions());
}

@Override
public String toString() {
return "Request [indices()=" + Arrays.toString(indices()) + ", indicesOptions()=" + indicesOptions() + "]";
}

public ExplainLifecycleResponse newResponse() {
return new ExplainLifecycleResponse();
}

}
Loading