Skip to content

HLRC: Add remove index lifecycle policy #34204

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 12 commits into from
Oct 16, 2018
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
import org.elasticsearch.client.indexlifecycle.PutLifecyclePolicyRequest;
import org.elasticsearch.client.indexlifecycle.ExplainLifecycleRequest;
import org.elasticsearch.client.indexlifecycle.ExplainLifecycleResponse;
import org.elasticsearch.client.indexlifecycle.RemoveIndexLifecyclePolicyRequest;
import org.elasticsearch.client.indexlifecycle.RemoveIndexLifecyclePolicyResponse;
import org.elasticsearch.client.indexlifecycle.SetIndexLifecyclePolicyRequest;
import org.elasticsearch.client.indexlifecycle.SetIndexLifecyclePolicyResponse;
import org.elasticsearch.client.indexlifecycle.StartILMRequest;
Expand Down Expand Up @@ -161,6 +163,35 @@ public void setIndexLifecyclePolicyAsync(SetIndexLifecyclePolicyRequest request,
SetIndexLifecyclePolicyResponse::fromXContent, listener, emptySet());
}

/**
* Remove the index lifecycle policy 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 RemoveIndexLifecyclePolicyResponse removeIndexLifecyclePolicy(RemoveIndexLifecyclePolicyRequest request,
RequestOptions options) throws IOException {
return restHighLevelClient.performRequestAndParseEntity(request, RequestConverters::removeIndexLifecyclePolicy, options,
RemoveIndexLifecyclePolicyResponse::fromXContent, emptySet());
}

/**
* Asynchronously remove the index lifecycle policy 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 removeIndexLifecyclePolicyAsync(RemoveIndexLifecyclePolicyRequest request, RequestOptions options,
ActionListener<RemoveIndexLifecyclePolicyResponse> listener) {
restHighLevelClient.performRequestAsyncAndParseEntity(request, RequestConverters::removeIndexLifecyclePolicy, options,
RemoveIndexLifecyclePolicyResponse::fromXContent, listener, emptySet());
}

/**
* Start the Index Lifecycle Management feature.
* See <a href="https://fix-me-when-we-have-docs.com">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
import org.elasticsearch.client.indexlifecycle.GetLifecyclePolicyRequest;
import org.elasticsearch.client.indexlifecycle.LifecycleManagementStatusRequest;
import org.elasticsearch.client.indexlifecycle.PutLifecyclePolicyRequest;
import org.elasticsearch.client.indexlifecycle.RemoveIndexLifecyclePolicyRequest;
import org.elasticsearch.client.indexlifecycle.SetIndexLifecyclePolicyRequest;
import org.elasticsearch.client.indexlifecycle.StartILMRequest;
import org.elasticsearch.client.indexlifecycle.StopILMRequest;
Expand Down Expand Up @@ -640,6 +641,19 @@ static Request setIndexLifecyclePolicy(SetIndexLifecyclePolicyRequest setPolicyR
return request;
}

static Request removeIndexLifecyclePolicy(RemoveIndexLifecyclePolicyRequest setPolicyRequest) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: can we named the variable removeLifecycleRequest?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops! Good catch, thanks.

String[] indices = setPolicyRequest.indices() == null ? Strings.EMPTY_ARRAY : setPolicyRequest.indices();
Request request = new Request(HttpDelete.METHOD_NAME,
new EndpointBuilder()
.addCommaSeparatedPathParts(indices)
.addPathPartAsIs("_ilm")
.build());
Params params = new Params(request);
params.withIndicesOptions(setPolicyRequest.indicesOptions());
params.withMasterTimeout(setPolicyRequest.masterNodeTimeout());
return request;
}

static Request startILM(StartILMRequest startILMRequest) {
Request request = new Request(HttpPost.METHOD_NAME,
new EndpointBuilder()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* 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.action.IndicesRequest;
import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.client.TimedRequest;

import java.util.Arrays;
import java.util.Objects;

public class RemoveIndexLifecyclePolicyRequest extends TimedRequest implements IndicesRequest.Replaceable {

private String[] indices;
private IndicesOptions indicesOptions = IndicesOptions.strictExpandOpen();

public RemoveIndexLifecyclePolicyRequest() {
}

public RemoveIndexLifecyclePolicyRequest(String... indices) {
if (indices == null) {
throw new IllegalArgumentException("indices cannot be null");
}
this.indices = indices;
}

@Override
public RemoveIndexLifecyclePolicyRequest indices(String... indices) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a question, not a change request: What is our philosophy regarding having setters vs. immutable request objects going forward for the HLRC? I've been under the impression we preferred immutable objects, but it doesn't seem to be consistent.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gwbrown Good question that I would like to know the answer to myself :). I was mostly going off what I saw within the set index lifecycle policy classes since that's the analog to this request.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the most important thing is for the API to be built in a way where you cannot create invalid requests. It would be good if any mandatory fields in the request were passed into the constructor and don't have setters. The reason this was done for the server side was because the request extends IndicesRequest.Replaceable but I think in order to achieve the client separation we want we actually can't extend that here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yea Im all for not exetnding that class. And Im also all for putting things that are primitive and easily validatable into the constructors. Optionals, i think im ok with setters but i think this also deserves a wider audience to discuss.

Copy link
Contributor Author

@jdconrad jdconrad Oct 3, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed the extension. However, IndicesOptions as a member variable still seems necessary. There is no way to specify how to handle wild cards appropriately without it, and the SetIndexLifecyclePolicyRequest also uses them. I'm open to suggestions here if this needs changes still.

this.indices = indices;
return this;
}

@Override
public String[] indices() {
return indices;
}

public void indicesOptions(IndicesOptions indicesOptions) {
this.indicesOptions = indicesOptions;
}

public IndicesOptions indicesOptions() {
return indicesOptions;
}

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

@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
RemoveIndexLifecyclePolicyRequest other = (RemoveIndexLifecyclePolicyRequest) obj;
return Objects.deepEquals(indices, other.indices) &&
Objects.equals(indicesOptions, other.indicesOptions);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* 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.common.ParseField;
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.ToXContentObject;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser;

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

public class RemoveIndexLifecyclePolicyResponse implements ToXContentObject {

public static final ParseField HAS_FAILURES_FIELD = new ParseField("has_failures");
public static final ParseField FAILED_INDEXES_FIELD = new ParseField("failed_indexes");
@SuppressWarnings("unchecked")
public static final ConstructingObjectParser<RemoveIndexLifecyclePolicyResponse, Void> PARSER = new ConstructingObjectParser<>(
"change_policy_for_index_response", a -> new RemoveIndexLifecyclePolicyResponse((List<String>) a[0]));
static {
PARSER.declareStringArray(ConstructingObjectParser.constructorArg(), FAILED_INDEXES_FIELD);
// Needs to be declared but not used in constructing the response object
PARSER.declareBoolean(ConstructingObjectParser.constructorArg(), HAS_FAILURES_FIELD);
}

private List<String> failedIndexes;

public RemoveIndexLifecyclePolicyResponse() {
}

public RemoveIndexLifecyclePolicyResponse(List<String> failedIndexes) {
if (failedIndexes == null) {
throw new IllegalArgumentException(FAILED_INDEXES_FIELD.getPreferredName() + " cannot be null");
}
this.failedIndexes = failedIndexes;
}

public List<String> getFailedIndexes() {
return failedIndexes;
}

public boolean hasFailures() {
return failedIndexes.isEmpty() == false;
}

@Override
public XContentBuilder toXContent(XContentBuilder builder, ToXContent.Params params) throws IOException {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this should not be in the responses. @nik9000 has recently merged some test stuff that will alter your test cases below as well, once this is removed. Pls update to use that.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

builder.startObject();
builder.field(HAS_FAILURES_FIELD.getPreferredName(), hasFailures());
builder.field(FAILED_INDEXES_FIELD.getPreferredName(), failedIndexes);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so this just returns emptyness if there are no failed indexes?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

disregard, this should be removed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed.

builder.endObject();
return builder;
}

public static RemoveIndexLifecyclePolicyResponse fromXContent(XContentParser parser) {
return PARSER.apply(parser, null);
}

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

@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
RemoveIndexLifecyclePolicyResponse other = (RemoveIndexLifecyclePolicyResponse) obj;
return Objects.equals(failedIndexes, other.failedIndexes);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@
import org.elasticsearch.client.indexlifecycle.Phase;
import org.elasticsearch.client.indexlifecycle.PhaseExecutionInfo;
import org.elasticsearch.client.indexlifecycle.PutLifecyclePolicyRequest;
import org.elasticsearch.client.indexlifecycle.RemoveIndexLifecyclePolicyRequest;
import org.elasticsearch.client.indexlifecycle.RemoveIndexLifecyclePolicyResponse;
import org.elasticsearch.client.indexlifecycle.RolloverAction;
import org.elasticsearch.client.indexlifecycle.SetIndexLifecyclePolicyRequest;
import org.elasticsearch.client.indexlifecycle.SetIndexLifecyclePolicyResponse;
Expand Down Expand Up @@ -88,6 +90,41 @@ public void testSetIndexLifecyclePolicy() throws Exception {
assertThat(settingsResponse.getSetting("baz", "index.lifecycle.name"), equalTo(policyName));
}

public void testRemoveIndexLifecyclePolicy() throws Exception {
String policyName = randomAlphaOfLength(10);
LifecyclePolicy policy = createRandomPolicy(policyName);
PutLifecyclePolicyRequest putRequest = new PutLifecyclePolicyRequest(policy);
assertAcked(execute(putRequest, highLevelClient().indexLifecycle()::putLifecyclePolicy,
highLevelClient().indexLifecycle()::putLifecyclePolicyAsync));

createIndex("foo", Settings.builder().put("index.lifecycle.name", "bar").build());
createIndex("baz", Settings.builder().put("index.lifecycle.name", "eggplant").build());
createIndex("rbh", Settings.builder().put("index.lifecycle.name", "whatisthis").build());
SetIndexLifecyclePolicyRequest setReq = new SetIndexLifecyclePolicyRequest(policyName, "foo", "baz", "rbh");
SetIndexLifecyclePolicyResponse setResp = execute(setReq, highLevelClient().indexLifecycle()::setIndexLifecyclePolicy,
highLevelClient().indexLifecycle()::setIndexLifecyclePolicyAsync);
assertThat(setResp.hasFailures(), is(false));
assertThat(setResp.getFailedIndexes().isEmpty(), is(true));

GetSettingsRequest getSettingsRequest = new GetSettingsRequest().indices("foo", "baz", "rbh");
GetSettingsResponse settingsResponse = highLevelClient().indices().getSettings(getSettingsRequest, RequestOptions.DEFAULT);
assertThat(settingsResponse.getSetting("foo", "index.lifecycle.name"), equalTo(policyName));
assertThat(settingsResponse.getSetting("baz", "index.lifecycle.name"), equalTo(policyName));
assertThat(settingsResponse.getSetting("rbh", "index.lifecycle.name"), equalTo(policyName));

RemoveIndexLifecyclePolicyRequest removeReq = new RemoveIndexLifecyclePolicyRequest("foo", "rbh");
RemoveIndexLifecyclePolicyResponse removeResp = execute(removeReq, highLevelClient().indexLifecycle()::removeIndexLifecyclePolicy,
highLevelClient().indexLifecycle()::removeIndexLifecyclePolicyAsync);
assertThat(removeResp.hasFailures(), is(false));
assertThat(removeResp.getFailedIndexes().isEmpty(), is(true));

getSettingsRequest = new GetSettingsRequest().indices("foo", "baz", "rbh");
settingsResponse = highLevelClient().indices().getSettings(getSettingsRequest, RequestOptions.DEFAULT);
assertNull(settingsResponse.getSetting("foo", "index.lifecycle.name"));
assertThat(settingsResponse.getSetting("baz", "index.lifecycle.name"), equalTo(policyName));
assertNull(settingsResponse.getSetting("rbh", "index.lifecycle.name"));
}

public void testStartStopILM() throws Exception {
String policyName = randomAlphaOfLength(10);
LifecyclePolicy policy = createRandomPolicy(policyName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
import org.elasticsearch.client.indexlifecycle.LifecyclePolicy;
import org.elasticsearch.client.indexlifecycle.PutLifecyclePolicyRequest;
import org.elasticsearch.client.indexlifecycle.DeleteLifecyclePolicyRequest;
import org.elasticsearch.client.indexlifecycle.RemoveIndexLifecyclePolicyRequest;
import org.elasticsearch.common.CheckedBiConsumer;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.bytes.BytesArray;
Expand Down Expand Up @@ -1517,6 +1518,21 @@ public void testSetIndexLifecyclePolicy() throws Exception {
assertThat(request.getParameters(), equalTo(expectedParams));
}

public void testRemoveIndexLifecyclePolicy() {
RemoveIndexLifecyclePolicyRequest req = new RemoveIndexLifecyclePolicyRequest();
String[] indices = randomIndicesNames(0, 10);
req.indices(indices);
Map<String, String> expectedParams = new HashMap<>();
setRandomMasterTimeout(req::setMasterTimeout, TimedRequest.DEFAULT_TIMEOUT, expectedParams);
setRandomIndicesOptions(req::indicesOptions, req::indicesOptions, expectedParams);

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

public void testStartILM() throws Exception {
StartILMRequest req = new StartILMRequest();
Map<String, String> expectedParams = new HashMap<>();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* 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.action.support.IndicesOptions;
import org.elasticsearch.test.ESTestCase;

public class RemoveIndexLifecyclePolicyRequestTests extends ESTestCase {

private RemoveIndexLifecyclePolicyRequest createTestInstance() {
RemoveIndexLifecyclePolicyRequest request = new RemoveIndexLifecyclePolicyRequest(generateRandomStringArray(20, 20, false));
if (randomBoolean()) {
IndicesOptions indicesOptions = IndicesOptions.fromOptions(randomBoolean(), randomBoolean(), randomBoolean(), randomBoolean(),
randomBoolean(), randomBoolean(), randomBoolean());
request.indicesOptions(indicesOptions);
}
if (randomBoolean()) {
request.indices(generateRandomStringArray(20, 20, false));
}
return request;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should implement mutateInstance so the hash code and equals tests can test non-equal instances too?

Copy link
Contributor Author

@jdconrad jdconrad Oct 3, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The framework changed with the removal the XContent methods. Added tests for equals and hashcode separately since this now extends from ESTestCase.


public void testNullIndices() {
IllegalArgumentException exception = expectThrows(IllegalArgumentException.class,
() -> new RemoveIndexLifecyclePolicyRequest((String[]) null));
assertEquals("indices cannot be null", exception.getMessage());
}

public void testValidate() {
RemoveIndexLifecyclePolicyRequest request = createTestInstance();
assertFalse(request.validate().isPresent());
}
}
Loading