Removes Set Policy API in favour of setting index.lifecycle.name directly (#34304)

* Removes Set Policy API in favour of setting index.lifecycle.name
directly

* Reinstates matcher that will still be used

* Cleans up code after rebase

* Adds test to check changing policy with ndex settings works

* Fixes TimeseriesLifecycleActionsIT after API removal

* Fixes docs tests

* Fixes case on close where lifecycle service was never created
This commit is contained in:
Colin Goodheart-Smithe 2018-10-24 16:14:59 +01:00 committed by GitHub
parent 89404ced9b
commit c7fe87e43f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 176 additions and 1967 deletions

View File

@ -22,18 +22,16 @@ package org.elasticsearch.client;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.client.indexlifecycle.DeleteLifecyclePolicyRequest;
import org.elasticsearch.client.indexlifecycle.ExplainLifecycleRequest;
import org.elasticsearch.client.indexlifecycle.ExplainLifecycleResponse;
import org.elasticsearch.client.indexlifecycle.GetLifecyclePolicyRequest;
import org.elasticsearch.client.indexlifecycle.GetLifecyclePolicyResponse;
import org.elasticsearch.client.indexlifecycle.LifecycleManagementStatusRequest;
import org.elasticsearch.client.indexlifecycle.LifecycleManagementStatusResponse;
import org.elasticsearch.client.indexlifecycle.PutLifecyclePolicyRequest;
import org.elasticsearch.client.indexlifecycle.ExplainLifecycleRequest;
import org.elasticsearch.client.indexlifecycle.ExplainLifecycleResponse;
import org.elasticsearch.client.indexlifecycle.RetryLifecyclePolicyRequest;
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;
import org.elasticsearch.client.indexlifecycle.StopILMRequest;
@ -135,35 +133,6 @@ public class IndexLifecycleClient {
AcknowledgedResponse::fromXContent, listener, emptySet());
}
/**
* Set 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 SetIndexLifecyclePolicyResponse setIndexLifecyclePolicy(SetIndexLifecyclePolicyRequest request,
RequestOptions options) throws IOException {
return restHighLevelClient.performRequestAndParseEntity(request, RequestConverters::setIndexLifecyclePolicy, options,
SetIndexLifecyclePolicyResponse::fromXContent, emptySet());
}
/**
* Asynchronously set 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 setIndexLifecyclePolicyAsync(SetIndexLifecyclePolicyRequest request, RequestOptions options,
ActionListener<SetIndexLifecyclePolicyResponse> listener) {
restHighLevelClient.performRequestAsyncAndParseEntity(request, RequestConverters::setIndexLifecyclePolicy, options,
SetIndexLifecyclePolicyResponse::fromXContent, listener, emptySet());
}
/**
* Remove the index lifecycle policy for an index
* See <a href="https://fix-me-when-we-have-docs.com">

View File

@ -57,7 +57,6 @@ import org.elasticsearch.client.indexlifecycle.LifecycleManagementStatusRequest;
import org.elasticsearch.client.indexlifecycle.PutLifecyclePolicyRequest;
import org.elasticsearch.client.indexlifecycle.RetryLifecyclePolicyRequest;
import org.elasticsearch.client.indexlifecycle.RemoveIndexLifecyclePolicyRequest;
import org.elasticsearch.client.indexlifecycle.SetIndexLifecyclePolicyRequest;
import org.elasticsearch.client.indexlifecycle.StartILMRequest;
import org.elasticsearch.client.indexlifecycle.StopILMRequest;
import org.elasticsearch.client.security.RefreshPolicy;
@ -641,20 +640,6 @@ final class RequestConverters {
return request;
}
static Request setIndexLifecyclePolicy(SetIndexLifecyclePolicyRequest setPolicyRequest) {
String[] indices = setPolicyRequest.indices() == null ? Strings.EMPTY_ARRAY : setPolicyRequest.indices();
Request request = new Request(HttpPut.METHOD_NAME,
new EndpointBuilder()
.addCommaSeparatedPathParts(indices)
.addPathPartAsIs("_ilm")
.addPathPart(setPolicyRequest.policy())
.build());
Params params = new Params(request);
params.withIndicesOptions(setPolicyRequest.indicesOptions());
params.withMasterTimeout(setPolicyRequest.masterNodeTimeout());
return request;
}
static Request removeIndexLifecyclePolicy(RemoveIndexLifecyclePolicyRequest removePolicyRequest) {
String[] indices = removePolicyRequest.indices() == null ?
Strings.EMPTY_ARRAY : removePolicyRequest.indices().toArray(new String[] {});

View File

@ -1,122 +0,0 @@
/*
* 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.ActionRequestValidationException;
import org.elasticsearch.action.IndicesRequest;
import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.action.support.master.AcknowledgedRequest;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import java.io.IOException;
import java.util.Arrays;
import java.util.Objects;
public class SetIndexLifecyclePolicyRequest extends AcknowledgedRequest<SetIndexLifecyclePolicyRequest>
implements IndicesRequest.Replaceable {
private String[] indices;
private IndicesOptions indicesOptions = IndicesOptions.strictExpandOpen();
private String policy;
public SetIndexLifecyclePolicyRequest() {
}
public SetIndexLifecyclePolicyRequest(String policy, String... indices) {
if (indices == null) {
throw new IllegalArgumentException("indices cannot be null");
}
if (policy == null) {
throw new IllegalArgumentException("policy cannot be null");
}
this.indices = indices;
this.policy = policy;
}
@Override
public SetIndexLifecyclePolicyRequest indices(String... indices) {
this.indices = indices;
return this;
}
@Override
public String[] indices() {
return indices;
}
public SetIndexLifecyclePolicyRequest policy(String policy) {
this.policy = policy;
return this;
}
public String policy() {
return policy;
}
public void indicesOptions(IndicesOptions indicesOptions) {
this.indicesOptions = indicesOptions;
}
public IndicesOptions indicesOptions() {
return indicesOptions;
}
@Override
public ActionRequestValidationException validate() {
return null;
}
@Override
public void readFrom(StreamInput in) throws IOException {
super.readFrom(in);
indices = in.readStringArray();
indicesOptions = IndicesOptions.readIndicesOptions(in);
policy = in.readString();
}
@Override
public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out);
out.writeStringArray(indices);
indicesOptions.writeIndicesOptions(out);
out.writeString(policy);
}
@Override
public int hashCode() {
return Objects.hash(Arrays.hashCode(indices), indicesOptions, policy);
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
SetIndexLifecyclePolicyRequest other = (SetIndexLifecyclePolicyRequest) obj;
return Objects.deepEquals(indices, other.indices) &&
Objects.equals(indicesOptions, other.indicesOptions) &&
Objects.equals(policy, other.policy);
}
}

View File

@ -1,111 +0,0 @@
/*
* 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.ActionResponse;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
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 SetIndexLifecyclePolicyResponse extends ActionResponse 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<SetIndexLifecyclePolicyResponse, Void> PARSER = new ConstructingObjectParser<>(
"change_policy_for_index_response", a -> new SetIndexLifecyclePolicyResponse((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 SetIndexLifecyclePolicyResponse() {
}
public SetIndexLifecyclePolicyResponse(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, Params params) throws IOException {
builder.startObject();
builder.field(HAS_FAILURES_FIELD.getPreferredName(), hasFailures());
builder.field(FAILED_INDEXES_FIELD.getPreferredName(), failedIndexes);
builder.endObject();
return builder;
}
public static SetIndexLifecyclePolicyResponse fromXContent(XContentParser parser) {
return PARSER.apply(parser, null);
}
@Override
public void readFrom(StreamInput in) throws IOException {
super.readFrom(in);
failedIndexes = in.readList(StreamInput::readString);
}
@Override
public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out);
out.writeStringList(failedIndexes);
}
@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;
}
SetIndexLifecyclePolicyResponse other = (SetIndexLifecyclePolicyResponse) obj;
return Objects.equals(failedIndexes, other.failedIndexes);
}
}

View File

@ -45,8 +45,6 @@ import org.elasticsearch.client.indexlifecycle.RetryLifecyclePolicyRequest;
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;
import org.elasticsearch.client.indexlifecycle.ShrinkAction;
import org.elasticsearch.client.indexlifecycle.StartILMRequest;
import org.elasticsearch.client.indexlifecycle.StopILMRequest;
@ -71,27 +69,6 @@ import static org.hamcrest.Matchers.is;
public class IndexLifecycleIT extends ESRestHighLevelClientTestCase {
public void testSetIndexLifecyclePolicy() 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());
SetIndexLifecyclePolicyRequest req = new SetIndexLifecyclePolicyRequest(policyName, "foo", "baz");
SetIndexLifecyclePolicyResponse response = execute(req, highLevelClient().indexLifecycle()::setIndexLifecyclePolicy,
highLevelClient().indexLifecycle()::setIndexLifecyclePolicyAsync);
assertThat(response.hasFailures(), is(false));
assertThat(response.getFailedIndexes().isEmpty(), is(true));
GetSettingsRequest getSettingsRequest = new GetSettingsRequest().indices("foo", "baz");
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));
}
public void testRemoveIndexLifecyclePolicy() throws Exception {
String policyName = randomAlphaOfLength(10);
LifecyclePolicy policy = createRandomPolicy(policyName);
@ -99,14 +76,9 @@ public class IndexLifecycleIT extends ESRestHighLevelClientTestCase {
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));
createIndex("foo", Settings.builder().put("index.lifecycle.name", policyName).build());
createIndex("baz", Settings.builder().put("index.lifecycle.name", policyName).build());
createIndex("rbh", Settings.builder().put("index.lifecycle.name", policyName).build());
GetSettingsRequest getSettingsRequest = new GetSettingsRequest().indices("foo", "baz", "rbh");
GetSettingsResponse settingsResponse = highLevelClient().indices().getSettings(getSettingsRequest, RequestOptions.DEFAULT);

View File

@ -55,13 +55,16 @@ import org.elasticsearch.action.support.master.MasterNodeRequest;
import org.elasticsearch.action.support.replication.ReplicationRequest;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.RequestConverters.EndpointBuilder;
import org.elasticsearch.client.indexlifecycle.DeleteLifecyclePolicyRequest;
import org.elasticsearch.client.indexlifecycle.ExplainLifecycleRequest;
import org.elasticsearch.client.indexlifecycle.GetLifecyclePolicyRequest;
import org.elasticsearch.client.indexlifecycle.LifecycleManagementStatusRequest;
import org.elasticsearch.client.indexlifecycle.LifecyclePolicy;
import org.elasticsearch.client.indexlifecycle.PutLifecyclePolicyRequest;
import org.elasticsearch.client.indexlifecycle.DeleteLifecyclePolicyRequest;
import org.elasticsearch.client.indexlifecycle.RetryLifecyclePolicyRequest;
import org.elasticsearch.client.indexlifecycle.RemoveIndexLifecyclePolicyRequest;
import org.elasticsearch.client.indexlifecycle.StartILMRequest;
import org.elasticsearch.client.indexlifecycle.StopILMRequest;
import org.elasticsearch.common.CheckedBiConsumer;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.bytes.BytesArray;
@ -88,10 +91,6 @@ import org.elasticsearch.index.reindex.DeleteByQueryRequest;
import org.elasticsearch.index.reindex.ReindexRequest;
import org.elasticsearch.index.reindex.RemoteInfo;
import org.elasticsearch.index.reindex.UpdateByQueryRequest;
import org.elasticsearch.client.indexlifecycle.ExplainLifecycleRequest;
import org.elasticsearch.client.indexlifecycle.SetIndexLifecyclePolicyRequest;
import org.elasticsearch.client.indexlifecycle.StartILMRequest;
import org.elasticsearch.client.indexlifecycle.StopILMRequest;
import org.elasticsearch.rest.action.search.RestSearchAction;
import org.elasticsearch.script.Script;
import org.elasticsearch.script.ScriptType;
@ -1510,25 +1509,6 @@ public class RequestConvertersTests extends ESTestCase {
assertEquals(request.getParameters(), expectedParams);
}
public void testSetIndexLifecyclePolicy() throws Exception {
SetIndexLifecyclePolicyRequest req = new SetIndexLifecyclePolicyRequest();
String policyName = randomAlphaOfLength(10);
String[] indices = rarely() ? null : randomIndicesNames(0, 10);
req.policy(policyName);
req.indices(indices);
Map<String, String> expectedParams = new HashMap<>();
setRandomMasterTimeout(req, expectedParams);
setRandomIndicesOptions(req::indicesOptions, req::indicesOptions, expectedParams);
Request request = RequestConverters.setIndexLifecyclePolicy(req);
assertThat(request.getMethod(), equalTo(HttpPut.METHOD_NAME));
String idxString = Strings.arrayToCommaDelimitedString(indices);
assertThat(request.getEndpoint(),
equalTo("/" + (idxString.isEmpty() ? "" : (idxString + "/")) +
"_ilm/" + policyName));
assertThat(request.getParameters(), equalTo(expectedParams));
}
public void testRemoveIndexLifecyclePolicy() {
Map<String, String> expectedParams = new HashMap<>();
String[] indices = randomIndicesNames(0, 10);

View File

@ -1,88 +0,0 @@
/*
* 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.AbstractStreamableTestCase;
import java.io.IOException;
import java.util.Arrays;
public class SetIndexLifecyclePolicyRequestTests extends AbstractStreamableTestCase<SetIndexLifecyclePolicyRequest> {
@Override
protected SetIndexLifecyclePolicyRequest createTestInstance() {
SetIndexLifecyclePolicyRequest request = new SetIndexLifecyclePolicyRequest(randomAlphaOfLength(20),
generateRandomStringArray(20, 20, false));
if (randomBoolean()) {
IndicesOptions indicesOptions = IndicesOptions.fromOptions(randomBoolean(), randomBoolean(), randomBoolean(), randomBoolean(),
randomBoolean(), randomBoolean(), randomBoolean());
request.indicesOptions(indicesOptions);
}
return request;
}
@Override
protected SetIndexLifecyclePolicyRequest createBlankInstance() {
return new SetIndexLifecyclePolicyRequest();
}
@Override
protected SetIndexLifecyclePolicyRequest mutateInstance(SetIndexLifecyclePolicyRequest instance) throws IOException {
String[] indices = instance.indices();
IndicesOptions indicesOptions = instance.indicesOptions();
String policy = instance.policy();
switch (between(0, 2)) {
case 0:
indices = randomValueOtherThanMany(i -> Arrays.equals(i, instance.indices()),
() -> generateRandomStringArray(20, 20, false));
break;
case 1:
indicesOptions = randomValueOtherThan(indicesOptions, () -> IndicesOptions.fromOptions(randomBoolean(), randomBoolean(),
randomBoolean(), randomBoolean(), randomBoolean(), randomBoolean(), randomBoolean()));
break;
case 2:
policy = randomValueOtherThan(policy, () -> randomAlphaOfLength(20));
break;
default:
throw new AssertionError("Illegal randomisation branch");
}
SetIndexLifecyclePolicyRequest newRequest = new SetIndexLifecyclePolicyRequest(policy, indices);
newRequest.indicesOptions(indicesOptions);
return newRequest;
}
public void testNullIndices() {
IllegalArgumentException exception = expectThrows(IllegalArgumentException.class,
() -> new SetIndexLifecyclePolicyRequest(randomAlphaOfLength(20), (String[]) null));
assertEquals("indices cannot be null", exception.getMessage());
}
public void testNullPolicy() {
IllegalArgumentException exception = expectThrows(IllegalArgumentException.class,
() -> new SetIndexLifecyclePolicyRequest(null, generateRandomStringArray(20, 20, false)));
assertEquals("policy cannot be null", exception.getMessage());
}
public void testValidate() {
SetIndexLifecyclePolicyRequest request = createTestInstance();
assertNull(request.validate());
}
}

View File

@ -1,81 +0,0 @@
/*
* 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.xcontent.XContentParser;
import org.elasticsearch.test.AbstractStreamableXContentTestCase;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class SetIndexLifecyclePolicyResponseTests extends AbstractStreamableXContentTestCase<SetIndexLifecyclePolicyResponse> {
@Override
protected SetIndexLifecyclePolicyResponse createBlankInstance() {
return new SetIndexLifecyclePolicyResponse();
}
@Override
protected SetIndexLifecyclePolicyResponse createTestInstance() {
List<String> failedIndexes = Arrays.asList(generateRandomStringArray(20, 20, false));
return new SetIndexLifecyclePolicyResponse(failedIndexes);
}
@Override
protected SetIndexLifecyclePolicyResponse mutateInstance(SetIndexLifecyclePolicyResponse instance) throws IOException {
List<String> failedIndices = randomValueOtherThan(instance.getFailedIndexes(),
() -> Arrays.asList(generateRandomStringArray(20, 20, false)));
return new SetIndexLifecyclePolicyResponse(failedIndices);
}
@Override
protected SetIndexLifecyclePolicyResponse doParseInstance(XContentParser parser) throws IOException {
return SetIndexLifecyclePolicyResponse.PARSER.apply(parser, null);
}
@Override
protected boolean supportsUnknownFields() {
return false;
}
public void testNullFailedIndices() {
IllegalArgumentException exception = expectThrows(IllegalArgumentException.class, () -> new SetIndexLifecyclePolicyResponse(null));
assertEquals("failed_indexes cannot be null", exception.getMessage());
}
public void testHasFailures() {
SetIndexLifecyclePolicyResponse response = new SetIndexLifecyclePolicyResponse(new ArrayList<>());
assertFalse(response.hasFailures());
assertEquals(Collections.emptyList(), response.getFailedIndexes());
int size = randomIntBetween(1, 10);
List<String> failedIndexes = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
failedIndexes.add(randomAlphaOfLength(20));
}
response = new SetIndexLifecyclePolicyResponse(failedIndexes);
assertTrue(response.hasFailures());
assertEquals(failedIndexes, response.getFailedIndexes());
}
}

View File

@ -67,8 +67,11 @@ PUT _ilm/my_policy
}
PUT my_index
PUT my_index/_ilm/my_policy
{
"settings": {
"index.lifecycle.name": "my_policy"
}
}
--------------------------------------------------
// CONSOLE
// TEST

View File

@ -1,96 +0,0 @@
[role="xpack"]
[testenv="basic"]
[[ilm-set-policy]]
=== Set Policy On Index API
++++
<titleabbrev>Set Policy On Index</titleabbrev>
++++
Assigns a policy to an index for management.
==== Request
`POST <index>/_ilm/<policy>`
==== Description
This action assigns a policy to an index. It is effectively the same as setting an index's
`index.lifecycle.name` setting.
==== Path Parameters
`index` (required)::
(string) Identifier for the index.
`policy` (required)::
(string) Identifier for the policy.
==== Request Parameters
`timeout`::
(time units) Specifies the period of time to wait for the completion of the
operation. When this period of time elapses, the API fails and returns
an error. The default value is `30s`. For more information about time units,
see <<time-units>>.
`master_timeout`::
(time units) Specifies the period of time to wait for the connection with master.
When this period of time elapses, the API fails and returns an error.
The default value is `30s`. For more information about time units, see <<time-units>>.
==== Examples
The following example assigns a policy `my_policy` to an index `my_index`.
//////////////////////////
[source,js]
--------------------------------------------------
PUT _ilm/my_policy
{
"policy": {
"phases": {
"warm": {
"minimum_age": "10d",
"actions": {
"forcemerge": {
"max_num_segments": 1
}
}
},
"delete": {
"minimum_age": "30d",
"actions": {
"delete": {}
}
}
}
}
}
PUT my_index
--------------------------------------------------
// CONSOLE
// TEST
//////////////////////////
[source,js]
--------------------------------------------------
PUT my_index/_ilm/my_policy
--------------------------------------------------
// CONSOLE
// TEST[continued]
If the request does not encounter errors, you receive the following result:
[source,js]
--------------------------------------------------
{
"has_failures" : false,
"failed_indexes" : []
}
--------------------------------------------------
// CONSOLE
// TESTRESPONSE

View File

@ -38,6 +38,7 @@ import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.Transport;
import org.elasticsearch.xpack.core.action.XPackInfoAction;
import org.elasticsearch.xpack.core.action.XPackUsageAction;
import org.elasticsearch.xpack.core.beats.BeatsFeatureSetUsage;
import org.elasticsearch.xpack.core.ccr.AutoFollowMetadata;
import org.elasticsearch.xpack.core.deprecation.DeprecationInfoAction;
import org.elasticsearch.xpack.core.graph.GraphFeatureSetUsage;
@ -60,9 +61,7 @@ import org.elasticsearch.xpack.core.indexlifecycle.action.MoveToStepAction;
import org.elasticsearch.xpack.core.indexlifecycle.action.PutLifecycleAction;
import org.elasticsearch.xpack.core.indexlifecycle.action.RemoveIndexLifecyclePolicyAction;
import org.elasticsearch.xpack.core.indexlifecycle.action.RetryAction;
import org.elasticsearch.xpack.core.indexlifecycle.action.SetIndexLifecyclePolicyAction;
import org.elasticsearch.xpack.core.logstash.LogstashFeatureSetUsage;
import org.elasticsearch.xpack.core.beats.BeatsFeatureSetUsage;
import org.elasticsearch.xpack.core.ml.MachineLearningFeatureSetUsage;
import org.elasticsearch.xpack.core.ml.MlMetadata;
import org.elasticsearch.xpack.core.ml.action.CloseJobAction;
@ -155,8 +154,8 @@ import org.elasticsearch.xpack.core.security.authc.support.mapper.expressiondsl.
import org.elasticsearch.xpack.core.security.authc.support.mapper.expressiondsl.ExceptExpression;
import org.elasticsearch.xpack.core.security.authc.support.mapper.expressiondsl.FieldExpression;
import org.elasticsearch.xpack.core.security.authc.support.mapper.expressiondsl.RoleMapperExpression;
import org.elasticsearch.xpack.core.security.authz.privilege.ConditionalClusterPrivileges;
import org.elasticsearch.xpack.core.security.authz.privilege.ConditionalClusterPrivilege;
import org.elasticsearch.xpack.core.security.authz.privilege.ConditionalClusterPrivileges;
import org.elasticsearch.xpack.core.security.transport.netty4.SecurityNetty4Transport;
import org.elasticsearch.xpack.core.ssl.SSLService;
import org.elasticsearch.xpack.core.ssl.action.GetCertificateInfoAction;
@ -342,7 +341,6 @@ public class XPackClientPlugin extends Plugin implements ActionPlugin, NetworkPl
GetLifecycleAction.INSTANCE,
PutLifecycleAction.INSTANCE,
ExplainLifecycleAction.INSTANCE,
SetIndexLifecyclePolicyAction.INSTANCE,
RemoveIndexLifecyclePolicyAction.INSTANCE,
MoveToStepAction.INSTANCE,
RetryAction.INSTANCE

View File

@ -241,82 +241,6 @@ public class LifecyclePolicy extends AbstractDiffable<LifecyclePolicy>
}
}
/**
* Finds the next valid {@link StepKey} on or after the provided
* {@link StepKey}. If the provided {@link StepKey} is valid in this policy
* it will be returned. If its not valid the next available {@link StepKey}
* will be returned.
*/
public StepKey getNextValidStep(StepKey stepKey) {
Phase phase = phases.get(stepKey.getPhase());
if (phase == null) {
// Phase doesn't exist so find the after step for the previous
// available phase
return getAfterStepBeforePhase(stepKey.getPhase());
} else {
// Phase exists so check if the action exists
LifecycleAction action = phase.getActions().get(stepKey.getAction());
if (action == null) {
// if action doesn't exist find the first step in the next
// available action
return getFirstStepInNextAction(stepKey.getAction(), phase);
} else {
// if the action exists check if the step itself exists
if (action.toStepKeys(phase.getName()).contains(stepKey)) {
// stepKey is valid still so return it
return stepKey;
} else {
// stepKey no longer exists in the action so we need to move
// to the first step in the next action since skipping steps
// in an action is not safe
return getFirstStepInNextAction(stepKey.getAction(), phase);
}
}
}
}
private StepKey getNextAfterStep(String currentPhaseName) {
String nextPhaseName = type.getNextPhaseName(currentPhaseName, phases);
if (nextPhaseName == null) {
// We don't have a next phase after this one so there is no after
// step to move to. Instead we need to go to the terminal step as
// there are no more steps we should execute
return TerminalPolicyStep.KEY;
} else {
return new StepKey(currentPhaseName, PhaseCompleteStep.NAME, PhaseCompleteStep.NAME);
}
}
private StepKey getAfterStepBeforePhase(String currentPhaseName) {
String nextPhaseName = type.getNextPhaseName(currentPhaseName, phases);
if (nextPhaseName == null) {
// We don't have a next phase after this one so the next step is the
// TerminalPolicyStep
return TerminalPolicyStep.KEY;
} else {
String prevPhaseName = type.getPreviousPhaseName(currentPhaseName, phases);
if (prevPhaseName == null) {
// no previous phase available so go to the
// InitializePolicyContextStep
return InitializePolicyContextStep.KEY;
}
return new StepKey(prevPhaseName, PhaseCompleteStep.NAME, PhaseCompleteStep.NAME);
}
}
private StepKey getFirstStepInNextAction(String currentActionName, Phase phase) {
String nextActionName = type.getNextActionName(currentActionName, phase);
if (nextActionName == null) {
// The current action is the last in this phase so we need to find
// the next after step
return getNextAfterStep(phase.getName());
} else {
LifecycleAction nextAction = phase.getActions().get(nextActionName);
// Return the first stepKey for nextAction
return nextAction.toStepKeys(phase.getName()).get(0);
}
}
@Override
public int hashCode() {
return Objects.hash(name, phases);

View File

@ -19,7 +19,7 @@ public class LifecycleSettings {
public static final Setting<TimeValue> LIFECYCLE_POLL_INTERVAL_SETTING = Setting.positiveTimeSetting(LIFECYCLE_POLL_INTERVAL,
TimeValue.timeValueMinutes(10), Setting.Property.Dynamic, Setting.Property.NodeScope);
public static final Setting<String> LIFECYCLE_NAME_SETTING = Setting.simpleString(LIFECYCLE_NAME,
Setting.Property.Dynamic, Setting.Property.IndexScope, Setting.Property.InternalIndex);
Setting.Property.Dynamic, Setting.Property.IndexScope);
public static final Setting<Boolean> LIFECYCLE_SKIP_SETTING = Setting.boolSetting(LIFECYCLE_SKIP, false,
Setting.Property.Dynamic, Setting.Property.IndexScope);
}

View File

@ -1,109 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
package org.elasticsearch.xpack.core.indexlifecycle;
import org.elasticsearch.action.ActionRequestValidationException;
import org.elasticsearch.action.IndicesRequest;
import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.action.support.master.AcknowledgedRequest;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import java.io.IOException;
import java.util.Arrays;
import java.util.Objects;
public class SetIndexLifecyclePolicyRequest extends AcknowledgedRequest<SetIndexLifecyclePolicyRequest>
implements IndicesRequest.Replaceable {
private String[] indices;
private IndicesOptions indicesOptions = IndicesOptions.strictExpandOpen();
private String policy;
public SetIndexLifecyclePolicyRequest() {
}
public SetIndexLifecyclePolicyRequest(String policy, String... indices) {
if (indices == null) {
throw new IllegalArgumentException("indices cannot be null");
}
if (policy == null) {
throw new IllegalArgumentException("policy cannot be null");
}
this.indices = indices;
this.policy = policy;
}
@Override
public SetIndexLifecyclePolicyRequest indices(String... indices) {
this.indices = indices;
return this;
}
@Override
public String[] indices() {
return indices;
}
public SetIndexLifecyclePolicyRequest policy(String policy) {
this.policy = policy;
return this;
}
public String policy() {
return policy;
}
public void indicesOptions(IndicesOptions indicesOptions) {
this.indicesOptions = indicesOptions;
}
public IndicesOptions indicesOptions() {
return indicesOptions;
}
@Override
public ActionRequestValidationException validate() {
return null;
}
@Override
public void readFrom(StreamInput in) throws IOException {
super.readFrom(in);
indices = in.readStringArray();
indicesOptions = IndicesOptions.readIndicesOptions(in);
policy = in.readString();
}
@Override
public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out);
out.writeStringArray(indices);
indicesOptions.writeIndicesOptions(out);
out.writeString(policy);
}
@Override
public int hashCode() {
return Objects.hash(Arrays.hashCode(indices), indicesOptions, policy);
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
SetIndexLifecyclePolicyRequest other = (SetIndexLifecyclePolicyRequest) obj;
return Objects.deepEquals(indices, other.indices) &&
Objects.equals(indicesOptions, other.indicesOptions) &&
Objects.equals(policy, other.policy);
}
}

View File

@ -1,98 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
package org.elasticsearch.xpack.core.indexlifecycle;
import org.elasticsearch.action.ActionResponse;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
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 SetIndexLifecyclePolicyResponse extends ActionResponse 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<SetIndexLifecyclePolicyResponse, Void> PARSER = new ConstructingObjectParser<>(
"change_policy_for_index_response", a -> new SetIndexLifecyclePolicyResponse((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 SetIndexLifecyclePolicyResponse() {
}
public SetIndexLifecyclePolicyResponse(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, Params params) throws IOException {
builder.startObject();
builder.field(HAS_FAILURES_FIELD.getPreferredName(), hasFailures());
builder.field(FAILED_INDEXES_FIELD.getPreferredName(), failedIndexes);
builder.endObject();
return builder;
}
public static SetIndexLifecyclePolicyResponse fromXContent(XContentParser parser) {
return PARSER.apply(parser, null);
}
@Override
public void readFrom(StreamInput in) throws IOException {
super.readFrom(in);
failedIndexes = in.readList(StreamInput::readString);
}
@Override
public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out);
out.writeStringList(failedIndexes);
}
@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;
}
SetIndexLifecyclePolicyResponse other = (SetIndexLifecyclePolicyResponse) obj;
return Objects.equals(failedIndexes, other.failedIndexes);
}
}

View File

@ -1,25 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
package org.elasticsearch.xpack.core.indexlifecycle.action;
import org.elasticsearch.action.Action;
import org.elasticsearch.xpack.core.indexlifecycle.SetIndexLifecyclePolicyResponse;
public class SetIndexLifecyclePolicyAction extends Action<SetIndexLifecyclePolicyResponse> {
public static final SetIndexLifecyclePolicyAction INSTANCE = new SetIndexLifecyclePolicyAction();
public static final String NAME = "indices:admin/ilm/set_index_policy";
protected SetIndexLifecyclePolicyAction() {
super(NAME);
}
@Override
public SetIndexLifecyclePolicyResponse newResponse() {
return new SetIndexLifecyclePolicyResponse();
}
}

View File

@ -12,8 +12,6 @@ import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.client.ElasticsearchClient;
import org.elasticsearch.xpack.core.indexlifecycle.ExplainLifecycleRequest;
import org.elasticsearch.xpack.core.indexlifecycle.ExplainLifecycleResponse;
import org.elasticsearch.xpack.core.indexlifecycle.SetIndexLifecyclePolicyRequest;
import org.elasticsearch.xpack.core.indexlifecycle.SetIndexLifecyclePolicyResponse;
import org.elasticsearch.xpack.core.indexlifecycle.StartILMRequest;
import org.elasticsearch.xpack.core.indexlifecycle.StopILMRequest;
import org.elasticsearch.xpack.core.indexlifecycle.action.DeleteLifecycleAction;
@ -23,7 +21,6 @@ import org.elasticsearch.xpack.core.indexlifecycle.action.GetStatusAction;
import org.elasticsearch.xpack.core.indexlifecycle.action.PutLifecycleAction;
import org.elasticsearch.xpack.core.indexlifecycle.action.RemoveIndexLifecyclePolicyAction;
import org.elasticsearch.xpack.core.indexlifecycle.action.RetryAction;
import org.elasticsearch.xpack.core.indexlifecycle.action.SetIndexLifecyclePolicyAction;
import org.elasticsearch.xpack.core.indexlifecycle.action.StartILMAction;
import org.elasticsearch.xpack.core.indexlifecycle.action.StopILMAction;
@ -108,20 +105,6 @@ public class ILMClient {
return client.execute(GetStatusAction.INSTANCE, request);
}
/**
* Sets the lifecycle policy to use for an index
*/
public void setIndexLifecyclePolicy(SetIndexLifecyclePolicyRequest request, ActionListener<SetIndexLifecyclePolicyResponse> listener) {
client.execute(SetIndexLifecyclePolicyAction.INSTANCE, request, listener);
}
/**
* Sets the lifecycle policy to use for an index
*/
public ActionFuture<SetIndexLifecyclePolicyResponse> setIndexLifecyclePolicy(SetIndexLifecyclePolicyRequest request) {
return client.execute(SetIndexLifecyclePolicyAction.INSTANCE, request);
}
/**
* Removes index lifecycle management from an index
*/

View File

@ -10,7 +10,6 @@ import org.elasticsearch.cluster.ClusterModule;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.io.stream.Writeable.Reader;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
@ -21,16 +20,13 @@ import org.elasticsearch.xpack.core.indexlifecycle.Step.StepKey;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.instanceOf;
@ -320,281 +316,4 @@ public class LifecyclePolicyTests extends AbstractSerializingTestCase<LifecycleP
assertTrue(policy.isActionSafe(new StepKey("new", randomAlphaOfLength(10), randomAlphaOfLength(10))));
}
public void testGetNextValidStep() {
List<String> orderedPhases = Arrays.asList("phase_1", "phase_2", "phase_3", "phase_4", "phase_5");
Map<String, List<String>> orderedActionNamesForPhases = new HashMap<>();
List<String> actionNamesforPhase = new ArrayList<>();
actionNamesforPhase.add("action_1");
actionNamesforPhase.add("action_2");
actionNamesforPhase.add("action_3");
actionNamesforPhase.add("action_4");
orderedActionNamesForPhases.put("phase_1", actionNamesforPhase);
orderedActionNamesForPhases.put("phase_2", actionNamesforPhase);
orderedActionNamesForPhases.put("phase_3", actionNamesforPhase);
orderedActionNamesForPhases.put("phase_4", actionNamesforPhase);
orderedActionNamesForPhases.put("phase_5", actionNamesforPhase);
LifecycleType lifecycleType = new ControllableLifecycleType(orderedPhases, orderedActionNamesForPhases);
// create a policy which has only phases 1,2, and 4 and within them has
// actions 1 and 3 which both contain steps 1, 2, and 3.
Map<String, Phase> phases = new HashMap<>();
for (int p = 1; p <= 4; p++) {
if (p == 3) {
continue;
}
String phaseName = "phase_" + p;
Map<String, LifecycleAction> actions = new HashMap<>();
for (int a = 1; a <= 3; a++) {
if (a == 2) {
continue;
}
String actionName = "action_" + a;
List<Step> steps = new ArrayList<>();
for (int s = 1; s <= 3; s++) {
String stepName = "step_" + s;
steps.add(new MockStep(new StepKey(phaseName, actionName, stepName), null));
}
NamedMockAction action = new NamedMockAction(actionName, steps);
actions.put(action.getWriteableName(), action);
}
Phase phase = new Phase(phaseName, TimeValue.ZERO, actions);
phases.put(phase.getName(), phase);
}
LifecyclePolicy policy = new LifecyclePolicy(lifecycleType, lifecycleName, phases);
// step still exists
StepKey currentStep = new StepKey(randomFrom("phase_1", "phase_2", "phase_4"), randomFrom("action_1", "action_3"),
randomFrom("step_1", "step_2", "step_3"));
StepKey nextStep = policy.getNextValidStep(currentStep);
assertNotNull(nextStep);
assertEquals(currentStep, nextStep);
// current action exists but step does not
currentStep = new StepKey("phase_1", "action_1", "step_missing");
nextStep = policy.getNextValidStep(currentStep);
assertNotNull(nextStep);
assertEquals(new StepKey("phase_1", "action_3", "step_1"), nextStep);
// current action exists but step does not and action is last in phase
currentStep = new StepKey("phase_1", "action_3", "step_missing");
nextStep = policy.getNextValidStep(currentStep);
assertNotNull(nextStep);
assertEquals(new StepKey("phase_1", PhaseCompleteStep.NAME, PhaseCompleteStep.NAME), nextStep);
// current action exists but step does not and action is last in the
// last phase
currentStep = new StepKey("phase_4", "action_3", "step_missing");
nextStep = policy.getNextValidStep(currentStep);
assertNotNull(nextStep);
assertEquals(TerminalPolicyStep.KEY, nextStep);
// current action no longer exists
currentStep = new StepKey("phase_1", "action_2", "step_2");
nextStep = policy.getNextValidStep(currentStep);
assertNotNull(nextStep);
assertEquals(new StepKey("phase_1", "action_3", "step_1"), nextStep);
// current action no longer exists and action was last in phase
currentStep = new StepKey("phase_1", "action_4", "step_2");
nextStep = policy.getNextValidStep(currentStep);
assertNotNull(nextStep);
assertEquals(new StepKey("phase_1", PhaseCompleteStep.NAME, PhaseCompleteStep.NAME), nextStep);
// current action no longer exists and action was last in the last phase
currentStep = new StepKey("phase_4", "action_4", "step_2");
nextStep = policy.getNextValidStep(currentStep);
assertNotNull(nextStep);
assertEquals(TerminalPolicyStep.KEY, nextStep);
// current phase no longer exists
currentStep = new StepKey("phase_3", "action_2", "step_2");
nextStep = policy.getNextValidStep(currentStep);
assertNotNull(nextStep);
assertEquals(new StepKey("phase_2", PhaseCompleteStep.NAME, PhaseCompleteStep.NAME), nextStep);
// current phase no longer exists and was last phase
currentStep = new StepKey("phase_5", "action_2", "step_2");
nextStep = policy.getNextValidStep(currentStep);
assertNotNull(nextStep);
assertEquals(TerminalPolicyStep.KEY, nextStep);
// create a new policy where only phase 2 exists and within it has
// actions 1 and 3 which both contain steps 1, 2, and 3.
phases = new HashMap<>();
String phaseName = "phase_2";
Map<String, LifecycleAction> actions = new HashMap<>();
for (int a = 1; a <= 3; a++) {
if (a == 2) {
continue;
}
String actionName = "action_" + a;
List<Step> steps = new ArrayList<>();
for (int s = 1; s <= 3; s++) {
String stepName = "step_" + s;
steps.add(new MockStep(new StepKey(phaseName, actionName, stepName), null));
}
NamedMockAction action = new NamedMockAction(actionName, steps);
actions.put(action.getWriteableName(), action);
}
Phase phase = new Phase(phaseName, TimeValue.ZERO, actions);
phases.put(phase.getName(), phase);
policy = new LifecyclePolicy(lifecycleType, lifecycleName, phases);
// current phase no longer exists and was first phase
currentStep = new StepKey("phase_1", "action_2", "step_2");
nextStep = policy.getNextValidStep(currentStep);
assertNotNull(nextStep);
assertEquals(InitializePolicyContextStep.KEY, nextStep);
}
private static class NamedMockAction extends MockAction {
private final String name;
NamedMockAction(String name, List<Step> steps) {
super(steps, true);
this.name = name;
}
@Override
public String getWriteableName() {
return name;
}
@Override
public void writeTo(StreamOutput out) throws IOException {
throw new UnsupportedOperationException();
}
}
private static class ControllableLifecycleType implements LifecycleType {
private final List<String> orderedPhaseNames;
private final Map<String, List<String>> orderedActionNamesForPhases;
ControllableLifecycleType(List<String> orderedPhases, Map<String, List<String>> orderedActionNamesForPhases) {
this.orderedPhaseNames = orderedPhases;
this.orderedActionNamesForPhases = orderedActionNamesForPhases;
}
@Override
public String getWriteableName() {
return "controllable_lifecycle_type";
}
@Override
public void writeTo(StreamOutput out) throws IOException {
}
@Override
public List<Phase> getOrderedPhases(Map<String, Phase> phases) {
return orderedPhaseNames.stream().map(n -> phases.get(n)).filter(Objects::nonNull).collect(Collectors.toList());
}
@Override
public String getNextPhaseName(String currentPhaseName, Map<String, Phase> phases) {
int index = orderedPhaseNames.indexOf(currentPhaseName);
if (index < 0) {
throw new IllegalArgumentException(
"[" + currentPhaseName + "] is not a valid phase for lifecycle type [" + getWriteableName() + "]");
} else if (index == orderedPhaseNames.size() - 1) {
return null;
} else {
// Find the next phase after `index` that exists in `phases` and return it
while (++index < orderedPhaseNames.size()) {
String phaseName = orderedPhaseNames.get(index);
if (phases.containsKey(phaseName)) {
return phaseName;
}
}
// if we have exhausted VALID_PHASES and haven't found a matching
// phase in `phases` return null indicating there is no next phase
// available
return null;
}
}
@Override
public String getPreviousPhaseName(String currentPhaseName, Map<String, Phase> phases) {
int index = orderedPhaseNames.indexOf(currentPhaseName);
if (index < 0) {
throw new IllegalArgumentException(
"[" + currentPhaseName + "] is not a valid phase for lifecycle type [" + getWriteableName() + "]");
} else if (index == orderedPhaseNames.size() - 1) {
return null;
} else {
// Find the previous phase before `index` that exists in `phases` and return it
while (--index >= 0) {
String phaseName = orderedPhaseNames.get(index);
if (phases.containsKey(phaseName)) {
return phaseName;
}
}
// if we have exhausted VALID_PHASES and haven't found a matching
// phase in `phases` return null indicating there is no next phase
// available
return null;
}
}
@Override
public List<LifecycleAction> getOrderedActions(Phase phase) {
List<String> orderedActionNames = orderedActionNamesForPhases.get(phase.getName());
if (orderedActionNames == null) {
throw new IllegalArgumentException(
"[" + phase.getName() + "] is not a valid phase for lifecycle type [" + getWriteableName() + "]");
}
return orderedActionNames.stream().map(n -> phase.getActions().get(n)).filter(Objects::nonNull).collect(Collectors.toList());
}
@Override
public String getNextActionName(String currentActionName, Phase phase) {
List<String> orderedActionNames = orderedActionNamesForPhases.get(phase.getName());
if (orderedActionNames == null) {
throw new IllegalArgumentException(
"[" + phase.getName() + "] is not a valid phase for lifecycle type [" + getWriteableName() + "]");
}
int index = orderedActionNames.indexOf(currentActionName);
if (index < 0) {
throw new IllegalArgumentException("[" + currentActionName + "] is not a valid action for phase [" + phase.getName()
+ "] in lifecycle type [" + getWriteableName() + "]");
} else {
// Find the next action after `index` that exists in the phase and return it
while (++index < orderedActionNames.size()) {
String actionName = orderedActionNames.get(index);
if (phase.getActions().containsKey(actionName)) {
return actionName;
}
}
// if we have exhausted `validActions` and haven't found a matching
// action in the Phase return null indicating there is no next
// action available
return null;
}
}
@Override
public void validate(Collection<Phase> phases) {
phases.forEach(phase -> {
if (orderedPhaseNames.contains(phase.getName()) == false) {
throw new IllegalArgumentException("Timeseries lifecycle does not support phase [" + phase.getName() + "]");
}
List<String> allowedActions = orderedActionNamesForPhases.get(phase.getName());
phase.getActions().forEach((actionName, action) -> {
if (allowedActions.contains(actionName) == false) {
throw new IllegalArgumentException(
"invalid action [" + actionName + "] " + "defined in phase [" + phase.getName() + "]");
}
});
});
}
}
}

View File

@ -1,75 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
package org.elasticsearch.xpack.core.indexlifecycle;
import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.test.AbstractStreamableTestCase;
import java.io.IOException;
import java.util.Arrays;
public class SetIndexLifecyclePolicyRequestTests extends AbstractStreamableTestCase<SetIndexLifecyclePolicyRequest> {
@Override
protected SetIndexLifecyclePolicyRequest createTestInstance() {
SetIndexLifecyclePolicyRequest request = new SetIndexLifecyclePolicyRequest(randomAlphaOfLength(20),
generateRandomStringArray(20, 20, false));
if (randomBoolean()) {
IndicesOptions indicesOptions = IndicesOptions.fromOptions(randomBoolean(), randomBoolean(), randomBoolean(), randomBoolean(),
randomBoolean(), randomBoolean(), randomBoolean());
request.indicesOptions(indicesOptions);
}
return request;
}
@Override
protected SetIndexLifecyclePolicyRequest createBlankInstance() {
return new SetIndexLifecyclePolicyRequest();
}
@Override
protected SetIndexLifecyclePolicyRequest mutateInstance(SetIndexLifecyclePolicyRequest instance) throws IOException {
String[] indices = instance.indices();
IndicesOptions indicesOptions = instance.indicesOptions();
String policy = instance.policy();
switch (between(0, 2)) {
case 0:
indices = randomValueOtherThanMany(i -> Arrays.equals(i, instance.indices()),
() -> generateRandomStringArray(20, 20, false));
break;
case 1:
indicesOptions = randomValueOtherThan(indicesOptions, () -> IndicesOptions.fromOptions(randomBoolean(), randomBoolean(),
randomBoolean(), randomBoolean(), randomBoolean(), randomBoolean(), randomBoolean()));
break;
case 2:
policy = randomValueOtherThan(policy, () -> randomAlphaOfLength(20));
break;
default:
throw new AssertionError("Illegal randomisation branch");
}
SetIndexLifecyclePolicyRequest newRequest = new SetIndexLifecyclePolicyRequest(policy, indices);
newRequest.indicesOptions(indicesOptions);
return newRequest;
}
public void testNullIndices() {
IllegalArgumentException exception = expectThrows(IllegalArgumentException.class,
() -> new SetIndexLifecyclePolicyRequest(randomAlphaOfLength(20), (String[]) null));
assertEquals("indices cannot be null", exception.getMessage());
}
public void testNullPolicy() {
IllegalArgumentException exception = expectThrows(IllegalArgumentException.class,
() -> new SetIndexLifecyclePolicyRequest(null, generateRandomStringArray(20, 20, false)));
assertEquals("policy cannot be null", exception.getMessage());
}
public void testValidate() {
SetIndexLifecyclePolicyRequest request = createTestInstance();
assertNull(request.validate());
}
}

View File

@ -1,68 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
package org.elasticsearch.xpack.core.indexlifecycle;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.test.AbstractStreamableXContentTestCase;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public class SetIndexLifecyclePolicyResponseTests extends AbstractStreamableXContentTestCase<SetIndexLifecyclePolicyResponse> {
@Override
protected SetIndexLifecyclePolicyResponse createBlankInstance() {
return new SetIndexLifecyclePolicyResponse();
}
@Override
protected SetIndexLifecyclePolicyResponse createTestInstance() {
List<String> failedIndexes = Arrays.asList(generateRandomStringArray(20, 20, false));
return new SetIndexLifecyclePolicyResponse(failedIndexes);
}
@Override
protected SetIndexLifecyclePolicyResponse mutateInstance(SetIndexLifecyclePolicyResponse instance) throws IOException {
List<String> failedIndices = randomValueOtherThan(instance.getFailedIndexes(),
() -> Arrays.asList(generateRandomStringArray(20, 20, false)));
return new SetIndexLifecyclePolicyResponse(failedIndices);
}
@Override
protected SetIndexLifecyclePolicyResponse doParseInstance(XContentParser parser) throws IOException {
return SetIndexLifecyclePolicyResponse.PARSER.apply(parser, null);
}
@Override
protected boolean supportsUnknownFields() {
return false;
}
public void testNullFailedIndices() {
IllegalArgumentException exception = expectThrows(IllegalArgumentException.class, () -> new SetIndexLifecyclePolicyResponse(null));
assertEquals("failed_indexes cannot be null", exception.getMessage());
}
public void testHasFailures() {
SetIndexLifecyclePolicyResponse response = new SetIndexLifecyclePolicyResponse(new ArrayList<>());
assertFalse(response.hasFailures());
assertEquals(Collections.emptyList(), response.getFailedIndexes());
int size = randomIntBetween(1, 10);
List<String> failedIndexes = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
failedIndexes.add(randomAlphaOfLength(20));
}
response = new SetIndexLifecyclePolicyResponse(failedIndexes);
assertTrue(response.hasFailures());
assertEquals(failedIndexes, response.getFailedIndexes());
}
}

View File

@ -10,8 +10,8 @@ import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.elasticsearch.client.Request;
import org.elasticsearch.client.Response;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.ResponseException;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.settings.Settings;
@ -59,8 +59,12 @@ public class TimeSeriesLifecycleActionsIT extends ESRestTestCase {
}
public static void updatePolicy(String indexName, String policy) throws IOException {
Request request = new Request("PUT", "/" + indexName + "/_ilm/" + policy);
assertOK(client().performRequest(request));
Request changePolicyRequest = new Request("PUT", "/" + indexName + "/_settings");
final StringEntity changePolicyEntity = new StringEntity("{ \"index.lifecycle.name\": \"" + policy + "\" }",
ContentType.APPLICATION_JSON);
changePolicyRequest.setEntity(changePolicyEntity);
assertOK(client().performRequest(changePolicyRequest));
}
public void testFullPolicy() throws Exception {

View File

@ -53,7 +53,6 @@ import org.elasticsearch.xpack.core.indexlifecycle.action.MoveToStepAction;
import org.elasticsearch.xpack.core.indexlifecycle.action.PutLifecycleAction;
import org.elasticsearch.xpack.core.indexlifecycle.action.RemoveIndexLifecyclePolicyAction;
import org.elasticsearch.xpack.core.indexlifecycle.action.RetryAction;
import org.elasticsearch.xpack.core.indexlifecycle.action.SetIndexLifecyclePolicyAction;
import org.elasticsearch.xpack.core.indexlifecycle.action.StartILMAction;
import org.elasticsearch.xpack.core.indexlifecycle.action.StopILMAction;
import org.elasticsearch.xpack.indexlifecycle.action.RestDeleteLifecycleAction;
@ -64,7 +63,6 @@ import org.elasticsearch.xpack.indexlifecycle.action.RestMoveToStepAction;
import org.elasticsearch.xpack.indexlifecycle.action.RestPutLifecycleAction;
import org.elasticsearch.xpack.indexlifecycle.action.RestRemoveIndexLifecyclePolicyAction;
import org.elasticsearch.xpack.indexlifecycle.action.RestRetryAction;
import org.elasticsearch.xpack.indexlifecycle.action.RestSetIndexLifecyclePolicyAction;
import org.elasticsearch.xpack.indexlifecycle.action.RestStartILMAction;
import org.elasticsearch.xpack.indexlifecycle.action.RestStopAction;
import org.elasticsearch.xpack.indexlifecycle.action.TransportDeleteLifecycleAction;
@ -75,7 +73,6 @@ import org.elasticsearch.xpack.indexlifecycle.action.TransportMoveToStepAction;
import org.elasticsearch.xpack.indexlifecycle.action.TransportPutLifecycleAction;
import org.elasticsearch.xpack.indexlifecycle.action.TransportRemoveIndexLifecyclePolicyAction;
import org.elasticsearch.xpack.indexlifecycle.action.TransportRetryAction;
import org.elasticsearch.xpack.indexlifecycle.action.TransportSetIndexLifecyclePolicyAction;
import org.elasticsearch.xpack.indexlifecycle.action.TransportStartILMAction;
import org.elasticsearch.xpack.indexlifecycle.action.TransportStopILMAction;
@ -176,7 +173,6 @@ public class IndexLifecycle extends Plugin implements ActionPlugin {
new RestGetLifecycleAction(settings, restController),
new RestDeleteLifecycleAction(settings, restController),
new RestExplainLifecycleAction(settings, restController),
new RestSetIndexLifecyclePolicyAction(settings, restController),
new RestRemoveIndexLifecyclePolicyAction(settings, restController),
new RestMoveToStepAction(settings, restController),
new RestRetryAction(settings, restController),
@ -196,7 +192,6 @@ public class IndexLifecycle extends Plugin implements ActionPlugin {
new ActionHandler<>(GetLifecycleAction.INSTANCE, TransportGetLifecycleAction.class),
new ActionHandler<>(DeleteLifecycleAction.INSTANCE, TransportDeleteLifecycleAction.class),
new ActionHandler<>(ExplainLifecycleAction.INSTANCE, TransportExplainLifecycleAction.class),
new ActionHandler<>(SetIndexLifecyclePolicyAction.INSTANCE, TransportSetIndexLifecyclePolicyAction.class),
new ActionHandler<>(RemoveIndexLifecyclePolicyAction.INSTANCE, TransportRemoveIndexLifecyclePolicyAction.class),
new ActionHandler<>(MoveToStepAction.INSTANCE, TransportMoveToStepAction.class),
new ActionHandler<>(RetryAction.INSTANCE, TransportRetryAction.class),
@ -207,6 +202,9 @@ public class IndexLifecycle extends Plugin implements ActionPlugin {
@Override
public void close() {
indexLifecycleInitialisationService.get().close();
IndexLifecycleService lifecycleService = indexLifecycleInitialisationService.get();
if (lifecycleService != null) {
lifecycleService.close();
}
}
}

View File

@ -476,56 +476,6 @@ public class IndexLifecycleRunner {
clusterService.submitStateUpdateTask("ilm-set-step-info", new SetStepInfoUpdateTask(index, policy, currentStepKey, stepInfo));
}
public static ClusterState setPolicyForIndexes(final String newPolicyName, final Index[] indices, ClusterState currentState,
LifecyclePolicyMetadata newPolicyMetadata, List<String> failedIndexes,
LongSupplier nowSupplier) {
MetaData.Builder newMetadata = MetaData.builder(currentState.getMetaData());
boolean clusterStateChanged = false;
for (Index index : indices) {
IndexMetaData indexMetadata = currentState.getMetaData().index(index);
if (indexMetadata == null) {
// Index doesn't exist so fail it
failedIndexes.add(index.getName());
} else {
IndexMetaData.Builder newIdxMetadata = IndexLifecycleRunner.setPolicyForIndex(newPolicyName,
newPolicyMetadata, indexMetadata, nowSupplier);
if (newIdxMetadata != null) {
newMetadata.put(newIdxMetadata);
clusterStateChanged = true;
}
}
}
if (clusterStateChanged) {
ClusterState.Builder newClusterState = ClusterState.builder(currentState);
newClusterState.metaData(newMetadata);
return newClusterState.build();
} else {
return currentState;
}
}
private static IndexMetaData.Builder setPolicyForIndex(final String newPolicyName, LifecyclePolicyMetadata newPolicyMetadata,
IndexMetaData indexMetadata, LongSupplier nowSupplier) {
LifecycleExecutionState lifecycleState = LifecycleExecutionState.fromIndexMetadata(indexMetadata);
StepKey currentStepKey = IndexLifecycleRunner.getCurrentStepKey(lifecycleState);
LifecycleExecutionState newState = LifecycleExecutionState.builder(lifecycleState).build();
if (currentStepKey != null) {
// Check if current step exists in new policy and if not move to
// next available step
StepKey nextValidStepKey = newPolicyMetadata.getPolicy().getNextValidStep(currentStepKey);
if (nextValidStepKey.equals(currentStepKey) == false) {
newState = moveExecutionStateToNextStep(newPolicyMetadata, lifecycleState, currentStepKey, nextValidStepKey, nowSupplier);
}
}
Settings.Builder newSettings = Settings.builder().put(indexMetadata.getSettings());
newSettings.put(LifecycleSettings.LIFECYCLE_NAME_SETTING.getKey(), newPolicyName);
return IndexMetaData.builder(indexMetadata)
.settings(newSettings).putCustom(ILM_CUSTOM_METADATA_KEY, newState.asMap())
.settingsVersion(1 + indexMetadata.getSettingsVersion());
}
public static ClusterState removePolicyForIndexes(final Index[] indices, ClusterState currentState, List<String> failedIndexes) {
MetaData.Builder newMetadata = MetaData.builder(currentState.getMetaData());
boolean clusterStateChanged = false;

View File

@ -1,45 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
package org.elasticsearch.xpack.indexlifecycle.action;
import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.client.node.NodeClient;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.xpack.core.indexlifecycle.SetIndexLifecyclePolicyRequest;
import org.elasticsearch.rest.BaseRestHandler;
import org.elasticsearch.rest.RestController;
import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.rest.action.RestToXContentListener;
import org.elasticsearch.xpack.core.indexlifecycle.action.SetIndexLifecyclePolicyAction;
import java.io.IOException;
public class RestSetIndexLifecyclePolicyAction extends BaseRestHandler {
public RestSetIndexLifecyclePolicyAction(Settings settings, RestController controller) {
super(settings);
controller.registerHandler(RestRequest.Method.PUT, "/{index}/_ilm/{new_policy}", this);
}
@Override
public String getName() {
return "ilm_set_index_policy_action";
}
@Override
protected RestChannelConsumer prepareRequest(RestRequest restRequest, NodeClient client) throws IOException {
String[] indexes = Strings.splitStringByCommaToArray(restRequest.param("index"));
String newPolicyName = restRequest.param("new_policy");
SetIndexLifecyclePolicyRequest changePolicyRequest = new SetIndexLifecyclePolicyRequest(newPolicyName, indexes);
changePolicyRequest.masterNodeTimeout(restRequest.paramAsTime("master_timeout", changePolicyRequest.masterNodeTimeout()));
changePolicyRequest.indicesOptions(IndicesOptions.fromRequest(restRequest, changePolicyRequest.indicesOptions()));
return channel -> client.execute(SetIndexLifecyclePolicyAction.INSTANCE,
changePolicyRequest, new RestToXContentListener<>(channel));
}
}

View File

@ -1,101 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
package org.elasticsearch.xpack.indexlifecycle.action;
import org.elasticsearch.ResourceNotFoundException;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.support.ActionFilters;
import org.elasticsearch.action.support.master.TransportMasterNodeAction;
import org.elasticsearch.cluster.AckedClusterStateUpdateTask;
import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.block.ClusterBlockException;
import org.elasticsearch.cluster.block.ClusterBlockLevel;
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.Index;
import org.elasticsearch.xpack.core.indexlifecycle.LifecyclePolicyMetadata;
import org.elasticsearch.xpack.core.indexlifecycle.SetIndexLifecyclePolicyRequest;
import org.elasticsearch.xpack.core.indexlifecycle.SetIndexLifecyclePolicyResponse;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportService;
import org.elasticsearch.xpack.core.indexlifecycle.IndexLifecycleMetadata;
import org.elasticsearch.xpack.core.indexlifecycle.action.SetIndexLifecyclePolicyAction;
import org.elasticsearch.xpack.indexlifecycle.IndexLifecycleRunner;
import java.util.ArrayList;
import java.util.List;
public class TransportSetIndexLifecyclePolicyAction
extends TransportMasterNodeAction<SetIndexLifecyclePolicyRequest, SetIndexLifecyclePolicyResponse> {
@Inject
public TransportSetIndexLifecyclePolicyAction(Settings settings, TransportService transportService, ClusterService clusterService,
ThreadPool threadPool, ActionFilters actionFilters,
IndexNameExpressionResolver indexNameExpressionResolver) {
super(settings, SetIndexLifecyclePolicyAction.NAME, transportService, clusterService, threadPool, actionFilters,
indexNameExpressionResolver, SetIndexLifecyclePolicyRequest::new);
}
@Override
protected String executor() {
return ThreadPool.Names.SAME;
}
@Override
protected SetIndexLifecyclePolicyResponse newResponse() {
return new SetIndexLifecyclePolicyResponse();
}
@Override
protected ClusterBlockException checkBlock(SetIndexLifecyclePolicyRequest request, ClusterState state) {
return state.blocks().globalBlockedException(ClusterBlockLevel.METADATA_WRITE);
}
@Override
protected void masterOperation(SetIndexLifecyclePolicyRequest request, ClusterState state,
ActionListener<SetIndexLifecyclePolicyResponse> listener) throws Exception {
final String newPolicyName = request.policy();
final Index[] indices = indexNameExpressionResolver.concreteIndices(state, request.indicesOptions(), request.indices());
clusterService.submitStateUpdateTask("change-lifecycle-for-index-" + newPolicyName,
new AckedClusterStateUpdateTask<SetIndexLifecyclePolicyResponse>(request, listener) {
private final List<String> failedIndexes = new ArrayList<>();
@Override
public ClusterState execute(ClusterState currentState) throws Exception {
IndexLifecycleMetadata ilmMetadata = (IndexLifecycleMetadata) currentState.metaData()
.custom(IndexLifecycleMetadata.TYPE);
if (ilmMetadata == null) {
throw new ResourceNotFoundException("Policy does not exist [{}]", newPolicyName);
}
LifecyclePolicyMetadata newPolicyMetadata = ilmMetadata.getPolicyMetadatas().get(newPolicyName);
if (newPolicyMetadata == null) {
throw new ResourceNotFoundException("Policy does not exist [{}]", newPolicyName);
}
return IndexLifecycleRunner.setPolicyForIndexes(newPolicyName, indices, currentState, newPolicyMetadata,
failedIndexes, System::currentTimeMillis);
}
@Override
public void onFailure(String source, Exception e) {
listener.onFailure(e);
}
@Override
protected SetIndexLifecyclePolicyResponse newResponse(boolean acknowledged) {
return new SetIndexLifecyclePolicyResponse(failedIndexes);
}
});
}
}

View File

@ -0,0 +1,144 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
package org.elasticsearch.xpack.indexlifecycle;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.elasticsearch.client.Request;
import org.elasticsearch.client.Response;
import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.test.rest.ESRestTestCase;
import org.elasticsearch.xpack.core.indexlifecycle.AllocateAction;
import org.elasticsearch.xpack.core.indexlifecycle.LifecyclePolicy;
import org.elasticsearch.xpack.core.indexlifecycle.LifecycleSettings;
import org.elasticsearch.xpack.core.indexlifecycle.Phase;
import org.elasticsearch.xpack.core.indexlifecycle.RolloverAction;
import org.elasticsearch.xpack.core.indexlifecycle.RolloverStep;
import org.elasticsearch.xpack.core.indexlifecycle.Step.StepKey;
import org.elasticsearch.xpack.core.indexlifecycle.TerminalPolicyStep;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import static java.util.Collections.singletonMap;
import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder;
public class ChangePolicyforIndexIT extends ESRestTestCase {
/**
* This test aims to prove that an index will finish the current phase on an
* existing definition when the policy is changed for that index, and that
* after completing the current phase the new policy will be used for
* subsequent phases.
*
* The test creates two policies, one with a hot phase requiring 1 document
* to rollover and a warm phase with an impossible allocation action. The
* second policy has a rollover action requiring 1000 document and a warm
* phase that moves the index to known nodes that will succeed. An index is
* created with the fiorst policy set and the test ensures the policy is in
* the rollover step. It then changes the policy for the index to the second
* policy. It indexes a single document and checks that the index moves past
* the hot phase and through the warm phasee (proving the hot phase
* definition from the first policy was used) and then checks the allocation
* settings from the second policy are set ont he index (proving the second
* policy was used for the warm phase)
*/
public void testChangePolicyForIndex() throws Exception {
String indexName = "test-000001";
// create policy_1 and policy_2
Map<String, Phase> phases1 = new HashMap<>();
phases1.put("hot", new Phase("hot", TimeValue.ZERO, singletonMap(RolloverAction.NAME, new RolloverAction(null, null, 1L))));
phases1.put("warm", new Phase("warm", TimeValue.ZERO,
singletonMap(AllocateAction.NAME, new AllocateAction(1, singletonMap("_name", "foobarbaz"), null, null))));
LifecyclePolicy lifecyclePolicy1 = new LifecyclePolicy("policy_1", phases1);
Map<String, Phase> phases2 = new HashMap<>();
phases2.put("hot", new Phase("hot", TimeValue.ZERO, singletonMap(RolloverAction.NAME, new RolloverAction(null, null, 1000L))));
phases2.put("warm", new Phase("warm", TimeValue.ZERO,
singletonMap(AllocateAction.NAME, new AllocateAction(1, singletonMap("_name", "node-1,node-2"), null, null))));
LifecyclePolicy lifecyclePolicy2 = new LifecyclePolicy("policy_1", phases2);
// PUT policy_1 and policy_2
XContentBuilder builder1 = jsonBuilder();
lifecyclePolicy1.toXContent(builder1, null);
final StringEntity entity1 = new StringEntity("{ \"policy\":" + Strings.toString(builder1) + "}", ContentType.APPLICATION_JSON);
Request request1 = new Request("PUT", "_ilm/" + "policy_1");
request1.setEntity(entity1);
assertOK(client().performRequest(request1));
XContentBuilder builder2 = jsonBuilder();
lifecyclePolicy2.toXContent(builder2, null);
final StringEntity entity2 = new StringEntity("{ \"policy\":" + Strings.toString(builder2) + "}", ContentType.APPLICATION_JSON);
Request request2 = new Request("PUT", "_ilm/" + "policy_2");
request2.setEntity(entity2);
assertOK(client().performRequest(request2));
// create the test-index index and set the policy to policy_1
Settings settings = Settings.builder().put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, 4)
.put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, 0).put("index.routing.allocation.include._name", "node-0")
.put(RolloverAction.LIFECYCLE_ROLLOVER_ALIAS, "alias").put(LifecycleSettings.LIFECYCLE_NAME, "policy_1").build();
Request createIndexRequest = new Request("PUT", "/" + indexName);
createIndexRequest.setJsonEntity(
"{\n \"settings\": " + Strings.toString(settings) + ", \"aliases\" : { \"alias\": { \"is_write_index\": true } } }");
client().performRequest(createIndexRequest);
// wait for the shards to initialize
ensureGreen(indexName);
// Check the index is on the attempt rollover step
assertBusy(() -> assertStep(indexName, new StepKey("hot", RolloverAction.NAME, RolloverStep.NAME)));
// Change the policy to policy_2
Request changePolicyRequest = new Request("PUT", "/" + indexName + "/_settings");
final StringEntity changePolicyEntity = new StringEntity("{ \"index.lifecycle.name\": \"policy_2\" }",
ContentType.APPLICATION_JSON);
changePolicyRequest.setEntity(changePolicyEntity);
assertOK(client().performRequest(changePolicyRequest));
// Check the index is still on the attempt rollover step
assertBusy(() -> assertStep(indexName, new StepKey("hot", RolloverAction.NAME, RolloverStep.NAME)));
// Index a single document
XContentBuilder document = jsonBuilder().startObject();
document.field("foo", "bar");
document.endObject();
final Request request = new Request("POST", "/" + indexName + "/_doc/1");
request.setJsonEntity(Strings.toString(document));
assertOK(client().performRequest(request));
// Check the index goes to the warm phase and completes
assertBusy(() -> assertStep(indexName, TerminalPolicyStep.KEY));
// Check index is allocated on node-1 and node-2 as per policy_2
Request getSettingsRequest = new Request("GET", "/" + indexName + "/_settings");
Response getSettingsResponse = client().performRequest(getSettingsRequest);
assertOK(getSettingsResponse);
Map<String, Object> getSettingsResponseMap = entityAsMap(getSettingsResponse);
@SuppressWarnings("unchecked")
Map<String, Object> indexSettings = (Map<String, Object>) ((Map<String, Object>) getSettingsResponseMap.get(indexName))
.get("settings");
@SuppressWarnings("unchecked")
Map<String, Object> routingSettings = (Map<String, Object>) ((Map<String, Object>) indexSettings.get("index")).get("routing");
@SuppressWarnings("unchecked")
String includesAllocation = (String) ((Map<String, Object>) ((Map<String, Object>) routingSettings.get("allocation"))
.get("include")).get("_name");
assertEquals("node-1,node-2", includesAllocation);
}
private void assertStep(String indexName, StepKey expectedStep) throws IOException {
Response explainResponse = client().performRequest(new Request("GET", "/" + indexName + "/_ilm/explain"));
assertOK(explainResponse);
Map<String, Object> explainResponseMap = entityAsMap(explainResponse);
@SuppressWarnings("unchecked")
Map<String, Object> indexExplainResponse = (Map<String, Object>) ((Map<String, Object>) explainResponseMap.get("indices"))
.get(indexName);
assertEquals(expectedStep.getPhase(), indexExplainResponse.get("phase"));
assertEquals(expectedStep.getAction(), indexExplainResponse.get("action"));
assertEquals(expectedStep.getName(), indexExplainResponse.get("step"));
}
}

View File

@ -80,9 +80,11 @@ public class IndexLifecycleRunnerTests extends ESTestCase {
private static final NamedXContentRegistry REGISTRY;
static {
List<NamedXContentRegistry.Entry> entries = new ArrayList<>(new IndexLifecycle(Settings.EMPTY).getNamedXContent());
try (IndexLifecycle indexLifecycle = new IndexLifecycle(Settings.EMPTY)) {
List<NamedXContentRegistry.Entry> entries = new ArrayList<>(indexLifecycle.getNamedXContent());
REGISTRY = new NamedXContentRegistry(entries);
}
}
/** A real policy steps registry where getStep can be overridden so that JSON doesn't have to be parsed */
private class MockPolicyStepsRegistry extends PolicyStepsRegistry {
@ -988,94 +990,6 @@ public class IndexLifecycleRunnerTests extends ESTestCase {
return ClusterState.builder(new ClusterName("my_cluster")).metaData(metadata).build();
}
public void testSetPolicyForIndex() {
long now = randomNonNegativeLong();
String indexName = randomAlphaOfLength(10);
String oldPolicyName = "old_policy";
String newPolicyName = "new_policy";
String phaseName = randomAlphaOfLength(10);
StepKey currentStep = new StepKey(phaseName, MockAction.NAME, randomAlphaOfLength(10));
LifecyclePolicy newPolicy = createPolicy(newPolicyName,
new StepKey(phaseName, MockAction.NAME, randomAlphaOfLength(9)), null);
LifecyclePolicy oldPolicy = createPolicy(oldPolicyName, currentStep, null);
Settings.Builder indexSettingsBuilder = Settings.builder().put(LifecycleSettings.LIFECYCLE_NAME, oldPolicyName)
.put(LifecycleSettings.LIFECYCLE_SKIP, true);
LifecycleExecutionState.Builder lifecycleState = LifecycleExecutionState.builder();
lifecycleState.setPhase(currentStep.getPhase());
lifecycleState.setAction(currentStep.getAction());
lifecycleState.setStep(currentStep.getName());
List<LifecyclePolicyMetadata> policyMetadatas = new ArrayList<>();
policyMetadatas.add(new LifecyclePolicyMetadata(oldPolicy, Collections.emptyMap(),
randomNonNegativeLong(), randomNonNegativeLong()));
LifecyclePolicyMetadata newPolicyMetadata = new LifecyclePolicyMetadata(newPolicy, Collections.emptyMap(),
randomNonNegativeLong(), randomNonNegativeLong());
policyMetadatas.add(newPolicyMetadata);
ClusterState clusterState = buildClusterState(indexName, indexSettingsBuilder, lifecycleState.build(), policyMetadatas);
Index index = clusterState.metaData().index(indexName).getIndex();
Index[] indices = new Index[] { index };
List<String> failedIndexes = new ArrayList<>();
ClusterState newClusterState = IndexLifecycleRunner.setPolicyForIndexes(newPolicyName, indices, clusterState, newPolicyMetadata,
failedIndexes, () -> now);
assertTrue(failedIndexes.isEmpty());
assertClusterStateOnPolicy(clusterState, index, newPolicyName, currentStep, TerminalPolicyStep.KEY, newClusterState, now);
}
public void testSetPolicyForIndexNoCurrentPolicy() {
long now = randomNonNegativeLong();
String indexName = randomAlphaOfLength(10);
String newPolicyName = "new_policy";
LifecyclePolicy newPolicy = newTestLifecyclePolicy(newPolicyName, Collections.emptyMap());
LifecyclePolicyMetadata newPolicyMetadata = new LifecyclePolicyMetadata(newPolicy, Collections.emptyMap(),
randomNonNegativeLong(), randomNonNegativeLong());
StepKey currentStep = new StepKey(null, null, null);
Settings.Builder indexSettingsBuilder = Settings.builder();
ClusterState clusterState = buildClusterState(indexName, indexSettingsBuilder, LifecycleExecutionState.builder().build(),
Collections.singletonList(newPolicyMetadata));
Index index = clusterState.metaData().index(indexName).getIndex();
Index[] indices = new Index[] { index };
List<String> failedIndexes = new ArrayList<>();
ClusterState newClusterState = IndexLifecycleRunner.setPolicyForIndexes(newPolicyName, indices, clusterState, newPolicyMetadata,
failedIndexes, () -> now);
assertTrue(failedIndexes.isEmpty());
assertClusterStateOnPolicy(clusterState, index, newPolicyName, currentStep, currentStep, newClusterState, now);
}
public void testSetPolicyForIndexIndexDoesntExist() {
long now = randomNonNegativeLong();
String indexName = randomAlphaOfLength(10);
String oldPolicyName = "old_policy";
String newPolicyName = "new_policy";
LifecyclePolicy oldPolicy = newTestLifecyclePolicy(oldPolicyName, Collections.emptyMap());
LifecyclePolicy newPolicy = newTestLifecyclePolicy(newPolicyName, Collections.emptyMap());
LifecyclePolicyMetadata newPolicyMetadata = new LifecyclePolicyMetadata(newPolicy, Collections.emptyMap(),
randomNonNegativeLong(), randomNonNegativeLong());
StepKey currentStep = AbstractStepTestCase.randomStepKey();
Settings.Builder indexSettingsBuilder = Settings.builder().put(LifecycleSettings.LIFECYCLE_NAME, oldPolicyName)
.put(LifecycleSettings.LIFECYCLE_SKIP, true);
LifecycleExecutionState.Builder lifecycleState = LifecycleExecutionState.builder();
lifecycleState.setPhase(currentStep.getPhase());
lifecycleState.setAction(currentStep.getAction());
lifecycleState.setStep(currentStep.getName());
List<LifecyclePolicyMetadata> policyMetadatas = new ArrayList<>();
policyMetadatas.add(new LifecyclePolicyMetadata(oldPolicy, Collections.emptyMap(),
randomNonNegativeLong(), randomNonNegativeLong()));
ClusterState clusterState = buildClusterState(indexName, indexSettingsBuilder, lifecycleState.build(), policyMetadatas);
Index index = new Index("doesnt_exist", "im_not_here");
Index[] indices = new Index[] { index };
List<String> failedIndexes = new ArrayList<>();
ClusterState newClusterState = IndexLifecycleRunner.setPolicyForIndexes(newPolicyName, indices, clusterState, newPolicyMetadata,
failedIndexes, () -> now);
assertEquals(1, failedIndexes.size());
assertEquals("doesnt_exist", failedIndexes.get(0));
assertSame(clusterState, newClusterState);
}
private static LifecyclePolicy createPolicy(String policyName, StepKey safeStep, StepKey unsafeStep) {
Map<String, Phase> phases = new HashMap<>();
if (safeStep != null) {
@ -1200,11 +1114,9 @@ public class IndexLifecycleRunnerTests extends ESTestCase {
SortedMap<String, LifecyclePolicyMetadata> lifecyclePolicyMap = new TreeMap<>(Collections.singletonMap(policyName,
new LifecyclePolicyMetadata(createPolicy(policyName, null, step.getKey()), new HashMap<>(),
randomNonNegativeLong(), randomNonNegativeLong())));
Index index = new Index("my_index", "uuid");
Map<String, Step> firstStepMap = Collections.singletonMap(policyName, step);
Map<StepKey, Step> policySteps = Collections.singletonMap(step.getKey(), step);
Map<String, Map<StepKey, Step>> stepMap = Collections.singletonMap(policyName, policySteps);
Map<Index, List<Step>> indexSteps = Collections.singletonMap(index, Collections.singletonList(step));
PolicyStepsRegistry policyStepsRegistry = new PolicyStepsRegistry(lifecyclePolicyMap, firstStepMap,
stepMap, NamedXContentRegistry.EMPTY, null);
ClusterService clusterService = mock(ClusterService.class);
@ -1375,10 +1287,6 @@ public class IndexLifecycleRunnerTests extends ESTestCase {
this.exception = exception;
}
void setIndexSurvives(boolean indexSurvives) {
this.indexSurvives = indexSurvives;
}
@Override
public boolean indexSurvives() {
return indexSurvives;
@ -1427,14 +1335,6 @@ public class IndexLifecycleRunnerTests extends ESTestCase {
this.exception = exception;
}
void setWillComplete(boolean willComplete) {
this.willComplete = willComplete;
}
void expectedInfo(ToXContentObject expectedInfo) {
this.expectedInfo = expectedInfo;
}
long getExecuteCount() {
return executeCount;
}
@ -1531,63 +1431,6 @@ public class IndexLifecycleRunnerTests extends ESTestCase {
}
private static class MoveToNextStepUpdateTaskMatcher extends ArgumentMatcher<MoveToNextStepUpdateTask> {
private Index index;
private String policy;
private StepKey currentStepKey;
private StepKey nextStepKey;
MoveToNextStepUpdateTaskMatcher(Index index, String policy, StepKey currentStepKey, StepKey nextStepKey) {
this.index = index;
this.policy = policy;
this.currentStepKey = currentStepKey;
this.nextStepKey = nextStepKey;
}
@Override
public boolean matches(Object argument) {
if (argument == null || argument instanceof MoveToNextStepUpdateTask == false) {
return false;
}
MoveToNextStepUpdateTask task = (MoveToNextStepUpdateTask) argument;
return Objects.equals(index, task.getIndex()) &&
Objects.equals(policy, task.getPolicy()) &&
Objects.equals(currentStepKey, task.getCurrentStepKey()) &&
Objects.equals(nextStepKey, task.getNextStepKey());
}
}
private static class MoveToErrorStepUpdateTaskMatcher extends ArgumentMatcher<MoveToErrorStepUpdateTask> {
private Index index;
private String policy;
private StepKey currentStepKey;
private Exception cause;
MoveToErrorStepUpdateTaskMatcher(Index index, String policy, StepKey currentStepKey, Exception cause) {
this.index = index;
this.policy = policy;
this.currentStepKey = currentStepKey;
this.cause = cause;
}
@Override
public boolean matches(Object argument) {
if (argument == null || argument instanceof MoveToErrorStepUpdateTask == false) {
return false;
}
MoveToErrorStepUpdateTask task = (MoveToErrorStepUpdateTask) argument;
return Objects.equals(index, task.getIndex()) &&
Objects.equals(policy, task.getPolicy())&&
Objects.equals(currentStepKey, task.getCurrentStepKey()) &&
Objects.equals(cause.getClass(), task.getCause().getClass()) &&
Objects.equals(cause.getMessage(), task.getCause().getMessage());
}
}
private static class SetStepInfoUpdateTaskMatcher extends ArgumentMatcher<SetStepInfoUpdateTask> {
private Index index;

View File

@ -1,23 +0,0 @@
{
"ilm.set_policy": {
"documentation": "http://www.elastic.co/guide/en/index_lifecycle/current/index_lifecycle.html",
"methods": [ "PUT" ],
"url": {
"path": "/{index}/_ilm/{new_policy}",
"paths": ["/{index}/_ilm/{new_policy}"],
"parts": {
"index": {
"type" : "string",
"description" : "The name of the index to set policy on"
},
"new_policy": {
"type" : "string",
"description" : "The name of the new policy to set"
}
},
"params": {
}
},
"body": null
}
}

View File

@ -1,221 +0,0 @@
---
setup:
- do:
cluster.health:
wait_for_status: yellow
- do:
acknowlege: true
ilm.put_lifecycle:
policy: "my_moveable_timeseries_lifecycle"
body: |
{
"policy": {
"phases": {
"warm": {
"minimum_age": "1000s",
"actions": {
"forcemerge": {
"max_num_segments": 10000
}
}
},
"hot": {
"minimum_age": "1000s",
"actions": { }
}
}
}
}
- do:
acknowledge: true
ilm.get_lifecycle:
policy: "my_moveable_timeseries_lifecycle"
- do:
acknowlege: true
ilm.put_lifecycle:
policy: "my_alternative_timeseries_lifecycle"
body: |
{
"policy": {
"phases": {
"warm": {
"minimum_age": "1000s",
"actions": {
"forcemerge": {
"max_num_segments": 10000
}
}
},
"hot": {
"minimum_age": "1000s",
"actions": { }
}
}
}
}
- do:
acknowledge: true
ilm.get_lifecycle:
policy: "my_alternative_timeseries_lifecycle"
- do:
indices.create:
index: my_index
body:
settings:
index.lifecycle.name: "my_moveable_timeseries_lifecycle"
- do:
indices.create:
index: my_index2
body:
settings:
index.lifecycle.name: "my_moveable_timeseries_lifecycle"
- do:
indices.create:
index: another_index
body:
settings:
index.lifecycle.name: "my_moveable_timeseries_lifecycle"
- do:
indices.create:
index: unmanaged_index
body:
settings: {}
- do:
indices.create:
index: my_index_no_policy
---
teardown:
- do:
acknowledge: true
indices.delete:
index: my_index
- do:
acknowledge: true
indices.delete:
index: my_index2
- do:
acknowledge: true
indices.delete:
index: another_index
- do:
acknowledge: true
indices.delete:
index: unmanaged_index
- do:
acknowledge: true
indices.delete:
index: my_index_no_policy
- do:
acknowledge: true
ilm.delete_lifecycle:
policy: "my_moveable_timeseries_lifecycle"
- do:
catch: missing
ilm.get_lifecycle:
policy: "my_moveable_timeseries_lifecycle"
- do:
acknowledge: true
ilm.delete_lifecycle:
policy: "my_alternative_timeseries_lifecycle"
- do:
catch: missing
ilm.get_lifecycle:
policy: "my_alternative_timeseries_lifecycle"
---
"Test Set Policy Single Index":
- do:
indices.get_settings:
index: "another_index"
- match: { another_index.settings.index.lifecycle.name: my_moveable_timeseries_lifecycle }
- do:
acknowledge: true
ilm.set_policy:
index: "another_index"
new_policy: my_alternative_timeseries_lifecycle
- is_false: has_failures
- length: { failed_indexes: 0 }
- do:
indices.get_settings:
index: "another_index"
- match: { another_index.settings.index.lifecycle.name: my_alternative_timeseries_lifecycle }
---
"Test Set Policy Index Pattern":
- do:
indices.get_settings:
index: "my_*"
- match: { my_index.settings.index.lifecycle.name: my_moveable_timeseries_lifecycle }
- match: { my_index2.settings.index.lifecycle.name: my_moveable_timeseries_lifecycle }
- do:
acknowledge: true
ilm.set_policy:
index: "my_*"
new_policy: my_alternative_timeseries_lifecycle
- is_false: has_failures
- length: { failed_indexes: 0 }
- do:
indices.get_settings:
index: "my_*"
- match: { my_index.settings.index.lifecycle.name: my_alternative_timeseries_lifecycle }
- match: { my_index2.settings.index.lifecycle.name: my_alternative_timeseries_lifecycle }
---
"Test Set Policy Unmanaged Index":
- do:
indices.get_settings:
index: "unmanaged_index"
- is_false: unmanaged_index.settings.index.lifecycle.name
- do:
acknowledge: true
ilm.set_policy:
index: "unmanaged_index"
new_policy: my_alternative_timeseries_lifecycle
- is_false: has_failures
- length: { failed_indexes: 0 }
- do:
indices.get_settings:
index: "unmanaged_index"
- match: { unmanaged_index.settings.index.lifecycle.name: my_alternative_timeseries_lifecycle }
---
"Test Set Policy Index Does Not Exist":
- do:
catch: missing
ilm.set_policy:
index: "doesnt_exist"
new_policy: my_alternative_timeseries_lifecycle