HLRC: Add Lifecycle Policy delete to the HLRC (#33142)

Adds support for Lifecycle Policy deletion to the Java High-Level Rest Client.

Relates to #33100
This commit is contained in:
Gordon Brown 2018-08-29 13:14:46 -06:00 committed by GitHub
parent 454ce99b01
commit ba8d4eba8b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 250 additions and 2 deletions

View File

@ -21,6 +21,7 @@ package org.elasticsearch.client;
import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.support.master.AcknowledgedResponse; import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.client.indexlifecycle.DeleteLifecyclePolicyRequest;
import org.elasticsearch.protocol.xpack.indexlifecycle.ExplainLifecycleRequest; import org.elasticsearch.protocol.xpack.indexlifecycle.ExplainLifecycleRequest;
import org.elasticsearch.protocol.xpack.indexlifecycle.ExplainLifecycleResponse; import org.elasticsearch.protocol.xpack.indexlifecycle.ExplainLifecycleResponse;
import org.elasticsearch.protocol.xpack.indexlifecycle.SetIndexLifecyclePolicyRequest; import org.elasticsearch.protocol.xpack.indexlifecycle.SetIndexLifecyclePolicyRequest;
@ -39,6 +40,35 @@ public class IndexLifecycleClient {
this.restHighLevelClient = restHighLevelClient; this.restHighLevelClient = restHighLevelClient;
} }
/**
* Delete a lifecycle definition
* 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 AcknowledgedResponse deleteLifecyclePolicy(DeleteLifecyclePolicyRequest request,
RequestOptions options) throws IOException {
return restHighLevelClient.performRequestAndParseEntity(request, RequestConverters::deleteLifecyclePolicy, options,
AcknowledgedResponse::fromXContent, emptySet());
}
/**
* Asynchronously delete a lifecycle definition
* 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 deleteLifecyclePolicyAsync(DeleteLifecyclePolicyRequest request, RequestOptions options,
ActionListener<AcknowledgedResponse> listener) {
restHighLevelClient.performRequestAsyncAndParseEntity(request, RequestConverters::deleteLifecyclePolicy, options,
AcknowledgedResponse::fromXContent, listener, emptySet());
}
/** /**
* Set the index lifecycle policy for an index * Set the index lifecycle policy for an index
* See <a href="https://fix-me-when-we-have-docs.com"> * See <a href="https://fix-me-when-we-have-docs.com">

View File

@ -88,6 +88,7 @@ import org.elasticsearch.action.support.ActiveShardCount;
import org.elasticsearch.action.support.IndicesOptions; import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.action.support.WriteRequest; import org.elasticsearch.action.support.WriteRequest;
import org.elasticsearch.action.update.UpdateRequest; import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.indexlifecycle.DeleteLifecyclePolicyRequest;
import org.elasticsearch.cluster.health.ClusterHealthStatus; import org.elasticsearch.cluster.health.ClusterHealthStatus;
import org.elasticsearch.common.Nullable; import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.Priority; import org.elasticsearch.common.Priority;
@ -1190,6 +1191,18 @@ final class RequestConverters {
return request; return request;
} }
static Request deleteLifecyclePolicy(DeleteLifecyclePolicyRequest deleteLifecyclePolicyRequest) {
Request request = new Request(HttpDelete.METHOD_NAME,
new EndpointBuilder()
.addPathPartAsIs("_ilm")
.addPathPartAsIs(deleteLifecyclePolicyRequest.getLifecyclePolicy())
.build());
Params params = new Params(request);
params.withMasterTimeout(deleteLifecyclePolicyRequest.masterNodeTimeout());
params.withTimeout(deleteLifecyclePolicyRequest.timeout());
return request;
}
static Request setIndexLifecyclePolicy(SetIndexLifecyclePolicyRequest setPolicyRequest) { static Request setIndexLifecyclePolicy(SetIndexLifecyclePolicyRequest setPolicyRequest) {
String[] indices = setPolicyRequest.indices() == null ? Strings.EMPTY_ARRAY : setPolicyRequest.indices(); String[] indices = setPolicyRequest.indices() == null ? Strings.EMPTY_ARRAY : setPolicyRequest.indices();
Request request = new Request(HttpPut.METHOD_NAME, Request request = new Request(HttpPut.METHOD_NAME,

View File

@ -28,8 +28,11 @@ import org.elasticsearch.common.unit.TimeValue;
*/ */
public class TimedRequest implements Validatable { public class TimedRequest implements Validatable {
private TimeValue timeout; public static final TimeValue DEFAULT_TIMEOUT = TimeValue.timeValueSeconds(30);
private TimeValue masterTimeout; public static final TimeValue DEFAULT_MASTER_TIMEOUT = TimeValue.timeValueSeconds(30);
private TimeValue timeout = DEFAULT_TIMEOUT;
private TimeValue masterTimeout = DEFAULT_MASTER_TIMEOUT;
public void setTimeout(TimeValue timeout) { public void setTimeout(TimeValue timeout) {
this.timeout = timeout; this.timeout = timeout;

View File

@ -0,0 +1,59 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.client.indexlifecycle;
import org.elasticsearch.client.TimedRequest;
import org.elasticsearch.common.Strings;
import java.util.Objects;
public class DeleteLifecyclePolicyRequest extends TimedRequest {
private final String lifecyclePolicy;
public DeleteLifecyclePolicyRequest(String lifecyclePolicy) {
if (Strings.isNullOrEmpty(lifecyclePolicy)) {
throw new IllegalArgumentException("lifecycle name must be present");
}
this.lifecyclePolicy = lifecyclePolicy;
}
public String getLifecyclePolicy() {
return lifecyclePolicy;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
DeleteLifecyclePolicyRequest that = (DeleteLifecyclePolicyRequest) o;
return Objects.equals(getLifecyclePolicy(), that.getLifecyclePolicy());
}
@Override
public int hashCode() {
return Objects.hash(getLifecyclePolicy());
}
}

View File

@ -26,6 +26,7 @@ import org.apache.http.util.EntityUtils;
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsRequest; import org.elasticsearch.action.admin.indices.settings.get.GetSettingsRequest;
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsResponse; import org.elasticsearch.action.admin.indices.settings.get.GetSettingsResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse; import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.client.indexlifecycle.DeleteLifecyclePolicyRequest;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.protocol.xpack.indexlifecycle.ExplainLifecycleRequest; import org.elasticsearch.protocol.xpack.indexlifecycle.ExplainLifecycleRequest;
import org.elasticsearch.protocol.xpack.indexlifecycle.ExplainLifecycleResponse; import org.elasticsearch.protocol.xpack.indexlifecycle.ExplainLifecycleResponse;
@ -36,8 +37,10 @@ import org.elasticsearch.protocol.xpack.indexlifecycle.StartILMRequest;
import org.elasticsearch.protocol.xpack.indexlifecycle.StopILMRequest; import org.elasticsearch.protocol.xpack.indexlifecycle.StopILMRequest;
import org.hamcrest.Matchers; import org.hamcrest.Matchers;
import java.io.IOException;
import java.util.Map; import java.util.Map;
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.is;
@ -286,4 +289,70 @@ public class IndexLifecycleIT extends ESRestHighLevelClientTestCase {
assertFalse(squashResponse.managedByILM()); assertFalse(squashResponse.managedByILM());
assertEquals("squash", squashResponse.getIndex()); assertEquals("squash", squashResponse.getIndex());
} }
public void testDeleteLifecycle() throws IOException {
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" +
" \"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" +
" \"allocate\": {\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);
DeleteLifecyclePolicyRequest deleteRequest = new DeleteLifecyclePolicyRequest(policy);
assertAcked(execute(deleteRequest, highLevelClient().indexLifecycle()::deleteLifecyclePolicy,
highLevelClient().indexLifecycle()::deleteLifecyclePolicyAsync));
// TODO: NORELEASE convert this to using the high level client once there are APIs for it
Request getLifecycle = new Request("GET", "/_ilm/" + policy);
try {
client().performRequest(getLifecycle);
fail("index should not exist after being deleted");
} catch (ResponseException ex) {
assertEquals(404, ex.getResponse().getStatusLine().getStatusCode());
}
}
} }

View File

@ -97,6 +97,7 @@ import org.elasticsearch.action.support.master.MasterNodeRequest;
import org.elasticsearch.action.support.replication.ReplicationRequest; import org.elasticsearch.action.support.replication.ReplicationRequest;
import org.elasticsearch.action.update.UpdateRequest; import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.RequestConverters.EndpointBuilder; import org.elasticsearch.client.RequestConverters.EndpointBuilder;
import org.elasticsearch.client.indexlifecycle.DeleteLifecyclePolicyRequest;
import org.elasticsearch.cluster.health.ClusterHealthStatus; import org.elasticsearch.cluster.health.ClusterHealthStatus;
import org.elasticsearch.common.CheckedBiConsumer; import org.elasticsearch.common.CheckedBiConsumer;
import org.elasticsearch.common.CheckedFunction; import org.elasticsearch.common.CheckedFunction;
@ -2698,6 +2699,19 @@ public class RequestConvertersTests extends ESTestCase {
assertToXContentBody(graphExploreRequest, request.getEntity()); assertToXContentBody(graphExploreRequest, request.getEntity());
} }
public void testDeleteLifecycle() {
String lifecycleName = randomAlphaOfLengthBetween(2,20);
DeleteLifecyclePolicyRequest req = new DeleteLifecyclePolicyRequest(lifecycleName);
Map<String, String> expectedParams = new HashMap<>();
setRandomMasterTimeout(req::setMasterTimeout, TimedRequest.DEFAULT_TIMEOUT, expectedParams);
setRandomTimeoutTimeValue(req::setTimeout, TimedRequest.DEFAULT_MASTER_TIMEOUT, expectedParams);
Request request = RequestConverters.deleteLifecyclePolicy(req);
assertEquals(request.getMethod(), HttpDelete.METHOD_NAME);
assertEquals(request.getEndpoint(), "/_ilm/" + lifecycleName);
assertEquals(request.getParameters(), expectedParams);
}
public void testSetIndexLifecyclePolicy() throws Exception { public void testSetIndexLifecyclePolicy() throws Exception {
SetIndexLifecyclePolicyRequest req = new SetIndexLifecyclePolicyRequest(); SetIndexLifecyclePolicyRequest req = new SetIndexLifecyclePolicyRequest();
String policyName = randomAlphaOfLength(10); String policyName = randomAlphaOfLength(10);
@ -2892,6 +2906,17 @@ public class RequestConvertersTests extends ESTestCase {
} }
} }
private static void setRandomTimeoutTimeValue(Consumer<TimeValue> setter, TimeValue defaultTimeout,
Map<String, String> expectedParams) {
if (randomBoolean()) {
TimeValue timeout = TimeValue.parseTimeValue(randomTimeValue(), "random_timeout");
setter.accept(timeout);
expectedParams.put("timeout", timeout.getStringRep());
} else {
expectedParams.put("timeout", defaultTimeout.getStringRep());
}
}
private static void setRandomMasterTimeout(MasterNodeRequest<?> request, Map<String, String> expectedParams) { private static void setRandomMasterTimeout(MasterNodeRequest<?> request, Map<String, String> expectedParams) {
if (randomBoolean()) { if (randomBoolean()) {
String masterTimeout = randomTimeValue(); String masterTimeout = randomTimeValue();
@ -2902,6 +2927,16 @@ public class RequestConvertersTests extends ESTestCase {
} }
} }
private static void setRandomMasterTimeout(Consumer<TimeValue> setter, TimeValue defaultTimeout, Map<String, String> expectedParams) {
if (randomBoolean()) {
TimeValue masterTimeout = TimeValue.parseTimeValue(randomTimeValue(), "random_master_timeout");
setter.accept(masterTimeout);
expectedParams.put("master_timeout", masterTimeout.getStringRep());
} else {
expectedParams.put("master_timeout", defaultTimeout.getStringRep());
}
}
private static void setRandomWaitForActiveShards(Consumer<ActiveShardCount> setter, Map<String, String> expectedParams) { private static void setRandomWaitForActiveShards(Consumer<ActiveShardCount> setter, Map<String, String> expectedParams) {
setRandomWaitForActiveShards(setter, ActiveShardCount.DEFAULT, expectedParams); setRandomWaitForActiveShards(setter, ActiveShardCount.DEFAULT, expectedParams);
} }

View File

@ -0,0 +1,39 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.client.indexlifecycle;
import org.elasticsearch.test.ESTestCase;
public class DeleteLifecyclePolicyRequestTests extends ESTestCase {
private DeleteLifecyclePolicyRequest createTestInstance() {
return new DeleteLifecyclePolicyRequest(randomAlphaOfLengthBetween(2, 20));
}
public void testValidate() {
DeleteLifecyclePolicyRequest req = createTestInstance();
assertFalse(req.validate().isPresent());
}
public void testValidationFailure() {
expectThrows(IllegalArgumentException.class, () -> new DeleteLifecyclePolicyRequest(randomFrom("", null)));
}
}