diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/IndexLifecycleIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/IndexLifecycleIT.java index e893f3a8926..08794137307 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/IndexLifecycleIT.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/IndexLifecycleIT.java @@ -26,9 +26,12 @@ import org.elasticsearch.action.support.master.AcknowledgedResponse; import org.elasticsearch.client.indexlifecycle.AllocateAction; import org.elasticsearch.client.indexlifecycle.DeleteAction; import org.elasticsearch.client.indexlifecycle.DeleteLifecyclePolicyRequest; +import org.elasticsearch.client.indexlifecycle.ExplainLifecycleRequest; +import org.elasticsearch.client.indexlifecycle.ExplainLifecycleResponse; import org.elasticsearch.client.indexlifecycle.ForceMergeAction; import org.elasticsearch.client.indexlifecycle.GetLifecyclePolicyRequest; import org.elasticsearch.client.indexlifecycle.GetLifecyclePolicyResponse; +import org.elasticsearch.client.indexlifecycle.IndexLifecycleExplainResponse; import org.elasticsearch.client.indexlifecycle.LifecycleAction; import org.elasticsearch.client.indexlifecycle.LifecycleManagementStatusRequest; import org.elasticsearch.client.indexlifecycle.LifecycleManagementStatusResponse; @@ -39,16 +42,13 @@ import org.elasticsearch.client.indexlifecycle.Phase; import org.elasticsearch.client.indexlifecycle.PhaseExecutionInfo; import org.elasticsearch.client.indexlifecycle.PutLifecyclePolicyRequest; import org.elasticsearch.client.indexlifecycle.RolloverAction; -import org.elasticsearch.client.indexlifecycle.ShrinkAction; -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.unit.TimeValue; -import org.elasticsearch.client.indexlifecycle.ExplainLifecycleRequest; -import org.elasticsearch.client.indexlifecycle.ExplainLifecycleResponse; -import org.elasticsearch.client.indexlifecycle.IndexLifecycleExplainResponse; import org.elasticsearch.client.indexlifecycle.SetIndexLifecyclePolicyRequest; import org.elasticsearch.client.indexlifecycle.SetIndexLifecyclePolicyResponse; +import org.elasticsearch.client.indexlifecycle.ShrinkAction; import org.elasticsearch.client.indexlifecycle.StartILMRequest; import org.elasticsearch.client.indexlifecycle.StopILMRequest; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.unit.TimeValue; import org.hamcrest.Matchers; import java.io.IOException; @@ -167,14 +167,6 @@ public class IndexLifecycleIT extends ESRestHighLevelClientTestCase { .put("index.lifecycle.rollover_alias", "baz-alias").build(), "", "\"baz-alias\" : {}"); createIndex("squash", Settings.EMPTY); - assertBusy(() -> { - GetSettingsRequest getSettingsRequest = new GetSettingsRequest().indices("foo-01", "baz-01"); - GetSettingsResponse settingsResponse = highLevelClient().indices().getSettings(getSettingsRequest, RequestOptions.DEFAULT); - assertThat(settingsResponse.getSetting("foo-01", "index.lifecycle.name"), equalTo(policy.getName())); - assertThat(settingsResponse.getSetting("baz-01", "index.lifecycle.name"), equalTo(policy.getName())); - assertThat(settingsResponse.getSetting("foo-01", "index.lifecycle.phase"), equalTo("hot")); - assertThat(settingsResponse.getSetting("baz-01", "index.lifecycle.phase"), equalTo("hot")); - }); ExplainLifecycleRequest req = new ExplainLifecycleRequest(); req.indices("foo-01", "baz-01", "squash"); diff --git a/server/src/main/java/org/elasticsearch/cluster/metadata/IndexMetaData.java b/server/src/main/java/org/elasticsearch/cluster/metadata/IndexMetaData.java index c1e70191417..3c5ec2f965e 100644 --- a/server/src/main/java/org/elasticsearch/cluster/metadata/IndexMetaData.java +++ b/server/src/main/java/org/elasticsearch/cluster/metadata/IndexMetaData.java @@ -955,6 +955,11 @@ public class IndexMetaData implements Diffable, ToXContentFragmen return this; } + public Builder removeCustom(String type) { + this.customMetaData.remove(type); + return this; + } + public Set getInSyncAllocationIds(int shardId) { return inSyncAllocationIds.get(shardId); } diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/CopyExecutionStateStep.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/CopyExecutionStateStep.java new file mode 100644 index 00000000000..b3bd4235fae --- /dev/null +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/CopyExecutionStateStep.java @@ -0,0 +1,75 @@ +/* + * 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.ClusterState; +import org.elasticsearch.cluster.metadata.IndexMetaData; +import org.elasticsearch.cluster.metadata.MetaData; +import org.elasticsearch.index.Index; + +import java.util.Objects; + +import static org.elasticsearch.xpack.core.indexlifecycle.LifecycleExecutionState.ILM_CUSTOM_METADATA_KEY; + +/** + * Copies the execution state data from one index to another, typically after a + * new index has been created. Useful for actions such as shrink. + */ +public class CopyExecutionStateStep extends ClusterStateActionStep { + public static final String NAME = "copy_execution_state"; + private String shrunkIndexPrefix; + + public CopyExecutionStateStep(StepKey key, StepKey nextStepKey, String shrunkIndexPrefix) { + super(key, nextStepKey); + this.shrunkIndexPrefix = shrunkIndexPrefix; + } + + String getShrunkIndexPrefix() { + return shrunkIndexPrefix; + } + + @Override + public ClusterState performAction(Index index, ClusterState clusterState) { + IndexMetaData indexMetaData = clusterState.metaData().index(index); + // get source index + String indexName = indexMetaData.getIndex().getName(); + // get target shrink index + String targetIndexName = shrunkIndexPrefix + indexName; + IndexMetaData targetIndexMetaData = clusterState.metaData().index(targetIndexName); + + LifecycleExecutionState lifecycleState = LifecycleExecutionState.fromIndexMetadata(indexMetaData); + String phase = lifecycleState.getPhase(); + String action = lifecycleState.getAction(); + long lifecycleDate = lifecycleState.getLifecycleDate(); + + LifecycleExecutionState.Builder relevantTargetCustomData = LifecycleExecutionState.builder(); + relevantTargetCustomData.setIndexCreationDate(lifecycleDate); + relevantTargetCustomData.setPhase(phase); + relevantTargetCustomData.setAction(action); + relevantTargetCustomData.setStep(ShrunkenIndexCheckStep.NAME); + + MetaData.Builder newMetaData = MetaData.builder(clusterState.getMetaData()) + .put(IndexMetaData.builder(targetIndexMetaData) + .putCustom(ILM_CUSTOM_METADATA_KEY, relevantTargetCustomData.build().asMap())); + + return ClusterState.builder(clusterState).metaData(newMetaData).build(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + if (!super.equals(o)) return false; + CopyExecutionStateStep that = (CopyExecutionStateStep) o; + return Objects.equals(shrunkIndexPrefix, that.shrunkIndexPrefix); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), shrunkIndexPrefix); + } +} diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/IndexLifecycleExplainResponse.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/IndexLifecycleExplainResponse.java index b110697ae07..0a451b5c14b 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/IndexLifecycleExplainResponse.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/IndexLifecycleExplainResponse.java @@ -48,14 +48,14 @@ public class IndexLifecycleExplainResponse implements ToXContentObject, Writeabl (boolean) a[1], (String) a[2], (boolean) (a[3] == null ? false: a[3]), - (long) (a[4] == null ? -1L: a[4]), + (Long) (a[4]), (String) a[5], (String) a[6], (String) a[7], (String) a[8], - (long) (a[9] == null ? -1L: a[9]), - (long) (a[10] == null ? -1L: a[10]), - (long) (a[11] == null ? -1L: a[11]), + (Long) (a[9]), + (Long) (a[10]), + (Long) (a[11]), (BytesReference) a[12], (PhaseExecutionInfo) a[13])); static { @@ -86,36 +86,36 @@ public class IndexLifecycleExplainResponse implements ToXContentObject, Writeabl private final String action; private final String step; private final String failedStep; - private final long lifecycleDate; - private final long phaseTime; - private final long actionTime; - private final long stepTime; + private final Long lifecycleDate; + private final Long phaseTime; + private final Long actionTime; + private final Long stepTime; private final boolean skip; private final boolean managedByILM; private final BytesReference stepInfo; private final PhaseExecutionInfo phaseExecutionInfo; - 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, + 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, BytesReference stepInfo, PhaseExecutionInfo phaseExecutionInfo) { return new IndexLifecycleExplainResponse(index, true, policyName, skip, lifecycleDate, phase, action, step, failedStep, phaseTime, actionTime, stepTime, stepInfo, phaseExecutionInfo); } public static IndexLifecycleExplainResponse newUnmanagedIndexResponse(String index) { - return new IndexLifecycleExplainResponse(index, false, null, false, -1L, null, null, null, null, -1L, -1L, -1L, null, null); + return new IndexLifecycleExplainResponse(index, false, null, false, null, null, null, null, null, null, null, null, null, null); } - 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, BytesReference stepInfo, PhaseExecutionInfo phaseExecutionInfo) { + 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, BytesReference stepInfo, PhaseExecutionInfo phaseExecutionInfo) { if (managedByILM) { if (policyName == null) { throw new IllegalArgumentException("[" + POLICY_NAME_FIELD.getPreferredName() + "] cannot be null for managed index"); } } else { - if (policyName != null || lifecycleDate >= 0 || phase != null || action != null || step != null || failedStep != null - || phaseTime >= 0 || actionTime >= 0 || stepTime >= 0 || stepInfo != null || phaseExecutionInfo != null) { + if (policyName != null || lifecycleDate != null || phase != null || action != null || step != null || failedStep != null + || phaseTime != null || actionTime != null || stepTime != null || stepInfo != null || phaseExecutionInfo != null) { throw new IllegalArgumentException( "Unmanaged index response must only contain fields: [" + MANAGED_BY_ILM_FIELD + ", " + INDEX_FIELD + "]"); } @@ -142,27 +142,27 @@ public class IndexLifecycleExplainResponse implements ToXContentObject, Writeabl if (managedByILM) { policyName = in.readString(); skip = in.readBoolean(); - lifecycleDate = in.readZLong(); - phase = in.readString(); - action = in.readString(); - step = in.readString(); + lifecycleDate = in.readOptionalLong(); + phase = in.readOptionalString(); + action = in.readOptionalString(); + step = in.readOptionalString(); failedStep = in.readOptionalString(); - phaseTime = in.readZLong(); - actionTime = in.readZLong(); - stepTime = in.readZLong(); + phaseTime = in.readOptionalLong(); + actionTime = in.readOptionalLong(); + stepTime = in.readOptionalLong(); stepInfo = in.readOptionalBytesReference(); phaseExecutionInfo = in.readOptionalWriteable(PhaseExecutionInfo::new); } else { policyName = null; skip = false; - lifecycleDate = -1L; + lifecycleDate = null; phase = null; action = null; step = null; failedStep = null; - phaseTime = -1L; - actionTime = -1L; - stepTime = -1L; + phaseTime = null; + actionTime = null; + stepTime = null; stepInfo = null; phaseExecutionInfo = null; } @@ -175,14 +175,14 @@ public class IndexLifecycleExplainResponse implements ToXContentObject, Writeabl if (managedByILM) { out.writeString(policyName); out.writeBoolean(skip); - out.writeZLong(lifecycleDate); - out.writeString(phase); - out.writeString(action); - out.writeString(step); + out.writeOptionalLong(lifecycleDate); + out.writeOptionalString(phase); + out.writeOptionalString(action); + out.writeOptionalString(step); out.writeOptionalString(failedStep); - out.writeZLong(phaseTime); - out.writeZLong(actionTime); - out.writeZLong(stepTime); + out.writeOptionalLong(phaseTime); + out.writeOptionalLong(actionTime); + out.writeOptionalLong(stepTime); out.writeOptionalBytesReference(stepInfo); out.writeOptionalWriteable(phaseExecutionInfo); } @@ -204,7 +204,7 @@ public class IndexLifecycleExplainResponse implements ToXContentObject, Writeabl return skip; } - public long getLifecycleDate() { + public Long getLifecycleDate() { return lifecycleDate; } @@ -212,7 +212,7 @@ public class IndexLifecycleExplainResponse implements ToXContentObject, Writeabl return phase; } - public long getPhaseTime() { + public Long getPhaseTime() { return phaseTime; } @@ -220,7 +220,7 @@ public class IndexLifecycleExplainResponse implements ToXContentObject, Writeabl return action; } - public long getActionTime() { + public Long getActionTime() { return actionTime; } @@ -228,7 +228,7 @@ public class IndexLifecycleExplainResponse implements ToXContentObject, Writeabl return step; } - public long getStepTime() { + public Long getStepTime() { return stepTime; } diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/InitializePolicyContextStep.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/InitializePolicyContextStep.java index 7ec357a3013..c9046cb5eb7 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/InitializePolicyContextStep.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/InitializePolicyContextStep.java @@ -10,9 +10,10 @@ import org.apache.logging.log4j.Logger; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.metadata.IndexMetaData; import org.elasticsearch.cluster.metadata.MetaData; -import org.elasticsearch.common.settings.Settings; import org.elasticsearch.index.Index; +import static org.elasticsearch.xpack.core.indexlifecycle.LifecycleExecutionState.ILM_CUSTOM_METADATA_KEY; + public final class InitializePolicyContextStep extends ClusterStateActionStep { public static final String INITIALIZATION_PHASE = "new"; public static final StepKey KEY = new StepKey(INITIALIZATION_PHASE, "init", "init"); @@ -30,18 +31,19 @@ public final class InitializePolicyContextStep extends ClusterStateActionStep { // Index must have been since deleted, ignore it return clusterState; } - Settings settings = indexMetaData.getSettings(); - if (settings.hasValue(LifecycleSettings.LIFECYCLE_INDEX_CREATION_DATE)) { + LifecycleExecutionState lifecycleState = LifecycleExecutionState + .fromIndexMetadata(indexMetaData); + if (lifecycleState.getLifecycleDate() != null) { return clusterState; } ClusterState.Builder newClusterStateBuilder = ClusterState.builder(clusterState); - IndexMetaData idxMeta = clusterState.getMetaData().index(index); - Settings.Builder indexSettings = Settings.builder().put(idxMeta.getSettings()) - .put(LifecycleSettings.LIFECYCLE_INDEX_CREATION_DATE, idxMeta.getCreationDate()); + + LifecycleExecutionState.Builder newCustomData = LifecycleExecutionState.builder(lifecycleState); + newCustomData.setIndexCreationDate(indexMetaData.getCreationDate()); newClusterStateBuilder.metaData(MetaData.builder(clusterState.getMetaData()).put(IndexMetaData - .builder(clusterState.getMetaData().index(index)) - .settings(indexSettings))); + .builder(indexMetaData) + .putCustom(ILM_CUSTOM_METADATA_KEY, newCustomData.build().asMap()))); return newClusterStateBuilder.build(); } } diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/LifecycleExecutionState.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/LifecycleExecutionState.java new file mode 100644 index 00000000000..b2d42bca733 --- /dev/null +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/LifecycleExecutionState.java @@ -0,0 +1,319 @@ +/* + * 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.ElasticsearchException; +import org.elasticsearch.cluster.metadata.IndexMetaData; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +/** + * Contains information about the execution of a lifecycle policy for a single + * index, and serializes/deserializes this information to and from custom + * index metadata. + */ +public class LifecycleExecutionState { + public static final String ILM_CUSTOM_METADATA_KEY = "ilm"; + + private static final String PHASE = "phase"; + private static final String ACTION = "action"; + private static final String STEP = "step"; + private static final String INDEX_CREATION_DATE = "creation_date"; + private static final String PHASE_TIME = "phase_time"; + private static final String ACTION_TIME = "action_time"; + private static final String STEP_TIME = "step_time"; + private static final String FAILED_STEP = "failed_step"; + private static final String STEP_INFO = "step_info"; + private static final String PHASE_DEFINITION = "phase_definition"; + + private final String phase; + private final String action; + private final String step; + private final String failedStep; + private final String stepInfo; + private final String phaseDefinition; + private final Long lifecycleDate; + private final Long phaseTime; + private final Long actionTime; + private final Long stepTime; + + private LifecycleExecutionState(String phase, String action, String step, String failedStep, + String stepInfo, String phaseDefinition, Long lifecycleDate, + Long phaseTime, Long actionTime, Long stepTime) { + this.phase = phase; + this.action = action; + this.step = step; + this.failedStep = failedStep; + this.stepInfo = stepInfo; + this.phaseDefinition = phaseDefinition; + this.lifecycleDate = lifecycleDate; + this.phaseTime = phaseTime; + this.actionTime = actionTime; + this.stepTime = stepTime; + } + + /** + * Retrieves the execution state from an {@link IndexMetaData} based on the + * custom metadata. + * @param indexMetaData The metadata of the index to retrieve the execution + * state from. + * @return The execution state of that index. + */ + public static LifecycleExecutionState fromIndexMetadata(IndexMetaData indexMetaData) { + Map customData = indexMetaData.getCustomData(ILM_CUSTOM_METADATA_KEY); + customData = customData == null ? new HashMap<>() : customData; + return fromCustomMetadata(customData); + } + + public static Builder builder() { + return new Builder(); + } + + public static Builder builder(LifecycleExecutionState state) { + return new Builder() + .setPhase(state.phase) + .setAction(state.action) + .setStep(state.step) + .setFailedStep(state.failedStep) + .setStepInfo(state.stepInfo) + .setPhaseDefinition(state.phaseDefinition) + .setIndexCreationDate(state.lifecycleDate) + .setPhaseTime(state.phaseTime) + .setActionTime(state.actionTime) + .setStepTime(state.stepTime); + } + + static LifecycleExecutionState fromCustomMetadata(Map customData) { + Builder builder = builder(); + if (customData.containsKey(PHASE)) { + builder.setPhase(customData.get(PHASE)); + } + if (customData.containsKey(ACTION)) { + builder.setAction(customData.get(ACTION)); + } + if (customData.containsKey(STEP)) { + builder.setStep(customData.get(STEP)); + } + if (customData.containsKey(FAILED_STEP)) { + builder.setFailedStep(customData.get(FAILED_STEP)); + } + if (customData.containsKey(STEP_INFO)) { + builder.setStepInfo(customData.get(STEP_INFO)); + } + if (customData.containsKey(PHASE_DEFINITION)) { + builder.setPhaseDefinition(customData.get(PHASE_DEFINITION)); + } + if (customData.containsKey(INDEX_CREATION_DATE)) { + try { + builder.setIndexCreationDate(Long.parseLong(customData.get(INDEX_CREATION_DATE))); + } catch (NumberFormatException e) { + throw new ElasticsearchException("Custom metadata field [{}] does not contain a valid long. Actual value: [{}]", + e, INDEX_CREATION_DATE, customData.get(INDEX_CREATION_DATE)); + } + } + if (customData.containsKey(PHASE_TIME)) { + try { + builder.setPhaseTime(Long.parseLong(customData.get(PHASE_TIME))); + } catch (NumberFormatException e) { + throw new ElasticsearchException("Custom metadata field [{}] does not contain a valid long. Actual value: [{}]", + e, PHASE_TIME, customData.get(PHASE_TIME)); + } + } + if (customData.containsKey(ACTION_TIME)) { + try { + builder.setActionTime(Long.parseLong(customData.get(ACTION_TIME))); + } catch (NumberFormatException e) { + throw new ElasticsearchException("Custom metadata field [{}] does not contain a valid long. Actual value: [{}]", + e, ACTION_TIME, customData.get(ACTION_TIME)); + } + } + if (customData.containsKey(STEP_TIME)) { + try { + builder.setStepTime(Long.parseLong(customData.get(STEP_TIME))); + } catch (NumberFormatException e) { + throw new ElasticsearchException("Custom metadata field [{}] does not contain a valid long. Actual value: [{}]", + e, STEP_TIME, customData.get(STEP_TIME)); + } + } + return builder.build(); + } + + /** + * Converts this object to an immutable map representation for use with + * {@link IndexMetaData.Builder#putCustom(String, Map)}. + * @return An immutable Map representation of this execution state. + */ + public Map asMap() { + Map result = new HashMap<>(); + if (phase != null) { + result.put(PHASE, phase); + } + if (action != null) { + result.put(ACTION, action); + } + if (step != null) { + result.put(STEP, step); + } + if (failedStep != null) { + result.put(FAILED_STEP, failedStep); + } + if (stepInfo != null) { + result.put(STEP_INFO, stepInfo); + } + if (lifecycleDate != null) { + result.put(INDEX_CREATION_DATE, String.valueOf(lifecycleDate)); + } + if (phaseTime != null) { + result.put(PHASE_TIME, String.valueOf(phaseTime)); + } + if (actionTime != null) { + result.put(ACTION_TIME, String.valueOf(actionTime)); + } + if (stepTime != null) { + result.put(STEP_TIME, String.valueOf(stepTime)); + } + if (phaseDefinition != null) { + result.put(PHASE_DEFINITION, String.valueOf(phaseDefinition)); + } + return Collections.unmodifiableMap(result); + } + + public String getPhase() { + return phase; + } + + public String getAction() { + return action; + } + + public String getStep() { + return step; + } + + public String getFailedStep() { + return failedStep; + } + + public String getStepInfo() { + return stepInfo; + } + + public String getPhaseDefinition() { + return phaseDefinition; + } + + public Long getLifecycleDate() { + return lifecycleDate; + } + + public Long getPhaseTime() { + return phaseTime; + } + + public Long getActionTime() { + return actionTime; + } + + public Long getStepTime() { + return stepTime; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + LifecycleExecutionState that = (LifecycleExecutionState) o; + return getLifecycleDate() == that.getLifecycleDate() && + getPhaseTime() == that.getPhaseTime() && + getActionTime() == that.getActionTime() && + getStepTime() == that.getStepTime() && + Objects.equals(getPhase(), that.getPhase()) && + Objects.equals(getAction(), that.getAction()) && + Objects.equals(getStep(), that.getStep()) && + Objects.equals(getFailedStep(), that.getFailedStep()) && + Objects.equals(getStepInfo(), that.getStepInfo()) && + Objects.equals(getPhaseDefinition(), that.getPhaseDefinition()); + } + + @Override + public int hashCode() { + return Objects.hash(getPhase(), getAction(), getStep(), getFailedStep(), getStepInfo(), getPhaseDefinition(), + getLifecycleDate(), getPhaseTime(), getActionTime(), getStepTime()); + } + + public static class Builder { + private String phase; + private String action; + private String step; + private String failedStep; + private String stepInfo; + private String phaseDefinition; + private Long indexCreationDate; + private Long phaseTime; + private Long actionTime; + private Long stepTime; + + public Builder setPhase(String phase) { + this.phase = phase; + return this; + } + + public Builder setAction(String action) { + this.action = action; + return this; + } + + public Builder setStep(String step) { + this.step = step; + return this; + } + + public Builder setFailedStep(String failedStep) { + this.failedStep = failedStep; + return this; + } + + public Builder setStepInfo(String stepInfo) { + this.stepInfo = stepInfo; + return this; + } + + public Builder setPhaseDefinition(String phaseDefinition) { + this.phaseDefinition = phaseDefinition; + return this; + } + + public Builder setIndexCreationDate(Long indexCreationDate) { + this.indexCreationDate = indexCreationDate; + return this; + } + + public Builder setPhaseTime(Long phaseTime) { + this.phaseTime = phaseTime; + return this; + } + + public Builder setActionTime(Long actionTime) { + this.actionTime = actionTime; + return this; + } + + public Builder setStepTime(Long stepTime) { + this.stepTime = stepTime; + return this; + } + + public LifecycleExecutionState build() { + return new LifecycleExecutionState(phase, action, step, failedStep, stepInfo, phaseDefinition, indexCreationDate, + phaseTime, actionTime, stepTime); + } + } + +} diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/LifecycleSettings.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/LifecycleSettings.java index 027904a31bf..7c9fc4f8e8a 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/LifecycleSettings.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/LifecycleSettings.java @@ -14,42 +14,12 @@ import org.elasticsearch.common.unit.TimeValue; public class LifecycleSettings { public static final String LIFECYCLE_POLL_INTERVAL = "indices.lifecycle.poll_interval"; public static final String LIFECYCLE_NAME = "index.lifecycle.name"; - public static final String LIFECYCLE_PHASE = "index.lifecycle.phase"; - public static final String LIFECYCLE_ACTION = "index.lifecycle.action"; - public static final String LIFECYCLE_STEP = "index.lifecycle.step"; - public static final String LIFECYCLE_INDEX_CREATION_DATE = "index.lifecycle.date"; - public static final String LIFECYCLE_PHASE_TIME = "index.lifecycle.phase_time"; - public static final String LIFECYCLE_ACTION_TIME = "index.lifecycle.action_time"; - public static final String LIFECYCLE_STEP_TIME = "index.lifecycle.step_time"; - public static final String LIFECYCLE_FAILED_STEP = "index.lifecycle.failed_step"; - public static final String LIFECYCLE_STEP_INFO = "index.lifecycle.step_info"; public static final String LIFECYCLE_SKIP = "index.lifecycle.skip"; - public static final String LIFECYCLE_PHASE_DEFINITION = "index.lifecycle.phase_definition"; public static final Setting LIFECYCLE_POLL_INTERVAL_SETTING = Setting.positiveTimeSetting(LIFECYCLE_POLL_INTERVAL, TimeValue.timeValueMinutes(10), Setting.Property.Dynamic, Setting.Property.NodeScope); public static final Setting LIFECYCLE_NAME_SETTING = Setting.simpleString(LIFECYCLE_NAME, Setting.Property.Dynamic, Setting.Property.IndexScope, Setting.Property.InternalIndex); - public static final Setting LIFECYCLE_PHASE_SETTING = Setting.simpleString(LIFECYCLE_PHASE, - Setting.Property.Dynamic, Setting.Property.IndexScope, Setting.Property.InternalIndex); - public static final Setting LIFECYCLE_ACTION_SETTING = Setting.simpleString(LIFECYCLE_ACTION, - Setting.Property.Dynamic, Setting.Property.IndexScope, Setting.Property.InternalIndex); - public static final Setting LIFECYCLE_STEP_SETTING = Setting.simpleString(LIFECYCLE_STEP, - Setting.Property.Dynamic, Setting.Property.IndexScope, Setting.Property.InternalIndex); - public static final Setting LIFECYCLE_FAILED_STEP_SETTING = Setting.simpleString(LIFECYCLE_FAILED_STEP, - Setting.Property.Dynamic, Setting.Property.IndexScope, Setting.Property.InternalIndex); - public static final Setting LIFECYCLE_INDEX_CREATION_DATE_SETTING = Setting.longSetting(LIFECYCLE_INDEX_CREATION_DATE, - -1L, -1L, Setting.Property.Dynamic, Setting.Property.IndexScope, Setting.Property.InternalIndex); - public static final Setting LIFECYCLE_PHASE_TIME_SETTING = Setting.longSetting(LIFECYCLE_PHASE_TIME, - -1L, -1L, Setting.Property.Dynamic, Setting.Property.IndexScope, Setting.Property.InternalIndex); - public static final Setting LIFECYCLE_ACTION_TIME_SETTING = Setting.longSetting(LIFECYCLE_ACTION_TIME, - -1L, -1L, Setting.Property.Dynamic, Setting.Property.IndexScope, Setting.Property.InternalIndex); - public static final Setting LIFECYCLE_STEP_TIME_SETTING = Setting.longSetting(LIFECYCLE_STEP_TIME, - -1L, -1L, Setting.Property.Dynamic, Setting.Property.IndexScope, Setting.Property.InternalIndex); - public static final Setting LIFECYCLE_STEP_INFO_SETTING = Setting.simpleString(LIFECYCLE_STEP_INFO, Setting.Property.Dynamic, - Setting.Property.IndexScope, Setting.Property.NotCopyableOnResize, Setting.Property.InternalIndex); public static final Setting LIFECYCLE_SKIP_SETTING = Setting.boolSetting(LIFECYCLE_SKIP, false, Setting.Property.Dynamic, Setting.Property.IndexScope); - public static final Setting LIFECYCLE_PHASE_DEFINITION_SETTING = Setting.simpleString(LIFECYCLE_PHASE_DEFINITION, - Setting.Property.Dynamic, Setting.Property.IndexScope); } diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/ShrinkAction.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/ShrinkAction.java index 5467d4a8a4d..cda03123606 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/ShrinkAction.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/ShrinkAction.java @@ -85,15 +85,18 @@ public class ShrinkAction implements LifecycleAction { StepKey allocationRoutedKey = new StepKey(phase, NAME, AllocationRoutedStep.NAME); StepKey shrinkKey = new StepKey(phase, NAME, ShrinkStep.NAME); StepKey enoughShardsKey = new StepKey(phase, NAME, ShrunkShardsAllocatedStep.NAME); + StepKey copyMetadataKey = new StepKey(phase, NAME, CopyExecutionStateStep.NAME); StepKey aliasKey = new StepKey(phase, NAME, ShrinkSetAliasStep.NAME); StepKey isShrunkIndexKey = new StepKey(phase, NAME, ShrunkenIndexCheckStep.NAME); + SetSingleNodeAllocateStep setSingleNodeStep = new SetSingleNodeAllocateStep(setSingleNodeKey, allocationRoutedKey, client); AllocationRoutedStep allocationStep = new AllocationRoutedStep(allocationRoutedKey, shrinkKey, false); ShrinkStep shrink = new ShrinkStep(shrinkKey, enoughShardsKey, client, numberOfShards, SHRUNKEN_INDEX_PREFIX); - ShrunkShardsAllocatedStep allocated = new ShrunkShardsAllocatedStep(enoughShardsKey, aliasKey, SHRUNKEN_INDEX_PREFIX); + ShrunkShardsAllocatedStep allocated = new ShrunkShardsAllocatedStep(enoughShardsKey, copyMetadataKey, SHRUNKEN_INDEX_PREFIX); + CopyExecutionStateStep copyMetadata = new CopyExecutionStateStep(copyMetadataKey, aliasKey, SHRUNKEN_INDEX_PREFIX); ShrinkSetAliasStep aliasSwapAndDelete = new ShrinkSetAliasStep(aliasKey, isShrunkIndexKey, client, SHRUNKEN_INDEX_PREFIX); ShrunkenIndexCheckStep waitOnShrinkTakeover = new ShrunkenIndexCheckStep(isShrunkIndexKey, nextStepKey, SHRUNKEN_INDEX_PREFIX); - return Arrays.asList(setSingleNodeStep, allocationStep, shrink, allocated, aliasSwapAndDelete, waitOnShrinkTakeover); + return Arrays.asList(setSingleNodeStep, allocationStep, shrink, allocated, copyMetadata, aliasSwapAndDelete, waitOnShrinkTakeover); } @Override @@ -102,9 +105,11 @@ public class ShrinkAction implements LifecycleAction { StepKey allocationRoutedKey = new StepKey(phase, NAME, AllocationRoutedStep.NAME); StepKey shrinkKey = new StepKey(phase, NAME, ShrinkStep.NAME); StepKey enoughShardsKey = new StepKey(phase, NAME, ShrunkShardsAllocatedStep.NAME); + StepKey copyMetadataKey = new StepKey(phase, NAME, CopyExecutionStateStep.NAME); StepKey aliasKey = new StepKey(phase, NAME, ShrinkSetAliasStep.NAME); StepKey isShrunkIndexKey = new StepKey(phase, NAME, ShrunkenIndexCheckStep.NAME); - return Arrays.asList(setSingleNodeKey, allocationRoutedKey, shrinkKey, enoughShardsKey, aliasKey, isShrunkIndexKey); + return Arrays.asList(setSingleNodeKey, allocationRoutedKey, shrinkKey, enoughShardsKey, + copyMetadataKey, aliasKey, isShrunkIndexKey); } @Override diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/ShrinkStep.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/ShrinkStep.java index 16fbf7dbc31..eb18fe98876 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/ShrinkStep.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/ShrinkStep.java @@ -37,28 +37,22 @@ public class ShrinkStep extends AsyncActionStep { @Override public void performAction(IndexMetaData indexMetaData, ClusterState currentState, Listener listener) { - // if operating on the shrunken index, do nothing - - Long lifecycleDate = LifecycleSettings.LIFECYCLE_INDEX_CREATION_DATE_SETTING.get(indexMetaData.getSettings()); - if (lifecycleDate == null) { - throw new IllegalStateException("source index[" + indexMetaData.getIndex().getName() + - "] is missing setting[" + LifecycleSettings.LIFECYCLE_INDEX_CREATION_DATE); + LifecycleExecutionState lifecycleState = LifecycleExecutionState.fromIndexMetadata(indexMetaData); + if (lifecycleState.getLifecycleDate() == null) { + throw new IllegalStateException("source index [" + indexMetaData.getIndex().getName() + + "] is missing lifecycle date"); } + String lifecycle = LifecycleSettings.LIFECYCLE_NAME_SETTING.get(indexMetaData.getSettings()); - String phase = LifecycleSettings.LIFECYCLE_PHASE_SETTING.get(indexMetaData.getSettings()); - String action = LifecycleSettings.LIFECYCLE_ACTION_SETTING.get(indexMetaData.getSettings()); Settings relevantTargetSettings = Settings.builder() .put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, numberOfShards) .put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, indexMetaData.getNumberOfReplicas()) - .put(LifecycleSettings.LIFECYCLE_INDEX_CREATION_DATE, lifecycleDate) .put(LifecycleSettings.LIFECYCLE_NAME, lifecycle) - .put(LifecycleSettings.LIFECYCLE_PHASE, phase) - .put(LifecycleSettings.LIFECYCLE_ACTION, action) - .put(LifecycleSettings.LIFECYCLE_STEP, ShrunkenIndexCheckStep.NAME) // skip source-index steps - .put(IndexMetaData.INDEX_ROUTING_REQUIRE_GROUP_SETTING.getKey() + "_name", (String) null) // need to remove the single shard + .put(IndexMetaData.INDEX_ROUTING_REQUIRE_GROUP_SETTING.getKey() + "_name", (String) null) // need to remove the single shard // allocation so replicas can be allocated .build(); + String shrunkenIndexName = shrunkIndexPrefix + indexMetaData.getIndex().getName(); ResizeRequest resizeRequest = new ResizeRequest(shrunkenIndexName, indexMetaData.getIndex().getName()); indexMetaData.getAliases().values().spliterator().forEachRemaining(aliasMetaDataObjectCursor -> { @@ -70,6 +64,7 @@ public class ShrinkStep extends AsyncActionStep { // TODO(talevy): when is this not acknowledged? listener.onResponse(response.isAcknowledged()); }, listener::onFailure)); + } @Override diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/UpdateRolloverLifecycleDateStep.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/UpdateRolloverLifecycleDateStep.java index 2d09bc7750f..9d1c7701faa 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/UpdateRolloverLifecycleDateStep.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/UpdateRolloverLifecycleDateStep.java @@ -10,9 +10,10 @@ import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.metadata.IndexMetaData; import org.elasticsearch.cluster.metadata.MetaData; import org.elasticsearch.common.Strings; -import org.elasticsearch.common.settings.Settings; import org.elasticsearch.index.Index; +import static org.elasticsearch.xpack.core.indexlifecycle.LifecycleExecutionState.ILM_CUSTOM_METADATA_KEY; + public class UpdateRolloverLifecycleDateStep extends ClusterStateActionStep { public static final String NAME = "update-rollover-lifecycle-date"; @@ -33,9 +34,15 @@ public class UpdateRolloverLifecycleDateStep extends ClusterStateActionStep { if (rolloverInfo == null) { throw new IllegalStateException("index [" + indexMetaData.getIndex().getName() + "] has not rolled over yet"); } - Settings settings = Settings.builder().put(LifecycleSettings.LIFECYCLE_INDEX_CREATION_DATE, rolloverInfo.getTime()).build(); + + LifecycleExecutionState.Builder newLifecycleState = LifecycleExecutionState + .builder(LifecycleExecutionState.fromIndexMetadata(indexMetaData)); + newLifecycleState.setIndexCreationDate(rolloverInfo.getTime()); + + IndexMetaData.Builder newIndexMetadata = IndexMetaData.builder(indexMetaData); + newIndexMetadata.putCustom(ILM_CUSTOM_METADATA_KEY, newLifecycleState.build().asMap()); return ClusterState.builder(currentState).metaData(MetaData.builder(currentState.metaData()) - .updateSettings(settings, indexMetaData.getIndex().getName())).build(); + .put(newIndexMetadata)).build(); } @Override diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/indexlifecycle/CopyExecutionStateStepTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/indexlifecycle/CopyExecutionStateStepTests.java new file mode 100644 index 00000000000..40dd022c05d --- /dev/null +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/indexlifecycle/CopyExecutionStateStepTests.java @@ -0,0 +1,89 @@ +/* + * 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.Version; +import org.elasticsearch.cluster.ClusterName; +import org.elasticsearch.cluster.ClusterState; +import org.elasticsearch.cluster.metadata.IndexMetaData; +import org.elasticsearch.cluster.metadata.MetaData; +import org.elasticsearch.xpack.core.indexlifecycle.Step.StepKey; + +import java.util.Map; + +import static org.elasticsearch.xpack.core.indexlifecycle.LifecycleExecutionState.ILM_CUSTOM_METADATA_KEY; +import static org.elasticsearch.xpack.core.indexlifecycle.LifecycleExecutionStateTests.createCustomMetadata; + +public class CopyExecutionStateStepTests extends AbstractStepTestCase { + @Override + protected CopyExecutionStateStep createRandomInstance() { + StepKey stepKey = randomStepKey(); + StepKey nextStepKey = randomStepKey(); + String shrunkIndexPrefix = randomAlphaOfLength(10); + return new CopyExecutionStateStep(stepKey, nextStepKey, shrunkIndexPrefix); + } + + @Override + protected CopyExecutionStateStep mutateInstance(CopyExecutionStateStep instance) { + StepKey key = instance.getKey(); + StepKey nextKey = instance.getNextStepKey(); + String shrunkIndexPrefix = instance.getShrunkIndexPrefix(); + + switch (between(0, 2)) { + case 0: + key = new StepKey(key.getPhase(), key.getAction(), key.getName() + randomAlphaOfLength(5)); + break; + case 1: + nextKey = new StepKey(key.getPhase(), key.getAction(), key.getName() + randomAlphaOfLength(5)); + break; + case 2: + shrunkIndexPrefix += randomAlphaOfLength(5); + break; + default: + throw new AssertionError("Illegal randomisation branch"); + } + + return new CopyExecutionStateStep(key, nextKey, shrunkIndexPrefix); + } + + @Override + protected CopyExecutionStateStep copyInstance(CopyExecutionStateStep instance) { + return new CopyExecutionStateStep(instance.getKey(), instance.getNextStepKey(), instance.getShrunkIndexPrefix()); + } + + public void testPerformAction() { + CopyExecutionStateStep step = createRandomInstance(); + String indexName = randomAlphaOfLengthBetween(5, 20); + Map customMetadata = createCustomMetadata(); + + IndexMetaData originalIndexMetaData = IndexMetaData.builder(indexName) + .settings(settings(Version.CURRENT)).numberOfShards(randomIntBetween(1,5)) + .numberOfReplicas(randomIntBetween(1,5)) + .putCustom(ILM_CUSTOM_METADATA_KEY, customMetadata) + .build(); + IndexMetaData shrunkIndexMetaData = IndexMetaData.builder(step.getShrunkIndexPrefix() + indexName) + .settings(settings(Version.CURRENT)).numberOfShards(randomIntBetween(1,5)) + .numberOfReplicas(randomIntBetween(1,5)) + .build(); + ClusterState originalClusterState = ClusterState.builder(ClusterName.DEFAULT) + .metaData(MetaData.builder() + .put(originalIndexMetaData, false) + .put(shrunkIndexMetaData, false)) + .build(); + + ClusterState newClusterState = step.performAction(originalIndexMetaData.getIndex(), originalClusterState); + + LifecycleExecutionState oldIndexData = LifecycleExecutionState.fromIndexMetadata(originalIndexMetaData); + LifecycleExecutionState newIndexData = LifecycleExecutionState + .fromIndexMetadata(newClusterState.metaData().index(step.getShrunkIndexPrefix() + indexName)); + + assertEquals(oldIndexData.getLifecycleDate(), newIndexData.getLifecycleDate()); + assertEquals(oldIndexData.getPhase(), newIndexData.getPhase()); + assertEquals(oldIndexData.getAction(), newIndexData.getAction()); + assertEquals(ShrunkenIndexCheckStep.NAME, newIndexData.getStep()); + } +} diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/indexlifecycle/IndexExplainResponseTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/indexlifecycle/IndexExplainResponseTests.java index f05def36c4f..1c9be6daacf 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/indexlifecycle/IndexExplainResponseTests.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/indexlifecycle/IndexExplainResponseTests.java @@ -71,10 +71,10 @@ public class IndexExplainResponseTests extends AbstractSerializingTestCase { @@ -69,8 +70,11 @@ public class InitializePolicyContextStepTests extends AbstractStepTestCase customMetadata = createCustomMetadata(); + LifecycleExecutionState parsed = LifecycleExecutionState.fromCustomMetadata(customMetadata); + assertEquals(customMetadata, parsed.asMap()); + } + + public void testEmptyValuesAreNotSerialized() { + LifecycleExecutionState empty = LifecycleExecutionState.builder().build(); + assertEquals(new HashMap().entrySet(), empty.asMap().entrySet()); + + Map originalMap = createCustomMetadata(); + LifecycleExecutionState originalState = LifecycleExecutionState.fromCustomMetadata(originalMap); + LifecycleExecutionState.Builder newState = LifecycleExecutionState.builder(originalState); + newState.setPhase(null); + assertFalse(newState.build().asMap().containsKey("phase")); + + newState = LifecycleExecutionState.builder(originalState); + newState.setAction(null); + assertFalse(newState.build().asMap().containsKey("action")); + + newState = LifecycleExecutionState.builder(originalState); + newState.setStep(null); + assertFalse(newState.build().asMap().containsKey("step")); + + newState = LifecycleExecutionState.builder(originalState); + newState.setFailedStep(null); + assertFalse(newState.build().asMap().containsKey("failed_step")); + + newState = LifecycleExecutionState.builder(originalState); + newState.setPhaseDefinition(null); + assertFalse(newState.build().asMap().containsKey("phase_definition")); + + newState = LifecycleExecutionState.builder(originalState); + newState.setStepInfo(null); + assertFalse(newState.build().asMap().containsKey("step_info")); + + newState = LifecycleExecutionState.builder(originalState); + newState.setPhaseTime(null); + assertFalse(newState.build().asMap().containsKey("phase_time")); + + newState = LifecycleExecutionState.builder(originalState); + newState.setActionTime(null); + assertFalse(newState.build().asMap().containsKey("action_time")); + + newState = LifecycleExecutionState.builder(originalState); + newState.setIndexCreationDate(null); + assertFalse(newState.build().asMap().containsKey("creation_date")); + } + + public void testEqualsAndHashcode() { + LifecycleExecutionState original = LifecycleExecutionState.fromCustomMetadata(createCustomMetadata()); + EqualsHashCodeTestUtils.checkEqualsAndHashCode( + original, + toCopy -> LifecycleExecutionState.builder(toCopy).build(), + LifecycleExecutionStateTests::mutate); + } + + private static LifecycleExecutionState mutate(LifecycleExecutionState toMutate) { + LifecycleExecutionState.Builder newState = LifecycleExecutionState.builder(toMutate); + boolean changed = false; + if (randomBoolean()) { + newState.setPhase(randomValueOtherThan(toMutate.getPhase(), () -> randomAlphaOfLengthBetween(5, 20))); + changed = true; + } + if (randomBoolean()) { + newState.setAction(randomValueOtherThan(toMutate.getAction(), () -> randomAlphaOfLengthBetween(5, 20))); + changed = true; + } + if (randomBoolean()) { + newState.setStep(randomValueOtherThan(toMutate.getStep(), () -> randomAlphaOfLengthBetween(5, 20))); + changed = true; + } + if (randomBoolean()) { + newState.setPhaseDefinition(randomValueOtherThan(toMutate.getPhaseDefinition(), () -> randomAlphaOfLengthBetween(5, 20))); + changed = true; + } + if (randomBoolean()) { + newState.setFailedStep(randomValueOtherThan(toMutate.getFailedStep(), () -> randomAlphaOfLengthBetween(5, 20))); + changed = true; + } + if (randomBoolean()) { + newState.setStepInfo(randomValueOtherThan(toMutate.getStepInfo(), () -> randomAlphaOfLengthBetween(5, 20))); + changed = true; + } + if (randomBoolean()) { + newState.setPhaseTime(randomValueOtherThan(toMutate.getPhaseTime(), ESTestCase::randomLong)); + changed = true; + } + if (randomBoolean()) { + newState.setActionTime(randomValueOtherThan(toMutate.getActionTime(), ESTestCase::randomLong)); + changed = true; + } + if (randomBoolean()) { + newState.setStepTime(randomValueOtherThan(toMutate.getStepTime(), ESTestCase::randomLong)); + changed = true; + } + if (randomBoolean()) { + newState.setIndexCreationDate(randomValueOtherThan(toMutate.getLifecycleDate(), ESTestCase::randomLong)); + changed = true; + } + + if (changed == false) { + return LifecycleExecutionState.builder().build(); + } + + return newState.build(); + } + + static Map createCustomMetadata() { + String phase = randomAlphaOfLengthBetween(5,20); + String action = randomAlphaOfLengthBetween(5,20); + String step = randomAlphaOfLengthBetween(5,20); + String failedStep = randomAlphaOfLengthBetween(5,20); + String stepInfo = randomAlphaOfLengthBetween(15,50); + String phaseDefinition = randomAlphaOfLengthBetween(15,50); + long indexCreationDate = randomLong(); + long phaseTime = randomLong(); + long actionTime = randomLong(); + long stepTime = randomLong(); + + Map customMetadata = new HashMap<>(); + customMetadata.put("phase", phase); + customMetadata.put("action", action); + customMetadata.put("step", step); + customMetadata.put("failed_step", failedStep); + customMetadata.put("step_info", stepInfo); + customMetadata.put("phase_definition", phaseDefinition); + customMetadata.put("creation_date", String.valueOf(indexCreationDate)); + customMetadata.put("phase_time", String.valueOf(phaseTime)); + customMetadata.put("action_time", String.valueOf(actionTime)); + customMetadata.put("step_time", String.valueOf(stepTime)); + return customMetadata; + } +} diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/indexlifecycle/ShrinkActionTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/indexlifecycle/ShrinkActionTests.java index 5ec140147ad..4409de2a59d 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/indexlifecycle/ShrinkActionTests.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/indexlifecycle/ShrinkActionTests.java @@ -51,13 +51,14 @@ public class ShrinkActionTests extends AbstractActionTestCase { StepKey nextStepKey = new StepKey(randomAlphaOfLengthBetween(1, 10), randomAlphaOfLengthBetween(1, 10), randomAlphaOfLengthBetween(1, 10)); List steps = action.toSteps(null, phase, nextStepKey); - assertThat(steps.size(), equalTo(6)); + assertThat(steps.size(), equalTo(7)); StepKey expectedFirstKey = new StepKey(phase, ShrinkAction.NAME, SetSingleNodeAllocateStep.NAME); StepKey expectedSecondKey = new StepKey(phase, ShrinkAction.NAME, AllocationRoutedStep.NAME); StepKey expectedThirdKey = new StepKey(phase, ShrinkAction.NAME, ShrinkStep.NAME); StepKey expectedFourthKey = new StepKey(phase, ShrinkAction.NAME, ShrunkShardsAllocatedStep.NAME); - StepKey expectedFifthKey = new StepKey(phase, ShrinkAction.NAME, ShrinkSetAliasStep.NAME); - StepKey expectedSixthKey = new StepKey(phase, ShrinkAction.NAME, ShrunkenIndexCheckStep.NAME); + StepKey expectedFifthKey = new StepKey(phase, ShrinkAction.NAME, CopyExecutionStateStep.NAME); + StepKey expectedSixthKey = new StepKey(phase, ShrinkAction.NAME, ShrinkSetAliasStep.NAME); + StepKey expectedSeventhKey = new StepKey(phase, ShrinkAction.NAME, ShrunkenIndexCheckStep.NAME); assertTrue(steps.get(0) instanceof SetSingleNodeAllocateStep); assertThat(steps.get(0).getKey(), equalTo(expectedFirstKey)); assertThat(steps.get(0).getNextStepKey(), equalTo(expectedSecondKey)); @@ -74,14 +75,18 @@ public class ShrinkActionTests extends AbstractActionTestCase { assertThat(steps.get(3).getKey(), equalTo(expectedFourthKey)); assertThat(steps.get(3).getNextStepKey(), equalTo(expectedFifthKey)); assertThat(((ShrunkShardsAllocatedStep) steps.get(3)).getShrunkIndexPrefix(), equalTo(ShrinkAction.SHRUNKEN_INDEX_PREFIX)); - assertTrue(steps.get(4) instanceof ShrinkSetAliasStep); + assertTrue(steps.get(4) instanceof CopyExecutionStateStep); assertThat(steps.get(4).getKey(), equalTo(expectedFifthKey)); assertThat(steps.get(4).getNextStepKey(), equalTo(expectedSixthKey)); - assertThat(((ShrinkSetAliasStep) steps.get(4)).getShrunkIndexPrefix(), equalTo(ShrinkAction.SHRUNKEN_INDEX_PREFIX)); - assertTrue(steps.get(5) instanceof ShrunkenIndexCheckStep); + assertThat(((CopyExecutionStateStep) steps.get(4)).getShrunkIndexPrefix(), equalTo(ShrinkAction.SHRUNKEN_INDEX_PREFIX)); + assertTrue(steps.get(5) instanceof ShrinkSetAliasStep); assertThat(steps.get(5).getKey(), equalTo(expectedSixthKey)); - assertThat(steps.get(5).getNextStepKey(), equalTo(nextStepKey)); - assertThat(((ShrunkenIndexCheckStep) steps.get(5)).getShrunkIndexPrefix(), equalTo(ShrinkAction.SHRUNKEN_INDEX_PREFIX)); + assertThat(steps.get(5).getNextStepKey(), equalTo(expectedSeventhKey)); + assertThat(((ShrinkSetAliasStep) steps.get(5)).getShrunkIndexPrefix(), equalTo(ShrinkAction.SHRUNKEN_INDEX_PREFIX)); + assertTrue(steps.get(6) instanceof ShrunkenIndexCheckStep); + assertThat(steps.get(6).getKey(), equalTo(expectedSeventhKey)); + assertThat(steps.get(6).getNextStepKey(), equalTo(nextStepKey)); + assertThat(((ShrunkenIndexCheckStep) steps.get(6)).getShrunkIndexPrefix(), equalTo(ShrinkAction.SHRUNKEN_INDEX_PREFIX)); } @Override diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/indexlifecycle/ShrinkStepTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/indexlifecycle/ShrinkStepTests.java index c66a29cb8b3..820d1d15ded 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/indexlifecycle/ShrinkStepTests.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/indexlifecycle/ShrinkStepTests.java @@ -27,6 +27,7 @@ import org.mockito.stubbing.Answer; import java.util.Collections; +import static org.elasticsearch.xpack.core.indexlifecycle.LifecycleExecutionState.ILM_CUSTOM_METADATA_KEY; import static org.hamcrest.Matchers.equalTo; public class ShrinkStepTests extends AbstractStepTestCase { @@ -82,16 +83,17 @@ public class ShrinkStepTests extends AbstractStepTestCase { public void testPerformAction() throws Exception { String lifecycleName = randomAlphaOfLength(5); - long creationDate = randomNonNegativeLong(); ShrinkStep step = createRandomInstance(); + LifecycleExecutionState.Builder lifecycleState = LifecycleExecutionState.builder(); + lifecycleState.setPhase(step.getKey().getPhase()); + lifecycleState.setAction(step.getKey().getAction()); + lifecycleState.setStep(step.getKey().getName()); + lifecycleState.setIndexCreationDate(randomNonNegativeLong()); IndexMetaData sourceIndexMetaData = IndexMetaData.builder(randomAlphaOfLength(10)) .settings(settings(Version.CURRENT) - .put(LifecycleSettings.LIFECYCLE_INDEX_CREATION_DATE, creationDate) .put(LifecycleSettings.LIFECYCLE_NAME, lifecycleName) - .put(LifecycleSettings.LIFECYCLE_PHASE, step.getKey().getPhase()) - .put(LifecycleSettings.LIFECYCLE_ACTION, step.getKey().getAction()) - .put(LifecycleSettings.LIFECYCLE_STEP, ShrunkenIndexCheckStep.NAME) ) + .putCustom(ILM_CUSTOM_METADATA_KEY, lifecycleState.build().asMap()) .numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)) .putAlias(AliasMetaData.builder("my_alias")) .build(); @@ -114,11 +116,7 @@ public class ShrinkStepTests extends AbstractStepTestCase { assertThat(request.getTargetIndexRequest().settings(), equalTo(Settings.builder() .put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, step.getNumberOfShards()) .put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, sourceIndexMetaData.getNumberOfReplicas()) - .put(LifecycleSettings.LIFECYCLE_INDEX_CREATION_DATE, creationDate) .put(LifecycleSettings.LIFECYCLE_NAME, lifecycleName) - .put(LifecycleSettings.LIFECYCLE_PHASE, step.getKey().getPhase()) - .put(LifecycleSettings.LIFECYCLE_ACTION, step.getKey().getAction()) - .put(LifecycleSettings.LIFECYCLE_STEP, ShrunkenIndexCheckStep.NAME) .put(IndexMetaData.INDEX_ROUTING_REQUIRE_GROUP_SETTING.getKey() + "_name", (String) null) .build())); assertThat(request.getTargetIndexRequest().settings() @@ -151,7 +149,10 @@ public class ShrinkStepTests extends AbstractStepTestCase { } public void testPerformActionNotComplete() throws Exception { + LifecycleExecutionState.Builder lifecycleState = LifecycleExecutionState.builder(); + lifecycleState.setIndexCreationDate(randomNonNegativeLong()); IndexMetaData indexMetaData = IndexMetaData.builder(randomAlphaOfLength(10)).settings(settings(Version.CURRENT)) + .putCustom(ILM_CUSTOM_METADATA_KEY, lifecycleState.build().asMap()) .numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build(); ShrinkStep step = createRandomInstance(); @@ -194,7 +195,10 @@ public class ShrinkStepTests extends AbstractStepTestCase { } public void testPerformActionFailure() throws Exception { + LifecycleExecutionState.Builder lifecycleState = LifecycleExecutionState.builder(); + lifecycleState.setIndexCreationDate(randomNonNegativeLong()); IndexMetaData indexMetaData = IndexMetaData.builder(randomAlphaOfLength(10)).settings(settings(Version.CURRENT)) + .putCustom(ILM_CUSTOM_METADATA_KEY, lifecycleState.build().asMap()) .numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build(); Exception exception = new RuntimeException(); ShrinkStep step = createRandomInstance(); diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/indexlifecycle/UpdateRolloverLifecycleDateStepTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/indexlifecycle/UpdateRolloverLifecycleDateStepTests.java index 96cbe1e8a3a..5a4c88eaa6a 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/indexlifecycle/UpdateRolloverLifecycleDateStepTests.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/indexlifecycle/UpdateRolloverLifecycleDateStepTests.java @@ -67,8 +67,9 @@ public class UpdateRolloverLifecycleDateStepTests extends AbstractStepTestCase= 0 : "expected index to have a lifecycle date but it did not"; + final Long lifecycleDate = lifecycleState.getLifecycleDate(); + assert lifecycleDate != null && lifecycleDate >= 0 : "expected index to have a lifecycle date but it did not"; final TimeValue after = stepRegistry.getIndexAgeForPhase(policy, phase); final long now = nowSupplier.getAsLong(); final TimeValue age = new TimeValue(now - lifecycleDate); @@ -80,18 +83,19 @@ public class IndexLifecycleRunner { } public void runPolicy(String policy, IndexMetaData indexMetaData, ClusterState currentState, - boolean fromClusterStateChange) { + boolean fromClusterStateChange) { Settings indexSettings = indexMetaData.getSettings(); + LifecycleExecutionState lifecycleState = LifecycleExecutionState.fromIndexMetadata(indexMetaData); if (LifecycleSettings.LIFECYCLE_SKIP_SETTING.get(indexSettings)) { logger.info("skipping policy [" + policy + "] for index [" + indexMetaData.getIndex().getName() + "]." + LifecycleSettings.LIFECYCLE_SKIP + "== true"); return; } - Step currentStep = getCurrentStep(stepRegistry, policy, indexMetaData, indexSettings); + Step currentStep = getCurrentStep(stepRegistry, policy, indexMetaData, lifecycleState); if (currentStep == null) { // This may happen in the case that there is invalid ilm-step index settings or the stepRegistry is out of // sync with the current cluster state - logger.warn("current step [" + getCurrentStepKey(indexSettings) + "] for index [" + indexMetaData.getIndex().getName() + logger.warn("current step [" + getCurrentStepKey(lifecycleState) + "] for index [" + indexMetaData.getIndex().getName() + "] with policy [" + policy + "] is not recognized"); return; } @@ -154,7 +158,7 @@ public class IndexLifecycleRunner { } } else { throw new IllegalStateException( - "Step with key [" + currentStep.getKey() + "] is not a recognised type: [" + currentStep.getClass().getName() + "]"); + "Step with key [" + currentStep.getKey() + "] is not a recognised type: [" + currentStep.getClass().getName() + "]"); } } @@ -179,13 +183,12 @@ public class IndexLifecycleRunner { * or for the step to be unset with the phase and/or action set. All three * settings must be either present or missing. * - * @param indexSettings - * the index settings to extract the {@link StepKey} from. + * @param lifecycleState the index custom data to extract the {@link StepKey} from. */ - public static StepKey getCurrentStepKey(Settings indexSettings) { - String currentPhase = LifecycleSettings.LIFECYCLE_PHASE_SETTING.get(indexSettings); - String currentAction = LifecycleSettings.LIFECYCLE_ACTION_SETTING.get(indexSettings); - String currentStep = LifecycleSettings.LIFECYCLE_STEP_SETTING.get(indexSettings); + public static StepKey getCurrentStepKey(LifecycleExecutionState lifecycleState) { + String currentPhase = lifecycleState.getPhase(); + String currentAction = lifecycleState.getAction(); + String currentStep = lifecycleState.getStep(); if (Strings.isNullOrEmpty(currentStep)) { assert Strings.isNullOrEmpty(currentPhase) : "Current phase is not empty: " + currentPhase; assert Strings.isNullOrEmpty(currentAction) : "Current action is not empty: " + currentAction; @@ -197,8 +200,9 @@ public class IndexLifecycleRunner { } } - static Step getCurrentStep(PolicyStepsRegistry stepRegistry, String policy, IndexMetaData indexMetaData, Settings indexSettings) { - StepKey currentStepKey = getCurrentStepKey(indexSettings); + static Step getCurrentStep(PolicyStepsRegistry stepRegistry, String policy, IndexMetaData indexMetaData, + LifecycleExecutionState lifecycleState) { + StepKey currentStepKey = getCurrentStepKey(lifecycleState); if (currentStepKey == null) { return stepRegistry.getFirstStep(policy); } else { @@ -209,18 +213,13 @@ public class IndexLifecycleRunner { /** * This method is intended for handling moving to different steps from {@link TransportAction} executions. * For this reason, it is reasonable to throw {@link IllegalArgumentException} when state is not as expected. - * @param indexName - * The index whose step is to change - * @param currentState - * The current {@link ClusterState} - * @param currentStepKey - * The current {@link StepKey} found for the index in the current cluster state - * @param nextStepKey - * The next step to move the index into - * @param nowSupplier - * The current-time supplier for updating when steps changed - * @param stepRegistry - * The steps registry to check a step-key's existence in the index's current policy + * + * @param indexName The index whose step is to change + * @param currentState The current {@link ClusterState} + * @param currentStepKey The current {@link StepKey} found for the index in the current cluster state + * @param nextStepKey The next step to move the index into + * @param nowSupplier The current-time supplier for updating when steps changed + * @param stepRegistry The steps registry to check a step-key's existence in the index's current policy * @return The updated cluster state where the index moved to nextStepKey */ static ClusterState moveClusterStateToStep(String indexName, ClusterState currentState, StepKey currentStepKey, @@ -235,7 +234,8 @@ public class IndexLifecycleRunner { throw new IllegalArgumentException("index [" + indexName + "] is not associated with an Index Lifecycle Policy"); } - if (currentStepKey.equals(IndexLifecycleRunner.getCurrentStepKey(indexSettings)) == false) { + LifecycleExecutionState lifecycleState = LifecycleExecutionState.fromIndexMetadata(idxMeta); + if (currentStepKey.equals(IndexLifecycleRunner.getCurrentStepKey(lifecycleState)) == false) { throw new IllegalArgumentException("index [" + indexName + "] is not on current step [" + currentStepKey + "]"); } @@ -248,19 +248,21 @@ public class IndexLifecycleRunner { } static ClusterState moveClusterStateToNextStep(Index index, ClusterState clusterState, StepKey currentStep, StepKey nextStep, - LongSupplier nowSupplier) { + LongSupplier nowSupplier) { IndexMetaData idxMeta = clusterState.getMetaData().index(index); IndexLifecycleMetadata ilmMeta = clusterState.metaData().custom(IndexLifecycleMetadata.TYPE); LifecyclePolicyMetadata policyMetadata = ilmMeta.getPolicyMetadatas() .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); + LifecycleExecutionState lifecycleState = LifecycleExecutionState.fromIndexMetadata(idxMeta); + LifecycleExecutionState newLifecycleState = moveExecutionStateToNextStep(policyMetadata, + lifecycleState, currentStep, nextStep, nowSupplier); + ClusterState.Builder newClusterStateBuilder = newClusterStateWithLifecycleState(index, clusterState, newLifecycleState); + return newClusterStateBuilder.build(); } static ClusterState moveClusterStateToErrorStep(Index index, ClusterState clusterState, StepKey currentStep, Exception cause, - LongSupplier nowSupplier) throws IOException { + LongSupplier nowSupplier) throws IOException { IndexMetaData idxMeta = clusterState.getMetaData().index(index); IndexLifecycleMetadata ilmMeta = clusterState.metaData().custom(IndexLifecycleMetadata.TYPE); LifecyclePolicyMetadata policyMetadata = ilmMeta.getPolicyMetadatas() @@ -269,11 +271,13 @@ public class IndexLifecycleRunner { causeXContentBuilder.startObject(); ElasticsearchException.generateThrowableXContent(causeXContentBuilder, ToXContent.EMPTY_PARAMS, cause); causeXContentBuilder.endObject(); - Settings.Builder indexSettings = moveIndexSettingsToNextStep(policyMetadata, idxMeta.getSettings(), currentStep, - new StepKey(currentStep.getPhase(), currentStep.getAction(), ErrorStep.NAME), nowSupplier) - .put(LifecycleSettings.LIFECYCLE_FAILED_STEP, currentStep.getName()) - .put(LifecycleSettings.LIFECYCLE_STEP_INFO, BytesReference.bytes(causeXContentBuilder).utf8ToString()); - ClusterState.Builder newClusterStateBuilder = newClusterStateWithIndexSettings(index, clusterState, indexSettings); + LifecycleExecutionState nextStepState = moveExecutionStateToNextStep(policyMetadata, + LifecycleExecutionState.fromIndexMetadata(idxMeta), currentStep, new StepKey(currentStep.getPhase(), + currentStep.getAction(), ErrorStep.NAME), nowSupplier); + LifecycleExecutionState.Builder failedState = LifecycleExecutionState.builder(nextStepState); + failedState.setFailedStep(currentStep.getName()); + failedState.setStepInfo(BytesReference.bytes(causeXContentBuilder).utf8ToString()); + ClusterState.Builder newClusterStateBuilder = newClusterStateWithLifecycleState(index, clusterState, failedState.build()); return newClusterStateBuilder.build(); } @@ -284,8 +288,9 @@ public class IndexLifecycleRunner { if (indexMetaData == null) { throw new IllegalArgumentException("index [" + index + "] does not exist"); } - StepKey currentStepKey = IndexLifecycleRunner.getCurrentStepKey(indexMetaData.getSettings()); - String failedStep = LifecycleSettings.LIFECYCLE_FAILED_STEP_SETTING.get(indexMetaData.getSettings()); + LifecycleExecutionState lifecycleState = LifecycleExecutionState.fromIndexMetadata(indexMetaData); + StepKey currentStepKey = IndexLifecycleRunner.getCurrentStepKey(lifecycleState); + String failedStep = lifecycleState.getFailedStep(); if (currentStepKey != null && ErrorStep.NAME.equals(currentStepKey.getName()) && Strings.isNullOrEmpty(failedStep) == false) { StepKey nextStepKey = new StepKey(currentStepKey.getPhase(), currentStepKey.getAction(), failedStep); @@ -298,15 +303,21 @@ public class IndexLifecycleRunner { return newState; } - private static Settings.Builder moveIndexSettingsToNextStep(LifecyclePolicyMetadata policyMetadata, Settings existingSettings, - StepKey currentStep, StepKey nextStep, LongSupplier nowSupplier) { + private static LifecycleExecutionState moveExecutionStateToNextStep(LifecyclePolicyMetadata policyMetadata, + LifecycleExecutionState existingState, + StepKey currentStep, StepKey nextStep, + LongSupplier nowSupplier) { long nowAsMillis = nowSupplier.getAsLong(); - Settings.Builder newSettings = Settings.builder().put(existingSettings).put(LifecycleSettings.LIFECYCLE_PHASE, nextStep.getPhase()) - .put(LifecycleSettings.LIFECYCLE_ACTION, nextStep.getAction()).put(LifecycleSettings.LIFECYCLE_STEP, nextStep.getName()) - .put(LifecycleSettings.LIFECYCLE_STEP_TIME, nowAsMillis) - // clear any step info or error-related settings from the current step - .put(LifecycleSettings.LIFECYCLE_FAILED_STEP, (String) null) - .put(LifecycleSettings.LIFECYCLE_STEP_INFO, (String) null); + LifecycleExecutionState.Builder updatedState = LifecycleExecutionState.builder(existingState); + updatedState.setPhase(nextStep.getPhase()); + updatedState.setAction(nextStep.getAction()); + updatedState.setStep(nextStep.getName()); + updatedState.setStepTime(nowAsMillis); + + // clear any step info or error-related settings from the current step + updatedState.setFailedStep(null); + updatedState.setStepInfo(null); + if (currentStep.getPhase().equals(nextStep.getPhase()) == false) { final String newPhaseDefinition; final Phase nextPhase; @@ -318,20 +329,21 @@ public class IndexLifecycleRunner { 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_TIME, nowAsMillis); + updatedState.setPhaseDefinition(newPhaseDefinition); + updatedState.setPhaseTime(nowAsMillis); } if (currentStep.getAction().equals(nextStep.getAction()) == false) { - newSettings.put(LifecycleSettings.LIFECYCLE_ACTION_TIME, nowAsMillis); + updatedState.setActionTime(nowAsMillis); } - return newSettings; + return updatedState.build(); } - static ClusterState.Builder newClusterStateWithIndexSettings(Index index, ClusterState clusterState, - Settings.Builder newSettings) { + static ClusterState.Builder newClusterStateWithLifecycleState(Index index, ClusterState clusterState, + LifecycleExecutionState lifecycleState) { ClusterState.Builder newClusterStateBuilder = ClusterState.builder(clusterState); newClusterStateBuilder.metaData(MetaData.builder(clusterState.getMetaData()) - .put(IndexMetaData.builder(clusterState.getMetaData().index(index)).settings(newSettings))); + .put(IndexMetaData.builder(clusterState.getMetaData().index(index)) + .putCustom(ILM_CUSTOM_METADATA_KEY, lifecycleState.asMap()))); return newClusterStateBuilder; } @@ -340,39 +352,44 @@ public class IndexLifecycleRunner { * built if the step info has changed, otherwise the same old clusterState is * returned * - * @param index the index to modify + * @param index the index to modify * @param clusterState the cluster state to modify - * @param stepInfo the new step info to update + * @param stepInfo the new step info to update * @return Updated cluster state with stepInfo if changed, otherwise the same cluster state - * if no changes to step info exist + * if no changes to step info exist * @throws IOException if parsing step info fails */ static ClusterState addStepInfoToClusterState(Index index, ClusterState clusterState, ToXContentObject stepInfo) throws IOException { - IndexMetaData idxMeta = clusterState.getMetaData().index(index); + IndexMetaData indexMetaData = clusterState.getMetaData().index(index); + if (indexMetaData == null) { + // This index doesn't exist anymore, we can't do anything + return clusterState; + } + LifecycleExecutionState lifecycleState = LifecycleExecutionState.fromIndexMetadata(indexMetaData); final String stepInfoString; try (XContentBuilder infoXContentBuilder = JsonXContent.contentBuilder()) { stepInfo.toXContent(infoXContentBuilder, ToXContent.EMPTY_PARAMS); stepInfoString = BytesReference.bytes(infoXContentBuilder).utf8ToString(); } - if (stepInfoString.equals(LifecycleSettings.LIFECYCLE_STEP_INFO_SETTING.get(idxMeta.getSettings()))) { + if (stepInfoString.equals(lifecycleState.getStepInfo())) { return clusterState; } - Settings.Builder indexSettings = Settings.builder().put(idxMeta.getSettings()) - .put(LifecycleSettings.LIFECYCLE_STEP_INFO_SETTING.getKey(), stepInfoString); - ClusterState.Builder newClusterStateBuilder = newClusterStateWithIndexSettings(index, clusterState, indexSettings); + LifecycleExecutionState.Builder newState = LifecycleExecutionState.builder(lifecycleState); + newState.setStepInfo(stepInfoString); + ClusterState.Builder newClusterStateBuilder = newClusterStateWithLifecycleState(index, clusterState, newState.build()); return newClusterStateBuilder.build(); } private void moveToStep(Index index, String policy, StepKey currentStepKey, StepKey nextStepKey) { logger.debug("moveToStep[" + policy + "] [" + index.getName() + "]" + currentStepKey + " -> " - + nextStepKey); + + nextStepKey); clusterService.submitStateUpdateTask("ILM", new MoveToNextStepUpdateTask(index, policy, currentStepKey, - nextStepKey, nowSupplier)); + nextStepKey, nowSupplier)); } private void moveToErrorStep(Index index, String policy, StepKey currentStepKey, Exception e) { logger.error("policy [" + policy + "] for index [" + index.getName() + "] failed on step [" + currentStepKey - + "]. Moving to ERROR step.", e); + + "]. Moving to ERROR step.", e); clusterService.submitStateUpdateTask("ILM", new MoveToErrorStepUpdateTask(index, policy, currentStepKey, e, nowSupplier)); } @@ -381,7 +398,8 @@ public class IndexLifecycleRunner { } public static ClusterState setPolicyForIndexes(final String newPolicyName, final Index[] indices, ClusterState currentState, - LifecyclePolicyMetadata newPolicyMetadata, List failedIndexes, LongSupplier nowSupplier) { + LifecyclePolicyMetadata newPolicyMetadata, List failedIndexes, + LongSupplier nowSupplier) { MetaData.Builder newMetadata = MetaData.builder(currentState.getMetaData()); boolean clusterStateChanged = false; for (Index index : indices) { @@ -409,20 +427,22 @@ public class IndexLifecycleRunner { private static IndexMetaData.Builder setPolicyForIndex(final String newPolicyName, LifecyclePolicyMetadata newPolicyMetadata, IndexMetaData indexMetadata, LongSupplier nowSupplier) { - Settings idxSettings = indexMetadata.getSettings(); - StepKey currentStepKey = IndexLifecycleRunner.getCurrentStepKey(idxSettings); + LifecycleExecutionState lifecycleState = LifecycleExecutionState.fromIndexMetadata(indexMetadata); + StepKey currentStepKey = IndexLifecycleRunner.getCurrentStepKey(lifecycleState); - Settings.Builder newSettings = Settings.builder().put(idxSettings); + LifecycleExecutionState newState = LifecycleExecutionState.builder(lifecycleState).build(); if (currentStepKey != null) { // Check if current step exists in new policy and if not move to // next available step StepKey nextValidStepKey = newPolicyMetadata.getPolicy().getNextValidStep(currentStepKey); if (nextValidStepKey.equals(currentStepKey) == false) { - newSettings = moveIndexSettingsToNextStep(newPolicyMetadata, idxSettings, currentStepKey, nextValidStepKey, nowSupplier); + newState = moveExecutionStateToNextStep(newPolicyMetadata, lifecycleState, currentStepKey, nextValidStepKey, nowSupplier); } } + + Settings.Builder newSettings = Settings.builder().put(indexMetadata.getSettings()); newSettings.put(LifecycleSettings.LIFECYCLE_NAME_SETTING.getKey(), newPolicyName); - return IndexMetaData.builder(indexMetadata).settings(newSettings); + return IndexMetaData.builder(indexMetadata).settings(newSettings).putCustom(ILM_CUSTOM_METADATA_KEY, newState.asMap()); } public static ClusterState removePolicyForIndexes(final Index[] indices, ClusterState currentState, List failedIndexes) { @@ -455,17 +475,11 @@ public class IndexLifecycleRunner { Settings.Builder newSettings = Settings.builder().put(idxSettings); newSettings.remove(LifecycleSettings.LIFECYCLE_NAME_SETTING.getKey()); - newSettings.remove(LifecycleSettings.LIFECYCLE_PHASE_SETTING.getKey()); - newSettings.remove(LifecycleSettings.LIFECYCLE_PHASE_TIME_SETTING.getKey()); - newSettings.remove(LifecycleSettings.LIFECYCLE_ACTION_SETTING.getKey()); - newSettings.remove(LifecycleSettings.LIFECYCLE_ACTION_TIME_SETTING.getKey()); - newSettings.remove(LifecycleSettings.LIFECYCLE_STEP_SETTING.getKey()); - newSettings.remove(LifecycleSettings.LIFECYCLE_STEP_TIME_SETTING.getKey()); - newSettings.remove(LifecycleSettings.LIFECYCLE_STEP_INFO_SETTING.getKey()); - newSettings.remove(LifecycleSettings.LIFECYCLE_FAILED_STEP_SETTING.getKey()); - newSettings.remove(LifecycleSettings.LIFECYCLE_INDEX_CREATION_DATE_SETTING.getKey()); newSettings.remove(LifecycleSettings.LIFECYCLE_SKIP_SETTING.getKey()); newSettings.remove(RolloverAction.LIFECYCLE_ROLLOVER_ALIAS_SETTING.getKey()); - return IndexMetaData.builder(indexMetadata).settings(newSettings); + + return IndexMetaData.builder(indexMetadata) + .removeCustom(ILM_CUSTOM_METADATA_KEY) + .settings(newSettings); } } diff --git a/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/indexlifecycle/IndexLifecycleService.java b/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/indexlifecycle/IndexLifecycleService.java index 23a8b16ee58..a96020b9958 100644 --- a/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/indexlifecycle/IndexLifecycleService.java +++ b/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/indexlifecycle/IndexLifecycleService.java @@ -6,7 +6,6 @@ package org.elasticsearch.xpack.indexlifecycle; import com.carrotsearch.hppc.cursors.ObjectCursor; - import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.lucene.util.SetOnce; @@ -25,6 +24,7 @@ import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.common.xcontent.NamedXContentRegistry; import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.xpack.core.XPackField; +import org.elasticsearch.xpack.core.indexlifecycle.LifecycleExecutionState; import org.elasticsearch.xpack.core.indexlifecycle.IndexLifecycleMetadata; import org.elasticsearch.xpack.core.indexlifecycle.LifecyclePolicy; import org.elasticsearch.xpack.core.indexlifecycle.LifecycleSettings; @@ -192,7 +192,7 @@ public class IndexLifecycleService extends AbstractComponent IndexMetaData idxMeta = cursor.value; String policyName = LifecycleSettings.LIFECYCLE_NAME_SETTING.get(idxMeta.getSettings()); if (Strings.isNullOrEmpty(policyName) == false) { - StepKey stepKey = IndexLifecycleRunner.getCurrentStepKey(idxMeta.getSettings()); + StepKey stepKey = IndexLifecycleRunner.getCurrentStepKey(LifecycleExecutionState.fromIndexMetadata(idxMeta)); if (OperationMode.STOPPING == currentMode && stepKey != null && IGNORE_ACTIONS_MAINTENANCE_REQUESTED.contains(stepKey.getAction()) == false) { logger.info("skipping policy [" + policyName + "] for index [" + idxMeta.getIndex().getName() diff --git a/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/indexlifecycle/MoveToErrorStepUpdateTask.java b/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/indexlifecycle/MoveToErrorStepUpdateTask.java index b4352246182..5af1a05309e 100644 --- a/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/indexlifecycle/MoveToErrorStepUpdateTask.java +++ b/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/indexlifecycle/MoveToErrorStepUpdateTask.java @@ -11,6 +11,7 @@ import org.elasticsearch.cluster.ClusterStateUpdateTask; import org.elasticsearch.cluster.metadata.IndexMetaData; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.index.Index; +import org.elasticsearch.xpack.core.indexlifecycle.LifecycleExecutionState; import org.elasticsearch.xpack.core.indexlifecycle.LifecycleSettings; import org.elasticsearch.xpack.core.indexlifecycle.Step; @@ -56,8 +57,9 @@ public class MoveToErrorStepUpdateTask extends ClusterStateUpdateTask { return currentState; } Settings indexSettings = idxMeta.getSettings(); + LifecycleExecutionState indexILMData = LifecycleExecutionState.fromIndexMetadata(idxMeta); if (policy.equals(LifecycleSettings.LIFECYCLE_NAME_SETTING.get(indexSettings)) - && currentStepKey.equals(IndexLifecycleRunner.getCurrentStepKey(indexSettings))) { + && currentStepKey.equals(IndexLifecycleRunner.getCurrentStepKey(indexILMData))) { return IndexLifecycleRunner.moveClusterStateToErrorStep(index, currentState, currentStepKey, cause, nowSupplier); } else { // either the policy has changed or the step is now diff --git a/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/indexlifecycle/MoveToNextStepUpdateTask.java b/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/indexlifecycle/MoveToNextStepUpdateTask.java index 96776d4e61c..f7aabce7778 100644 --- a/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/indexlifecycle/MoveToNextStepUpdateTask.java +++ b/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/indexlifecycle/MoveToNextStepUpdateTask.java @@ -11,6 +11,7 @@ import org.elasticsearch.cluster.ClusterStateUpdateTask; import org.elasticsearch.cluster.metadata.IndexMetaData; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.index.Index; +import org.elasticsearch.xpack.core.indexlifecycle.LifecycleExecutionState; import org.elasticsearch.xpack.core.indexlifecycle.LifecycleSettings; import org.elasticsearch.xpack.core.indexlifecycle.Step; @@ -56,8 +57,9 @@ public class MoveToNextStepUpdateTask extends ClusterStateUpdateTask { return currentState; } Settings indexSettings = indexMetaData.getSettings(); + LifecycleExecutionState indexILMData = LifecycleExecutionState.fromIndexMetadata(currentState.getMetaData().index(index)); if (policy.equals(LifecycleSettings.LIFECYCLE_NAME_SETTING.get(indexSettings)) - && currentStepKey.equals(IndexLifecycleRunner.getCurrentStepKey(indexSettings))) { + && currentStepKey.equals(IndexLifecycleRunner.getCurrentStepKey(indexILMData))) { return IndexLifecycleRunner.moveClusterStateToNextStep(index, currentState, currentStepKey, nextStepKey, nowSupplier); } else { // either the policy has changed or the step is now diff --git a/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/indexlifecycle/PolicyStepsRegistry.java b/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/indexlifecycle/PolicyStepsRegistry.java index 8ec789f5390..89b8c9b4319 100644 --- a/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/indexlifecycle/PolicyStepsRegistry.java +++ b/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/indexlifecycle/PolicyStepsRegistry.java @@ -27,6 +27,7 @@ import org.elasticsearch.xpack.core.ClientHelper; import org.elasticsearch.xpack.core.indexlifecycle.ErrorStep; import org.elasticsearch.xpack.core.indexlifecycle.IndexLifecycleMetadata; import org.elasticsearch.xpack.core.indexlifecycle.InitializePolicyContextStep; +import org.elasticsearch.xpack.core.indexlifecycle.LifecycleExecutionState; import org.elasticsearch.xpack.core.indexlifecycle.LifecyclePolicy; import org.elasticsearch.xpack.core.indexlifecycle.LifecyclePolicyMetadata; import org.elasticsearch.xpack.core.indexlifecycle.LifecycleSettings; @@ -40,6 +41,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.SortedMap; import java.util.TreeMap; import java.util.stream.Collectors; @@ -187,10 +189,9 @@ public class PolicyStepsRegistry { throw new IllegalArgumentException("failed to retrieve step " + stepKey + " as index [" + index.getName() + "] has no policy"); } - // parse phase steps from the phase definition in the index settings - final String phaseJson = indexMetaData.getSettings().get(LifecycleSettings.LIFECYCLE_PHASE_DEFINITION, - InitializePolicyContextStep.INITIALIZATION_PHASE); + final String phaseJson = Optional.ofNullable(LifecycleExecutionState.fromIndexMetadata(indexMetaData).getPhaseDefinition()) + .orElse(InitializePolicyContextStep.INITIALIZATION_PHASE); final List phaseSteps; try { diff --git a/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/indexlifecycle/SetStepInfoUpdateTask.java b/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/indexlifecycle/SetStepInfoUpdateTask.java index 273da9e5e17..bbba07fd852 100644 --- a/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/indexlifecycle/SetStepInfoUpdateTask.java +++ b/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/indexlifecycle/SetStepInfoUpdateTask.java @@ -13,6 +13,7 @@ import org.elasticsearch.cluster.metadata.IndexMetaData; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.xcontent.ToXContentObject; import org.elasticsearch.index.Index; +import org.elasticsearch.xpack.core.indexlifecycle.LifecycleExecutionState; import org.elasticsearch.xpack.core.indexlifecycle.LifecycleSettings; import org.elasticsearch.xpack.core.indexlifecycle.Step; @@ -55,8 +56,9 @@ public class SetStepInfoUpdateTask extends ClusterStateUpdateTask { return currentState; } Settings indexSettings = idxMeta.getSettings(); + LifecycleExecutionState indexILMData = LifecycleExecutionState.fromIndexMetadata(idxMeta); if (policy.equals(LifecycleSettings.LIFECYCLE_NAME_SETTING.get(indexSettings)) - && currentStepKey.equals(IndexLifecycleRunner.getCurrentStepKey(indexSettings))) { + && currentStepKey.equals(IndexLifecycleRunner.getCurrentStepKey(indexILMData))) { return IndexLifecycleRunner.addStepInfoToClusterState(index, currentState, stepInfo); } else { // either the policy has changed or the step is now diff --git a/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/indexlifecycle/action/TransportExplainLifecycleAction.java b/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/indexlifecycle/action/TransportExplainLifecycleAction.java index 5c4eaeeef5a..5695c207029 100644 --- a/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/indexlifecycle/action/TransportExplainLifecycleAction.java +++ b/x-pack/plugin/ilm/src/main/java/org/elasticsearch/xpack/indexlifecycle/action/TransportExplainLifecycleAction.java @@ -24,11 +24,12 @@ 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.threadpool.ThreadPool; +import org.elasticsearch.transport.TransportService; import org.elasticsearch.xpack.core.indexlifecycle.ExplainLifecycleRequest; import org.elasticsearch.xpack.core.indexlifecycle.ExplainLifecycleResponse; import org.elasticsearch.xpack.core.indexlifecycle.IndexLifecycleExplainResponse; -import org.elasticsearch.threadpool.ThreadPool; -import org.elasticsearch.transport.TransportService; +import org.elasticsearch.xpack.core.indexlifecycle.LifecycleExecutionState; import org.elasticsearch.xpack.core.indexlifecycle.LifecycleSettings; import org.elasticsearch.xpack.core.indexlifecycle.PhaseExecutionInfo; import org.elasticsearch.xpack.core.indexlifecycle.action.ExplainLifecycleAction; @@ -76,10 +77,16 @@ public class TransportExplainLifecycleAction for (String index : concreteIndices) { IndexMetaData idxMetadata = state.metaData().index(index); Settings idxSettings = idxMetadata.getSettings(); + LifecycleExecutionState lifecycleState = LifecycleExecutionState.fromIndexMetadata(idxMetadata); String policyName = LifecycleSettings.LIFECYCLE_NAME_SETTING.get(idxSettings); - String currentPhase = LifecycleSettings.LIFECYCLE_PHASE_SETTING.get(idxSettings); + String currentPhase = lifecycleState.getPhase(); + String stepInfo = lifecycleState.getStepInfo(); + BytesArray stepInfoBytes = null; + if (stepInfo != null) { + stepInfoBytes = new BytesArray(stepInfo); + } // parse existing phase steps from the phase definition in the index settings - String phaseDef = idxSettings.get(LifecycleSettings.LIFECYCLE_PHASE_DEFINITION); + String phaseDef = lifecycleState.getPhaseDefinition(); PhaseExecutionInfo phaseExecutionInfo = null; if (Strings.isNullOrEmpty(phaseDef) == false) { try (XContentParser parser = JsonXContent.jsonXContent.createParser(xContentRegistry, @@ -87,7 +94,7 @@ public class TransportExplainLifecycleAction phaseExecutionInfo = PhaseExecutionInfo.parse(parser, currentPhase); } catch (IOException e) { listener.onFailure(new ElasticsearchParseException( - "failed to parse [" + LifecycleSettings.LIFECYCLE_PHASE_DEFINITION + "] for index [" + index + "]", e)); + "failed to parse phase definition for index [" + index + "]", e)); return; } } @@ -95,15 +102,15 @@ public class TransportExplainLifecycleAction if (Strings.hasLength(policyName)) { indexResponse = IndexLifecycleExplainResponse.newManagedIndexResponse(index, policyName, LifecycleSettings.LIFECYCLE_SKIP_SETTING.get(idxSettings), - LifecycleSettings.LIFECYCLE_INDEX_CREATION_DATE_SETTING.get(idxSettings), - LifecycleSettings.LIFECYCLE_PHASE_SETTING.get(idxSettings), - LifecycleSettings.LIFECYCLE_ACTION_SETTING.get(idxSettings), - LifecycleSettings.LIFECYCLE_STEP_SETTING.get(idxSettings), - LifecycleSettings.LIFECYCLE_FAILED_STEP_SETTING.get(idxSettings), - LifecycleSettings.LIFECYCLE_PHASE_TIME_SETTING.get(idxSettings), - LifecycleSettings.LIFECYCLE_ACTION_TIME_SETTING.get(idxSettings), - LifecycleSettings.LIFECYCLE_STEP_TIME_SETTING.get(idxSettings), - new BytesArray(LifecycleSettings.LIFECYCLE_STEP_INFO_SETTING.get(idxSettings)), + lifecycleState.getLifecycleDate(), + lifecycleState.getPhase(), + lifecycleState.getAction(), + lifecycleState.getStep(), + lifecycleState.getFailedStep(), + lifecycleState.getPhaseTime(), + lifecycleState.getActionTime(), + lifecycleState.getStepTime(), + stepInfoBytes, phaseExecutionInfo); } else { indexResponse = IndexLifecycleExplainResponse.newUnmanagedIndexResponse(index); diff --git a/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/indexlifecycle/ExecuteStepsUpdateTaskTests.java b/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/indexlifecycle/ExecuteStepsUpdateTaskTests.java index 7697507d6cd..a10afb631eb 100644 --- a/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/indexlifecycle/ExecuteStepsUpdateTaskTests.java +++ b/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/indexlifecycle/ExecuteStepsUpdateTaskTests.java @@ -22,6 +22,7 @@ import org.elasticsearch.common.xcontent.NamedXContentRegistry; import org.elasticsearch.index.Index; import org.elasticsearch.node.Node; import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.xpack.core.indexlifecycle.LifecycleExecutionState; import org.elasticsearch.xpack.core.indexlifecycle.IndexLifecycleMetadata; import org.elasticsearch.xpack.core.indexlifecycle.LifecyclePolicy; import org.elasticsearch.xpack.core.indexlifecycle.LifecyclePolicyMetadata; @@ -44,8 +45,10 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; +import static org.elasticsearch.xpack.core.indexlifecycle.LifecycleExecutionState.ILM_CUSTOM_METADATA_KEY; import static org.elasticsearch.xpack.core.indexlifecycle.LifecyclePolicyTestsUtils.newTestLifecyclePolicy; import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.Matchers.sameInstance; public class ExecuteStepsUpdateTaskTests extends ESTestCase { @@ -110,12 +113,14 @@ public class ExecuteStepsUpdateTaskTests extends ESTestCase { private IndexMetaData setupIndexPolicy(String policyName) { // Reset the index to use the "allClusterPolicyName" + LifecycleExecutionState.Builder lifecycleState = LifecycleExecutionState.builder(); + lifecycleState.setPhase("new"); + lifecycleState.setAction("init"); + lifecycleState.setStep("init"); IndexMetaData indexMetadata = IndexMetaData.builder(indexName) .settings(settings(Version.CURRENT) - .put(LifecycleSettings.LIFECYCLE_NAME, policyName) - .put(LifecycleSettings.LIFECYCLE_PHASE, "new") - .put(LifecycleSettings.LIFECYCLE_ACTION, "init") - .put(LifecycleSettings.LIFECYCLE_STEP, "init")) + .put(LifecycleSettings.LIFECYCLE_NAME, policyName)) + .putCustom(ILM_CUSTOM_METADATA_KEY, lifecycleState.build().asMap()) .numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build(); index = indexMetadata.getIndex(); MetaData metaData = MetaData.builder() @@ -149,24 +154,28 @@ public class ExecuteStepsUpdateTaskTests extends ESTestCase { long now = randomNonNegativeLong(); ExecuteStepsUpdateTask task = new ExecuteStepsUpdateTask(mixedPolicyName, index, startStep, policyStepsRegistry, () -> now); ClusterState newState = task.execute(clusterState); - StepKey currentStepKey = IndexLifecycleRunner.getCurrentStepKey(newState.metaData().index(index).getSettings()); + LifecycleExecutionState lifecycleState = LifecycleExecutionState.fromIndexMetadata(newState.getMetaData().index(index)); + StepKey currentStepKey = IndexLifecycleRunner.getCurrentStepKey(lifecycleState); assertThat(currentStepKey, equalTo(thirdStepKey)); assertThat(firstStep.getExecuteCount(), equalTo(0L)); assertThat(secondStep.getExecuteCount(), equalTo(1L)); - assertThat(LifecycleSettings.LIFECYCLE_PHASE_TIME_SETTING.get(newState.metaData().index(index).getSettings()), equalTo(-1L)); - assertThat(LifecycleSettings.LIFECYCLE_ACTION_TIME_SETTING.get(newState.metaData().index(index).getSettings()), equalTo(-1L)); - assertThat(LifecycleSettings.LIFECYCLE_STEP_INFO_SETTING.get(newState.metaData().index(index).getSettings()), equalTo("")); + assertThat(lifecycleState.getPhaseTime(), nullValue()); + assertThat(lifecycleState.getActionTime(), nullValue()); + assertThat(lifecycleState.getStepInfo(), nullValue()); } public void testExecuteInvalidStartStep() throws IOException { // Unset the index's phase/action/step to simulate starting from scratch + LifecycleExecutionState.Builder lifecycleState = LifecycleExecutionState.builder( + LifecycleExecutionState.fromIndexMetadata(clusterState.getMetaData().index(index))); + lifecycleState.setPhase(null); + lifecycleState.setAction(null); + lifecycleState.setStep(null); clusterState = ClusterState.builder(clusterState) - .metaData(MetaData.builder(clusterState.metaData()) - .put(IndexMetaData.builder(clusterState.metaData().index(indexName)) - .settings(Settings.builder().put(clusterState.metaData().index(indexName).getSettings()) - .put(LifecycleSettings.LIFECYCLE_PHASE, (String) null) - .put(LifecycleSettings.LIFECYCLE_ACTION, (String) null) - .put(LifecycleSettings.LIFECYCLE_STEP, (String) null).build()))).build(); + .metaData(MetaData.builder(clusterState.getMetaData()) + .put(IndexMetaData.builder(clusterState.getMetaData().index(index)) + .putCustom(ILM_CUSTOM_METADATA_KEY, lifecycleState.build().asMap()))).build(); + policyStepsRegistry.update(clusterState); Step invalidStep = new MockClusterStateActionStep(firstStepKey, secondStepKey); @@ -183,13 +192,14 @@ public class ExecuteStepsUpdateTaskTests extends ESTestCase { long now = randomNonNegativeLong(); ExecuteStepsUpdateTask task = new ExecuteStepsUpdateTask(mixedPolicyName, index, startStep, policyStepsRegistry, () -> now); ClusterState newState = task.execute(clusterState); - StepKey currentStepKey = IndexLifecycleRunner.getCurrentStepKey(newState.metaData().index(index).getSettings()); + LifecycleExecutionState lifecycleState = LifecycleExecutionState.fromIndexMetadata(newState.getMetaData().index(index)); + StepKey currentStepKey = IndexLifecycleRunner.getCurrentStepKey(lifecycleState); assertThat(currentStepKey, equalTo(secondStepKey)); assertThat(firstStep.getExecuteCount(), equalTo(0L)); assertThat(secondStep.getExecuteCount(), equalTo(1L)); - assertThat(LifecycleSettings.LIFECYCLE_PHASE_TIME_SETTING.get(newState.metaData().index(index).getSettings()), equalTo(-1L)); - assertThat(LifecycleSettings.LIFECYCLE_ACTION_TIME_SETTING.get(newState.metaData().index(index).getSettings()), equalTo(-1L)); - assertThat(LifecycleSettings.LIFECYCLE_STEP_INFO_SETTING.get(newState.metaData().index(index).getSettings()), equalTo("")); + assertThat(lifecycleState.getPhaseTime(), nullValue()); + assertThat(lifecycleState.getActionTime(), nullValue()); + assertThat(lifecycleState.getStepInfo(), nullValue()); } public void testExecuteIncompleteWaitStepWithInfo() throws IOException { @@ -201,14 +211,14 @@ public class ExecuteStepsUpdateTaskTests extends ESTestCase { long now = randomNonNegativeLong(); ExecuteStepsUpdateTask task = new ExecuteStepsUpdateTask(mixedPolicyName, index, startStep, policyStepsRegistry, () -> now); ClusterState newState = task.execute(clusterState); - StepKey currentStepKey = IndexLifecycleRunner.getCurrentStepKey(newState.metaData().index(index).getSettings()); + LifecycleExecutionState lifecycleState = LifecycleExecutionState.fromIndexMetadata(newState.getMetaData().index(index)); + StepKey currentStepKey = IndexLifecycleRunner.getCurrentStepKey(lifecycleState); assertThat(currentStepKey, equalTo(secondStepKey)); assertThat(firstStep.getExecuteCount(), equalTo(0L)); assertThat(secondStep.getExecuteCount(), equalTo(1L)); - assertThat(LifecycleSettings.LIFECYCLE_PHASE_TIME_SETTING.get(newState.metaData().index(index).getSettings()), equalTo(-1L)); - assertThat(LifecycleSettings.LIFECYCLE_ACTION_TIME_SETTING.get(newState.metaData().index(index).getSettings()), equalTo(-1L)); - assertThat(LifecycleSettings.LIFECYCLE_STEP_INFO_SETTING.get(newState.metaData().index(index).getSettings()), - equalTo(stepInfo.toString())); + assertThat(lifecycleState.getPhaseTime(), nullValue()); + assertThat(lifecycleState.getActionTime(), nullValue()); + assertThat(lifecycleState.getStepInfo(), equalTo(stepInfo.toString())); } public void testOnFailure() throws IOException { @@ -225,13 +235,15 @@ public class ExecuteStepsUpdateTaskTests extends ESTestCase { } private void setStateToKey(StepKey stepKey) throws IOException { + LifecycleExecutionState.Builder lifecycleState = LifecycleExecutionState.builder( + LifecycleExecutionState.fromIndexMetadata(clusterState.getMetaData().index(index))); + lifecycleState.setPhase(stepKey.getPhase()); + lifecycleState.setAction(stepKey.getAction()); + lifecycleState.setStep(stepKey.getName()); clusterState = ClusterState.builder(clusterState) - .metaData(MetaData.builder(clusterState.metaData()) - .put(IndexMetaData.builder(clusterState.metaData().index(indexName)) - .settings(Settings.builder().put(clusterState.metaData().index(indexName).getSettings()) - .put(LifecycleSettings.LIFECYCLE_PHASE, stepKey.getPhase()) - .put(LifecycleSettings.LIFECYCLE_ACTION, stepKey.getAction()) - .put(LifecycleSettings.LIFECYCLE_STEP, stepKey.getName()).build()))).build(); + .metaData(MetaData.builder(clusterState.getMetaData()) + .put(IndexMetaData.builder(clusterState.getMetaData().index(index)) + .putCustom(ILM_CUSTOM_METADATA_KEY, lifecycleState.build().asMap()))).build(); policyStepsRegistry.update(clusterState); } } diff --git a/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/indexlifecycle/IndexLifecycleInitialisationIT.java b/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/indexlifecycle/IndexLifecycleInitialisationIT.java index 58df9ce8d46..423b7976190 100644 --- a/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/indexlifecycle/IndexLifecycleInitialisationIT.java +++ b/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/indexlifecycle/IndexLifecycleInitialisationIT.java @@ -7,7 +7,7 @@ package org.elasticsearch.xpack.indexlifecycle; import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse; import org.elasticsearch.action.admin.indices.create.CreateIndexResponse; -import org.elasticsearch.action.admin.indices.settings.get.GetSettingsResponse; +import org.elasticsearch.action.support.master.AcknowledgedResponse; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.health.ClusterHealthStatus; import org.elasticsearch.cluster.routing.RoutingNode; @@ -32,6 +32,7 @@ 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.LifecycleExecutionState; import org.elasticsearch.xpack.core.indexlifecycle.LifecyclePolicy; import org.elasticsearch.xpack.core.indexlifecycle.LifecycleSettings; import org.elasticsearch.xpack.core.indexlifecycle.LifecycleType; @@ -176,9 +177,9 @@ public class IndexLifecycleInitialisationIT extends ESIntegTestCase { assertThat(indexLifecycleService.getScheduler().jobCount(), equalTo(1)); assertNotNull(indexLifecycleService.getScheduledJob()); assertBusy(() -> { - GetSettingsResponse settingsResponse = client().admin().indices().prepareGetSettings("test").get(); - String step = settingsResponse.getSetting("test", "index.lifecycle.step"); - assertThat(step, equalTo(TerminalPolicyStep.KEY.getName())); + LifecycleExecutionState lifecycleState = LifecycleExecutionState.fromIndexMetadata(client().admin().cluster() + .prepareState().execute().actionGet().getState().getMetaData().index("test")); + assertThat(lifecycleState.getStep(), equalTo(TerminalPolicyStep.KEY.getName())); }); } @@ -273,9 +274,9 @@ public class IndexLifecycleInitialisationIT extends ESIntegTestCase { assertEquals(true, client().admin().indices().prepareExists("test").get().isExists()); }); assertBusy(() -> { - GetSettingsResponse settingsResponse = client().admin().indices().prepareGetSettings("test").get(); - String step = settingsResponse.getSetting("test", "index.lifecycle.step"); - assertThat(step, equalTo(TerminalPolicyStep.KEY.getName())); + LifecycleExecutionState lifecycleState = LifecycleExecutionState.fromIndexMetadata(client().admin().cluster() + .prepareState().execute().actionGet().getState().getMetaData().index("test")); + assertThat(lifecycleState.getStep(), equalTo(TerminalPolicyStep.KEY.getName())); }); } @@ -313,9 +314,9 @@ public class IndexLifecycleInitialisationIT extends ESIntegTestCase { // check step in progress in lifecycle assertBusy(() -> { - GetSettingsResponse settingsResponse = client().admin().indices().prepareGetSettings("test").get(); - String step = settingsResponse.getSetting("test", "index.lifecycle.step"); - assertThat(step, equalTo(ObservableClusterStateWaitStep.NAME)); + LifecycleExecutionState lifecycleState = LifecycleExecutionState.fromIndexMetadata(client().admin().cluster() + .prepareState().execute().actionGet().getState().getMetaData().index("test")); + assertThat(lifecycleState.getStep(), equalTo(ObservableClusterStateWaitStep.NAME)); }); if (randomBoolean()) { @@ -335,19 +336,20 @@ public class IndexLifecycleInitialisationIT extends ESIntegTestCase { // check that index lifecycle picked back up where it assertBusy(() -> { - GetSettingsResponse settingsResponse = client().admin().indices().prepareGetSettings("test").get(); - String step = settingsResponse.getSetting("test", "index.lifecycle.step"); - assertThat(step, equalTo(ObservableClusterStateWaitStep.NAME)); + LifecycleExecutionState lifecycleState = LifecycleExecutionState.fromIndexMetadata(client().admin().cluster() + .prepareState().execute().actionGet().getState().getMetaData().index("test")); + assertThat(lifecycleState.getStep(), equalTo(ObservableClusterStateWaitStep.NAME)); }); + logger.info("new master is operation"); // complete the step - client().admin().indices().prepareUpdateSettings("test") + AcknowledgedResponse repsonse = client().admin().indices().prepareUpdateSettings("test") .setSettings(Collections.singletonMap("index.lifecycle.test.complete", true)).get(); assertBusy(() -> { - GetSettingsResponse settingsResponse = client().admin().indices().prepareGetSettings("test").get(); - String step = settingsResponse.getSetting("test", "index.lifecycle.step"); - assertThat(step, equalTo(TerminalPolicyStep.KEY.getName())); + LifecycleExecutionState lifecycleState = LifecycleExecutionState.fromIndexMetadata(client().admin().cluster() + .prepareState().execute().actionGet().getState().getMetaData().index("test")); + assertThat(lifecycleState.getStep(), equalTo(TerminalPolicyStep.KEY.getName())); }); } diff --git a/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/indexlifecycle/IndexLifecycleRunnerTests.java b/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/indexlifecycle/IndexLifecycleRunnerTests.java index f8b811d54af..9994b56612c 100644 --- a/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/indexlifecycle/IndexLifecycleRunnerTests.java +++ b/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/indexlifecycle/IndexLifecycleRunnerTests.java @@ -33,6 +33,7 @@ import org.elasticsearch.xpack.core.indexlifecycle.ClusterStateWaitStep; import org.elasticsearch.xpack.core.indexlifecycle.ErrorStep; import org.elasticsearch.xpack.core.indexlifecycle.IndexLifecycleMetadata; import org.elasticsearch.xpack.core.indexlifecycle.LifecycleAction; +import org.elasticsearch.xpack.core.indexlifecycle.LifecycleExecutionState; import org.elasticsearch.xpack.core.indexlifecycle.LifecyclePolicy; import org.elasticsearch.xpack.core.indexlifecycle.LifecyclePolicyMetadata; import org.elasticsearch.xpack.core.indexlifecycle.LifecyclePolicyTests; @@ -62,6 +63,7 @@ import java.util.concurrent.atomic.AtomicLong; import java.util.function.Function; import java.util.stream.Collectors; +import static org.elasticsearch.xpack.core.indexlifecycle.LifecycleExecutionState.ILM_CUSTOM_METADATA_KEY; import static org.elasticsearch.xpack.core.indexlifecycle.LifecyclePolicyTestsUtils.newTestLifecyclePolicy; import static org.hamcrest.Matchers.equalTo; import static org.mockito.Mockito.mock; @@ -110,10 +112,12 @@ public class IndexLifecycleRunnerTests extends ESTestCase { PolicyStepsRegistry stepRegistry = createOneStepPolicyStepRegistry(policyName, step); ClusterService clusterService = mock(ClusterService.class); IndexLifecycleRunner runner = new IndexLifecycleRunner(stepRegistry, clusterService, () -> 0L); - IndexMetaData indexMetaData = IndexMetaData.builder("my_index").settings(settings(Version.CURRENT) - .put(LifecycleSettings.LIFECYCLE_PHASE, stepKey.getPhase()) - .put(LifecycleSettings.LIFECYCLE_ACTION, stepKey.getAction()) - .put(LifecycleSettings.LIFECYCLE_STEP, ErrorStep.NAME)) + LifecycleExecutionState.Builder newState = LifecycleExecutionState.builder(); + newState.setPhase(stepKey.getPhase()); + newState.setAction(stepKey.getAction()); + newState.setStep(ErrorStep.NAME); + IndexMetaData indexMetaData = IndexMetaData.builder("my_index").settings(settings(Version.CURRENT)) + .putCustom(ILM_CUSTOM_METADATA_KEY, newState.build().asMap()) .numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build(); runner.runPolicy(policyName, indexMetaData, null, false); @@ -375,19 +379,18 @@ public class IndexLifecycleRunnerTests extends ESTestCase { } public void testGetCurrentStepKey() { - Settings indexSettings = Settings.EMPTY; - StepKey stepKey = IndexLifecycleRunner.getCurrentStepKey(indexSettings); + LifecycleExecutionState.Builder lifecycleState = LifecycleExecutionState.builder(); + StepKey stepKey = IndexLifecycleRunner.getCurrentStepKey(lifecycleState.build()); assertNull(stepKey); String phase = randomAlphaOfLength(20); String action = randomAlphaOfLength(20); String step = randomAlphaOfLength(20); - Settings indexSettings2 = Settings.builder() - .put(LifecycleSettings.LIFECYCLE_PHASE, phase) - .put(LifecycleSettings.LIFECYCLE_ACTION, action) - .put(LifecycleSettings.LIFECYCLE_STEP, step) - .build(); - stepKey = IndexLifecycleRunner.getCurrentStepKey(indexSettings2); + LifecycleExecutionState.Builder lifecycleState2 = LifecycleExecutionState.builder(); + lifecycleState2.setPhase(phase); + lifecycleState2.setAction(action); + lifecycleState2.setStep(step); + stepKey = IndexLifecycleRunner.getCurrentStepKey(lifecycleState2.build()); assertNotNull(stepKey); assertEquals(phase, stepKey.getPhase()); assertEquals(action, stepKey.getAction()); @@ -395,46 +398,42 @@ public class IndexLifecycleRunnerTests extends ESTestCase { phase = randomAlphaOfLength(20); action = randomAlphaOfLength(20); - step = randomBoolean() ? null : ""; - Settings indexSettings3 = Settings.builder() - .put(LifecycleSettings.LIFECYCLE_PHASE, phase) - .put(LifecycleSettings.LIFECYCLE_ACTION, action) - .put(LifecycleSettings.LIFECYCLE_STEP, step) - .build(); - AssertionError error3 = expectThrows(AssertionError.class, () -> IndexLifecycleRunner.getCurrentStepKey(indexSettings3)); + step = null; + LifecycleExecutionState.Builder lifecycleState3 = LifecycleExecutionState.builder(); + lifecycleState3.setPhase(phase); + lifecycleState3.setAction(action); + lifecycleState3.setStep(step); + AssertionError error3 = expectThrows(AssertionError.class, () -> IndexLifecycleRunner.getCurrentStepKey(lifecycleState3.build())); assertEquals("Current phase is not empty: " + phase, error3.getMessage()); - phase = randomBoolean() ? null : ""; + phase = null; action = randomAlphaOfLength(20); - step = randomBoolean() ? null : ""; - Settings indexSettings4 = Settings.builder() - .put(LifecycleSettings.LIFECYCLE_PHASE, phase) - .put(LifecycleSettings.LIFECYCLE_ACTION, action) - .put(LifecycleSettings.LIFECYCLE_STEP, step) - .build(); - AssertionError error4 = expectThrows(AssertionError.class, () -> IndexLifecycleRunner.getCurrentStepKey(indexSettings4)); + step = null; + LifecycleExecutionState.Builder lifecycleState4 = LifecycleExecutionState.builder(); + lifecycleState4.setPhase(phase); + lifecycleState4.setAction(action); + lifecycleState4.setStep(step); + AssertionError error4 = expectThrows(AssertionError.class, () -> IndexLifecycleRunner.getCurrentStepKey(lifecycleState4.build())); assertEquals("Current action is not empty: " + action, error4.getMessage()); - phase = randomBoolean() ? null : ""; + phase = null; action = randomAlphaOfLength(20); step = randomAlphaOfLength(20); - Settings indexSettings5 = Settings.builder() - .put(LifecycleSettings.LIFECYCLE_PHASE, phase) - .put(LifecycleSettings.LIFECYCLE_ACTION, action) - .put(LifecycleSettings.LIFECYCLE_STEP, step) - .build(); - AssertionError error5 = expectThrows(AssertionError.class, () -> IndexLifecycleRunner.getCurrentStepKey(indexSettings5)); + LifecycleExecutionState.Builder lifecycleState5 = LifecycleExecutionState.builder(); + lifecycleState5.setPhase(phase); + lifecycleState5.setAction(action); + lifecycleState5.setStep(step); + AssertionError error5 = expectThrows(AssertionError.class, () -> IndexLifecycleRunner.getCurrentStepKey(lifecycleState5.build())); assertEquals(null, error5.getMessage()); - phase = randomBoolean() ? null : ""; - action = randomBoolean() ? null : ""; + phase = null; + action = null; step = randomAlphaOfLength(20); - Settings indexSettings6 = Settings.builder() - .put(LifecycleSettings.LIFECYCLE_PHASE, phase) - .put(LifecycleSettings.LIFECYCLE_ACTION, action) - .put(LifecycleSettings.LIFECYCLE_STEP, step) - .build(); - AssertionError error6 = expectThrows(AssertionError.class, () -> IndexLifecycleRunner.getCurrentStepKey(indexSettings6)); + LifecycleExecutionState.Builder lifecycleState6 = LifecycleExecutionState.builder(); + lifecycleState6.setPhase(phase); + lifecycleState6.setAction(action); + lifecycleState6.setStep(step); + AssertionError error6 = expectThrows(AssertionError.class, () -> IndexLifecycleRunner.getCurrentStepKey(lifecycleState6.build())); assertEquals(null, error6.getMessage()); } @@ -464,22 +463,27 @@ public class IndexLifecycleRunnerTests extends ESTestCase { .put("index.number_of_replicas", 0) .put("index.version.created", Version.CURRENT) .put(LifecycleSettings.LIFECYCLE_NAME, policyName) - .put(LifecycleSettings.LIFECYCLE_PHASE_DEFINITION, phaseJson) - .put(LifecycleSettings.LIFECYCLE_PHASE, step.getKey().getPhase()) - .put(LifecycleSettings.LIFECYCLE_ACTION, step.getKey().getAction()) - .put(LifecycleSettings.LIFECYCLE_STEP, step.getKey().getName()) .build(); - IndexMetaData indexMetaData = IndexMetaData.builder(index.getName()).settings(indexSettings).build(); + LifecycleExecutionState.Builder lifecycleState = LifecycleExecutionState.builder(); + lifecycleState.setPhaseDefinition(phaseJson); + lifecycleState.setPhase(step.getKey().getPhase()); + lifecycleState.setAction(step.getKey().getAction()); + lifecycleState.setStep(step.getKey().getName()); + IndexMetaData indexMetaData = IndexMetaData.builder(index.getName()) + .settings(indexSettings) + .putCustom(ILM_CUSTOM_METADATA_KEY, lifecycleState.build().asMap()) + .build(); SortedMap metas = new TreeMap<>(); metas.put(policyName, policyMetadata); PolicyStepsRegistry registry = new PolicyStepsRegistry(metas, firstStepMap, stepMap, REGISTRY, client); // First step is retrieved because there are no settings for the index - Step stepFromNoSettings = IndexLifecycleRunner.getCurrentStep(registry, policy.getName(), indexMetaData, Settings.EMPTY); + Step stepFromNoSettings = IndexLifecycleRunner.getCurrentStep(registry, policy.getName(), indexMetaData, + LifecycleExecutionState.builder().build()); assertEquals(firstStep, stepFromNoSettings); // The step that was written into the metadata is retrieved - Step currentStep = IndexLifecycleRunner.getCurrentStep(registry, policy.getName(), indexMetaData, indexSettings); + Step currentStep = IndexLifecycleRunner.getCurrentStep(registry, policy.getName(), indexMetaData, lifecycleState.build()); assertEquals(step.getKey(), currentStep.getKey()); } @@ -496,22 +500,25 @@ public class IndexLifecycleRunnerTests extends ESTestCase { // test going from null lifecycle settings to next step ClusterState clusterState = buildClusterState(indexName, - Settings.builder().put(LifecycleSettings.LIFECYCLE_NAME, policy.getName()), policyMetadatas); + Settings.builder() + .put(LifecycleSettings.LIFECYCLE_NAME, policy.getName()), LifecycleExecutionState.builder().build(), policyMetadatas); Index index = clusterState.metaData().index(indexName).getIndex(); ClusterState newClusterState = IndexLifecycleRunner.moveClusterStateToNextStep(index, clusterState, currentStep, nextStep, () -> now); assertClusterStateOnNextStep(clusterState, index, currentStep, nextStep, newClusterState, now); + LifecycleExecutionState.Builder lifecycleState = LifecycleExecutionState.builder(); + lifecycleState.setPhase(currentStep.getPhase()); + lifecycleState.setAction(currentStep.getAction()); + lifecycleState.setStep(currentStep.getName()); // test going from set currentStep settings to nextStep Builder indexSettingsBuilder = Settings.builder() - .put(LifecycleSettings.LIFECYCLE_NAME, policy.getName()) - .put(LifecycleSettings.LIFECYCLE_PHASE, currentStep.getPhase()) - .put(LifecycleSettings.LIFECYCLE_ACTION, currentStep.getAction()) - .put(LifecycleSettings.LIFECYCLE_STEP, currentStep.getName()); + .put(LifecycleSettings.LIFECYCLE_NAME, policy.getName()); if (randomBoolean()) { - indexSettingsBuilder.put(LifecycleSettings.LIFECYCLE_STEP_INFO, randomAlphaOfLength(20)); + lifecycleState.setStepInfo(randomAlphaOfLength(20)); } - clusterState = buildClusterState(indexName, indexSettingsBuilder, policyMetadatas); + + clusterState = buildClusterState(indexName, indexSettingsBuilder, lifecycleState.build(), policyMetadatas); index = clusterState.metaData().index(indexName).getIndex(); newClusterState = IndexLifecycleRunner.moveClusterStateToNextStep(index, clusterState, currentStep, nextStep, () -> now); assertClusterStateOnNextStep(clusterState, index, currentStep, nextStep, newClusterState, now); @@ -523,20 +530,22 @@ public class IndexLifecycleRunnerTests extends ESTestCase { StepKey nextStep = new StepKey("current_phase", "next_action", "next_step"); long now = randomNonNegativeLong(); - ClusterState clusterState = buildClusterState(indexName, Settings.builder(), Collections.emptyList()); + ClusterState clusterState = buildClusterState(indexName, Settings.builder(), LifecycleExecutionState.builder().build(), + Collections.emptyList()); Index index = clusterState.metaData().index(indexName).getIndex(); ClusterState newClusterState = IndexLifecycleRunner.moveClusterStateToNextStep(index, clusterState, currentStep, nextStep, () -> now); assertClusterStateOnNextStep(clusterState, index, currentStep, nextStep, newClusterState, now); - Builder indexSettingsBuilder = Settings.builder().put(LifecycleSettings.LIFECYCLE_PHASE, currentStep.getPhase()) - .put(LifecycleSettings.LIFECYCLE_ACTION, currentStep.getAction()) - .put(LifecycleSettings.LIFECYCLE_STEP, currentStep.getName()); + LifecycleExecutionState.Builder lifecycleState = LifecycleExecutionState.builder(); + lifecycleState.setPhase(currentStep.getPhase()); + lifecycleState.setAction(currentStep.getAction()); + lifecycleState.setStep(currentStep.getName()); if (randomBoolean()) { - indexSettingsBuilder.put(LifecycleSettings.LIFECYCLE_STEP_INFO, randomAlphaOfLength(20)); + lifecycleState.setStepInfo(randomAlphaOfLength(20)); } - clusterState = buildClusterState(indexName, - indexSettingsBuilder, Collections.emptyList()); + + clusterState = buildClusterState(indexName, Settings.builder(), lifecycleState.build(), Collections.emptyList()); index = clusterState.metaData().index(indexName).getIndex(); newClusterState = IndexLifecycleRunner.moveClusterStateToNextStep(index, clusterState, currentStep, nextStep, () -> now); assertClusterStateOnNextStep(clusterState, index, currentStep, nextStep, newClusterState, now); @@ -548,20 +557,21 @@ public class IndexLifecycleRunnerTests extends ESTestCase { StepKey nextStep = new StepKey("current_phase", "current_action", "next_step"); long now = randomNonNegativeLong(); - ClusterState clusterState = buildClusterState(indexName, Settings.builder(), Collections.emptyList()); + ClusterState clusterState = buildClusterState(indexName, Settings.builder(), LifecycleExecutionState.builder().build(), + Collections.emptyList()); Index index = clusterState.metaData().index(indexName).getIndex(); ClusterState newClusterState = IndexLifecycleRunner.moveClusterStateToNextStep(index, clusterState, currentStep, nextStep, () -> now); assertClusterStateOnNextStep(clusterState, index, currentStep, nextStep, newClusterState, now); - Builder indexSettingsBuilder = Settings.builder().put(LifecycleSettings.LIFECYCLE_PHASE, currentStep.getPhase()) - .put(LifecycleSettings.LIFECYCLE_ACTION, currentStep.getAction()) - .put(LifecycleSettings.LIFECYCLE_STEP, currentStep.getName()); + LifecycleExecutionState.Builder lifecycleState = LifecycleExecutionState.builder(); + lifecycleState.setPhase(currentStep.getPhase()); + lifecycleState.setAction(currentStep.getAction()); + lifecycleState.setStep(currentStep.getName()); if (randomBoolean()) { - indexSettingsBuilder.put(LifecycleSettings.LIFECYCLE_STEP_INFO, randomAlphaOfLength(20)); + lifecycleState.setStepInfo(randomAlphaOfLength(20)); } - clusterState = buildClusterState(indexName, - indexSettingsBuilder, Collections.emptyList()); + clusterState = buildClusterState(indexName, Settings.builder(), lifecycleState.build(), Collections.emptyList()); index = clusterState.metaData().index(indexName).getIndex(); newClusterState = IndexLifecycleRunner.moveClusterStateToNextStep(index, clusterState, currentStep, nextStep, () -> now); assertClusterStateOnNextStep(clusterState, index, currentStep, nextStep, newClusterState, now); @@ -581,11 +591,13 @@ public class IndexLifecycleRunnerTests extends ESTestCase { Step step = new MockStep(nextStepKey, nextStepKey); PolicyStepsRegistry stepRegistry = createOneStepPolicyStepRegistry(policyName, step, indexName); - Builder indexSettingsBuilder = Settings.builder().put(LifecycleSettings.LIFECYCLE_NAME, policyName) - .put(LifecycleSettings.LIFECYCLE_PHASE, currentStepKey.getPhase()) - .put(LifecycleSettings.LIFECYCLE_ACTION, currentStepKey.getAction()) - .put(LifecycleSettings.LIFECYCLE_STEP, currentStepKey.getName()); - ClusterState clusterState = buildClusterState(indexName, indexSettingsBuilder, policyMetadatas); + LifecycleExecutionState.Builder lifecycleState = LifecycleExecutionState.builder(); + lifecycleState.setPhase(currentStepKey.getPhase()); + lifecycleState.setAction(currentStepKey.getAction()); + lifecycleState.setStep(currentStepKey.getName()); + + Builder indexSettingsBuilder = Settings.builder().put(LifecycleSettings.LIFECYCLE_NAME, policyName); + ClusterState clusterState = buildClusterState(indexName, indexSettingsBuilder, lifecycleState.build(), policyMetadatas); Index index = clusterState.metaData().index(indexName).getIndex(); ClusterState newClusterState = IndexLifecycleRunner.moveClusterStateToStep(indexName, clusterState, currentStepKey, nextStepKey, () -> now, stepRegistry); @@ -601,11 +613,13 @@ public class IndexLifecycleRunnerTests extends ESTestCase { Step step = new MockStep(nextStepKey, nextStepKey); PolicyStepsRegistry stepRegistry = createOneStepPolicyStepRegistry(policyName, step); - Builder indexSettingsBuilder = Settings.builder().put(LifecycleSettings.LIFECYCLE_NAME, policyName) - .put(LifecycleSettings.LIFECYCLE_PHASE, currentStepKey.getPhase()) - .put(LifecycleSettings.LIFECYCLE_ACTION, currentStepKey.getAction()) - .put(LifecycleSettings.LIFECYCLE_STEP, currentStepKey.getName()); - ClusterState clusterState = buildClusterState(indexName, indexSettingsBuilder, Collections.emptyList()); + Builder indexSettingsBuilder = Settings.builder().put(LifecycleSettings.LIFECYCLE_NAME, policyName); + LifecycleExecutionState.Builder lifecycleState = LifecycleExecutionState.builder(); + lifecycleState.setPhase(currentStepKey.getPhase()); + lifecycleState.setAction(currentStepKey.getAction()); + lifecycleState.setStep(currentStepKey.getName()); + + ClusterState clusterState = buildClusterState(indexName, indexSettingsBuilder, lifecycleState.build(), Collections.emptyList()); IllegalArgumentException exception = expectThrows(IllegalArgumentException.class, () -> IndexLifecycleRunner.moveClusterStateToStep(indexName, clusterState, currentStepKey, nextStepKey, () -> now, stepRegistry)); @@ -622,11 +636,13 @@ public class IndexLifecycleRunnerTests extends ESTestCase { Step step = new MockStep(nextStepKey, nextStepKey); PolicyStepsRegistry stepRegistry = createOneStepPolicyStepRegistry(policyName, step); - Builder indexSettingsBuilder = Settings.builder().put(LifecycleSettings.LIFECYCLE_NAME, policyName) - .put(LifecycleSettings.LIFECYCLE_PHASE, currentStepKey.getPhase()) - .put(LifecycleSettings.LIFECYCLE_ACTION, currentStepKey.getAction()) - .put(LifecycleSettings.LIFECYCLE_STEP, currentStepKey.getName()); - ClusterState clusterState = buildClusterState(indexName, indexSettingsBuilder, Collections.emptyList()); + Builder indexSettingsBuilder = Settings.builder().put(LifecycleSettings.LIFECYCLE_NAME, policyName); + LifecycleExecutionState.Builder lifecycleState = LifecycleExecutionState.builder(); + lifecycleState.setPhase(currentStepKey.getPhase()); + lifecycleState.setAction(currentStepKey.getAction()); + lifecycleState.setStep(currentStepKey.getName()); + + ClusterState clusterState = buildClusterState(indexName, indexSettingsBuilder, lifecycleState.build(), Collections.emptyList()); IllegalArgumentException exception = expectThrows(IllegalArgumentException.class, () -> IndexLifecycleRunner.moveClusterStateToStep(indexName, clusterState, notCurrentStepKey, nextStepKey, () -> now, stepRegistry)); @@ -643,11 +659,13 @@ public class IndexLifecycleRunnerTests extends ESTestCase { Step step = new MockStep(currentStepKey, nextStepKey); PolicyStepsRegistry stepRegistry = createOneStepPolicyStepRegistry(policyName, step); - Builder indexSettingsBuilder = Settings.builder().put(LifecycleSettings.LIFECYCLE_NAME, policyName) - .put(LifecycleSettings.LIFECYCLE_PHASE, currentStepKey.getPhase()) - .put(LifecycleSettings.LIFECYCLE_ACTION, currentStepKey.getAction()) - .put(LifecycleSettings.LIFECYCLE_STEP, currentStepKey.getName()); - ClusterState clusterState = buildClusterState(indexName, indexSettingsBuilder, Collections.emptyList()); + Builder indexSettingsBuilder = Settings.builder().put(LifecycleSettings.LIFECYCLE_NAME, policyName); + LifecycleExecutionState.Builder lifecycleState = LifecycleExecutionState.builder(); + lifecycleState.setPhase(currentStepKey.getPhase()); + lifecycleState.setAction(currentStepKey.getAction()); + lifecycleState.setStep(currentStepKey.getName()); + + ClusterState clusterState = buildClusterState(indexName, indexSettingsBuilder, lifecycleState.build(), Collections.emptyList()); IllegalArgumentException exception = expectThrows(IllegalArgumentException.class, () -> IndexLifecycleRunner.moveClusterStateToStep(indexName, clusterState, currentStepKey, nextStepKey, () -> now, stepRegistry)); @@ -662,11 +680,11 @@ public class IndexLifecycleRunnerTests extends ESTestCase { long now = randomNonNegativeLong(); Exception cause = new ElasticsearchException("THIS IS AN EXPECTED CAUSE"); - ClusterState clusterState = buildClusterState(indexName, - Settings.builder().put(LifecycleSettings.LIFECYCLE_PHASE, currentStep.getPhase()) - .put(LifecycleSettings.LIFECYCLE_ACTION, currentStep.getAction()) - .put(LifecycleSettings.LIFECYCLE_STEP, currentStep.getName()), - Collections.emptyList()); + LifecycleExecutionState.Builder lifecycleState = LifecycleExecutionState.builder(); + lifecycleState.setPhase(currentStep.getPhase()); + lifecycleState.setAction(currentStep.getAction()); + lifecycleState.setStep(currentStep.getName()); + ClusterState clusterState = buildClusterState(indexName, Settings.builder(), lifecycleState.build(), Collections.emptyList()); Index index = clusterState.metaData().index(indexName).getIndex(); ClusterState newClusterState = IndexLifecycleRunner.moveClusterStateToErrorStep(index, clusterState, currentStep, cause, () -> now); @@ -689,12 +707,13 @@ public class IndexLifecycleRunnerTests extends ESTestCase { Step step = new MockStep(failedStepKey, null); PolicyStepsRegistry policyRegistry = createOneStepPolicyStepRegistry(policyName, step, indexName); Settings.Builder indexSettingsBuilder = Settings.builder() - .put(LifecycleSettings.LIFECYCLE_NAME, policyName) - .put(LifecycleSettings.LIFECYCLE_PHASE, errorStepKey.getPhase()) - .put(LifecycleSettings.LIFECYCLE_ACTION, errorStepKey.getAction()) - .put(LifecycleSettings.LIFECYCLE_FAILED_STEP, failedStepKey.getName()) - .put(LifecycleSettings.LIFECYCLE_STEP, errorStepKey.getName()); - ClusterState clusterState = buildClusterState(indexName, indexSettingsBuilder, Collections.emptyList()); + .put(LifecycleSettings.LIFECYCLE_NAME, policyName); + LifecycleExecutionState.Builder lifecycleState = LifecycleExecutionState.builder(); + lifecycleState.setPhase(errorStepKey.getPhase()); + lifecycleState.setAction(errorStepKey.getAction()); + lifecycleState.setStep(errorStepKey.getName()); + lifecycleState.setFailedStep(failedStepKey.getName()); + ClusterState clusterState = buildClusterState(indexName, indexSettingsBuilder, lifecycleState.build(), Collections.emptyList()); Index index = clusterState.metaData().index(indexName).getIndex(); IndexLifecycleRunner runner = new IndexLifecycleRunner(policyRegistry, null, () -> now); ClusterState nextClusterState = runner.moveClusterStateToFailedStep(clusterState, indices); @@ -705,7 +724,8 @@ public class IndexLifecycleRunnerTests extends ESTestCase { public void testMoveClusterStateToFailedStepIndexNotFound() { String existingIndexName = "my_index"; String invalidIndexName = "does_not_exist"; - ClusterState clusterState = buildClusterState(existingIndexName, Settings.builder(), Collections.emptyList()); + ClusterState clusterState = buildClusterState(existingIndexName, Settings.builder(), LifecycleExecutionState.builder().build(), + Collections.emptyList()); IndexLifecycleRunner runner = new IndexLifecycleRunner(null, null, () -> 0L); IllegalArgumentException exception = expectThrows(IllegalArgumentException.class, () -> runner.moveClusterStateToFailedStep(clusterState, new String[] { invalidIndexName })); @@ -722,12 +742,13 @@ public class IndexLifecycleRunnerTests extends ESTestCase { Step step = new MockStep(failedStepKey, null); PolicyStepsRegistry policyRegistry = createOneStepPolicyStepRegistry(policyName, step); Settings.Builder indexSettingsBuilder = Settings.builder() - .put(LifecycleSettings.LIFECYCLE_NAME, (String) null) - .put(LifecycleSettings.LIFECYCLE_PHASE, errorStepKey.getPhase()) - .put(LifecycleSettings.LIFECYCLE_ACTION, errorStepKey.getAction()) - .put(LifecycleSettings.LIFECYCLE_FAILED_STEP, failedStepKey.getName()) - .put(LifecycleSettings.LIFECYCLE_STEP, errorStepKey.getName()); - ClusterState clusterState = buildClusterState(indexName, indexSettingsBuilder, Collections.emptyList()); + .put(LifecycleSettings.LIFECYCLE_NAME, (String) null); + LifecycleExecutionState.Builder lifecycleState = LifecycleExecutionState.builder(); + lifecycleState.setPhase(errorStepKey.getPhase()); + lifecycleState.setAction(errorStepKey.getAction()); + lifecycleState.setStep(errorStepKey.getName()); + lifecycleState.setFailedStep(failedStepKey.getName()); + ClusterState clusterState = buildClusterState(indexName, indexSettingsBuilder, lifecycleState.build(), Collections.emptyList()); IndexLifecycleRunner runner = new IndexLifecycleRunner(policyRegistry, null, () -> now); IllegalArgumentException exception = expectThrows(IllegalArgumentException.class, () -> runner.moveClusterStateToFailedStep(clusterState, indices)); @@ -743,11 +764,12 @@ public class IndexLifecycleRunnerTests extends ESTestCase { Step step = new MockStep(failedStepKey, null); PolicyStepsRegistry policyRegistry = createOneStepPolicyStepRegistry(policyName, step); Settings.Builder indexSettingsBuilder = Settings.builder() - .put(LifecycleSettings.LIFECYCLE_NAME, (String) null) - .put(LifecycleSettings.LIFECYCLE_PHASE, failedStepKey.getPhase()) - .put(LifecycleSettings.LIFECYCLE_ACTION, failedStepKey.getAction()) - .put(LifecycleSettings.LIFECYCLE_STEP, failedStepKey.getName()); - ClusterState clusterState = buildClusterState(indexName, indexSettingsBuilder, Collections.emptyList()); + .put(LifecycleSettings.LIFECYCLE_NAME, (String) null); + LifecycleExecutionState.Builder lifecycleState = LifecycleExecutionState.builder(); + lifecycleState.setPhase(failedStepKey.getPhase()); + lifecycleState.setAction(failedStepKey.getAction()); + lifecycleState.setStep(failedStepKey.getName()); + ClusterState clusterState = buildClusterState(indexName, indexSettingsBuilder, lifecycleState.build(), Collections.emptyList()); IndexLifecycleRunner runner = new IndexLifecycleRunner(policyRegistry, null, () -> now); IllegalArgumentException exception = expectThrows(IllegalArgumentException.class, () -> runner.moveClusterStateToFailedStep(clusterState, indices)); @@ -760,11 +782,11 @@ public class IndexLifecycleRunnerTests extends ESTestCase { StepKey currentStep = new StepKey("current_phase", "current_action", "current_step"); RandomStepInfo stepInfo = new RandomStepInfo(() -> randomAlphaOfLength(10)); - ClusterState clusterState = buildClusterState(indexName, - Settings.builder().put(LifecycleSettings.LIFECYCLE_PHASE, currentStep.getPhase()) - .put(LifecycleSettings.LIFECYCLE_ACTION, currentStep.getAction()) - .put(LifecycleSettings.LIFECYCLE_STEP, currentStep.getName()), - Collections.emptyList()); + LifecycleExecutionState.Builder lifecycleState = LifecycleExecutionState.builder(); + lifecycleState.setPhase(currentStep.getPhase()); + lifecycleState.setAction(currentStep.getAction()); + lifecycleState.setStep(currentStep.getName()); + ClusterState clusterState = buildClusterState(indexName, Settings.builder(), lifecycleState.build(), Collections.emptyList()); Index index = clusterState.metaData().index(indexName).getIndex(); ClusterState newClusterState = IndexLifecycleRunner.addStepInfoToClusterState(index, clusterState, stepInfo); assertClusterStateStepInfo(clusterState, index, currentStep, newClusterState, stepInfo); @@ -776,13 +798,14 @@ public class IndexLifecycleRunnerTests extends ESTestCase { public void testSkipped() { String policy = randomAlphaOfLength(5); String index = randomAlphaOfLength(10); + LifecycleExecutionState.Builder lifecycleState = LifecycleExecutionState.builder(); + lifecycleState.setPhase(randomAlphaOfLength(5)); + lifecycleState.setAction(randomAlphaOfLength(5)); + lifecycleState.setStep(randomAlphaOfLength(5)); ClusterState clusterState = buildClusterState(index, - Settings.builder().put(LifecycleSettings.LIFECYCLE_NAME, policy) - .put(LifecycleSettings.LIFECYCLE_PHASE, randomAlphaOfLength(5)) - .put(LifecycleSettings.LIFECYCLE_ACTION, randomAlphaOfLength(5)) - .put(LifecycleSettings.LIFECYCLE_STEP, randomAlphaOfLength(5)) - .put(LifecycleSettings.LIFECYCLE_SKIP, true), - Collections.emptyList()); + Settings.builder().put(LifecycleSettings.LIFECYCLE_NAME, policy).put(LifecycleSettings.LIFECYCLE_SKIP, true), + lifecycleState.build(), + Collections.emptyList()); Step step = mock(randomFrom(TerminalPolicyStep.class, ClusterStateActionStep.class, ClusterStateWaitStep.class, AsyncActionStep.class, AsyncWaitStep.class)); PolicyStepsRegistry stepRegistry = createOneStepPolicyStepRegistry(policy, step); @@ -793,11 +816,14 @@ public class IndexLifecycleRunnerTests extends ESTestCase { } private ClusterState buildClusterState(String indexName, Settings.Builder indexSettingsBuilder, - List lifecyclePolicyMetadatas) { + LifecycleExecutionState lifecycleState, + List lifecyclePolicyMetadatas) { Settings indexSettings = indexSettingsBuilder.put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, 1) .put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, 0).put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT).build(); - IndexMetaData indexMetadata = IndexMetaData.builder(indexName).settings(indexSettings) - .build(); + IndexMetaData indexMetadata = IndexMetaData.builder(indexName) + .settings(indexSettings) + .putCustom(ILM_CUSTOM_METADATA_KEY, lifecycleState.asMap()) + .build(); Map lifecyclePolicyMetadatasMap = lifecyclePolicyMetadatas.stream() .collect(Collectors.toMap(LifecyclePolicyMetadata::getName, Function.identity())); @@ -819,16 +845,18 @@ public class IndexLifecycleRunnerTests extends ESTestCase { new StepKey(phaseName, MockAction.NAME, randomAlphaOfLength(9)), null); LifecyclePolicy oldPolicy = createPolicy(oldPolicyName, currentStep, null); Settings.Builder indexSettingsBuilder = Settings.builder().put(LifecycleSettings.LIFECYCLE_NAME, oldPolicyName) - .put(LifecycleSettings.LIFECYCLE_PHASE, currentStep.getPhase()) - .put(LifecycleSettings.LIFECYCLE_ACTION, currentStep.getAction()) - .put(LifecycleSettings.LIFECYCLE_STEP, currentStep.getName()).put(LifecycleSettings.LIFECYCLE_SKIP, true); + .put(LifecycleSettings.LIFECYCLE_SKIP, true); + LifecycleExecutionState.Builder lifecycleState = LifecycleExecutionState.builder(); + lifecycleState.setPhase(currentStep.getPhase()); + lifecycleState.setAction(currentStep.getAction()); + lifecycleState.setStep(currentStep.getName()); List policyMetadatas = new ArrayList<>(); policyMetadatas.add(new LifecyclePolicyMetadata(oldPolicy, Collections.emptyMap(), randomNonNegativeLong(), randomNonNegativeLong())); LifecyclePolicyMetadata newPolicyMetadata = new LifecyclePolicyMetadata(newPolicy, Collections.emptyMap(), randomNonNegativeLong(), randomNonNegativeLong()); policyMetadatas.add(newPolicyMetadata); - ClusterState clusterState = buildClusterState(indexName, indexSettingsBuilder, policyMetadatas); + ClusterState clusterState = buildClusterState(indexName, indexSettingsBuilder, lifecycleState.build(), policyMetadatas); Index index = clusterState.metaData().index(indexName).getIndex(); Index[] indices = new Index[] { index }; List failedIndexes = new ArrayList<>(); @@ -847,9 +875,10 @@ public class IndexLifecycleRunnerTests extends ESTestCase { LifecyclePolicy newPolicy = newTestLifecyclePolicy(newPolicyName, Collections.emptyMap()); LifecyclePolicyMetadata newPolicyMetadata = new LifecyclePolicyMetadata(newPolicy, Collections.emptyMap(), randomNonNegativeLong(), randomNonNegativeLong()); - StepKey currentStep = new StepKey("", "", ""); + StepKey currentStep = new StepKey(null, null, null); Settings.Builder indexSettingsBuilder = Settings.builder(); - ClusterState clusterState = buildClusterState(indexName, indexSettingsBuilder, Collections.singletonList(newPolicyMetadata)); + ClusterState clusterState = buildClusterState(indexName, indexSettingsBuilder, LifecycleExecutionState.builder().build(), + Collections.singletonList(newPolicyMetadata)); Index index = clusterState.metaData().index(indexName).getIndex(); Index[] indices = new Index[] { index }; List failedIndexes = new ArrayList<>(); @@ -872,13 +901,15 @@ public class IndexLifecycleRunnerTests extends ESTestCase { randomNonNegativeLong(), randomNonNegativeLong()); StepKey currentStep = AbstractStepTestCase.randomStepKey(); Settings.Builder indexSettingsBuilder = Settings.builder().put(LifecycleSettings.LIFECYCLE_NAME, oldPolicyName) - .put(LifecycleSettings.LIFECYCLE_PHASE, currentStep.getPhase()) - .put(LifecycleSettings.LIFECYCLE_ACTION, currentStep.getAction()) - .put(LifecycleSettings.LIFECYCLE_STEP, currentStep.getName()).put(LifecycleSettings.LIFECYCLE_SKIP, true); + .put(LifecycleSettings.LIFECYCLE_SKIP, true); + LifecycleExecutionState.Builder lifecycleState = LifecycleExecutionState.builder(); + lifecycleState.setPhase(currentStep.getPhase()); + lifecycleState.setAction(currentStep.getAction()); + lifecycleState.setStep(currentStep.getName()); List policyMetadatas = new ArrayList<>(); policyMetadatas.add(new LifecyclePolicyMetadata(oldPolicy, Collections.emptyMap(), randomNonNegativeLong(), randomNonNegativeLong())); - ClusterState clusterState = buildClusterState(indexName, indexSettingsBuilder, policyMetadatas); + ClusterState clusterState = buildClusterState(indexName, indexSettingsBuilder, lifecycleState.build(), policyMetadatas); Index index = new Index("doesnt_exist", "im_not_here"); Index[] indices = new Index[] { index }; List failedIndexes = new ArrayList<>(); @@ -922,13 +953,15 @@ public class IndexLifecycleRunnerTests extends ESTestCase { StepKey currentStep = new StepKey(randomAlphaOfLength(10), MockAction.NAME, randomAlphaOfLength(10)); LifecyclePolicy oldPolicy = createPolicy(oldPolicyName, currentStep, null); Settings.Builder indexSettingsBuilder = Settings.builder().put(LifecycleSettings.LIFECYCLE_NAME, oldPolicyName) - .put(LifecycleSettings.LIFECYCLE_PHASE, currentStep.getPhase()) - .put(LifecycleSettings.LIFECYCLE_ACTION, currentStep.getAction()) - .put(LifecycleSettings.LIFECYCLE_STEP, currentStep.getName()).put(LifecycleSettings.LIFECYCLE_SKIP, true); + .put(LifecycleSettings.LIFECYCLE_SKIP, true); + LifecycleExecutionState.Builder lifecycleState = LifecycleExecutionState.builder(); + lifecycleState.setPhase(currentStep.getPhase()); + lifecycleState.setAction(currentStep.getAction()); + lifecycleState.setStep(currentStep.getName()); List policyMetadatas = new ArrayList<>(); policyMetadatas.add(new LifecyclePolicyMetadata(oldPolicy, Collections.emptyMap(), randomNonNegativeLong(), randomNonNegativeLong())); - ClusterState clusterState = buildClusterState(indexName, indexSettingsBuilder, policyMetadatas); + ClusterState clusterState = buildClusterState(indexName, indexSettingsBuilder, lifecycleState.build(), policyMetadatas); Index index = clusterState.metaData().index(indexName).getIndex(); Index[] indices = new Index[] { index }; List failedIndexes = new ArrayList<>(); @@ -942,7 +975,8 @@ public class IndexLifecycleRunnerTests extends ESTestCase { public void testRemovePolicyForIndexNoCurrentPolicy() { String indexName = randomAlphaOfLength(10); Settings.Builder indexSettingsBuilder = Settings.builder(); - ClusterState clusterState = buildClusterState(indexName, indexSettingsBuilder, Collections.emptyList()); + ClusterState clusterState = buildClusterState(indexName, indexSettingsBuilder, LifecycleExecutionState.builder().build(), + Collections.emptyList()); Index index = clusterState.metaData().index(indexName).getIndex(); Index[] indices = new Index[] { index }; List failedIndexes = new ArrayList<>(); @@ -959,13 +993,15 @@ public class IndexLifecycleRunnerTests extends ESTestCase { LifecyclePolicy oldPolicy = newTestLifecyclePolicy(oldPolicyName, Collections.emptyMap()); StepKey currentStep = AbstractStepTestCase.randomStepKey(); Settings.Builder indexSettingsBuilder = Settings.builder().put(LifecycleSettings.LIFECYCLE_NAME, oldPolicyName) - .put(LifecycleSettings.LIFECYCLE_PHASE, currentStep.getPhase()) - .put(LifecycleSettings.LIFECYCLE_ACTION, currentStep.getAction()) - .put(LifecycleSettings.LIFECYCLE_STEP, currentStep.getName()).put(LifecycleSettings.LIFECYCLE_SKIP, true); + .put(LifecycleSettings.LIFECYCLE_SKIP, true); + LifecycleExecutionState.Builder lifecycleState = LifecycleExecutionState.builder(); + lifecycleState.setPhase(currentStep.getPhase()); + lifecycleState.setAction(currentStep.getAction()); + lifecycleState.setStep(currentStep.getName()); List policyMetadatas = new ArrayList<>(); policyMetadatas.add(new LifecyclePolicyMetadata(oldPolicy, Collections.emptyMap(), randomNonNegativeLong(), randomNonNegativeLong())); - ClusterState clusterState = buildClusterState(indexName, indexSettingsBuilder, policyMetadatas); + ClusterState clusterState = buildClusterState(indexName, indexSettingsBuilder, lifecycleState.build(), policyMetadatas); Index index = new Index("doesnt_exist", "im_not_here"); Index[] indices = new Index[] { index }; List failedIndexes = new ArrayList<>(); @@ -983,13 +1019,15 @@ public class IndexLifecycleRunnerTests extends ESTestCase { StepKey currentStep = new StepKey(randomAlphaOfLength(10), MockAction.NAME, randomAlphaOfLength(10)); LifecyclePolicy oldPolicy = createPolicy(oldPolicyName, null, currentStep); Settings.Builder indexSettingsBuilder = Settings.builder().put(LifecycleSettings.LIFECYCLE_NAME, oldPolicyName) - .put(LifecycleSettings.LIFECYCLE_PHASE, currentStep.getPhase()) - .put(LifecycleSettings.LIFECYCLE_ACTION, currentStep.getAction()) - .put(LifecycleSettings.LIFECYCLE_STEP, currentStep.getName()).put(LifecycleSettings.LIFECYCLE_SKIP, true); + .put(LifecycleSettings.LIFECYCLE_SKIP, true); + LifecycleExecutionState.Builder lifecycleState = LifecycleExecutionState.builder(); + lifecycleState.setPhase(currentStep.getPhase()); + lifecycleState.setAction(currentStep.getAction()); + lifecycleState.setStep(currentStep.getName()); List policyMetadatas = new ArrayList<>(); policyMetadatas.add(new LifecyclePolicyMetadata(oldPolicy, Collections.emptyMap(), randomNonNegativeLong(), randomNonNegativeLong())); - ClusterState clusterState = buildClusterState(indexName, indexSettingsBuilder, policyMetadatas); + ClusterState clusterState = buildClusterState(indexName, indexSettingsBuilder, lifecycleState.build(), policyMetadatas); Index index = clusterState.metaData().index(indexName).getIndex(); Index[] indices = new Index[] { index }; List failedIndexes = new ArrayList<>(); @@ -1025,11 +1063,14 @@ public class IndexLifecycleRunnerTests extends ESTestCase { // With no time, always transition assertTrue("index should be able to transition with no creation date", runner.isReadyToTransitionToThisPhase(policyName, indexMetaData, "phase")); + + LifecycleExecutionState.Builder lifecycleState = LifecycleExecutionState.builder(); + lifecycleState.setIndexCreationDate(10L); indexMetaData = IndexMetaData.builder(indexMetaData) .settings(Settings.builder() .put(indexMetaData.getSettings()) - .put(LifecycleSettings.LIFECYCLE_INDEX_CREATION_DATE, 10L) .build()) + .putCustom(ILM_CUSTOM_METADATA_KEY, lifecycleState.build().asMap()) .build(); // Index is not old enough to transition assertFalse("index is not able to transition if it isn't old enough", @@ -1050,15 +1091,6 @@ public class IndexLifecycleRunnerTests extends ESTestCase { Settings indexSettings = indexMetadata.getSettings(); assertNotNull(indexSettings); assertFalse(LifecycleSettings.LIFECYCLE_NAME_SETTING.exists(indexSettings)); - assertFalse(LifecycleSettings.LIFECYCLE_PHASE_SETTING.exists(indexSettings)); - assertFalse(LifecycleSettings.LIFECYCLE_PHASE_TIME_SETTING.exists(indexSettings)); - assertFalse(LifecycleSettings.LIFECYCLE_ACTION_SETTING.exists(indexSettings)); - assertFalse(LifecycleSettings.LIFECYCLE_ACTION_TIME_SETTING.exists(indexSettings)); - assertFalse(LifecycleSettings.LIFECYCLE_STEP_SETTING.exists(indexSettings)); - assertFalse(LifecycleSettings.LIFECYCLE_STEP_TIME_SETTING.exists(indexSettings)); - assertFalse(LifecycleSettings.LIFECYCLE_STEP_INFO_SETTING.exists(indexSettings)); - assertFalse(LifecycleSettings.LIFECYCLE_FAILED_STEP_SETTING.exists(indexSettings)); - assertFalse(LifecycleSettings.LIFECYCLE_INDEX_CREATION_DATE_SETTING.exists(indexSettings)); assertFalse(LifecycleSettings.LIFECYCLE_SKIP_SETTING.exists(indexSettings)); assertFalse(RolloverAction.LIFECYCLE_ROLLOVER_ALIAS_SETTING.exists(indexSettings)); } @@ -1070,31 +1102,31 @@ public class IndexLifecycleRunnerTests extends ESTestCase { assertNotSame(oldClusterState.metaData(), newMetadata); IndexMetaData newIndexMetadata = newMetadata.getIndexSafe(index); assertNotSame(oldClusterState.metaData().index(index), newIndexMetadata); - Settings newIndexSettings = newIndexMetadata.getSettings(); - assertNotSame(oldClusterState.metaData().index(index).getSettings(), newIndexSettings); - assertEquals(expectedStep.getPhase(), LifecycleSettings.LIFECYCLE_PHASE_SETTING.get(newIndexSettings)); - assertEquals(expectedStep.getAction(), LifecycleSettings.LIFECYCLE_ACTION_SETTING.get(newIndexSettings)); - assertEquals(expectedStep.getName(), LifecycleSettings.LIFECYCLE_STEP_SETTING.get(newIndexSettings)); - if (previousStep.getPhase().equals(expectedStep.getPhase())) { - assertEquals(LifecycleSettings.LIFECYCLE_PHASE_TIME_SETTING.get(oldClusterState.metaData().index(index).getSettings()), - LifecycleSettings.LIFECYCLE_PHASE_TIME_SETTING.get(newIndexSettings)); + LifecycleExecutionState newLifecycleState = LifecycleExecutionState + .fromIndexMetadata(newClusterState.metaData().index(index)); + LifecycleExecutionState oldLifecycleState = LifecycleExecutionState + .fromIndexMetadata(oldClusterState.metaData().index(index)); + assertNotSame(oldLifecycleState, newLifecycleState); + assertEquals(expectedStep.getPhase(), newLifecycleState.getPhase()); + assertEquals(expectedStep.getAction(), newLifecycleState.getAction()); + assertEquals(expectedStep.getName(), newLifecycleState.getStep()); + if (Objects.equals(previousStep.getPhase(), expectedStep.getPhase())) { + assertEquals(oldLifecycleState.getPhase(), newLifecycleState.getPhase()); } else { - assertEquals(now, (long) LifecycleSettings.LIFECYCLE_PHASE_TIME_SETTING.get(newIndexSettings)); + assertEquals(now, newLifecycleState.getPhaseTime().longValue()); } - if (previousStep.getAction().equals(expectedStep.getAction())) { - assertEquals(LifecycleSettings.LIFECYCLE_ACTION_TIME_SETTING.get(oldClusterState.metaData().index(index).getSettings()), - LifecycleSettings.LIFECYCLE_ACTION_TIME_SETTING.get(newIndexSettings)); + if (Objects.equals(previousStep.getAction(), expectedStep.getAction())) { + assertEquals(oldLifecycleState.getActionTime(), newLifecycleState.getActionTime()); } else { - assertEquals(now, (long) LifecycleSettings.LIFECYCLE_ACTION_TIME_SETTING.get(newIndexSettings)); + assertEquals(now, newLifecycleState.getActionTime().longValue()); } - if (previousStep.getName().equals(expectedStep.getName())) { - assertEquals(LifecycleSettings.LIFECYCLE_STEP_TIME_SETTING.get(oldClusterState.metaData().index(index).getSettings()), - LifecycleSettings.LIFECYCLE_STEP_TIME_SETTING.get(newIndexSettings)); + if (Objects.equals(previousStep.getName(), expectedStep.getName())) { + assertEquals(oldLifecycleState.getStepTime(), newLifecycleState.getStepTime()); } else { - assertEquals(now, (long) LifecycleSettings.LIFECYCLE_STEP_TIME_SETTING.get(newIndexSettings)); + assertEquals(now, newLifecycleState.getStepTime().longValue()); } - assertEquals("", LifecycleSettings.LIFECYCLE_FAILED_STEP_SETTING.get(newIndexSettings)); - assertEquals("", LifecycleSettings.LIFECYCLE_STEP_INFO_SETTING.get(newIndexSettings)); + assertEquals(null, newLifecycleState.getFailedStep()); + assertEquals(null, newLifecycleState.getStepInfo()); } public static void assertClusterStateOnNextStep(ClusterState oldClusterState, Index index, StepKey currentStep, StepKey nextStep, @@ -1104,26 +1136,27 @@ public class IndexLifecycleRunnerTests extends ESTestCase { assertNotSame(oldClusterState.metaData(), newMetadata); IndexMetaData newIndexMetadata = newMetadata.getIndexSafe(index); assertNotSame(oldClusterState.metaData().index(index), newIndexMetadata); - Settings newIndexSettings = newIndexMetadata.getSettings(); - assertNotSame(oldClusterState.metaData().index(index).getSettings(), newIndexSettings); - assertEquals(nextStep.getPhase(), LifecycleSettings.LIFECYCLE_PHASE_SETTING.get(newIndexSettings)); - assertEquals(nextStep.getAction(), LifecycleSettings.LIFECYCLE_ACTION_SETTING.get(newIndexSettings)); - assertEquals(nextStep.getName(), LifecycleSettings.LIFECYCLE_STEP_SETTING.get(newIndexSettings)); + LifecycleExecutionState newLifecycleState = LifecycleExecutionState + .fromIndexMetadata(newClusterState.metaData().index(index)); + LifecycleExecutionState oldLifecycleState = LifecycleExecutionState + .fromIndexMetadata(oldClusterState.metaData().index(index)); + assertNotSame(oldLifecycleState, newLifecycleState); + assertEquals(nextStep.getPhase(), newLifecycleState.getPhase()); + assertEquals(nextStep.getAction(), newLifecycleState.getAction()); + assertEquals(nextStep.getName(), newLifecycleState.getStep()); if (currentStep.getPhase().equals(nextStep.getPhase())) { - assertEquals(LifecycleSettings.LIFECYCLE_PHASE_TIME_SETTING.get(oldClusterState.metaData().index(index).getSettings()), - LifecycleSettings.LIFECYCLE_PHASE_TIME_SETTING.get(newIndexSettings)); + assertEquals(oldLifecycleState.getPhaseTime(), newLifecycleState.getPhaseTime()); } else { - assertEquals(now, (long) LifecycleSettings.LIFECYCLE_PHASE_TIME_SETTING.get(newIndexSettings)); + assertEquals(now, newLifecycleState.getPhaseTime().longValue()); } if (currentStep.getAction().equals(nextStep.getAction())) { - assertEquals(LifecycleSettings.LIFECYCLE_ACTION_TIME_SETTING.get(oldClusterState.metaData().index(index).getSettings()), - LifecycleSettings.LIFECYCLE_ACTION_TIME_SETTING.get(newIndexSettings)); + assertEquals(oldLifecycleState.getActionTime(), newLifecycleState.getActionTime()); } else { - assertEquals(now, (long) LifecycleSettings.LIFECYCLE_ACTION_TIME_SETTING.get(newIndexSettings)); + assertEquals(now, newLifecycleState.getActionTime().longValue()); } - assertEquals(now, (long) LifecycleSettings.LIFECYCLE_STEP_TIME_SETTING.get(newIndexSettings)); - assertEquals("", LifecycleSettings.LIFECYCLE_FAILED_STEP_SETTING.get(newIndexSettings)); - assertEquals("", LifecycleSettings.LIFECYCLE_STEP_INFO_SETTING.get(newIndexSettings)); + assertEquals(now, newLifecycleState.getStepTime().longValue()); + assertEquals(null, newLifecycleState.getFailedStep()); + assertEquals(null, newLifecycleState.getStepInfo()); } private void assertClusterStateOnErrorStep(ClusterState oldClusterState, Index index, StepKey currentStep, @@ -1133,18 +1166,19 @@ public class IndexLifecycleRunnerTests extends ESTestCase { assertNotSame(oldClusterState.metaData(), newMetadata); IndexMetaData newIndexMetadata = newMetadata.getIndexSafe(index); assertNotSame(oldClusterState.metaData().index(index), newIndexMetadata); - Settings newIndexSettings = newIndexMetadata.getSettings(); - assertNotSame(oldClusterState.metaData().index(index).getSettings(), newIndexSettings); - assertEquals(currentStep.getPhase(), LifecycleSettings.LIFECYCLE_PHASE_SETTING.get(newIndexSettings)); - assertEquals(currentStep.getAction(), LifecycleSettings.LIFECYCLE_ACTION_SETTING.get(newIndexSettings)); - assertEquals(ErrorStep.NAME, LifecycleSettings.LIFECYCLE_STEP_SETTING.get(newIndexSettings)); - assertEquals(currentStep.getName(), LifecycleSettings.LIFECYCLE_FAILED_STEP_SETTING.get(newIndexSettings)); - assertEquals(expectedCauseValue, LifecycleSettings.LIFECYCLE_STEP_INFO_SETTING.get(newIndexSettings)); - assertEquals(LifecycleSettings.LIFECYCLE_PHASE_TIME_SETTING.get(oldClusterState.metaData().index(index).getSettings()), - LifecycleSettings.LIFECYCLE_PHASE_TIME_SETTING.get(newIndexSettings)); - assertEquals(LifecycleSettings.LIFECYCLE_ACTION_TIME_SETTING.get(oldClusterState.metaData().index(index).getSettings()), - LifecycleSettings.LIFECYCLE_ACTION_TIME_SETTING.get(newIndexSettings)); - assertEquals(now, (long) LifecycleSettings.LIFECYCLE_STEP_TIME_SETTING.get(newIndexSettings)); + LifecycleExecutionState newLifecycleState = LifecycleExecutionState + .fromIndexMetadata(newClusterState.metaData().index(index)); + LifecycleExecutionState oldLifecycleState = LifecycleExecutionState + .fromIndexMetadata(oldClusterState.metaData().index(index)); + assertNotSame(oldLifecycleState, newLifecycleState); + assertEquals(currentStep.getPhase(), newLifecycleState.getPhase()); + assertEquals(currentStep.getAction(), newLifecycleState.getAction()); + assertEquals(ErrorStep.NAME, newLifecycleState.getStep()); + assertEquals(currentStep.getName(), newLifecycleState.getFailedStep()); + assertEquals(expectedCauseValue, newLifecycleState.getStepInfo()); + assertEquals(oldLifecycleState.getPhaseTime(), newLifecycleState.getPhaseTime()); + assertEquals(oldLifecycleState.getActionTime(), newLifecycleState.getActionTime()); + assertEquals(now, newLifecycleState.getStepTime().longValue()); } private void assertClusterStateStepInfo(ClusterState oldClusterState, Index index, StepKey currentStep, ClusterState newClusterState, @@ -1157,18 +1191,18 @@ public class IndexLifecycleRunnerTests extends ESTestCase { assertNotSame(oldClusterState.metaData(), newMetadata); IndexMetaData newIndexMetadata = newMetadata.getIndexSafe(index); assertNotSame(oldClusterState.metaData().index(index), newIndexMetadata); - Settings newIndexSettings = newIndexMetadata.getSettings(); - assertNotSame(oldClusterState.metaData().index(index).getSettings(), newIndexSettings); - assertEquals(currentStep.getPhase(), LifecycleSettings.LIFECYCLE_PHASE_SETTING.get(newIndexSettings)); - assertEquals(currentStep.getAction(), LifecycleSettings.LIFECYCLE_ACTION_SETTING.get(newIndexSettings)); - assertEquals(currentStep.getName(), LifecycleSettings.LIFECYCLE_STEP_SETTING.get(newIndexSettings)); - assertEquals(expectedstepInfoValue, LifecycleSettings.LIFECYCLE_STEP_INFO_SETTING.get(newIndexSettings)); - assertEquals(LifecycleSettings.LIFECYCLE_PHASE_TIME_SETTING.get(oldClusterState.metaData().index(index).getSettings()), - LifecycleSettings.LIFECYCLE_PHASE_TIME_SETTING.get(newIndexSettings)); - assertEquals(LifecycleSettings.LIFECYCLE_ACTION_TIME_SETTING.get(oldClusterState.metaData().index(index).getSettings()), - LifecycleSettings.LIFECYCLE_ACTION_TIME_SETTING.get(newIndexSettings)); - assertEquals(LifecycleSettings.LIFECYCLE_STEP_TIME_SETTING.get(oldClusterState.metaData().index(index).getSettings()), - LifecycleSettings.LIFECYCLE_STEP_TIME_SETTING.get(newIndexSettings)); + LifecycleExecutionState newLifecycleState = LifecycleExecutionState + .fromIndexMetadata(newClusterState.metaData().index(index)); + LifecycleExecutionState oldLifecycleState = LifecycleExecutionState + .fromIndexMetadata(oldClusterState.metaData().index(index)); + assertNotSame(oldLifecycleState, newLifecycleState); + assertEquals(currentStep.getPhase(), newLifecycleState.getPhase()); + assertEquals(currentStep.getAction(), newLifecycleState.getAction()); + assertEquals(currentStep.getName(), newLifecycleState.getStep()); + assertEquals(expectedstepInfoValue, newLifecycleState.getStepInfo()); + assertEquals(oldLifecycleState.getPhaseTime(), newLifecycleState.getPhaseTime()); + assertEquals(oldLifecycleState.getActionTime(), newLifecycleState.getActionTime()); + assertEquals(newLifecycleState.getStepTime(), newLifecycleState.getStepTime()); } private static class MockAsyncActionStep extends AsyncActionStep { diff --git a/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/indexlifecycle/IndexLifecycleServiceTests.java b/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/indexlifecycle/IndexLifecycleServiceTests.java index d7296ffc816..a1ea3c2cd7f 100644 --- a/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/indexlifecycle/IndexLifecycleServiceTests.java +++ b/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/indexlifecycle/IndexLifecycleServiceTests.java @@ -24,13 +24,14 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.transport.TransportAddress; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.index.Index; -import org.elasticsearch.xpack.core.indexlifecycle.OperationMode; import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.xpack.core.indexlifecycle.LifecycleExecutionState; 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.MockAction; +import org.elasticsearch.xpack.core.indexlifecycle.OperationMode; import org.elasticsearch.xpack.core.indexlifecycle.Phase; import org.elasticsearch.xpack.core.indexlifecycle.ShrinkAction; import org.elasticsearch.xpack.core.indexlifecycle.Step; @@ -49,6 +50,7 @@ import java.util.concurrent.ExecutorService; import static org.elasticsearch.node.Node.NODE_MASTER_SETTING; import static org.elasticsearch.xpack.core.indexlifecycle.AbstractStepTestCase.randomStepKey; +import static org.elasticsearch.xpack.core.indexlifecycle.LifecycleExecutionState.ILM_CUSTOM_METADATA_KEY; import static org.elasticsearch.xpack.core.indexlifecycle.LifecyclePolicyTestsUtils.newTestLifecyclePolicy; import static org.hamcrest.Matchers.equalTo; import static org.mockito.Matchers.any; @@ -148,11 +150,13 @@ public class IndexLifecycleServiceTests extends ESTestCase { policyMap.put(policyName, new LifecyclePolicyMetadata(policy, Collections.emptyMap(), randomNonNegativeLong(), randomNonNegativeLong())); Index index = new Index(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20)); + LifecycleExecutionState.Builder lifecycleState = LifecycleExecutionState.builder(); + lifecycleState.setPhase(mockShrinkStep.getPhase()); + lifecycleState.setAction(mockShrinkStep.getAction()); + lifecycleState.setStep(mockShrinkStep.getName()); IndexMetaData indexMetadata = IndexMetaData.builder(index.getName()) - .settings(settings(Version.CURRENT).put(LifecycleSettings.LIFECYCLE_NAME_SETTING.getKey(), policyName) - .put(LifecycleSettings.LIFECYCLE_PHASE, mockShrinkStep.getPhase()) - .put(LifecycleSettings.LIFECYCLE_ACTION, mockShrinkStep.getAction()) - .put(LifecycleSettings.LIFECYCLE_STEP, mockShrinkStep.getName())) + .settings(settings(Version.CURRENT).put(LifecycleSettings.LIFECYCLE_NAME_SETTING.getKey(), policyName)) + .putCustom(ILM_CUSTOM_METADATA_KEY, lifecycleState.build().asMap()) .numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build(); ImmutableOpenMap.Builder indices = ImmutableOpenMap. builder() .fPut(index.getName(), indexMetadata); @@ -189,11 +193,13 @@ public class IndexLifecycleServiceTests extends ESTestCase { policyMap.put(policyName, new LifecyclePolicyMetadata(policy, Collections.emptyMap(), randomNonNegativeLong(), randomNonNegativeLong())); Index index = new Index(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20)); + LifecycleExecutionState.Builder lifecycleState = LifecycleExecutionState.builder(); + lifecycleState.setPhase(currentStepKey.getPhase()); + lifecycleState.setAction(currentStepKey.getAction()); + lifecycleState.setStep(currentStepKey.getName()); IndexMetaData indexMetadata = IndexMetaData.builder(index.getName()) - .settings(settings(Version.CURRENT).put(LifecycleSettings.LIFECYCLE_NAME_SETTING.getKey(), policyName) - .put(LifecycleSettings.LIFECYCLE_PHASE, currentStepKey.getPhase()) - .put(LifecycleSettings.LIFECYCLE_ACTION, currentStepKey.getAction()) - .put(LifecycleSettings.LIFECYCLE_STEP, currentStepKey.getName())) + .settings(settings(Version.CURRENT).put(LifecycleSettings.LIFECYCLE_NAME_SETTING.getKey(), policyName)) + .putCustom(ILM_CUSTOM_METADATA_KEY, lifecycleState.build().asMap()) .numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build(); ImmutableOpenMap.Builder indices = ImmutableOpenMap. builder() .fPut(index.getName(), indexMetadata); diff --git a/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/indexlifecycle/MoveToErrorStepUpdateTaskTests.java b/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/indexlifecycle/MoveToErrorStepUpdateTaskTests.java index 40844d0f93d..dc3a6602f39 100644 --- a/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/indexlifecycle/MoveToErrorStepUpdateTaskTests.java +++ b/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/indexlifecycle/MoveToErrorStepUpdateTaskTests.java @@ -19,6 +19,7 @@ import org.elasticsearch.common.xcontent.json.JsonXContent; import org.elasticsearch.index.Index; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.xpack.core.indexlifecycle.ErrorStep; +import org.elasticsearch.xpack.core.indexlifecycle.LifecycleExecutionState; import org.elasticsearch.xpack.core.indexlifecycle.IndexLifecycleMetadata; import org.elasticsearch.xpack.core.indexlifecycle.LifecyclePolicy; import org.elasticsearch.xpack.core.indexlifecycle.LifecyclePolicyMetadata; @@ -31,7 +32,9 @@ import org.junit.Before; import java.io.IOException; import java.util.Collections; +import static org.elasticsearch.xpack.core.indexlifecycle.LifecycleExecutionState.ILM_CUSTOM_METADATA_KEY; import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.Matchers.sameInstance; public class MoveToErrorStepUpdateTaskTests extends ESTestCase { @@ -70,21 +73,20 @@ public class MoveToErrorStepUpdateTaskTests extends ESTestCase { MoveToErrorStepUpdateTask task = new MoveToErrorStepUpdateTask(index, policy, currentStepKey, cause, () -> now); ClusterState newState = task.execute(clusterState); - StepKey actualKey = IndexLifecycleRunner.getCurrentStepKey(newState.metaData().index(index).getSettings()); + LifecycleExecutionState lifecycleState = LifecycleExecutionState.fromIndexMetadata(newState.getMetaData().index(index)); + StepKey actualKey = IndexLifecycleRunner.getCurrentStepKey(lifecycleState); assertThat(actualKey, equalTo(new StepKey(currentStepKey.getPhase(), currentStepKey.getAction(), ErrorStep.NAME))); - assertThat(LifecycleSettings.LIFECYCLE_FAILED_STEP_SETTING.get(newState.metaData().index(index).getSettings()), - equalTo(currentStepKey.getName())); - assertThat(LifecycleSettings.LIFECYCLE_PHASE_TIME_SETTING.get(newState.metaData().index(index).getSettings()), equalTo(-1L)); - assertThat(LifecycleSettings.LIFECYCLE_ACTION_TIME_SETTING.get(newState.metaData().index(index).getSettings()), equalTo(-1L)); - assertThat(LifecycleSettings.LIFECYCLE_STEP_TIME_SETTING.get(newState.metaData().index(index).getSettings()), equalTo(now)); + assertThat(lifecycleState.getFailedStep(), equalTo(currentStepKey.getName())); + assertThat(lifecycleState.getPhaseTime(), nullValue()); + assertThat(lifecycleState.getActionTime(), nullValue()); + assertThat(lifecycleState.getStepTime(), equalTo(now)); XContentBuilder causeXContentBuilder = JsonXContent.contentBuilder(); causeXContentBuilder.startObject(); ElasticsearchException.generateThrowableXContent(causeXContentBuilder, ToXContent.EMPTY_PARAMS, cause); causeXContentBuilder.endObject(); String expectedCauseValue = BytesReference.bytes(causeXContentBuilder).utf8ToString(); - assertThat(LifecycleSettings.LIFECYCLE_STEP_INFO_SETTING.get(newState.metaData().index(index).getSettings()), - equalTo(expectedCauseValue)); + assertThat(lifecycleState.getStepInfo(), equalTo(expectedCauseValue)); } public void testExecuteNoopDifferentStep() throws IOException { @@ -133,11 +135,15 @@ public class MoveToErrorStepUpdateTaskTests extends ESTestCase { } private void setStateToKey(StepKey stepKey) { + LifecycleExecutionState.Builder lifecycleState = LifecycleExecutionState.builder( + LifecycleExecutionState.fromIndexMetadata(clusterState.metaData().index(index))); + lifecycleState.setPhase(stepKey.getPhase()); + lifecycleState.setAction(stepKey.getAction()); + lifecycleState.setStep(stepKey.getName()); + clusterState = ClusterState.builder(clusterState) - .metaData(MetaData.builder(clusterState.metaData()) - .updateSettings(Settings.builder() - .put(LifecycleSettings.LIFECYCLE_PHASE, stepKey.getPhase()) - .put(LifecycleSettings.LIFECYCLE_ACTION, stepKey.getAction()) - .put(LifecycleSettings.LIFECYCLE_STEP, stepKey.getName()).build(), index.getName())).build(); + .metaData(MetaData.builder(clusterState.getMetaData()) + .put(IndexMetaData.builder(clusterState.getMetaData().index(index)) + .putCustom(ILM_CUSTOM_METADATA_KEY, lifecycleState.build().asMap()))).build(); } } diff --git a/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/indexlifecycle/MoveToNextStepUpdateTaskTests.java b/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/indexlifecycle/MoveToNextStepUpdateTaskTests.java index 727b957c349..16c4e332177 100644 --- a/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/indexlifecycle/MoveToNextStepUpdateTaskTests.java +++ b/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/indexlifecycle/MoveToNextStepUpdateTaskTests.java @@ -15,6 +15,7 @@ import org.elasticsearch.cluster.metadata.MetaData; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.index.Index; import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.xpack.core.indexlifecycle.LifecycleExecutionState; import org.elasticsearch.xpack.core.indexlifecycle.IndexLifecycleMetadata; import org.elasticsearch.xpack.core.indexlifecycle.LifecyclePolicy; import org.elasticsearch.xpack.core.indexlifecycle.LifecyclePolicyMetadata; @@ -28,6 +29,7 @@ import org.junit.Before; import java.util.Collections; import java.util.List; +import static org.elasticsearch.xpack.core.indexlifecycle.LifecycleExecutionState.ILM_CUSTOM_METADATA_KEY; import static org.hamcrest.Matchers.equalTo; public class MoveToNextStepUpdateTaskTests extends ESTestCase { @@ -68,11 +70,12 @@ public class MoveToNextStepUpdateTaskTests extends ESTestCase { MoveToNextStepUpdateTask task = new MoveToNextStepUpdateTask(index, policy, currentStepKey, nextStepKey, () -> now); ClusterState newState = task.execute(clusterState); - StepKey actualKey = IndexLifecycleRunner.getCurrentStepKey(newState.metaData().index(index).getSettings()); + LifecycleExecutionState lifecycleState = LifecycleExecutionState.fromIndexMetadata(newState.getMetaData().index(index)); + StepKey actualKey = IndexLifecycleRunner.getCurrentStepKey(lifecycleState); assertThat(actualKey, equalTo(nextStepKey)); - assertThat(LifecycleSettings.LIFECYCLE_PHASE_TIME_SETTING.get(newState.metaData().index(index).getSettings()), equalTo(now)); - assertThat(LifecycleSettings.LIFECYCLE_ACTION_TIME_SETTING.get(newState.metaData().index(index).getSettings()), equalTo(now)); - assertThat(LifecycleSettings.LIFECYCLE_STEP_TIME_SETTING.get(newState.metaData().index(index).getSettings()), equalTo(now)); + assertThat(lifecycleState.getPhaseTime(), equalTo(now)); + assertThat(lifecycleState.getActionTime(), equalTo(now)); + assertThat(lifecycleState.getStepTime(), equalTo(now)); task.clusterStateProcessed("source", clusterState, newState); } @@ -107,11 +110,12 @@ public class MoveToNextStepUpdateTaskTests extends ESTestCase { SetOnce changed = new SetOnce<>(); MoveToNextStepUpdateTask task = new MoveToNextStepUpdateTask(index, policy, currentStepKey, invalidNextStep, () -> now); ClusterState newState = task.execute(clusterState); - StepKey actualKey = IndexLifecycleRunner.getCurrentStepKey(newState.metaData().index(index).getSettings()); + LifecycleExecutionState lifecycleState = LifecycleExecutionState.fromIndexMetadata(newState.getMetaData().index(index)); + StepKey actualKey = IndexLifecycleRunner.getCurrentStepKey(lifecycleState); assertThat(actualKey, equalTo(invalidNextStep)); - assertThat(LifecycleSettings.LIFECYCLE_PHASE_TIME_SETTING.get(newState.metaData().index(index).getSettings()), equalTo(now)); - assertThat(LifecycleSettings.LIFECYCLE_ACTION_TIME_SETTING.get(newState.metaData().index(index).getSettings()), equalTo(now)); - assertThat(LifecycleSettings.LIFECYCLE_STEP_TIME_SETTING.get(newState.metaData().index(index).getSettings()), equalTo(now)); + assertThat(lifecycleState.getPhaseTime(), equalTo(now)); + assertThat(lifecycleState.getActionTime(), equalTo(now)); + assertThat(lifecycleState.getStepTime(), equalTo(now)); task.clusterStateProcessed("source", clusterState, newState); } @@ -139,15 +143,18 @@ public class MoveToNextStepUpdateTaskTests extends ESTestCase { } private void setStateToKey(StepKey stepKey, long now) { + LifecycleExecutionState.Builder lifecycleState = LifecycleExecutionState.builder( + LifecycleExecutionState.fromIndexMetadata(clusterState.metaData().index(index))); + lifecycleState.setPhase(stepKey.getPhase()); + lifecycleState.setPhaseTime(now); + lifecycleState.setAction(stepKey.getAction()); + lifecycleState.setActionTime(now); + lifecycleState.setStep(stepKey.getName()); + lifecycleState.setStepTime(now); + lifecycleState.setPhaseDefinition("{\"actions\":{\"TEST_ACTION\":{}}}"); clusterState = ClusterState.builder(clusterState) - .metaData(MetaData.builder(clusterState.metaData()) - .updateSettings(Settings.builder() - .put(LifecycleSettings.LIFECYCLE_PHASE_DEFINITION, "{\"actions\":{\"TEST_ACTION\":{}}}") - .put(LifecycleSettings.LIFECYCLE_PHASE, stepKey.getPhase()) - .put(LifecycleSettings.LIFECYCLE_PHASE_TIME, now) - .put(LifecycleSettings.LIFECYCLE_ACTION, stepKey.getAction()) - .put(LifecycleSettings.LIFECYCLE_ACTION_TIME, now) - .put(LifecycleSettings.LIFECYCLE_STEP, stepKey.getName()) - .put(LifecycleSettings.LIFECYCLE_STEP_TIME, now).build(), index.getName())).build(); + .metaData(MetaData.builder(clusterState.getMetaData()) + .put(IndexMetaData.builder(clusterState.getMetaData().index(index)) + .putCustom(ILM_CUSTOM_METADATA_KEY, lifecycleState.build().asMap()))).build(); } } diff --git a/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/indexlifecycle/PolicyStepsRegistryTests.java b/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/indexlifecycle/PolicyStepsRegistryTests.java index 95a24c76838..611522a59b0 100644 --- a/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/indexlifecycle/PolicyStepsRegistryTests.java +++ b/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/indexlifecycle/PolicyStepsRegistryTests.java @@ -25,6 +25,7 @@ import org.elasticsearch.index.Index; import org.elasticsearch.node.Node; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.xpack.core.indexlifecycle.ErrorStep; +import org.elasticsearch.xpack.core.indexlifecycle.LifecycleExecutionState; import org.elasticsearch.xpack.core.indexlifecycle.IndexLifecycleMetadata; import org.elasticsearch.xpack.core.indexlifecycle.InitializePolicyContextStep; import org.elasticsearch.xpack.core.indexlifecycle.LifecycleAction; @@ -48,6 +49,7 @@ import java.util.Map; import java.util.SortedMap; import java.util.TreeMap; +import static org.elasticsearch.xpack.core.indexlifecycle.LifecycleExecutionState.ILM_CUSTOM_METADATA_KEY; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.sameInstance; @@ -91,14 +93,16 @@ public class PolicyStepsRegistryTests extends ESTestCase { String phaseJson = Strings.toString(pei); LifecycleAction action = randomFrom(phase.getActions().values()); Step step = randomFrom(action.toSteps(client, phaseName, MOCK_STEP_KEY)); + LifecycleExecutionState.Builder lifecycleState = LifecycleExecutionState.builder(); + lifecycleState.setPhaseDefinition(phaseJson); IndexMetaData indexMetaData = IndexMetaData.builder("test") .settings(Settings.builder() .put("index.number_of_shards", 1) .put("index.number_of_replicas", 0) .put("index.version.created", Version.CURRENT) .put(LifecycleSettings.LIFECYCLE_NAME, "policy") - .put(LifecycleSettings.LIFECYCLE_PHASE_DEFINITION, phaseJson) .build()) + .putCustom(ILM_CUSTOM_METADATA_KEY, lifecycleState.build().asMap()) .build(); SortedMap metas = new TreeMap<>(); metas.put("policy", policyMetadata); @@ -157,14 +161,16 @@ public class PolicyStepsRegistryTests extends ESTestCase { String phaseJson = Strings.toString(pei); LifecycleAction action = randomFrom(phase.getActions().values()); Step step = randomFrom(action.toSteps(client, phaseName, MOCK_STEP_KEY)); + LifecycleExecutionState.Builder lifecycleState = LifecycleExecutionState.builder(); + lifecycleState.setPhaseDefinition(phaseJson); IndexMetaData indexMetaData = IndexMetaData.builder("test") .settings(Settings.builder() .put("index.number_of_shards", 1) .put("index.number_of_replicas", 0) .put("index.version.created", Version.CURRENT) .put(LifecycleSettings.LIFECYCLE_NAME, "policy") - .put(LifecycleSettings.LIFECYCLE_PHASE_DEFINITION, phaseJson) .build()) + .putCustom(ILM_CUSTOM_METADATA_KEY, lifecycleState.build().asMap()) .build(); SortedMap metas = new TreeMap<>(); metas.put("policy", policyMetadata); @@ -190,6 +196,8 @@ public class PolicyStepsRegistryTests extends ESTestCase { Map policyMap = Collections.singletonMap(newPolicy.getName(), new LifecyclePolicyMetadata(newPolicy, headers, randomNonNegativeLong(), randomNonNegativeLong())); IndexLifecycleMetadata lifecycleMetadata = new IndexLifecycleMetadata(policyMap, OperationMode.RUNNING); + LifecycleExecutionState.Builder lifecycleState = LifecycleExecutionState.builder(); + lifecycleState.setPhase("new"); MetaData metaData = MetaData.builder() .persistentSettings(settings(Version.CURRENT).build()) .putCustom(IndexLifecycleMetadata.TYPE, lifecycleMetadata) @@ -199,8 +207,8 @@ public class PolicyStepsRegistryTests extends ESTestCase { .put("index.number_of_shards", 1) .put("index.number_of_replicas", 0) .put("index.version.created", Version.CURRENT.id) - .put(LifecycleSettings.LIFECYCLE_NAME, policyName) - .put(LifecycleSettings.LIFECYCLE_PHASE, "new"))) + .put(LifecycleSettings.LIFECYCLE_NAME, policyName)) + .putCustom(ILM_CUSTOM_METADATA_KEY, lifecycleState.build().asMap())) .build(); try (XContentBuilder builder = JsonXContent.contentBuilder()) { builder.startObject(); @@ -232,11 +240,13 @@ public class PolicyStepsRegistryTests extends ESTestCase { Map registeredStepsForPolicy = registry.getStepMap().get(newPolicy.getName()); assertThat(registeredStepsForPolicy.size(), equalTo(policySteps.size())); for (Step step : policySteps) { + LifecycleExecutionState.Builder newIndexState = LifecycleExecutionState.builder(); + newIndexState.setPhase(step.getKey().getPhase()); currentState = ClusterState.builder(currentState) .metaData(MetaData.builder(currentState.metaData()) .put(IndexMetaData.builder(currentState.metaData().index("test")) - .settings(Settings.builder().put(currentState.metaData().index("test").getSettings()) - .put(LifecycleSettings.LIFECYCLE_PHASE, step.getKey().getPhase())))) + .settings(Settings.builder().put(currentState.metaData().index("test").getSettings())) + .putCustom(ILM_CUSTOM_METADATA_KEY, newIndexState.build().asMap()))) .nodes(DiscoveryNodes.builder().localNodeId(nodeId).masterNodeId(nodeId).add(masterNode).build()) .build(); registry.update(currentState); @@ -334,6 +344,9 @@ public class PolicyStepsRegistryTests extends ESTestCase { Map policyMap = Collections.singletonMap(newPolicy.getName(), new LifecyclePolicyMetadata(newPolicy, headers, randomNonNegativeLong(), randomNonNegativeLong())); IndexLifecycleMetadata lifecycleMetadata = new IndexLifecycleMetadata(policyMap, OperationMode.RUNNING); + LifecycleExecutionState.Builder lifecycleState = LifecycleExecutionState.builder(); + lifecycleState.setPhase("warm"); + lifecycleState.setPhaseDefinition(phaseJson); MetaData metaData = MetaData.builder() .persistentSettings(settings(Version.CURRENT).build()) .putCustom(IndexLifecycleMetadata.TYPE, lifecycleMetadata) @@ -343,9 +356,8 @@ public class PolicyStepsRegistryTests extends ESTestCase { .put("index.number_of_shards", 1) .put("index.number_of_replicas", 0) .put("index.version.created", Version.CURRENT.id) - .put(LifecycleSettings.LIFECYCLE_NAME, policyName) - .put(LifecycleSettings.LIFECYCLE_PHASE, "warm") - .put(LifecycleSettings.LIFECYCLE_PHASE_DEFINITION, phaseJson))) + .put(LifecycleSettings.LIFECYCLE_NAME, policyName)) + .putCustom(ILM_CUSTOM_METADATA_KEY, lifecycleState.build().asMap())) .build(); try (XContentBuilder builder = JsonXContent.contentBuilder()) { builder.startObject(); diff --git a/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/indexlifecycle/SetStepInfoUpdateTaskTests.java b/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/indexlifecycle/SetStepInfoUpdateTaskTests.java index df2c0fa0e69..a8b16d3ecfd 100644 --- a/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/indexlifecycle/SetStepInfoUpdateTaskTests.java +++ b/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/indexlifecycle/SetStepInfoUpdateTaskTests.java @@ -20,13 +20,16 @@ import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.json.JsonXContent; import org.elasticsearch.index.Index; import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.xpack.core.indexlifecycle.LifecycleExecutionState; import org.elasticsearch.xpack.core.indexlifecycle.LifecycleSettings; import org.elasticsearch.xpack.core.indexlifecycle.Step.StepKey; import org.junit.Before; import java.io.IOException; +import static org.elasticsearch.xpack.core.indexlifecycle.LifecycleExecutionState.ILM_CUSTOM_METADATA_KEY; import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.Matchers.sameInstance; public class SetStepInfoUpdateTaskTests extends ESTestCase { @@ -57,17 +60,17 @@ public class SetStepInfoUpdateTaskTests extends ESTestCase { SetStepInfoUpdateTask task = new SetStepInfoUpdateTask(index, policy, currentStepKey, stepInfo); ClusterState newState = task.execute(clusterState); - StepKey actualKey = IndexLifecycleRunner.getCurrentStepKey(newState.metaData().index(index).getSettings()); + LifecycleExecutionState lifecycleState = LifecycleExecutionState.fromIndexMetadata(newState.getMetaData().index(index)); + StepKey actualKey = IndexLifecycleRunner.getCurrentStepKey(lifecycleState); assertThat(actualKey, equalTo(currentStepKey)); - assertThat(LifecycleSettings.LIFECYCLE_PHASE_TIME_SETTING.get(newState.metaData().index(index).getSettings()), equalTo(-1L)); - assertThat(LifecycleSettings.LIFECYCLE_ACTION_TIME_SETTING.get(newState.metaData().index(index).getSettings()), equalTo(-1L)); - assertThat(LifecycleSettings.LIFECYCLE_STEP_TIME_SETTING.get(newState.metaData().index(index).getSettings()), equalTo(-1L)); + assertThat(lifecycleState.getPhaseTime(), nullValue()); + assertThat(lifecycleState.getActionTime(), nullValue()); + assertThat(lifecycleState.getStepTime(), nullValue()); XContentBuilder infoXContentBuilder = JsonXContent.contentBuilder(); stepInfo.toXContent(infoXContentBuilder, ToXContent.EMPTY_PARAMS); String expectedCauseValue = BytesReference.bytes(infoXContentBuilder).utf8ToString(); - assertThat(LifecycleSettings.LIFECYCLE_STEP_INFO_SETTING.get(newState.metaData().index(index).getSettings()), - equalTo(expectedCauseValue)); + assertThat(lifecycleState.getStepInfo(), equalTo(expectedCauseValue)); } private ToXContentObject getRandomStepInfo() { @@ -124,11 +127,15 @@ public class SetStepInfoUpdateTaskTests extends ESTestCase { } private void setStateToKey(StepKey stepKey) { + LifecycleExecutionState.Builder lifecycleState = LifecycleExecutionState.builder( + LifecycleExecutionState.fromIndexMetadata(clusterState.metaData().index(index))); + lifecycleState.setPhase(stepKey.getPhase()); + lifecycleState.setAction(stepKey.getAction()); + lifecycleState.setStep(stepKey.getName()); + clusterState = ClusterState.builder(clusterState) - .metaData(MetaData.builder(clusterState.metaData()) - .updateSettings(Settings.builder() - .put(LifecycleSettings.LIFECYCLE_PHASE, stepKey.getPhase()) - .put(LifecycleSettings.LIFECYCLE_ACTION, stepKey.getAction()) - .put(LifecycleSettings.LIFECYCLE_STEP, stepKey.getName()).build(), index.getName())).build(); + .metaData(MetaData.builder(clusterState.getMetaData()) + .put(IndexMetaData.builder(clusterState.getMetaData().index(index)) + .putCustom(ILM_CUSTOM_METADATA_KEY, lifecycleState.build().asMap()))).build(); } } diff --git a/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/indexlifecycle/TimeSeriesLifecycleActionsIT.java b/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/indexlifecycle/TimeSeriesLifecycleActionsIT.java index 30737168c1f..14ae060c89d 100644 --- a/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/indexlifecycle/TimeSeriesLifecycleActionsIT.java +++ b/x-pack/plugin/ilm/src/test/java/org/elasticsearch/xpack/indexlifecycle/TimeSeriesLifecycleActionsIT.java @@ -9,11 +9,14 @@ package org.elasticsearch.xpack.indexlifecycle; import org.apache.http.entity.ContentType; import org.apache.http.entity.StringEntity; import org.elasticsearch.client.Request; +import org.elasticsearch.client.Response; import org.elasticsearch.cluster.metadata.IndexMetaData; import org.elasticsearch.common.Strings; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentHelper; +import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.common.xcontent.json.JsonXContent; import org.elasticsearch.test.rest.ESRestTestCase; import org.elasticsearch.xpack.core.indexlifecycle.AllocateAction; @@ -30,6 +33,7 @@ import org.elasticsearch.xpack.core.indexlifecycle.TerminalPolicyStep; import org.junit.Before; import java.io.IOException; +import java.io.InputStream; import java.util.Collections; import java.util.List; import java.util.Locale; @@ -75,8 +79,7 @@ public class TimeSeriesLifecycleActionsIT extends ESRestTestCase { createNewSingletonPolicy(randomFrom("warm", "cold"), allocateAction); updatePolicy(index, policy); assertBusy(() -> { - Map settings = getOnlyIndexSettings(index); - assertThat(getStepKey(settings), equalTo(TerminalPolicyStep.KEY)); + assertThat(getStepKeyForIndex(index), equalTo(TerminalPolicyStep.KEY)); }); ensureGreen(index); } @@ -92,7 +95,7 @@ public class TimeSeriesLifecycleActionsIT extends ESRestTestCase { updatePolicy(index, policy); assertBusy(() -> { Map settings = getOnlyIndexSettings(index); - assertThat(getStepKey(settings), equalTo(TerminalPolicyStep.KEY)); + assertThat(getStepKeyForIndex(index), equalTo(TerminalPolicyStep.KEY)); assertThat(settings.get(IndexMetaData.INDEX_NUMBER_OF_REPLICAS_SETTING.getKey()), equalTo(String.valueOf(finalNumReplicas))); }); } @@ -112,7 +115,7 @@ public class TimeSeriesLifecycleActionsIT extends ESRestTestCase { updatePolicy(index, policy); assertBusy(() -> { Map settings = getOnlyIndexSettings(index); - assertThat(getStepKey(settings), equalTo(TerminalPolicyStep.KEY)); + assertThat(getStepKeyForIndex(index), equalTo(TerminalPolicyStep.KEY)); assertThat(settings.get(IndexMetaData.INDEX_BLOCKS_WRITE_SETTING.getKey()), equalTo("true")); }); } @@ -146,7 +149,7 @@ public class TimeSeriesLifecycleActionsIT extends ESRestTestCase { updatePolicy(index, policy); assertBusy(() -> { - assertThat(getStepKey(getOnlyIndexSettings(index)), equalTo(TerminalPolicyStep.KEY)); + assertThat(getStepKeyForIndex(index), equalTo(TerminalPolicyStep.KEY)); assertThat(numSegments.get(), equalTo(1)); }); } @@ -164,7 +167,7 @@ public class TimeSeriesLifecycleActionsIT extends ESRestTestCase { assertTrue(indexExists(shrunkenIndex)); assertTrue(aliasExists(shrunkenIndex, index)); Map settings = getOnlyIndexSettings(shrunkenIndex); - assertThat(getStepKey(settings), equalTo(TerminalPolicyStep.KEY)); + assertThat(getStepKeyForIndex(shrunkenIndex), equalTo(TerminalPolicyStep.KEY)); assertThat(settings.get(IndexMetaData.SETTING_NUMBER_OF_SHARDS), equalTo(String.valueOf(expectedFinalShards))); }); } @@ -198,10 +201,22 @@ public class TimeSeriesLifecycleActionsIT extends ESRestTestCase { return (Map) response.get("settings"); } - private StepKey getStepKey(Map settings) { - String phase = (String) settings.get(LifecycleSettings.LIFECYCLE_PHASE); - String action = (String) settings.get(LifecycleSettings.LIFECYCLE_ACTION); - String step = (String) settings.get(LifecycleSettings.LIFECYCLE_STEP); + private StepKey getStepKeyForIndex(String indexName) throws IOException { + Request explainRequest = new Request("GET", indexName + "/_ilm/explain"); + Response response = client().performRequest(explainRequest); + Map responseMap; + try (InputStream is = response.getEntity().getContent()) { + responseMap = XContentHelper.convertToMap(XContentType.JSON.xContent(), is, true); + } + + @SuppressWarnings("unchecked") Map indexResponse = ((Map>) responseMap.get("indices")) + .get(indexName); + if (indexResponse == null) { + return new StepKey(null, null, null); + } + String phase = indexResponse.get("phase"); + String action = indexResponse.get("action"); + String step = indexResponse.get("step"); return new StepKey(phase, action, step); } } diff --git a/x-pack/plugin/src/test/resources/rest-api-spec/test/ilm/20_move_to_step.yml b/x-pack/plugin/src/test/resources/rest-api-spec/test/ilm/20_move_to_step.yml index 94c21926e23..f102a801c81 100644 --- a/x-pack/plugin/src/test/resources/rest-api-spec/test/ilm/20_move_to_step.yml +++ b/x-pack/plugin/src/test/resources/rest-api-spec/test/ilm/20_move_to_step.yml @@ -84,13 +84,13 @@ teardown: name: "forcemerge" - do: - acknowledge: true - indices.get: - index: my_index - - match: { my_index.settings.index.lifecycle.name: "my_moveable_timeseries_lifecycle" } - - match: { my_index.settings.index.lifecycle.step: "forcemerge" } - - match: { my_index.settings.index.lifecycle.action: "forcemerge" } - - match: { my_index.settings.index.lifecycle.phase: "warm" } + acknowledge: true + ilm.explain_lifecycle: + index: "my_index" + - match: { indices.my_index.policy: "my_moveable_timeseries_lifecycle" } + - match: { indices.my_index.step: "forcemerge" } + - match: { indices.my_index.action: "forcemerge" } + - match: { indices.my_index.phase: "warm" } --- "Test Invalid Move To Step With Incorrect Current Step": @@ -111,14 +111,15 @@ teardown: - match: { error.root_cause.0.type: "illegal_argument_exception" } - match: { error.root_cause.0.reason: "index [my_index] is not on current step [{\"phase\":\"warm\",\"action\":\"forcemerge\",\"name\":\"forcemerge\"}]" } + - do: acknowledge: true - indices.get: - index: my_index - - match: { my_index.settings.index.lifecycle.name: "my_moveable_timeseries_lifecycle" } - - match: { my_index.settings.index.lifecycle.step: "complete" } - - match: { my_index.settings.index.lifecycle.action: "complete" } - - match: { my_index.settings.index.lifecycle.phase: "new" } + ilm.explain_lifecycle: + index: "my_index" + - match: { indices.my_index.policy: "my_moveable_timeseries_lifecycle" } + - match: { indices.my_index.step: "complete" } + - match: { indices.my_index.action: "complete" } + - match: { indices.my_index.phase: "new" } --- "Test Invalid Move To Step With Invalid Next Step": @@ -141,12 +142,12 @@ teardown: - do: acknowledge: true - indices.get: - index: my_index - - match: { my_index.settings.index.lifecycle.name: "my_moveable_timeseries_lifecycle" } - - match: { my_index.settings.index.lifecycle.step: "complete" } - - match: { my_index.settings.index.lifecycle.action: "complete" } - - match: { my_index.settings.index.lifecycle.phase: "new" } + ilm.explain_lifecycle: + index: "my_index" + - match: { indices.my_index.policy: "my_moveable_timeseries_lifecycle" } + - match: { indices.my_index.step: "complete" } + - match: { indices.my_index.action: "complete" } + - match: { indices.my_index.phase: "new" } --- "Test Invalid Move To Step With Invalid Policy": diff --git a/x-pack/plugin/src/test/resources/rest-api-spec/test/ilm/30_retry.yml b/x-pack/plugin/src/test/resources/rest-api-spec/test/ilm/30_retry.yml index 6e0e0095480..0ffcc74a70e 100644 --- a/x-pack/plugin/src/test/resources/rest-api-spec/test/ilm/30_retry.yml +++ b/x-pack/plugin/src/test/resources/rest-api-spec/test/ilm/30_retry.yml @@ -70,12 +70,12 @@ teardown: - do: acknowledge: true - indices.get: - index: my_index - - match: { my_index.settings.index.lifecycle.name: "my_lifecycle" } - - match: { my_index.settings.index.lifecycle.step: "complete" } - - match: { my_index.settings.index.lifecycle.action: "complete" } - - match: { my_index.settings.index.lifecycle.phase: "new" } + ilm.explain_lifecycle: + index: "my_index" + - match: { indices.my_index.policy: "my_lifecycle" } + - match: { indices.my_index.step: "complete" } + - match: { indices.my_index.action: "complete" } + - match: { indices.my_index.phase: "new" } ---