add phase execution info to ILM Explain API (#33488)

adds a section for phase execution to the Explain API.

This contains

- phase definition
- policy name
- policy version
- modified date
This commit is contained in:
Tal Levy 2018-09-17 17:00:00 -07:00 committed by GitHub
parent 7ff11b4ae1
commit 94a66c556d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 760 additions and 301 deletions

View File

@ -19,18 +19,14 @@
package org.elasticsearch.client.indexlifecycle; package org.elasticsearch.client.indexlifecycle;
import org.elasticsearch.action.ActionResponse;
import org.elasticsearch.common.ParseField; import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.Strings; import org.elasticsearch.common.Strings;
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.ConstructingObjectParser;
import org.elasticsearch.common.xcontent.ToXContentObject; import org.elasticsearch.common.xcontent.ToXContentObject;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentParser;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
@ -43,9 +39,9 @@ import java.util.stream.Collectors;
* Since the API can be run over multiple indices the response provides a map of * Since the API can be run over multiple indices the response provides a map of
* index to the explanation of the lifecycle status for that index. * index to the explanation of the lifecycle status for that index.
*/ */
public class ExplainLifecycleResponse extends ActionResponse implements ToXContentObject { public class ExplainLifecycleResponse implements ToXContentObject {
public static final ParseField INDICES_FIELD = new ParseField("indices"); private static final ParseField INDICES_FIELD = new ParseField("indices");
private Map<String, IndexLifecycleExplainResponse> indexResponses; private Map<String, IndexLifecycleExplainResponse> indexResponses;
@ -62,9 +58,6 @@ public class ExplainLifecycleResponse extends ActionResponse implements ToXConte
return PARSER.apply(parser, null); return PARSER.apply(parser, null);
} }
public ExplainLifecycleResponse() {
}
public ExplainLifecycleResponse(Map<String, IndexLifecycleExplainResponse> indexResponses) { public ExplainLifecycleResponse(Map<String, IndexLifecycleExplainResponse> indexResponses) {
this.indexResponses = indexResponses; this.indexResponses = indexResponses;
} }
@ -91,25 +84,6 @@ public class ExplainLifecycleResponse extends ActionResponse implements ToXConte
return builder; return builder;
} }
@Override
public void readFrom(StreamInput in) throws IOException {
int size = in.readVInt();
Map<String, IndexLifecycleExplainResponse> indexResponses = new HashMap<>(size);
for (int i = 0; i < size; i++) {
IndexLifecycleExplainResponse indexResponse = new IndexLifecycleExplainResponse(in);
indexResponses.put(indexResponse.getIndex(), indexResponse);
}
this.indexResponses = indexResponses;
}
@Override
public void writeTo(StreamOutput out) throws IOException {
out.writeVInt(indexResponses.size());
for (IndexLifecycleExplainResponse e : indexResponses.values()) {
e.writeTo(out);
}
}
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(indexResponses); return Objects.hash(indexResponses);

View File

@ -23,9 +23,6 @@ import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.Strings; import org.elasticsearch.common.Strings;
import org.elasticsearch.common.bytes.BytesArray; import org.elasticsearch.common.bytes.BytesArray;
import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.io.stream.Writeable;
import org.elasticsearch.common.xcontent.ConstructingObjectParser; import org.elasticsearch.common.xcontent.ConstructingObjectParser;
import org.elasticsearch.common.xcontent.ToXContentObject; import org.elasticsearch.common.xcontent.ToXContentObject;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
@ -37,7 +34,7 @@ import org.joda.time.chrono.ISOChronology;
import java.io.IOException; import java.io.IOException;
import java.util.Objects; import java.util.Objects;
public class IndexLifecycleExplainResponse implements ToXContentObject, Writeable { public class IndexLifecycleExplainResponse implements ToXContentObject {
private static final ParseField INDEX_FIELD = new ParseField("index"); private static final ParseField INDEX_FIELD = new ParseField("index");
private static final ParseField MANAGED_BY_ILM_FIELD = new ParseField("managed"); private static final ParseField MANAGED_BY_ILM_FIELD = new ParseField("managed");
@ -52,6 +49,7 @@ public class IndexLifecycleExplainResponse implements ToXContentObject, Writeabl
private static final ParseField ACTION_TIME_FIELD = new ParseField("action_time"); private static final ParseField ACTION_TIME_FIELD = new ParseField("action_time");
private static final ParseField STEP_TIME_FIELD = new ParseField("step_time"); private static final ParseField STEP_TIME_FIELD = new ParseField("step_time");
private static final ParseField STEP_INFO_FIELD = new ParseField("step_info"); private static final ParseField STEP_INFO_FIELD = new ParseField("step_info");
private static final ParseField PHASE_EXECUTION_INFO = new ParseField("phase_execution");
public static final ConstructingObjectParser<IndexLifecycleExplainResponse, Void> PARSER = new ConstructingObjectParser<>( public static final ConstructingObjectParser<IndexLifecycleExplainResponse, Void> PARSER = new ConstructingObjectParser<>(
"index_lifecycle_explain_response", "index_lifecycle_explain_response",
@ -68,7 +66,8 @@ public class IndexLifecycleExplainResponse implements ToXContentObject, Writeabl
(long) (a[9] == null ? -1L: a[9]), (long) (a[9] == null ? -1L: a[9]),
(long) (a[10] == null ? -1L: a[10]), (long) (a[10] == null ? -1L: a[10]),
(long) (a[11] == null ? -1L: a[11]), (long) (a[11] == null ? -1L: a[11]),
(BytesReference) a[12])); (BytesReference) a[12],
(PhaseExecutionInfo) a[13]));
static { static {
PARSER.declareString(ConstructingObjectParser.constructorArg(), INDEX_FIELD); PARSER.declareString(ConstructingObjectParser.constructorArg(), INDEX_FIELD);
PARSER.declareBoolean(ConstructingObjectParser.constructorArg(), MANAGED_BY_ILM_FIELD); PARSER.declareBoolean(ConstructingObjectParser.constructorArg(), MANAGED_BY_ILM_FIELD);
@ -87,6 +86,8 @@ public class IndexLifecycleExplainResponse implements ToXContentObject, Writeabl
builder.copyCurrentStructure(p); builder.copyCurrentStructure(p);
return BytesArray.bytes(builder); return BytesArray.bytes(builder);
}, STEP_INFO_FIELD); }, STEP_INFO_FIELD);
PARSER.declareObject(ConstructingObjectParser.optionalConstructorArg(), (p, c) -> PhaseExecutionInfo.parse(p, ""),
PHASE_EXECUTION_INFO);
} }
private final String index; private final String index;
@ -102,28 +103,30 @@ public class IndexLifecycleExplainResponse implements ToXContentObject, Writeabl
private final boolean skip; private final boolean skip;
private final boolean managedByILM; private final boolean managedByILM;
private final BytesReference stepInfo; private final BytesReference stepInfo;
private final PhaseExecutionInfo phaseExecutionInfo;
public static IndexLifecycleExplainResponse newManagedIndexResponse(String index, String policyName, boolean skip, long lifecycleDate, public static IndexLifecycleExplainResponse newManagedIndexResponse(String index, String policyName, boolean skip, long lifecycleDate,
String phase, String action, String step, String failedStep, long phaseTime, long actionTime, long stepTime, String phase, String action, String step, String failedStep,
BytesReference stepInfo) { long phaseTime, long actionTime, long stepTime,
BytesReference stepInfo, PhaseExecutionInfo phaseExecutionInfo) {
return new IndexLifecycleExplainResponse(index, true, policyName, skip, lifecycleDate, phase, action, step, failedStep, phaseTime, return new IndexLifecycleExplainResponse(index, true, policyName, skip, lifecycleDate, phase, action, step, failedStep, phaseTime,
actionTime, stepTime, stepInfo); actionTime, stepTime, stepInfo, phaseExecutionInfo);
} }
public static IndexLifecycleExplainResponse newUnmanagedIndexResponse(String index) { public static IndexLifecycleExplainResponse newUnmanagedIndexResponse(String index) {
return new IndexLifecycleExplainResponse(index, false, null, false, -1L, null, null, null, null, -1L, -1L, -1L, null); return new IndexLifecycleExplainResponse(index, false, null, false, -1L, null, null, null, null, -1L, -1L, -1L, null, null);
} }
private IndexLifecycleExplainResponse(String index, boolean managedByILM, String policyName, boolean skip, long lifecycleDate, private IndexLifecycleExplainResponse(String index, boolean managedByILM, String policyName, boolean skip, long lifecycleDate,
String phase, String action, String step, String failedStep, long phaseTime, long actionTime, long stepTime, String phase, String action, String step, String failedStep, long phaseTime, long actionTime,
BytesReference stepInfo) { long stepTime, BytesReference stepInfo, PhaseExecutionInfo phaseExecutionInfo) {
if (managedByILM) { if (managedByILM) {
if (policyName == null) { if (policyName == null) {
throw new IllegalArgumentException("[" + POLICY_NAME_FIELD.getPreferredName() + "] cannot be null for managed index"); throw new IllegalArgumentException("[" + POLICY_NAME_FIELD.getPreferredName() + "] cannot be null for managed index");
} }
} else { } else {
if (policyName != null || lifecycleDate >= 0 || phase != null || action != null || step != null || failedStep != null if (policyName != null || lifecycleDate >= 0 || phase != null || action != null || step != null || failedStep != null
|| phaseTime >= 0 || actionTime >= 0 || stepTime >= 0 || stepInfo != null) { || phaseTime >= 0 || actionTime >= 0 || stepTime >= 0 || stepInfo != null || phaseExecutionInfo != null) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Unmanaged index response must only contain fields: [" + MANAGED_BY_ILM_FIELD + ", " + INDEX_FIELD + "]"); "Unmanaged index response must only contain fields: [" + MANAGED_BY_ILM_FIELD + ", " + INDEX_FIELD + "]");
} }
@ -141,56 +144,7 @@ public class IndexLifecycleExplainResponse implements ToXContentObject, Writeabl
this.stepTime = stepTime; this.stepTime = stepTime;
this.failedStep = failedStep; this.failedStep = failedStep;
this.stepInfo = stepInfo; this.stepInfo = stepInfo;
} this.phaseExecutionInfo = phaseExecutionInfo;
public IndexLifecycleExplainResponse(StreamInput in) throws IOException {
index = in.readString();
managedByILM = in.readBoolean();
if (managedByILM) {
policyName = in.readString();
skip = in.readBoolean();
lifecycleDate = in.readZLong();
phase = in.readString();
action = in.readString();
step = in.readString();
failedStep = in.readOptionalString();
phaseTime = in.readZLong();
actionTime = in.readZLong();
stepTime = in.readZLong();
stepInfo = in.readOptionalBytesReference();
} else {
policyName = null;
skip = false;
lifecycleDate = -1L;
phase = null;
action = null;
step = null;
failedStep = null;
phaseTime = -1L;
actionTime = -1L;
stepTime = -1L;
stepInfo = null;
}
}
@Override
public void writeTo(StreamOutput out) throws IOException {
out.writeString(index);
out.writeBoolean(managedByILM);
if (managedByILM) {
out.writeString(policyName);
out.writeBoolean(skip);
out.writeZLong(lifecycleDate);
out.writeString(phase);
out.writeString(action);
out.writeString(step);
out.writeOptionalString(failedStep);
out.writeZLong(phaseTime);
out.writeZLong(actionTime);
out.writeZLong(stepTime);
out.writeOptionalBytesReference(stepInfo);
}
} }
public String getIndex() { public String getIndex() {
@ -245,6 +199,10 @@ public class IndexLifecycleExplainResponse implements ToXContentObject, Writeabl
return stepInfo; return stepInfo;
} }
public PhaseExecutionInfo getPhaseExecutionInfo() {
return phaseExecutionInfo;
}
@Override @Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject(); builder.startObject();
@ -282,6 +240,9 @@ public class IndexLifecycleExplainResponse implements ToXContentObject, Writeabl
if (stepInfo != null && stepInfo.length() > 0) { if (stepInfo != null && stepInfo.length() > 0) {
builder.rawField(STEP_INFO_FIELD.getPreferredName(), stepInfo.streamInput(), XContentType.JSON); builder.rawField(STEP_INFO_FIELD.getPreferredName(), stepInfo.streamInput(), XContentType.JSON);
} }
if (phaseExecutionInfo != null) {
builder.field(PHASE_EXECUTION_INFO.getPreferredName(), phaseExecutionInfo);
}
} }
builder.endObject(); builder.endObject();
return builder; return builder;
@ -290,7 +251,7 @@ public class IndexLifecycleExplainResponse implements ToXContentObject, Writeabl
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(index, managedByILM, policyName, skip, lifecycleDate, phase, action, step, failedStep, phaseTime, actionTime, return Objects.hash(index, managedByILM, policyName, skip, lifecycleDate, phase, action, step, failedStep, phaseTime, actionTime,
stepTime, stepInfo); stepTime, stepInfo, phaseExecutionInfo);
} }
@Override @Override
@ -314,7 +275,8 @@ public class IndexLifecycleExplainResponse implements ToXContentObject, Writeabl
Objects.equals(phaseTime, other.phaseTime) && Objects.equals(phaseTime, other.phaseTime) &&
Objects.equals(actionTime, other.actionTime) && Objects.equals(actionTime, other.actionTime) &&
Objects.equals(stepTime, other.stepTime) && Objects.equals(stepTime, other.stepTime) &&
Objects.equals(stepInfo, other.stepInfo); Objects.equals(stepInfo, other.stepInfo) &&
Objects.equals(phaseExecutionInfo, other.phaseExecutionInfo);
} }
@Override @Override
@ -323,3 +285,4 @@ public class IndexLifecycleExplainResponse implements ToXContentObject, Writeabl
} }
} }

View File

@ -0,0 +1,130 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.client.indexlifecycle;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.Strings;
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.Objects;
/**
* This class contains information about the current phase being executed by Index
* Lifecycle Management on the specific index.
*/
public class PhaseExecutionInfo implements ToXContentObject {
private static final ParseField POLICY_NAME_FIELD = new ParseField("policy");
private static final ParseField PHASE_DEFINITION_FIELD = new ParseField("phase_definition");
private static final ParseField VERSION_FIELD = new ParseField("version");
private static final ParseField MODIFIED_DATE_IN_MILLIS_FIELD = new ParseField("modified_date_in_millis");
private static final ConstructingObjectParser<PhaseExecutionInfo, String> PARSER = new ConstructingObjectParser<>(
"phase_execution_info", false,
(a, name) -> new PhaseExecutionInfo((String) a[0], (Phase) a[1], (long) a[2], (long) a[3]));
static {
PARSER.declareString(ConstructingObjectParser.constructorArg(), POLICY_NAME_FIELD);
PARSER.declareObject(ConstructingObjectParser.optionalConstructorArg(), Phase::parse, PHASE_DEFINITION_FIELD);
PARSER.declareLong(ConstructingObjectParser.constructorArg(), VERSION_FIELD);
PARSER.declareLong(ConstructingObjectParser.constructorArg(), MODIFIED_DATE_IN_MILLIS_FIELD);
}
public static PhaseExecutionInfo parse(XContentParser parser, String name) {
return PARSER.apply(parser, name);
}
private final String policyName;
private final Phase phase;
private final long version;
private final long modifiedDate;
/**
* This class holds information about the current phase that is being executed
*
* @param policyName the name of the policy being executed, this may not be the current policy assigned to an index
* @param phase the current phase definition executed
* @param version the version of the <code>policyName</code> being executed
* @param modifiedDate the time the executing version of the phase was modified
*/
public PhaseExecutionInfo(String policyName, Phase phase, long version, long modifiedDate) {
this.policyName = policyName;
this.phase = phase;
this.version = version;
this.modifiedDate = modifiedDate;
}
public String getPolicyName() {
return policyName;
}
public Phase getPhase() {
return phase;
}
public long getVersion() {
return version;
}
public long getModifiedDate() {
return modifiedDate;
}
@Override
public int hashCode() {
return Objects.hash(policyName, phase, version, modifiedDate);
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
PhaseExecutionInfo other = (PhaseExecutionInfo) obj;
return Objects.equals(policyName, other.policyName) &&
Objects.equals(phase, other.phase) &&
Objects.equals(version, other.version) &&
Objects.equals(modifiedDate, other.modifiedDate);
}
@Override
public String toString() {
return Strings.toString(this, false, true);
}
@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject();
builder.field(POLICY_NAME_FIELD.getPreferredName(), policyName);
if (phase != null) {
builder.field(PHASE_DEFINITION_FIELD.getPreferredName(), phase);
}
builder.field(VERSION_FIELD.getPreferredName(), version);
builder.timeField(MODIFIED_DATE_IN_MILLIS_FIELD.getPreferredName(), "modified_date", modifiedDate);
builder.endObject();
return builder;
}
}

View File

@ -36,6 +36,7 @@ import org.elasticsearch.client.indexlifecycle.LifecyclePolicy;
import org.elasticsearch.client.indexlifecycle.LifecyclePolicyMetadata; import org.elasticsearch.client.indexlifecycle.LifecyclePolicyMetadata;
import org.elasticsearch.client.indexlifecycle.OperationMode; import org.elasticsearch.client.indexlifecycle.OperationMode;
import org.elasticsearch.client.indexlifecycle.Phase; import org.elasticsearch.client.indexlifecycle.Phase;
import org.elasticsearch.client.indexlifecycle.PhaseExecutionInfo;
import org.elasticsearch.client.indexlifecycle.PutLifecyclePolicyRequest; import org.elasticsearch.client.indexlifecycle.PutLifecyclePolicyRequest;
import org.elasticsearch.client.indexlifecycle.RolloverAction; import org.elasticsearch.client.indexlifecycle.RolloverAction;
import org.elasticsearch.client.indexlifecycle.ShrinkAction; import org.elasticsearch.client.indexlifecycle.ShrinkAction;
@ -132,7 +133,8 @@ public class IndexLifecycleIT extends ESRestHighLevelClientTestCase {
Map<String, LifecycleAction> hotActions = Collections.singletonMap( Map<String, LifecycleAction> hotActions = Collections.singletonMap(
RolloverAction.NAME, RolloverAction.NAME,
new RolloverAction(null, TimeValue.timeValueHours(50 * 24), null)); new RolloverAction(null, TimeValue.timeValueHours(50 * 24), null));
lifecyclePhases.put("hot", new Phase("hot", randomFrom(TimeValue.ZERO, null), hotActions)); Phase hotPhase = new Phase("hot", randomFrom(TimeValue.ZERO, null), hotActions);
lifecyclePhases.put("hot", hotPhase);
Map<String, LifecycleAction> warmActions = new HashMap<>(); Map<String, LifecycleAction> warmActions = new HashMap<>();
warmActions.put(AllocateAction.NAME, new AllocateAction(null, null, null, Collections.singletonMap("_name", "node-1"))); warmActions.put(AllocateAction.NAME, new AllocateAction(null, null, null, Collections.singletonMap("_name", "node-1")));
@ -152,6 +154,11 @@ public class IndexLifecycleIT extends ESRestHighLevelClientTestCase {
AcknowledgedResponse putResponse = execute(putRequest, highLevelClient().indexLifecycle()::putLifecyclePolicy, AcknowledgedResponse putResponse = execute(putRequest, highLevelClient().indexLifecycle()::putLifecyclePolicy,
highLevelClient().indexLifecycle()::putLifecyclePolicyAsync); highLevelClient().indexLifecycle()::putLifecyclePolicyAsync);
assertTrue(putResponse.isAcknowledged()); assertTrue(putResponse.isAcknowledged());
GetLifecyclePolicyRequest getRequest = new GetLifecyclePolicyRequest(policy.getName());
GetLifecyclePolicyResponse getResponse = execute(getRequest, highLevelClient().indexLifecycle()::getLifecyclePolicy,
highLevelClient().indexLifecycle()::getLifecyclePolicyAsync);
long expectedPolicyModifiedDate = getResponse.getPolicies().get(policy.getName()).getModifiedDate();
createIndex("foo-01", Settings.builder().put("index.lifecycle.name", policy.getName()) createIndex("foo-01", Settings.builder().put("index.lifecycle.name", policy.getName())
.put("index.lifecycle.rollover_alias", "foo-alias").build(), "", "\"foo-alias\" : {}"); .put("index.lifecycle.rollover_alias", "foo-alias").build(), "", "\"foo-alias\" : {}");
@ -182,6 +189,8 @@ public class IndexLifecycleIT extends ESRestHighLevelClientTestCase {
assertEquals("hot", fooResponse.getPhase()); assertEquals("hot", fooResponse.getPhase());
assertEquals("rollover", fooResponse.getAction()); assertEquals("rollover", fooResponse.getAction());
assertEquals("attempt_rollover", fooResponse.getStep()); assertEquals("attempt_rollover", fooResponse.getStep());
assertEquals(new PhaseExecutionInfo(policy.getName(), new Phase("", hotPhase.getMinimumAge(), hotPhase.getActions()),
1L, expectedPolicyModifiedDate), fooResponse.getPhaseExecutionInfo());
IndexLifecycleExplainResponse bazResponse = indexResponses.get("baz-01"); IndexLifecycleExplainResponse bazResponse = indexResponses.get("baz-01");
assertNotNull(bazResponse); assertNotNull(bazResponse);
assertTrue(bazResponse.managedByILM()); assertTrue(bazResponse.managedByILM());

View File

@ -18,14 +18,19 @@
*/ */
package org.elasticsearch.client.indexlifecycle; package org.elasticsearch.client.indexlifecycle;
import org.elasticsearch.cluster.ClusterModule;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.test.AbstractStreamableXContentTestCase; import org.elasticsearch.test.AbstractXContentTestCase;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
public class ExplainLifecycleResponseTests extends AbstractStreamableXContentTestCase<ExplainLifecycleResponse> { public class ExplainLifecycleResponseTests extends AbstractXContentTestCase<ExplainLifecycleResponse> {
@Override @Override
protected ExplainLifecycleResponse createTestInstance() { protected ExplainLifecycleResponse createTestInstance() {
@ -37,19 +42,6 @@ public class ExplainLifecycleResponseTests extends AbstractStreamableXContentTes
return new ExplainLifecycleResponse(indexResponses); return new ExplainLifecycleResponse(indexResponses);
} }
@Override
protected ExplainLifecycleResponse createBlankInstance() {
return new ExplainLifecycleResponse();
}
@Override
protected ExplainLifecycleResponse mutateInstance(ExplainLifecycleResponse response) {
Map<String, IndexLifecycleExplainResponse> indexResponses = new HashMap<>(response.getIndexResponses());
IndexLifecycleExplainResponse indexResponse = IndexExplainResponseTests.randomIndexExplainResponse();
indexResponses.put(indexResponse.getIndex(), indexResponse);
return new ExplainLifecycleResponse(indexResponses);
}
@Override @Override
protected ExplainLifecycleResponse doParseInstance(XContentParser parser) throws IOException { protected ExplainLifecycleResponse doParseInstance(XContentParser parser) throws IOException {
return ExplainLifecycleResponse.fromXContent(parser); return ExplainLifecycleResponse.fromXContent(parser);
@ -59,4 +51,11 @@ public class ExplainLifecycleResponseTests extends AbstractStreamableXContentTes
protected boolean supportsUnknownFields() { protected boolean supportsUnknownFields() {
return false; return false;
} }
@Override
protected NamedXContentRegistry xContentRegistry() {
List<NamedXContentRegistry.Entry> entries = new ArrayList<>(ClusterModule.getNamedXWriteables());
entries.add(new NamedXContentRegistry.Entry(LifecycleAction.class, new ParseField(DeleteAction.NAME), DeleteAction::parse));
return new NamedXContentRegistry(entries);
}
} }

View File

@ -19,20 +19,23 @@
package org.elasticsearch.client.indexlifecycle; package org.elasticsearch.client.indexlifecycle;
import org.elasticsearch.cluster.ClusterModule;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.Strings; import org.elasticsearch.common.Strings;
import org.elasticsearch.common.bytes.BytesArray; import org.elasticsearch.common.bytes.BytesArray;
import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.xcontent.NamedXContentRegistry;
import org.elasticsearch.common.io.stream.Writeable.Reader;
import org.elasticsearch.common.xcontent.ToXContentObject; import org.elasticsearch.common.xcontent.ToXContentObject;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.test.AbstractSerializingTestCase; import org.elasticsearch.test.AbstractXContentTestCase;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.function.Supplier; import java.util.function.Supplier;
public class IndexExplainResponseTests extends AbstractSerializingTestCase<IndexLifecycleExplainResponse> { public class IndexExplainResponseTests extends AbstractXContentTestCase<IndexLifecycleExplainResponse> {
static IndexLifecycleExplainResponse randomIndexExplainResponse() { static IndexLifecycleExplainResponse randomIndexExplainResponse() {
if (frequently()) { if (frequently()) {
@ -50,7 +53,8 @@ public class IndexExplainResponseTests extends AbstractSerializingTestCase<Index
return IndexLifecycleExplainResponse.newManagedIndexResponse(randomAlphaOfLength(10), randomAlphaOfLength(10), randomBoolean(), return IndexLifecycleExplainResponse.newManagedIndexResponse(randomAlphaOfLength(10), randomAlphaOfLength(10), randomBoolean(),
randomNonNegativeLong(), randomAlphaOfLength(10), randomAlphaOfLength(10), randomAlphaOfLength(10), randomNonNegativeLong(), randomAlphaOfLength(10), randomAlphaOfLength(10), randomAlphaOfLength(10),
randomBoolean() ? null : randomAlphaOfLength(10), randomNonNegativeLong(), randomNonNegativeLong(), randomNonNegativeLong(), randomBoolean() ? null : randomAlphaOfLength(10), randomNonNegativeLong(), randomNonNegativeLong(), randomNonNegativeLong(),
randomBoolean() ? null : new BytesArray(new RandomStepInfo(() -> randomAlphaOfLength(10)).toString())); randomBoolean() ? null : new BytesArray(new RandomStepInfo(() -> randomAlphaOfLength(10)).toString()),
randomBoolean() ? null : PhaseExecutionInfoTests.randomPhaseExecutionInfo(""));
} }
@Override @Override
@ -58,99 +62,14 @@ public class IndexExplainResponseTests extends AbstractSerializingTestCase<Index
return randomIndexExplainResponse(); return randomIndexExplainResponse();
} }
@Override
protected Reader<IndexLifecycleExplainResponse> instanceReader() {
return IndexLifecycleExplainResponse::new;
}
@Override @Override
protected IndexLifecycleExplainResponse doParseInstance(XContentParser parser) throws IOException { protected IndexLifecycleExplainResponse doParseInstance(XContentParser parser) throws IOException {
return IndexLifecycleExplainResponse.PARSER.apply(parser, null); return IndexLifecycleExplainResponse.PARSER.apply(parser, null);
} }
@Override @Override
protected IndexLifecycleExplainResponse mutateInstance(IndexLifecycleExplainResponse instance) throws IOException { protected boolean supportsUnknownFields() {
String index = instance.getIndex(); return false;
String policy = instance.getPolicyName();
String phase = instance.getPhase();
String action = instance.getAction();
String step = instance.getStep();
String failedStep = instance.getFailedStep();
long policyTime = instance.getLifecycleDate();
long phaseTime = instance.getPhaseTime();
long actionTime = instance.getActionTime();
long stepTime = instance.getStepTime();
boolean managed = instance.managedByILM();
boolean skip = instance.skip();
BytesReference stepInfo = instance.getStepInfo();
if (managed) {
switch (between(0, 12)) {
case 0:
index = index + randomAlphaOfLengthBetween(1, 5);
break;
case 1:
policy = policy + randomAlphaOfLengthBetween(1, 5);
break;
case 2:
phase = phase + randomAlphaOfLengthBetween(1, 5);
break;
case 3:
action = action + randomAlphaOfLengthBetween(1, 5);
break;
case 4:
step = step + randomAlphaOfLengthBetween(1, 5);
break;
case 5:
if (Strings.hasLength(failedStep) == false) {
failedStep = randomAlphaOfLength(10);
} else if (randomBoolean()) {
failedStep = failedStep + randomAlphaOfLengthBetween(1, 5);
} else {
failedStep = null;
}
break;
case 6:
policyTime += randomLongBetween(0, 100000);
break;
case 7:
phaseTime += randomLongBetween(0, 100000);
break;
case 8:
actionTime += randomLongBetween(0, 100000);
break;
case 9:
stepTime += randomLongBetween(0, 100000);
break;
case 10:
if (Strings.hasLength(stepInfo) == false) {
stepInfo = new BytesArray(randomByteArrayOfLength(100));
} else if (randomBoolean()) {
stepInfo = randomValueOtherThan(stepInfo,
() -> new BytesArray(new RandomStepInfo(() -> randomAlphaOfLength(10)).toString()));
} else {
stepInfo = null;
}
break;
case 11:
skip = skip == false;
break;
case 12:
return IndexLifecycleExplainResponse.newUnmanagedIndexResponse(index);
default:
throw new AssertionError("Illegal randomisation branch");
}
return IndexLifecycleExplainResponse.newManagedIndexResponse(index, policy, skip, policyTime, phase, action, step, failedStep,
phaseTime, actionTime, stepTime, stepInfo);
} else {
switch (between(0, 1)) {
case 0:
return IndexLifecycleExplainResponse.newUnmanagedIndexResponse(index + randomAlphaOfLengthBetween(1, 5));
case 1:
return randomManagedIndexExplainResponse();
default:
throw new AssertionError("Illegal randomisation branch");
}
}
} }
private static class RandomStepInfo implements ToXContentObject { private static class RandomStepInfo implements ToXContentObject {
@ -194,4 +113,10 @@ public class IndexExplainResponseTests extends AbstractSerializingTestCase<Index
} }
} }
@Override
protected NamedXContentRegistry xContentRegistry() {
List<NamedXContentRegistry.Entry> entries = new ArrayList<>(ClusterModule.getNamedXWriteables());
entries.add(new NamedXContentRegistry.Entry(LifecycleAction.class, new ParseField(DeleteAction.NAME), DeleteAction::parse));
return new NamedXContentRegistry(entries);
}
} }

View File

@ -0,0 +1,67 @@
/*
* 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.cluster.ClusterModule;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.test.AbstractXContentTestCase;
import org.junit.Before;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class PhaseExecutionInfoTests extends AbstractXContentTestCase<PhaseExecutionInfo> {
static PhaseExecutionInfo randomPhaseExecutionInfo(String phaseName) {
return new PhaseExecutionInfo(randomAlphaOfLength(5), PhaseTests.randomPhase(phaseName),
randomNonNegativeLong(), randomNonNegativeLong());
}
String phaseName;
@Before
public void setupPhaseName() {
phaseName = randomAlphaOfLength(7);
}
@Override
protected PhaseExecutionInfo createTestInstance() {
return randomPhaseExecutionInfo(phaseName);
}
@Override
protected PhaseExecutionInfo doParseInstance(XContentParser parser) throws IOException {
return PhaseExecutionInfo.parse(parser, phaseName);
}
@Override
protected boolean supportsUnknownFields() {
return false;
}
@Override
protected NamedXContentRegistry xContentRegistry() {
List<NamedXContentRegistry.Entry> entries = new ArrayList<>(ClusterModule.getNamedXWriteables());
entries.add(new NamedXContentRegistry.Entry(LifecycleAction.class, new ParseField(DeleteAction.NAME), DeleteAction::parse));
return new NamedXContentRegistry(entries);
}
}

View File

@ -41,6 +41,10 @@ public class PhaseTests extends AbstractXContentTestCase<Phase> {
@Override @Override
protected Phase createTestInstance() { protected Phase createTestInstance() {
return randomPhase(phaseName);
}
static Phase randomPhase(String phaseName) {
TimeValue after = null; TimeValue after = null;
if (randomBoolean()) { if (randomBoolean()) {
after = TimeValue.parseTimeValue(randomTimeValue(0, 1000000000, "s", "m", "h", "d"), "test_after"); after = TimeValue.parseTimeValue(randomTimeValue(0, 1000000000, "s", "m", "h", "d"), "test_after");

View File

@ -39,6 +39,7 @@ public class IndexLifecycleExplainResponse implements ToXContentObject, Writeabl
private static final ParseField ACTION_TIME_FIELD = new ParseField("action_time"); private static final ParseField ACTION_TIME_FIELD = new ParseField("action_time");
private static final ParseField STEP_TIME_FIELD = new ParseField("step_time"); private static final ParseField STEP_TIME_FIELD = new ParseField("step_time");
private static final ParseField STEP_INFO_FIELD = new ParseField("step_info"); private static final ParseField STEP_INFO_FIELD = new ParseField("step_info");
private static final ParseField PHASE_EXECUTION_INFO = new ParseField("phase_execution");
public static final ConstructingObjectParser<IndexLifecycleExplainResponse, Void> PARSER = new ConstructingObjectParser<>( public static final ConstructingObjectParser<IndexLifecycleExplainResponse, Void> PARSER = new ConstructingObjectParser<>(
"index_lifecycle_explain_response", "index_lifecycle_explain_response",
@ -55,7 +56,8 @@ public class IndexLifecycleExplainResponse implements ToXContentObject, Writeabl
(long) (a[9] == null ? -1L: a[9]), (long) (a[9] == null ? -1L: a[9]),
(long) (a[10] == null ? -1L: a[10]), (long) (a[10] == null ? -1L: a[10]),
(long) (a[11] == null ? -1L: a[11]), (long) (a[11] == null ? -1L: a[11]),
(BytesReference) a[12])); (BytesReference) a[12],
(PhaseExecutionInfo) a[13]));
static { static {
PARSER.declareString(ConstructingObjectParser.constructorArg(), INDEX_FIELD); PARSER.declareString(ConstructingObjectParser.constructorArg(), INDEX_FIELD);
PARSER.declareBoolean(ConstructingObjectParser.constructorArg(), MANAGED_BY_ILM_FIELD); PARSER.declareBoolean(ConstructingObjectParser.constructorArg(), MANAGED_BY_ILM_FIELD);
@ -74,6 +76,8 @@ public class IndexLifecycleExplainResponse implements ToXContentObject, Writeabl
builder.copyCurrentStructure(p); builder.copyCurrentStructure(p);
return BytesArray.bytes(builder); return BytesArray.bytes(builder);
}, STEP_INFO_FIELD); }, STEP_INFO_FIELD);
PARSER.declareObject(ConstructingObjectParser.optionalConstructorArg(), (p, c) -> PhaseExecutionInfo.parse(p, ""),
PHASE_EXECUTION_INFO);
} }
private final String index; private final String index;
@ -89,28 +93,29 @@ public class IndexLifecycleExplainResponse implements ToXContentObject, Writeabl
private final boolean skip; private final boolean skip;
private final boolean managedByILM; private final boolean managedByILM;
private final BytesReference stepInfo; private final BytesReference stepInfo;
private final PhaseExecutionInfo phaseExecutionInfo;
public static IndexLifecycleExplainResponse newManagedIndexResponse(String index, String policyName, boolean skip, long lifecycleDate, public static IndexLifecycleExplainResponse newManagedIndexResponse(String index, String policyName, boolean skip, long lifecycleDate,
String phase, String action, String step, String failedStep, long phaseTime, long actionTime, long stepTime, String phase, String action, String step, String failedStep, long phaseTime, long actionTime, long stepTime,
BytesReference stepInfo) { BytesReference stepInfo, PhaseExecutionInfo phaseExecutionInfo) {
return new IndexLifecycleExplainResponse(index, true, policyName, skip, lifecycleDate, phase, action, step, failedStep, phaseTime, return new IndexLifecycleExplainResponse(index, true, policyName, skip, lifecycleDate, phase, action, step, failedStep, phaseTime,
actionTime, stepTime, stepInfo); actionTime, stepTime, stepInfo, phaseExecutionInfo);
} }
public static IndexLifecycleExplainResponse newUnmanagedIndexResponse(String index) { public static IndexLifecycleExplainResponse newUnmanagedIndexResponse(String index) {
return new IndexLifecycleExplainResponse(index, false, null, false, -1L, null, null, null, null, -1L, -1L, -1L, null); return new IndexLifecycleExplainResponse(index, false, null, false, -1L, null, null, null, null, -1L, -1L, -1L, null, null);
} }
private IndexLifecycleExplainResponse(String index, boolean managedByILM, String policyName, boolean skip, long lifecycleDate, private IndexLifecycleExplainResponse(String index, boolean managedByILM, String policyName, boolean skip, long lifecycleDate,
String phase, String action, String step, String failedStep, long phaseTime, long actionTime, String phase, String action, String step, String failedStep, long phaseTime, long actionTime,
long stepTime, BytesReference stepInfo) { long stepTime, BytesReference stepInfo, PhaseExecutionInfo phaseExecutionInfo) {
if (managedByILM) { if (managedByILM) {
if (policyName == null) { if (policyName == null) {
throw new IllegalArgumentException("[" + POLICY_NAME_FIELD.getPreferredName() + "] cannot be null for managed index"); throw new IllegalArgumentException("[" + POLICY_NAME_FIELD.getPreferredName() + "] cannot be null for managed index");
} }
} else { } else {
if (policyName != null || lifecycleDate >= 0 || phase != null || action != null || step != null || failedStep != null if (policyName != null || lifecycleDate >= 0 || phase != null || action != null || step != null || failedStep != null
|| phaseTime >= 0 || actionTime >= 0 || stepTime >= 0 || stepInfo != null) { || phaseTime >= 0 || actionTime >= 0 || stepTime >= 0 || stepInfo != null || phaseExecutionInfo != null) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"Unmanaged index response must only contain fields: [" + MANAGED_BY_ILM_FIELD + ", " + INDEX_FIELD + "]"); "Unmanaged index response must only contain fields: [" + MANAGED_BY_ILM_FIELD + ", " + INDEX_FIELD + "]");
} }
@ -128,6 +133,7 @@ public class IndexLifecycleExplainResponse implements ToXContentObject, Writeabl
this.stepTime = stepTime; this.stepTime = stepTime;
this.failedStep = failedStep; this.failedStep = failedStep;
this.stepInfo = stepInfo; this.stepInfo = stepInfo;
this.phaseExecutionInfo = phaseExecutionInfo;
} }
public IndexLifecycleExplainResponse(StreamInput in) throws IOException { public IndexLifecycleExplainResponse(StreamInput in) throws IOException {
@ -145,7 +151,7 @@ public class IndexLifecycleExplainResponse implements ToXContentObject, Writeabl
actionTime = in.readZLong(); actionTime = in.readZLong();
stepTime = in.readZLong(); stepTime = in.readZLong();
stepInfo = in.readOptionalBytesReference(); stepInfo = in.readOptionalBytesReference();
phaseExecutionInfo = in.readOptionalWriteable(PhaseExecutionInfo::new);
} else { } else {
policyName = null; policyName = null;
skip = false; skip = false;
@ -158,6 +164,7 @@ public class IndexLifecycleExplainResponse implements ToXContentObject, Writeabl
actionTime = -1L; actionTime = -1L;
stepTime = -1L; stepTime = -1L;
stepInfo = null; stepInfo = null;
phaseExecutionInfo = null;
} }
} }
@ -177,6 +184,7 @@ public class IndexLifecycleExplainResponse implements ToXContentObject, Writeabl
out.writeZLong(actionTime); out.writeZLong(actionTime);
out.writeZLong(stepTime); out.writeZLong(stepTime);
out.writeOptionalBytesReference(stepInfo); out.writeOptionalBytesReference(stepInfo);
out.writeOptionalWriteable(phaseExecutionInfo);
} }
} }
@ -232,6 +240,10 @@ public class IndexLifecycleExplainResponse implements ToXContentObject, Writeabl
return stepInfo; return stepInfo;
} }
public PhaseExecutionInfo getPhaseExecutionInfo() {
return phaseExecutionInfo;
}
@Override @Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject(); builder.startObject();
@ -269,6 +281,9 @@ public class IndexLifecycleExplainResponse implements ToXContentObject, Writeabl
if (stepInfo != null && stepInfo.length() > 0) { if (stepInfo != null && stepInfo.length() > 0) {
builder.rawField(STEP_INFO_FIELD.getPreferredName(), stepInfo.streamInput(), XContentType.JSON); builder.rawField(STEP_INFO_FIELD.getPreferredName(), stepInfo.streamInput(), XContentType.JSON);
} }
if (phaseExecutionInfo != null) {
builder.field(PHASE_EXECUTION_INFO.getPreferredName(), phaseExecutionInfo);
}
} }
builder.endObject(); builder.endObject();
return builder; return builder;
@ -277,7 +292,7 @@ public class IndexLifecycleExplainResponse implements ToXContentObject, Writeabl
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(index, managedByILM, policyName, skip, lifecycleDate, phase, action, step, failedStep, phaseTime, actionTime, return Objects.hash(index, managedByILM, policyName, skip, lifecycleDate, phase, action, step, failedStep, phaseTime, actionTime,
stepTime, stepInfo); stepTime, stepInfo, phaseExecutionInfo);
} }
@Override @Override
@ -301,7 +316,8 @@ public class IndexLifecycleExplainResponse implements ToXContentObject, Writeabl
Objects.equals(phaseTime, other.phaseTime) && Objects.equals(phaseTime, other.phaseTime) &&
Objects.equals(actionTime, other.actionTime) && Objects.equals(actionTime, other.actionTime) &&
Objects.equals(stepTime, other.stepTime) && Objects.equals(stepTime, other.stepTime) &&
Objects.equals(stepInfo, other.stepInfo); Objects.equals(stepInfo, other.stepInfo) &&
Objects.equals(phaseExecutionInfo, other.phaseExecutionInfo);
} }
@Override @Override

View File

@ -0,0 +1,135 @@
/*
* 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.Nullable;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.io.stream.Writeable;
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.Objects;
/**
* This class contains information about the current phase being executed by Index
* Lifecycle Management on the specific index.
*/
public class PhaseExecutionInfo implements ToXContentObject, Writeable {
private static final ParseField POLICY_NAME_FIELD = new ParseField("policy");
private static final ParseField PHASE_DEFINITION_FIELD = new ParseField("phase_definition");
private static final ParseField VERSION_FIELD = new ParseField("version");
private static final ParseField MODIFIED_DATE_IN_MILLIS_FIELD = new ParseField("modified_date_in_millis");
private static final ConstructingObjectParser<PhaseExecutionInfo, String> PARSER = new ConstructingObjectParser<>(
"phase_execution_info", false,
(a, name) -> new PhaseExecutionInfo((String) a[0], (Phase) a[1], (long) a[2], (long) a[3]));
static {
PARSER.declareString(ConstructingObjectParser.constructorArg(), POLICY_NAME_FIELD);
PARSER.declareObject(ConstructingObjectParser.optionalConstructorArg(), Phase::parse, PHASE_DEFINITION_FIELD);
PARSER.declareLong(ConstructingObjectParser.constructorArg(), VERSION_FIELD);
PARSER.declareLong(ConstructingObjectParser.constructorArg(), MODIFIED_DATE_IN_MILLIS_FIELD);
}
public static PhaseExecutionInfo parse(XContentParser parser, String name) {
return PARSER.apply(parser, name);
}
private final String policyName;
private final Phase phase;
private final long version;
private final long modifiedDate;
/**
* This class holds information about the current phase that is being executed
*
* @param policyName the name of the policy being executed, this may not be the current policy assigned to an index
* @param phase the current phase definition executed
* @param version the version of the <code>policyName</code> being executed
* @param modifiedDate the time the executing version of the phase was modified
*/
public PhaseExecutionInfo(String policyName, @Nullable Phase phase, long version, long modifiedDate) {
this.policyName = policyName;
this.phase = phase;
this.version = version;
this.modifiedDate = modifiedDate;
}
PhaseExecutionInfo(StreamInput in) throws IOException {
this.policyName = in.readString();
this.phase = in.readOptionalWriteable(Phase::new);
this.version = in.readVLong();
this.modifiedDate = in.readVLong();
}
@Override
public void writeTo(StreamOutput out) throws IOException {
out.writeString(policyName);
out.writeOptionalWriteable(phase);
out.writeVLong(version);
out.writeVLong(modifiedDate);
}
public String getPolicyName() {
return policyName;
}
public Phase getPhase() {
return phase;
}
public long getVersion() {
return version;
}
public long getModifiedDate() {
return modifiedDate;
}
@Override
public int hashCode() {
return Objects.hash(policyName, phase, version, modifiedDate);
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
PhaseExecutionInfo other = (PhaseExecutionInfo) obj;
return Objects.equals(policyName, other.policyName) &&
Objects.equals(phase, other.phase) &&
Objects.equals(version, other.version) &&
Objects.equals(modifiedDate, other.modifiedDate);
}
@Override
public String toString() {
return Strings.toString(this, false, true);
}
@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject();
builder.field(POLICY_NAME_FIELD.getPreferredName(), policyName);
if (phase != null) {
builder.field(PHASE_DEFINITION_FIELD.getPreferredName(), phase);
}
builder.field(VERSION_FIELD.getPreferredName(), version);
builder.timeField(MODIFIED_DATE_IN_MILLIS_FIELD.getPreferredName(), "modified_date", modifiedDate);
builder.endObject();
return builder;
}
}

View File

@ -6,11 +6,18 @@
package org.elasticsearch.xpack.core.indexlifecycle; package org.elasticsearch.xpack.core.indexlifecycle;
import org.elasticsearch.cluster.ClusterModule;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.test.AbstractStreamableXContentTestCase; import org.elasticsearch.test.AbstractStreamableXContentTestCase;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
public class ExplainLifecycleResponseTests extends AbstractStreamableXContentTestCase<ExplainLifecycleResponse> { public class ExplainLifecycleResponseTests extends AbstractStreamableXContentTestCase<ExplainLifecycleResponse> {
@ -47,4 +54,16 @@ public class ExplainLifecycleResponseTests extends AbstractStreamableXContentTes
protected boolean supportsUnknownFields() { protected boolean supportsUnknownFields() {
return false; return false;
} }
protected NamedWriteableRegistry getNamedWriteableRegistry() {
return new NamedWriteableRegistry(Arrays
.asList(new NamedWriteableRegistry.Entry(LifecycleAction.class, MockAction.NAME, MockAction::new)));
}
@Override
protected NamedXContentRegistry xContentRegistry() {
List<NamedXContentRegistry.Entry> entries = new ArrayList<>(ClusterModule.getNamedXWriteables());
entries.add(new NamedXContentRegistry.Entry(LifecycleAction.class, new ParseField(MockAction.NAME), MockAction::parse));
return new NamedXContentRegistry(entries);
}
} }

View File

@ -6,16 +6,23 @@
package org.elasticsearch.xpack.core.indexlifecycle; package org.elasticsearch.xpack.core.indexlifecycle;
import org.elasticsearch.cluster.ClusterModule;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.Strings; import org.elasticsearch.common.Strings;
import org.elasticsearch.common.bytes.BytesArray; import org.elasticsearch.common.bytes.BytesArray;
import org.elasticsearch.common.bytes.BytesReference; import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
import org.elasticsearch.common.io.stream.Writeable.Reader; import org.elasticsearch.common.io.stream.Writeable.Reader;
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
import org.elasticsearch.common.xcontent.ToXContentObject; import org.elasticsearch.common.xcontent.ToXContentObject;
import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.test.AbstractSerializingTestCase; import org.elasticsearch.test.AbstractSerializingTestCase;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.function.Supplier; import java.util.function.Supplier;
@ -37,7 +44,8 @@ public class IndexExplainResponseTests extends AbstractSerializingTestCase<Index
return IndexLifecycleExplainResponse.newManagedIndexResponse(randomAlphaOfLength(10), randomAlphaOfLength(10), randomBoolean(), return IndexLifecycleExplainResponse.newManagedIndexResponse(randomAlphaOfLength(10), randomAlphaOfLength(10), randomBoolean(),
randomNonNegativeLong(), randomAlphaOfLength(10), randomAlphaOfLength(10), randomAlphaOfLength(10), randomNonNegativeLong(), randomAlphaOfLength(10), randomAlphaOfLength(10), randomAlphaOfLength(10),
randomBoolean() ? null : randomAlphaOfLength(10), randomNonNegativeLong(), randomNonNegativeLong(), randomNonNegativeLong(), randomBoolean() ? null : randomAlphaOfLength(10), randomNonNegativeLong(), randomNonNegativeLong(), randomNonNegativeLong(),
randomBoolean() ? null : new BytesArray(new RandomStepInfo(() -> randomAlphaOfLength(10)).toString())); randomBoolean() ? null : new BytesArray(new RandomStepInfo(() -> randomAlphaOfLength(10)).toString()),
randomBoolean() ? null : PhaseExecutionInfoTests.randomPhaseExecutionInfo(""));
} }
@Override @Override
@ -70,8 +78,9 @@ public class IndexExplainResponseTests extends AbstractSerializingTestCase<Index
boolean managed = instance.managedByILM(); boolean managed = instance.managedByILM();
boolean skip = instance.skip(); boolean skip = instance.skip();
BytesReference stepInfo = instance.getStepInfo(); BytesReference stepInfo = instance.getStepInfo();
PhaseExecutionInfo phaseExecutionInfo = instance.getPhaseExecutionInfo();
if (managed) { if (managed) {
switch (between(0, 12)) { switch (between(0, 13)) {
case 0: case 0:
index = index + randomAlphaOfLengthBetween(1, 5); index = index + randomAlphaOfLengthBetween(1, 5);
break; break;
@ -122,12 +131,15 @@ public class IndexExplainResponseTests extends AbstractSerializingTestCase<Index
skip = skip == false; skip = skip == false;
break; break;
case 12: case 12:
phaseExecutionInfo = randomValueOtherThan(phaseExecutionInfo, () -> PhaseExecutionInfoTests.randomPhaseExecutionInfo(""));
break;
case 13:
return IndexLifecycleExplainResponse.newUnmanagedIndexResponse(index); return IndexLifecycleExplainResponse.newUnmanagedIndexResponse(index);
default: default:
throw new AssertionError("Illegal randomisation branch"); throw new AssertionError("Illegal randomisation branch");
} }
return IndexLifecycleExplainResponse.newManagedIndexResponse(index, policy, skip, policyTime, phase, action, step, failedStep, return IndexLifecycleExplainResponse.newManagedIndexResponse(index, policy, skip, policyTime, phase, action, step, failedStep,
phaseTime, actionTime, stepTime, stepInfo); phaseTime, actionTime, stepTime, stepInfo, phaseExecutionInfo);
} else { } else {
switch (between(0, 1)) { switch (between(0, 1)) {
case 0: case 0:
@ -140,6 +152,18 @@ public class IndexExplainResponseTests extends AbstractSerializingTestCase<Index
} }
} }
protected NamedWriteableRegistry getNamedWriteableRegistry() {
return new NamedWriteableRegistry(Arrays
.asList(new NamedWriteableRegistry.Entry(LifecycleAction.class, MockAction.NAME, MockAction::new)));
}
@Override
protected NamedXContentRegistry xContentRegistry() {
List<NamedXContentRegistry.Entry> entries = new ArrayList<>(ClusterModule.getNamedXWriteables());
entries.add(new NamedXContentRegistry.Entry(LifecycleAction.class, new ParseField(MockAction.NAME), MockAction::parse));
return new NamedXContentRegistry(entries);
}
private static class RandomStepInfo implements ToXContentObject { private static class RandomStepInfo implements ToXContentObject {
private final String key; private final String key;

View File

@ -0,0 +1,88 @@
/*
* 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.cluster.ClusterModule;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
import org.elasticsearch.common.io.stream.Writeable.Reader;
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.test.AbstractSerializingTestCase;
import org.junit.Before;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class PhaseExecutionInfoTests extends AbstractSerializingTestCase<PhaseExecutionInfo> {
static PhaseExecutionInfo randomPhaseExecutionInfo(String phaseName) {
return new PhaseExecutionInfo(randomAlphaOfLength(5), PhaseTests.randomTestPhase(phaseName),
randomNonNegativeLong(), randomNonNegativeLong());
}
String phaseName;
@Before
public void setupPhaseName() {
phaseName = randomAlphaOfLength(7);
}
@Override
protected PhaseExecutionInfo createTestInstance() {
return randomPhaseExecutionInfo(phaseName);
}
@Override
protected Reader<PhaseExecutionInfo> instanceReader() {
return PhaseExecutionInfo::new;
}
@Override
protected PhaseExecutionInfo doParseInstance(XContentParser parser) throws IOException {
return PhaseExecutionInfo.parse(parser, phaseName);
}
@Override
protected PhaseExecutionInfo mutateInstance(PhaseExecutionInfo instance) throws IOException {
String policyName = instance.getPolicyName();
Phase phase = instance.getPhase();
long version = instance.getVersion();
long modifiedDate = instance.getModifiedDate();
switch (between(0, 3)) {
case 0:
policyName = policyName + randomAlphaOfLengthBetween(1, 5);
break;
case 1:
phase = randomValueOtherThan(phase, () -> PhaseTests.randomTestPhase(randomAlphaOfLength(6)));
break;
case 2:
version++;
break;
case 3:
modifiedDate++;
break;
default:
throw new AssertionError("Illegal randomisation branch");
}
return new PhaseExecutionInfo(policyName, phase, version, modifiedDate);
}
protected NamedWriteableRegistry getNamedWriteableRegistry() {
return new NamedWriteableRegistry(Arrays
.asList(new NamedWriteableRegistry.Entry(LifecycleAction.class, MockAction.NAME, MockAction::new)));
}
@Override
protected NamedXContentRegistry xContentRegistry() {
List<NamedXContentRegistry.Entry> entries = new ArrayList<>(ClusterModule.getNamedXWriteables());
entries.add(new NamedXContentRegistry.Entry(LifecycleAction.class, new ParseField(MockAction.NAME), MockAction::parse));
return new NamedXContentRegistry(entries);
}
}

View File

@ -33,6 +33,10 @@ public class PhaseTests extends AbstractSerializingTestCase<Phase> {
@Override @Override
protected Phase createTestInstance() { protected Phase createTestInstance() {
return randomTestPhase(phaseName);
}
static Phase randomTestPhase(String phaseName) {
TimeValue after = null; TimeValue after = null;
if (randomBoolean()) { if (randomBoolean()) {
after = TimeValue.parseTimeValue(randomTimeValue(0, 1000000000, "s", "m", "h", "d"), "test_after"); after = TimeValue.parseTimeValue(randomTimeValue(0, 1000000000, "s", "m", "h", "d"), "test_after");

View File

@ -28,10 +28,11 @@ import org.elasticsearch.xpack.core.indexlifecycle.ClusterStateActionStep;
import org.elasticsearch.xpack.core.indexlifecycle.ClusterStateWaitStep; import org.elasticsearch.xpack.core.indexlifecycle.ClusterStateWaitStep;
import org.elasticsearch.xpack.core.indexlifecycle.ErrorStep; import org.elasticsearch.xpack.core.indexlifecycle.ErrorStep;
import org.elasticsearch.xpack.core.indexlifecycle.IndexLifecycleMetadata; import org.elasticsearch.xpack.core.indexlifecycle.IndexLifecycleMetadata;
import org.elasticsearch.xpack.core.indexlifecycle.LifecyclePolicy; import org.elasticsearch.xpack.core.indexlifecycle.LifecyclePolicyMetadata;
import org.elasticsearch.xpack.core.indexlifecycle.LifecycleSettings; import org.elasticsearch.xpack.core.indexlifecycle.LifecycleSettings;
import org.elasticsearch.xpack.core.indexlifecycle.Phase; import org.elasticsearch.xpack.core.indexlifecycle.Phase;
import org.elasticsearch.xpack.core.indexlifecycle.PhaseCompleteStep; import org.elasticsearch.xpack.core.indexlifecycle.PhaseCompleteStep;
import org.elasticsearch.xpack.core.indexlifecycle.PhaseExecutionInfo;
import org.elasticsearch.xpack.core.indexlifecycle.RolloverAction; import org.elasticsearch.xpack.core.indexlifecycle.RolloverAction;
import org.elasticsearch.xpack.core.indexlifecycle.Step; import org.elasticsearch.xpack.core.indexlifecycle.Step;
import org.elasticsearch.xpack.core.indexlifecycle.Step.StepKey; import org.elasticsearch.xpack.core.indexlifecycle.Step.StepKey;
@ -250,8 +251,10 @@ public class IndexLifecycleRunner {
LongSupplier nowSupplier) { LongSupplier nowSupplier) {
IndexMetaData idxMeta = clusterState.getMetaData().index(index); IndexMetaData idxMeta = clusterState.getMetaData().index(index);
IndexLifecycleMetadata ilmMeta = clusterState.metaData().custom(IndexLifecycleMetadata.TYPE); IndexLifecycleMetadata ilmMeta = clusterState.metaData().custom(IndexLifecycleMetadata.TYPE);
LifecyclePolicy policy = ilmMeta.getPolicies().get(LifecycleSettings.LIFECYCLE_NAME_SETTING.get(idxMeta.getSettings())); LifecyclePolicyMetadata policyMetadata = ilmMeta.getPolicyMetadatas()
Settings.Builder indexSettings = moveIndexSettingsToNextStep(policy, idxMeta.getSettings(), currentStep, nextStep, nowSupplier); .get(LifecycleSettings.LIFECYCLE_NAME_SETTING.get(idxMeta.getSettings()));
Settings.Builder indexSettings = moveIndexSettingsToNextStep(policyMetadata, idxMeta.getSettings(), currentStep,
nextStep, nowSupplier);
ClusterState.Builder newClusterStateBuilder = newClusterStateWithIndexSettings(index, clusterState, indexSettings); ClusterState.Builder newClusterStateBuilder = newClusterStateWithIndexSettings(index, clusterState, indexSettings);
return newClusterStateBuilder.build(); return newClusterStateBuilder.build();
} }
@ -260,12 +263,13 @@ public class IndexLifecycleRunner {
LongSupplier nowSupplier) throws IOException { LongSupplier nowSupplier) throws IOException {
IndexMetaData idxMeta = clusterState.getMetaData().index(index); IndexMetaData idxMeta = clusterState.getMetaData().index(index);
IndexLifecycleMetadata ilmMeta = clusterState.metaData().custom(IndexLifecycleMetadata.TYPE); IndexLifecycleMetadata ilmMeta = clusterState.metaData().custom(IndexLifecycleMetadata.TYPE);
LifecyclePolicy policy = ilmMeta.getPolicies().get(LifecycleSettings.LIFECYCLE_NAME_SETTING.get(idxMeta.getSettings())); LifecyclePolicyMetadata policyMetadata = ilmMeta.getPolicyMetadatas()
.get(LifecycleSettings.LIFECYCLE_NAME_SETTING.get(idxMeta.getSettings()));
XContentBuilder causeXContentBuilder = JsonXContent.contentBuilder(); XContentBuilder causeXContentBuilder = JsonXContent.contentBuilder();
causeXContentBuilder.startObject(); causeXContentBuilder.startObject();
ElasticsearchException.generateThrowableXContent(causeXContentBuilder, ToXContent.EMPTY_PARAMS, cause); ElasticsearchException.generateThrowableXContent(causeXContentBuilder, ToXContent.EMPTY_PARAMS, cause);
causeXContentBuilder.endObject(); causeXContentBuilder.endObject();
Settings.Builder indexSettings = moveIndexSettingsToNextStep(policy, idxMeta.getSettings(), currentStep, Settings.Builder indexSettings = moveIndexSettingsToNextStep(policyMetadata, idxMeta.getSettings(), currentStep,
new StepKey(currentStep.getPhase(), currentStep.getAction(), ErrorStep.NAME), nowSupplier) new StepKey(currentStep.getPhase(), currentStep.getAction(), ErrorStep.NAME), nowSupplier)
.put(LifecycleSettings.LIFECYCLE_FAILED_STEP, currentStep.getName()) .put(LifecycleSettings.LIFECYCLE_FAILED_STEP, currentStep.getName())
.put(LifecycleSettings.LIFECYCLE_STEP_INFO, BytesReference.bytes(causeXContentBuilder).utf8ToString()); .put(LifecycleSettings.LIFECYCLE_STEP_INFO, BytesReference.bytes(causeXContentBuilder).utf8ToString());
@ -294,7 +298,7 @@ public class IndexLifecycleRunner {
return newState; return newState;
} }
private static Settings.Builder moveIndexSettingsToNextStep(LifecyclePolicy policy, Settings existingSettings, private static Settings.Builder moveIndexSettingsToNextStep(LifecyclePolicyMetadata policyMetadata, Settings existingSettings,
StepKey currentStep, StepKey nextStep, LongSupplier nowSupplier) { StepKey currentStep, StepKey nextStep, LongSupplier nowSupplier) {
long nowAsMillis = nowSupplier.getAsLong(); long nowAsMillis = nowSupplier.getAsLong();
Settings.Builder newSettings = Settings.builder().put(existingSettings).put(LifecycleSettings.LIFECYCLE_PHASE, nextStep.getPhase()) Settings.Builder newSettings = Settings.builder().put(existingSettings).put(LifecycleSettings.LIFECYCLE_PHASE, nextStep.getPhase())
@ -305,16 +309,15 @@ public class IndexLifecycleRunner {
.put(LifecycleSettings.LIFECYCLE_STEP_INFO, (String) null); .put(LifecycleSettings.LIFECYCLE_STEP_INFO, (String) null);
if (currentStep.getPhase().equals(nextStep.getPhase()) == false) { if (currentStep.getPhase().equals(nextStep.getPhase()) == false) {
final String newPhaseDefinition; final String newPhaseDefinition;
final Phase nextPhase;
if ("new".equals(nextStep.getPhase()) || TerminalPolicyStep.KEY.equals(nextStep)) { if ("new".equals(nextStep.getPhase()) || TerminalPolicyStep.KEY.equals(nextStep)) {
newPhaseDefinition = nextStep.getPhase(); nextPhase = null;
} else { } else {
Phase nextPhase = policy.getPhases().get(nextStep.getPhase()); nextPhase = policyMetadata.getPolicy().getPhases().get(nextStep.getPhase());
if (nextPhase == null) {
newPhaseDefinition = null;
} else {
newPhaseDefinition = Strings.toString(nextPhase, false, false);
}
} }
PhaseExecutionInfo phaseExecutionInfo = new PhaseExecutionInfo(policyMetadata.getName(), nextPhase,
policyMetadata.getVersion(), policyMetadata.getModifiedDate());
newPhaseDefinition = Strings.toString(phaseExecutionInfo, false, false);
newSettings.put(LifecycleSettings.LIFECYCLE_PHASE_DEFINITION, newPhaseDefinition); newSettings.put(LifecycleSettings.LIFECYCLE_PHASE_DEFINITION, newPhaseDefinition);
newSettings.put(LifecycleSettings.LIFECYCLE_PHASE_TIME, nowAsMillis); newSettings.put(LifecycleSettings.LIFECYCLE_PHASE_TIME, nowAsMillis);
} }
@ -378,7 +381,7 @@ public class IndexLifecycleRunner {
} }
public static ClusterState setPolicyForIndexes(final String newPolicyName, final Index[] indices, ClusterState currentState, public static ClusterState setPolicyForIndexes(final String newPolicyName, final Index[] indices, ClusterState currentState,
LifecyclePolicy newPolicy, List<String> failedIndexes, LongSupplier nowSupplier) { LifecyclePolicyMetadata newPolicyMetadata, List<String> failedIndexes, LongSupplier nowSupplier) {
MetaData.Builder newMetadata = MetaData.builder(currentState.getMetaData()); MetaData.Builder newMetadata = MetaData.builder(currentState.getMetaData());
boolean clusterStateChanged = false; boolean clusterStateChanged = false;
for (Index index : indices) { for (Index index : indices) {
@ -388,7 +391,7 @@ public class IndexLifecycleRunner {
failedIndexes.add(index.getName()); failedIndexes.add(index.getName());
} else { } else {
IndexMetaData.Builder newIdxMetadata = IndexLifecycleRunner.setPolicyForIndex(newPolicyName, IndexMetaData.Builder newIdxMetadata = IndexLifecycleRunner.setPolicyForIndex(newPolicyName,
newPolicy, indexMetadata, nowSupplier); newPolicyMetadata, indexMetadata, nowSupplier);
if (newIdxMetadata != null) { if (newIdxMetadata != null) {
newMetadata.put(newIdxMetadata); newMetadata.put(newIdxMetadata);
clusterStateChanged = true; clusterStateChanged = true;
@ -404,7 +407,7 @@ public class IndexLifecycleRunner {
} }
} }
private static IndexMetaData.Builder setPolicyForIndex(final String newPolicyName, LifecyclePolicy newPolicy, private static IndexMetaData.Builder setPolicyForIndex(final String newPolicyName, LifecyclePolicyMetadata newPolicyMetadata,
IndexMetaData indexMetadata, LongSupplier nowSupplier) { IndexMetaData indexMetadata, LongSupplier nowSupplier) {
Settings idxSettings = indexMetadata.getSettings(); Settings idxSettings = indexMetadata.getSettings();
StepKey currentStepKey = IndexLifecycleRunner.getCurrentStepKey(idxSettings); StepKey currentStepKey = IndexLifecycleRunner.getCurrentStepKey(idxSettings);
@ -413,9 +416,9 @@ public class IndexLifecycleRunner {
if (currentStepKey != null) { if (currentStepKey != null) {
// Check if current step exists in new policy and if not move to // Check if current step exists in new policy and if not move to
// next available step // next available step
StepKey nextValidStepKey = newPolicy.getNextValidStep(currentStepKey); StepKey nextValidStepKey = newPolicyMetadata.getPolicy().getNextValidStep(currentStepKey);
if (nextValidStepKey.equals(currentStepKey) == false) { if (nextValidStepKey.equals(currentStepKey) == false) {
newSettings = moveIndexSettingsToNextStep(newPolicy, idxSettings, currentStepKey, nextValidStepKey, nowSupplier); newSettings = moveIndexSettingsToNextStep(newPolicyMetadata, idxSettings, currentStepKey, nextValidStepKey, nowSupplier);
} }
} }
newSettings.put(LifecycleSettings.LIFECYCLE_NAME_SETTING.getKey(), newPolicyName); newSettings.put(LifecycleSettings.LIFECYCLE_NAME_SETTING.getKey(), newPolicyName);

View File

@ -30,6 +30,7 @@ import org.elasticsearch.xpack.core.indexlifecycle.LifecyclePolicy;
import org.elasticsearch.xpack.core.indexlifecycle.LifecyclePolicyMetadata; import org.elasticsearch.xpack.core.indexlifecycle.LifecyclePolicyMetadata;
import org.elasticsearch.xpack.core.indexlifecycle.LifecycleSettings; import org.elasticsearch.xpack.core.indexlifecycle.LifecycleSettings;
import org.elasticsearch.xpack.core.indexlifecycle.Phase; import org.elasticsearch.xpack.core.indexlifecycle.Phase;
import org.elasticsearch.xpack.core.indexlifecycle.PhaseExecutionInfo;
import org.elasticsearch.xpack.core.indexlifecycle.Step; import org.elasticsearch.xpack.core.indexlifecycle.Step;
import org.elasticsearch.xpack.core.indexlifecycle.TerminalPolicyStep; import org.elasticsearch.xpack.core.indexlifecycle.TerminalPolicyStep;
@ -170,7 +171,7 @@ public class PolicyStepsRegistry {
// parse existing phase steps from the phase definition in the index settings // parse existing phase steps from the phase definition in the index settings
String phaseDef = imd.value.getSettings().get(LifecycleSettings.LIFECYCLE_PHASE_DEFINITION, String phaseDef = imd.value.getSettings().get(LifecycleSettings.LIFECYCLE_PHASE_DEFINITION,
InitializePolicyContextStep.INITIALIZATION_PHASE); InitializePolicyContextStep.INITIALIZATION_PHASE);
final Phase phase; final PhaseExecutionInfo phaseExecutionInfo;
LifecyclePolicy currentPolicy = lifecyclePolicyMap.get(policy).getPolicy(); LifecyclePolicy currentPolicy = lifecyclePolicyMap.get(policy).getPolicy();
final LifecyclePolicy policyToExecute; final LifecyclePolicy policyToExecute;
if (InitializePolicyContextStep.INITIALIZATION_PHASE.equals(phaseDef) if (InitializePolicyContextStep.INITIALIZATION_PHASE.equals(phaseDef)
@ -181,15 +182,15 @@ public class PolicyStepsRegistry {
// if the current phase definition describes an internal step/phase, do not parse // if the current phase definition describes an internal step/phase, do not parse
try (XContentParser parser = JsonXContent.jsonXContent.createParser(xContentRegistry, try (XContentParser parser = JsonXContent.jsonXContent.createParser(xContentRegistry,
DeprecationHandler.THROW_UNSUPPORTED_OPERATION, phaseDef)) { DeprecationHandler.THROW_UNSUPPORTED_OPERATION, phaseDef)) {
phase = Phase.parse(parser, currentPhase); phaseExecutionInfo = PhaseExecutionInfo.parse(parser, currentPhase);
} catch (IOException e) { } catch (IOException e) {
logger.error("failed to configure phase [" + currentPhase + "] for index [" + index.getName() + "]", e); logger.error("failed to configure phase [" + currentPhase + "] for index [" + index.getName() + "]", e);
indexPhaseSteps.remove(index); indexPhaseSteps.remove(index);
continue; continue;
} }
Map<String, Phase> phaseMap = new HashMap<>(currentPolicy.getPhases()); Map<String, Phase> phaseMap = new HashMap<>(currentPolicy.getPhases());
if (phase != null) { if (phaseExecutionInfo.getPhase() != null) {
phaseMap.put(currentPhase, phase); phaseMap.put(currentPhase, phaseExecutionInfo.getPhase());
} }
policyToExecute = new LifecyclePolicy(currentPolicy.getType(), currentPolicy.getName(), phaseMap); policyToExecute = new LifecyclePolicy(currentPolicy.getType(), currentPolicy.getName(), phaseMap);
} }

View File

@ -6,6 +6,7 @@
package org.elasticsearch.xpack.indexlifecycle.action; package org.elasticsearch.xpack.indexlifecycle.action;
import org.elasticsearch.ElasticsearchParseException;
import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.support.ActionFilters; import org.elasticsearch.action.support.ActionFilters;
import org.elasticsearch.action.support.master.info.TransportClusterInfoAction; import org.elasticsearch.action.support.master.info.TransportClusterInfoAction;
@ -19,25 +20,36 @@ import org.elasticsearch.common.Strings;
import org.elasticsearch.common.bytes.BytesArray; import org.elasticsearch.common.bytes.BytesArray;
import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.DeprecationHandler;
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.json.JsonXContent;
import org.elasticsearch.xpack.core.indexlifecycle.ExplainLifecycleRequest; import org.elasticsearch.xpack.core.indexlifecycle.ExplainLifecycleRequest;
import org.elasticsearch.xpack.core.indexlifecycle.ExplainLifecycleResponse; import org.elasticsearch.xpack.core.indexlifecycle.ExplainLifecycleResponse;
import org.elasticsearch.xpack.core.indexlifecycle.IndexLifecycleExplainResponse; import org.elasticsearch.xpack.core.indexlifecycle.IndexLifecycleExplainResponse;
import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportService; import org.elasticsearch.transport.TransportService;
import org.elasticsearch.xpack.core.indexlifecycle.LifecycleSettings; import org.elasticsearch.xpack.core.indexlifecycle.LifecycleSettings;
import org.elasticsearch.xpack.core.indexlifecycle.PhaseExecutionInfo;
import org.elasticsearch.xpack.core.indexlifecycle.action.ExplainLifecycleAction; import org.elasticsearch.xpack.core.indexlifecycle.action.ExplainLifecycleAction;
import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
public class TransportExplainLifecycleAction public class TransportExplainLifecycleAction
extends TransportClusterInfoAction<ExplainLifecycleRequest, ExplainLifecycleResponse> { extends TransportClusterInfoAction<ExplainLifecycleRequest, ExplainLifecycleResponse> {
private final NamedXContentRegistry xContentRegistry;
@Inject @Inject
public TransportExplainLifecycleAction(Settings settings, TransportService transportService, ClusterService clusterService, public TransportExplainLifecycleAction(Settings settings, TransportService transportService, ClusterService clusterService,
ThreadPool threadPool, ActionFilters actionFilters, IndexNameExpressionResolver indexNameExpressionResolver) { ThreadPool threadPool, ActionFilters actionFilters,
IndexNameExpressionResolver indexNameExpressionResolver,
NamedXContentRegistry xContentRegistry) {
super(settings, ExplainLifecycleAction.NAME, transportService, clusterService, threadPool, actionFilters, super(settings, ExplainLifecycleAction.NAME, transportService, clusterService, threadPool, actionFilters,
ExplainLifecycleRequest::new, indexNameExpressionResolver); ExplainLifecycleRequest::new, indexNameExpressionResolver);
this.xContentRegistry = xContentRegistry;
} }
@Override @Override
@ -65,6 +77,20 @@ public class TransportExplainLifecycleAction
IndexMetaData idxMetadata = state.metaData().index(index); IndexMetaData idxMetadata = state.metaData().index(index);
Settings idxSettings = idxMetadata.getSettings(); Settings idxSettings = idxMetadata.getSettings();
String policyName = LifecycleSettings.LIFECYCLE_NAME_SETTING.get(idxSettings); String policyName = LifecycleSettings.LIFECYCLE_NAME_SETTING.get(idxSettings);
String currentPhase = LifecycleSettings.LIFECYCLE_PHASE_SETTING.get(idxSettings);
// parse existing phase steps from the phase definition in the index settings
String phaseDef = idxSettings.get(LifecycleSettings.LIFECYCLE_PHASE_DEFINITION);
PhaseExecutionInfo phaseExecutionInfo = null;
if (Strings.isNullOrEmpty(phaseDef) == false) {
try (XContentParser parser = JsonXContent.jsonXContent.createParser(xContentRegistry,
DeprecationHandler.THROW_UNSUPPORTED_OPERATION, phaseDef)) {
phaseExecutionInfo = PhaseExecutionInfo.parse(parser, currentPhase);
} catch (IOException e) {
listener.onFailure(new ElasticsearchParseException(
"failed to parse [" + LifecycleSettings.LIFECYCLE_PHASE_DEFINITION + "] for index [" + index + "]", e));
return;
}
}
final IndexLifecycleExplainResponse indexResponse; final IndexLifecycleExplainResponse indexResponse;
if (Strings.hasLength(policyName)) { if (Strings.hasLength(policyName)) {
indexResponse = IndexLifecycleExplainResponse.newManagedIndexResponse(index, policyName, indexResponse = IndexLifecycleExplainResponse.newManagedIndexResponse(index, policyName,
@ -77,7 +103,8 @@ public class TransportExplainLifecycleAction
LifecycleSettings.LIFECYCLE_PHASE_TIME_SETTING.get(idxSettings), LifecycleSettings.LIFECYCLE_PHASE_TIME_SETTING.get(idxSettings),
LifecycleSettings.LIFECYCLE_ACTION_TIME_SETTING.get(idxSettings), LifecycleSettings.LIFECYCLE_ACTION_TIME_SETTING.get(idxSettings),
LifecycleSettings.LIFECYCLE_STEP_TIME_SETTING.get(idxSettings), LifecycleSettings.LIFECYCLE_STEP_TIME_SETTING.get(idxSettings),
new BytesArray(LifecycleSettings.LIFECYCLE_STEP_INFO_SETTING.get(idxSettings))); new BytesArray(LifecycleSettings.LIFECYCLE_STEP_INFO_SETTING.get(idxSettings)),
phaseExecutionInfo);
} else { } else {
indexResponse = IndexLifecycleExplainResponse.newUnmanagedIndexResponse(index); indexResponse = IndexLifecycleExplainResponse.newUnmanagedIndexResponse(index);
} }

View File

@ -19,12 +19,12 @@ import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.Index; 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.SetIndexLifecyclePolicyRequest;
import org.elasticsearch.xpack.core.indexlifecycle.SetIndexLifecyclePolicyResponse; import org.elasticsearch.xpack.core.indexlifecycle.SetIndexLifecyclePolicyResponse;
import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportService; import org.elasticsearch.transport.TransportService;
import org.elasticsearch.xpack.core.indexlifecycle.IndexLifecycleMetadata; import org.elasticsearch.xpack.core.indexlifecycle.IndexLifecycleMetadata;
import org.elasticsearch.xpack.core.indexlifecycle.LifecyclePolicy;
import org.elasticsearch.xpack.core.indexlifecycle.action.SetIndexLifecyclePolicyAction; import org.elasticsearch.xpack.core.indexlifecycle.action.SetIndexLifecyclePolicyAction;
import org.elasticsearch.xpack.indexlifecycle.IndexLifecycleRunner; import org.elasticsearch.xpack.indexlifecycle.IndexLifecycleRunner;
@ -76,14 +76,14 @@ public class TransportSetIndexLifecyclePolicyAction
throw new ResourceNotFoundException("Policy does not exist [{}]", newPolicyName); throw new ResourceNotFoundException("Policy does not exist [{}]", newPolicyName);
} }
LifecyclePolicy newPolicy = ilmMetadata.getPolicies().get(newPolicyName); LifecyclePolicyMetadata newPolicyMetadata = ilmMetadata.getPolicyMetadatas().get(newPolicyName);
if (newPolicy == null) { if (newPolicyMetadata == null) {
throw new ResourceNotFoundException("Policy does not exist [{}]", newPolicyName); throw new ResourceNotFoundException("Policy does not exist [{}]", newPolicyName);
} }
return IndexLifecycleRunner.setPolicyForIndexes(newPolicyName, indices, currentState, newPolicy, failedIndexes, return IndexLifecycleRunner.setPolicyForIndexes(newPolicyName, indices, currentState, newPolicyMetadata,
() -> System.currentTimeMillis()); failedIndexes, System::currentTimeMillis);
} }
@Override @Override

View File

@ -28,14 +28,19 @@ import org.elasticsearch.transport.TransportService;
import org.elasticsearch.xpack.core.LocalStateCompositeXPackPlugin; import org.elasticsearch.xpack.core.LocalStateCompositeXPackPlugin;
import org.elasticsearch.xpack.core.XPackSettings; import org.elasticsearch.xpack.core.XPackSettings;
import org.elasticsearch.xpack.core.indexlifecycle.ClusterStateWaitStep; import org.elasticsearch.xpack.core.indexlifecycle.ClusterStateWaitStep;
import org.elasticsearch.xpack.core.indexlifecycle.ExplainLifecycleRequest;
import org.elasticsearch.xpack.core.indexlifecycle.ExplainLifecycleResponse;
import org.elasticsearch.xpack.core.indexlifecycle.IndexLifecycleExplainResponse;
import org.elasticsearch.xpack.core.indexlifecycle.LifecycleAction; import org.elasticsearch.xpack.core.indexlifecycle.LifecycleAction;
import org.elasticsearch.xpack.core.indexlifecycle.LifecyclePolicy; import org.elasticsearch.xpack.core.indexlifecycle.LifecyclePolicy;
import org.elasticsearch.xpack.core.indexlifecycle.LifecycleSettings; import org.elasticsearch.xpack.core.indexlifecycle.LifecycleSettings;
import org.elasticsearch.xpack.core.indexlifecycle.LifecycleType; import org.elasticsearch.xpack.core.indexlifecycle.LifecycleType;
import org.elasticsearch.xpack.core.indexlifecycle.MockAction; import org.elasticsearch.xpack.core.indexlifecycle.MockAction;
import org.elasticsearch.xpack.core.indexlifecycle.Phase; import org.elasticsearch.xpack.core.indexlifecycle.Phase;
import org.elasticsearch.xpack.core.indexlifecycle.PhaseExecutionInfo;
import org.elasticsearch.xpack.core.indexlifecycle.Step; import org.elasticsearch.xpack.core.indexlifecycle.Step;
import org.elasticsearch.xpack.core.indexlifecycle.TerminalPolicyStep; import org.elasticsearch.xpack.core.indexlifecycle.TerminalPolicyStep;
import org.elasticsearch.xpack.core.indexlifecycle.action.ExplainLifecycleAction;
import org.elasticsearch.xpack.core.indexlifecycle.action.GetLifecycleAction; import org.elasticsearch.xpack.core.indexlifecycle.action.GetLifecycleAction;
import org.elasticsearch.xpack.core.indexlifecycle.action.PutLifecycleAction; import org.elasticsearch.xpack.core.indexlifecycle.action.PutLifecycleAction;
import org.junit.Before; import org.junit.Before;
@ -69,6 +74,7 @@ import static org.hamcrest.core.IsNull.nullValue;
public class IndexLifecycleInitialisationIT extends ESIntegTestCase { public class IndexLifecycleInitialisationIT extends ESIntegTestCase {
private Settings settings; private Settings settings;
private LifecyclePolicy lifecyclePolicy; private LifecyclePolicy lifecyclePolicy;
private Phase mockPhase;
private static final ObservableAction OBSERVABLE_ACTION; private static final ObservableAction OBSERVABLE_ACTION;
static { static {
List<Step> steps = new ArrayList<>(); List<Step> steps = new ArrayList<>();
@ -127,7 +133,8 @@ public class IndexLifecycleInitialisationIT extends ESIntegTestCase {
Step.StepKey key = new Step.StepKey("mock", ObservableAction.NAME, ObservableClusterStateWaitStep.NAME); Step.StepKey key = new Step.StepKey("mock", ObservableAction.NAME, ObservableClusterStateWaitStep.NAME);
steps.add(new ObservableClusterStateWaitStep(key, TerminalPolicyStep.KEY)); steps.add(new ObservableClusterStateWaitStep(key, TerminalPolicyStep.KEY));
Map<String, LifecycleAction> actions = Collections.singletonMap(ObservableAction.NAME, OBSERVABLE_ACTION); Map<String, LifecycleAction> actions = Collections.singletonMap(ObservableAction.NAME, OBSERVABLE_ACTION);
Map<String, Phase> phases = Collections.singletonMap("mock", new Phase("mock", TimeValue.timeValueSeconds(0), actions)); mockPhase = new Phase("mock", TimeValue.timeValueSeconds(0), actions);
Map<String, Phase> phases = Collections.singletonMap("mock", mockPhase);
lifecyclePolicy = newLockableLifecyclePolicy("test", phases); lifecyclePolicy = newLockableLifecyclePolicy("test", phases);
} }
@ -175,6 +182,58 @@ public class IndexLifecycleInitialisationIT extends ESIntegTestCase {
}); });
} }
public void testExplainExecution() throws Exception {
// start node
logger.info("Starting server1");
final String server_1 = internalCluster().startNode();
logger.info("Creating lifecycle [test_lifecycle]");
PutLifecycleAction.Request putLifecycleRequest = new PutLifecycleAction.Request(lifecyclePolicy);
PutLifecycleAction.Response putLifecycleResponse = client().execute(PutLifecycleAction.INSTANCE, putLifecycleRequest).get();
assertAcked(putLifecycleResponse);
GetLifecycleAction.Response getLifecycleResponse = client().execute(GetLifecycleAction.INSTANCE,
new GetLifecycleAction.Request()).get();
assertThat(getLifecycleResponse.getPolicies().size(), equalTo(1));
GetLifecycleAction.LifecyclePolicyResponseItem responseItem = getLifecycleResponse.getPolicies().get(0);
assertThat(responseItem.getLifecyclePolicy(), equalTo(lifecyclePolicy));
assertThat(responseItem.getVersion(), equalTo(1L));
long actualModifiedDate = Instant.parse(responseItem.getModifiedDate()).toEpochMilli();
logger.info("Creating index [test]");
CreateIndexResponse createIndexResponse = client().admin().indices().create(createIndexRequest("test").settings(settings))
.actionGet();
assertAcked(createIndexResponse);
{
PhaseExecutionInfo expectedExecutionInfo = new PhaseExecutionInfo(lifecyclePolicy.getName(), mockPhase, 1L, actualModifiedDate);
assertBusy(() -> {
ExplainLifecycleRequest explainRequest = new ExplainLifecycleRequest();
ExplainLifecycleResponse explainResponse = client().execute(ExplainLifecycleAction.INSTANCE, explainRequest).get();
assertThat(explainResponse.getIndexResponses().size(), equalTo(1));
IndexLifecycleExplainResponse indexResponse = explainResponse.getIndexResponses().get("test");
assertThat(indexResponse.getStep(), equalTo("observable_cluster_state_action"));
assertThat(indexResponse.getPhaseExecutionInfo(), equalTo(expectedExecutionInfo));
});
}
// complete the step
client().admin().indices().prepareUpdateSettings("test")
.setSettings(Collections.singletonMap("index.lifecycle.test.complete", true)).get();
{
PhaseExecutionInfo expectedExecutionInfo = new PhaseExecutionInfo(lifecyclePolicy.getName(), null, 1L, actualModifiedDate);
assertBusy(() -> {
ExplainLifecycleRequest explainRequest = new ExplainLifecycleRequest();
ExplainLifecycleResponse explainResponse = client().execute(ExplainLifecycleAction.INSTANCE, explainRequest).get();
assertThat(explainResponse.getIndexResponses().size(), equalTo(1));
IndexLifecycleExplainResponse indexResponse = explainResponse.getIndexResponses().get("test");
assertThat(indexResponse.getPhase(), equalTo(TerminalPolicyStep.COMPLETED_PHASE));
assertThat(indexResponse.getStep(), equalTo(TerminalPolicyStep.KEY.getName()));
assertThat(indexResponse.getPhaseExecutionInfo(), equalTo(expectedExecutionInfo));
});
}
}
public void testMasterDedicatedDataDedicated() throws Exception { public void testMasterDedicatedDataDedicated() throws Exception {
settings = Settings.builder().put(settings).put("index.lifecycle.test.complete", true).build(); settings = Settings.builder().put(settings).put("index.lifecycle.test.complete", true).build();
// start master node // start master node

View File

@ -896,14 +896,15 @@ public class IndexLifecycleRunnerTests extends ESTestCase {
List<LifecyclePolicyMetadata> policyMetadatas = new ArrayList<>(); List<LifecyclePolicyMetadata> policyMetadatas = new ArrayList<>();
policyMetadatas.add(new LifecyclePolicyMetadata(oldPolicy, Collections.emptyMap(), policyMetadatas.add(new LifecyclePolicyMetadata(oldPolicy, Collections.emptyMap(),
randomNonNegativeLong(), randomNonNegativeLong())); randomNonNegativeLong(), randomNonNegativeLong()));
policyMetadatas.add(new LifecyclePolicyMetadata(newPolicy, Collections.emptyMap(), LifecyclePolicyMetadata newPolicyMetadata = new LifecyclePolicyMetadata(newPolicy, Collections.emptyMap(),
randomNonNegativeLong(), randomNonNegativeLong())); randomNonNegativeLong(), randomNonNegativeLong());
policyMetadatas.add(newPolicyMetadata);
ClusterState clusterState = buildClusterState(indexName, indexSettingsBuilder, policyMetadatas); ClusterState clusterState = buildClusterState(indexName, indexSettingsBuilder, policyMetadatas);
Index index = clusterState.metaData().index(indexName).getIndex(); Index index = clusterState.metaData().index(indexName).getIndex();
Index[] indices = new Index[] { index }; Index[] indices = new Index[] { index };
List<String> failedIndexes = new ArrayList<>(); List<String> failedIndexes = new ArrayList<>();
ClusterState newClusterState = IndexLifecycleRunner.setPolicyForIndexes(newPolicyName, indices, clusterState, newPolicy, ClusterState newClusterState = IndexLifecycleRunner.setPolicyForIndexes(newPolicyName, indices, clusterState, newPolicyMetadata,
failedIndexes, () -> now); failedIndexes, () -> now);
assertTrue(failedIndexes.isEmpty()); assertTrue(failedIndexes.isEmpty());
@ -915,14 +916,16 @@ public class IndexLifecycleRunnerTests extends ESTestCase {
String indexName = randomAlphaOfLength(10); String indexName = randomAlphaOfLength(10);
String newPolicyName = "new_policy"; String newPolicyName = "new_policy";
LifecyclePolicy newPolicy = newTestLifecyclePolicy(newPolicyName, Collections.emptyMap()); LifecyclePolicy newPolicy = newTestLifecyclePolicy(newPolicyName, Collections.emptyMap());
LifecyclePolicyMetadata newPolicyMetadata = new LifecyclePolicyMetadata(newPolicy, Collections.emptyMap(),
randomNonNegativeLong(), randomNonNegativeLong());
StepKey currentStep = new StepKey("", "", ""); StepKey currentStep = new StepKey("", "", "");
Settings.Builder indexSettingsBuilder = Settings.builder(); Settings.Builder indexSettingsBuilder = Settings.builder();
ClusterState clusterState = buildClusterState(indexName, indexSettingsBuilder, Collections.emptyList()); ClusterState clusterState = buildClusterState(indexName, indexSettingsBuilder, Collections.singletonList(newPolicyMetadata));
Index index = clusterState.metaData().index(indexName).getIndex(); Index index = clusterState.metaData().index(indexName).getIndex();
Index[] indices = new Index[] { index }; Index[] indices = new Index[] { index };
List<String> failedIndexes = new ArrayList<>(); List<String> failedIndexes = new ArrayList<>();
ClusterState newClusterState = IndexLifecycleRunner.setPolicyForIndexes(newPolicyName, indices, clusterState, newPolicy, ClusterState newClusterState = IndexLifecycleRunner.setPolicyForIndexes(newPolicyName, indices, clusterState, newPolicyMetadata,
failedIndexes, () -> now); failedIndexes, () -> now);
assertTrue(failedIndexes.isEmpty()); assertTrue(failedIndexes.isEmpty());
@ -936,6 +939,8 @@ public class IndexLifecycleRunnerTests extends ESTestCase {
String newPolicyName = "new_policy"; String newPolicyName = "new_policy";
LifecyclePolicy oldPolicy = newTestLifecyclePolicy(oldPolicyName, Collections.emptyMap()); LifecyclePolicy oldPolicy = newTestLifecyclePolicy(oldPolicyName, Collections.emptyMap());
LifecyclePolicy newPolicy = newTestLifecyclePolicy(newPolicyName, Collections.emptyMap()); LifecyclePolicy newPolicy = newTestLifecyclePolicy(newPolicyName, Collections.emptyMap());
LifecyclePolicyMetadata newPolicyMetadata = new LifecyclePolicyMetadata(newPolicy, Collections.emptyMap(),
randomNonNegativeLong(), randomNonNegativeLong());
StepKey currentStep = AbstractStepTestCase.randomStepKey(); StepKey currentStep = AbstractStepTestCase.randomStepKey();
Settings.Builder indexSettingsBuilder = Settings.builder().put(LifecycleSettings.LIFECYCLE_NAME, oldPolicyName) Settings.Builder indexSettingsBuilder = Settings.builder().put(LifecycleSettings.LIFECYCLE_NAME, oldPolicyName)
.put(LifecycleSettings.LIFECYCLE_PHASE, currentStep.getPhase()) .put(LifecycleSettings.LIFECYCLE_PHASE, currentStep.getPhase())
@ -949,7 +954,7 @@ public class IndexLifecycleRunnerTests extends ESTestCase {
Index[] indices = new Index[] { index }; Index[] indices = new Index[] { index };
List<String> failedIndexes = new ArrayList<>(); List<String> failedIndexes = new ArrayList<>();
ClusterState newClusterState = IndexLifecycleRunner.setPolicyForIndexes(newPolicyName, indices, clusterState, newPolicy, ClusterState newClusterState = IndexLifecycleRunner.setPolicyForIndexes(newPolicyName, indices, clusterState, newPolicyMetadata,
failedIndexes, () -> now); failedIndexes, () -> now);
assertEquals(1, failedIndexes.size()); assertEquals(1, failedIndexes.size());

View File

@ -114,6 +114,7 @@ teardown:
- match: { indices.my_index.step: "complete" } - match: { indices.my_index.step: "complete" }
- is_false: indices.my_index.failed_step - is_false: indices.my_index.failed_step
- is_false: indices.my_index.step_info - is_false: indices.my_index.step_info
- is_false: indices.my_index.phase_execution
- is_false: indices.my_index2 - is_false: indices.my_index2
- is_false: indices.another_index - is_false: indices.another_index
@ -135,6 +136,7 @@ teardown:
- match: { indices.my_index.step: "complete" } - match: { indices.my_index.step: "complete" }
- is_false: indices.my_index.failed_step - is_false: indices.my_index.failed_step
- is_false: indices.my_index.step_info - is_false: indices.my_index.step_info
- is_false: indices.my_index.phase_execution
- is_true: indices.my_index2.managed - is_true: indices.my_index2.managed
- match: { indices.my_index2.index: "my_index2" } - match: { indices.my_index2.index: "my_index2" }
@ -144,6 +146,7 @@ teardown:
- match: { indices.my_index2.step: "complete" } - match: { indices.my_index2.step: "complete" }
- is_false: indices.my_index2.failed_step - is_false: indices.my_index2.failed_step
- is_false: indices.my_index2.step_info - is_false: indices.my_index2.step_info
- is_false: indices.my_index2.phase_execution
- is_false: indices.another_index - is_false: indices.another_index
- is_false: indices.unmanaged_index - is_false: indices.unmanaged_index
@ -165,6 +168,7 @@ teardown:
- match: { indices.my_index.step: "complete" } - match: { indices.my_index.step: "complete" }
- is_false: indices.my_index.failed_step - is_false: indices.my_index.failed_step
- is_false: indices.my_index.step_info - is_false: indices.my_index.step_info
- is_false: indices.my_index.phase_execution
- is_true: indices.my_index2.managed - is_true: indices.my_index2.managed
- match: { indices.my_index2.index: "my_index2" } - match: { indices.my_index2.index: "my_index2" }
@ -174,6 +178,7 @@ teardown:
- match: { indices.my_index2.step: "complete" } - match: { indices.my_index2.step: "complete" }
- is_false: indices.my_index2.failed_step - is_false: indices.my_index2.failed_step
- is_false: indices.my_index2.step_info - is_false: indices.my_index2.step_info
- is_false: indices.my_index2.phase_execution
- is_true: indices.another_index.managed - is_true: indices.another_index.managed
- match: { indices.another_index.index: "another_index" } - match: { indices.another_index.index: "another_index" }
@ -183,6 +188,7 @@ teardown:
- match: { indices.another_index.step: "complete" } - match: { indices.another_index.step: "complete" }
- is_false: indices.another_index.failed_step - is_false: indices.another_index.failed_step
- is_false: indices.another_index.step_info - is_false: indices.another_index.step_info
- is_false: indices.another_index.phase_execution
- match: { indices.unmanaged_index.index: "unmanaged_index" } - match: { indices.unmanaged_index.index: "unmanaged_index" }
- is_false: indices.unmanaged_index.managed - is_false: indices.unmanaged_index.managed
@ -207,6 +213,7 @@ teardown:
- is_false: indices.unmanaged_index.phase - is_false: indices.unmanaged_index.phase
- is_false: indices.unmanaged_index.action - is_false: indices.unmanaged_index.action
- is_false: indices.unmanaged_index.step - is_false: indices.unmanaged_index.step
- is_false: indices.unmanaged_index.phase_execution
- is_false: indices.another_index.failed_step - is_false: indices.another_index.failed_step
- is_false: indices.another_index.step_info - is_false: indices.another_index.step_info
- is_false: indices.my_index - is_false: indices.my_index