Split RolloverStep into Wait and Action steps (#35524)
RolloverAction will now periodically check the rollover conditions using the Rollover API with the dry_run option as an AsyncWaitStep, then run the rollover itself by calling the Rollover API with no conditions, which will always roll over, as an AsyncActionStep. This will resolve race condition issues in policies using RolloverAction.
This commit is contained in:
parent
ce35d049e9
commit
3883e9bf4c
|
@ -194,7 +194,7 @@ public class IndexLifecycleIT extends ESRestHighLevelClientTestCase {
|
|||
assertEquals("foo-01", fooResponse.getIndex());
|
||||
assertEquals("hot", fooResponse.getPhase());
|
||||
assertEquals("rollover", fooResponse.getAction());
|
||||
assertEquals("attempt_rollover", fooResponse.getStep());
|
||||
assertEquals("check-rollover-ready", fooResponse.getStep());
|
||||
assertEquals(new PhaseExecutionInfo(policy.getName(), new Phase("", hotPhase.getMinimumAge(), hotPhase.getActions()),
|
||||
1L, expectedPolicyModifiedDate), fooResponse.getPhaseExecutionInfo());
|
||||
IndexLifecycleExplainResponse bazResponse = indexResponses.get("baz-01");
|
||||
|
@ -203,7 +203,7 @@ public class IndexLifecycleIT extends ESRestHighLevelClientTestCase {
|
|||
assertEquals("baz-01", bazResponse.getIndex());
|
||||
assertEquals("hot", bazResponse.getPhase());
|
||||
assertEquals("rollover", bazResponse.getAction());
|
||||
assertEquals("attempt_rollover", bazResponse.getStep());
|
||||
assertEquals("check-rollover-ready", bazResponse.getStep());
|
||||
IndexLifecycleExplainResponse squashResponse = indexResponses.get("squash");
|
||||
assertNotNull(squashResponse);
|
||||
assertFalse(squashResponse.managedByILM());
|
||||
|
|
|
@ -177,7 +177,7 @@ PUT my_index
|
|||
////
|
||||
|
||||
The <<ilm-explain-lifecycle,Explain API>> is useful to introspect managed indices to see which phase definition they are currently executing.
|
||||
Using this API, we can find out that `my_index` is currently attempting to be rolled over.
|
||||
Using this API, we can find out that `my_index` is currently checking if it is ready to be rolled over.
|
||||
|
||||
[source,js]
|
||||
--------------------------------------------------
|
||||
|
@ -199,7 +199,7 @@ GET my_index/_ilm/explain
|
|||
"phase_time_millis": 1538475653317,
|
||||
"action": "rollover",
|
||||
"action_time_millis": 1538475653317,
|
||||
"step": "attempt_rollover",
|
||||
"step": "check-rollover-ready",
|
||||
"step_time_millis": 1538475653317,
|
||||
"phase_execution": {
|
||||
"policy": "my_executing_policy",
|
||||
|
@ -275,7 +275,7 @@ GET my_index/_ilm/explain
|
|||
"phase_time_millis": 1538475653317,
|
||||
"action": "rollover",
|
||||
"action_time_millis": 1538475653317,
|
||||
"step": "attempt_rollover",
|
||||
"step": "check-rollover-ready",
|
||||
"step_time_millis": 1538475653317,
|
||||
"phase_execution": {
|
||||
"policy": "my_executing_policy",
|
||||
|
|
|
@ -132,18 +132,23 @@ public class RolloverAction implements LifecycleAction {
|
|||
|
||||
@Override
|
||||
public List<Step> toSteps(Client client, String phase, Step.StepKey nextStepKey) {
|
||||
StepKey waitForRolloverReadyStepKey = new StepKey(phase, NAME, WaitForRolloverReadyStep.NAME);
|
||||
StepKey rolloverStepKey = new StepKey(phase, NAME, RolloverStep.NAME);
|
||||
StepKey updateDateStepKey = new StepKey(phase, NAME, UpdateRolloverLifecycleDateStep.NAME);
|
||||
RolloverStep rolloverStep = new RolloverStep(new StepKey(phase, NAME, RolloverStep.NAME), updateDateStepKey, client,
|
||||
maxSize, maxAge, maxDocs);
|
||||
|
||||
WaitForRolloverReadyStep waitForRolloverReadyStep = new WaitForRolloverReadyStep(waitForRolloverReadyStepKey, rolloverStepKey,
|
||||
client, maxSize, maxAge, maxDocs);
|
||||
RolloverStep rolloverStep = new RolloverStep(rolloverStepKey, updateDateStepKey, client);
|
||||
UpdateRolloverLifecycleDateStep updateDateStep = new UpdateRolloverLifecycleDateStep(updateDateStepKey, nextStepKey);
|
||||
return Arrays.asList(rolloverStep, updateDateStep);
|
||||
return Arrays.asList(waitForRolloverReadyStep, rolloverStep, updateDateStep);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<StepKey> toStepKeys(String phase) {
|
||||
StepKey rolloverReadyStepKey = new StepKey(phase, NAME, WaitForRolloverReadyStep.NAME);
|
||||
StepKey rolloverStepKey = new StepKey(phase, NAME, RolloverStep.NAME);
|
||||
StepKey updateDateStepKey = new StepKey(phase, NAME, UpdateRolloverLifecycleDateStep.NAME);
|
||||
return Arrays.asList(rolloverStepKey, updateDateStepKey);
|
||||
return Arrays.asList(rolloverReadyStepKey, rolloverStepKey, updateDateStepKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -5,43 +5,28 @@
|
|||
*/
|
||||
package org.elasticsearch.xpack.core.indexlifecycle;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.logging.log4j.message.ParameterizedMessage;
|
||||
import org.elasticsearch.ResourceAlreadyExistsException;
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.action.admin.indices.rollover.RolloverRequest;
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.cluster.ClusterState;
|
||||
import org.elasticsearch.cluster.metadata.IndexMetaData;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.unit.ByteSizeValue;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.common.xcontent.ToXContentObject;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
|
||||
public class RolloverStep extends AsyncWaitStep {
|
||||
/**
|
||||
* Unconditionally rolls over an index using the Rollover API.
|
||||
*/
|
||||
public class RolloverStep extends AsyncActionStep {
|
||||
public static final String NAME = "attempt_rollover";
|
||||
|
||||
private static final Logger logger = LogManager.getLogger(RolloverStep.class);
|
||||
|
||||
private ByteSizeValue maxSize;
|
||||
private TimeValue maxAge;
|
||||
private Long maxDocs;
|
||||
|
||||
public RolloverStep(StepKey key, StepKey nextStepKey, Client client, ByteSizeValue maxSize, TimeValue maxAge,
|
||||
Long maxDocs) {
|
||||
public RolloverStep(StepKey key, StepKey nextStepKey, Client client) {
|
||||
super(key, nextStepKey, client);
|
||||
this.maxSize = maxSize;
|
||||
this.maxAge = maxAge;
|
||||
this.maxDocs = maxDocs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evaluateCondition(IndexMetaData indexMetaData, Listener listener) {
|
||||
public void performAction(IndexMetaData indexMetaData, ClusterState currentClusterState, Listener listener) {
|
||||
String rolloverAlias = RolloverAction.LIFECYCLE_ROLLOVER_ALIAS_SETTING.get(indexMetaData.getSettings());
|
||||
|
||||
if (Strings.isNullOrEmpty(rolloverAlias)) {
|
||||
|
@ -58,49 +43,19 @@ public class RolloverStep extends AsyncWaitStep {
|
|||
return;
|
||||
}
|
||||
|
||||
// Calling rollover with no conditions will always roll over the index
|
||||
RolloverRequest rolloverRequest = new RolloverRequest(rolloverAlias, null);
|
||||
if (maxAge != null) {
|
||||
rolloverRequest.addMaxIndexAgeCondition(maxAge);
|
||||
}
|
||||
if (maxSize != null) {
|
||||
rolloverRequest.addMaxIndexSizeCondition(maxSize);
|
||||
}
|
||||
if (maxDocs != null) {
|
||||
rolloverRequest.addMaxIndexDocsCondition(maxDocs);
|
||||
}
|
||||
getClient().admin().indices().rolloverIndex(rolloverRequest,
|
||||
ActionListener.wrap(response -> listener.onResponse(response.isRolledOver(), new EmptyInfo()), exception -> {
|
||||
if (exception instanceof ResourceAlreadyExistsException) {
|
||||
// This can happen sometimes when this step is executed multiple times
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.debug(() -> new ParameterizedMessage("{} index cannot roll over because the next index already exists, " +
|
||||
"skipping to next step", indexMetaData.getIndex()), exception);
|
||||
} else {
|
||||
logger.debug("{} index cannot roll over because the next index already exists, skipping to next step",
|
||||
indexMetaData.getIndex());
|
||||
}
|
||||
listener.onResponse(true, new EmptyInfo());
|
||||
} else {
|
||||
listener.onFailure(exception);
|
||||
}
|
||||
}));
|
||||
ActionListener.wrap(response -> {
|
||||
assert response.isRolledOver() : "the only way this rollover call should fail is with an exception";
|
||||
listener.onResponse(response.isRolledOver());
|
||||
}, listener::onFailure));
|
||||
}
|
||||
|
||||
ByteSizeValue getMaxSize() {
|
||||
return maxSize;
|
||||
}
|
||||
|
||||
TimeValue getMaxAge() {
|
||||
return maxAge;
|
||||
}
|
||||
|
||||
Long getMaxDocs() {
|
||||
return maxDocs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(super.hashCode(), maxSize, maxAge, maxDocs);
|
||||
return Objects.hash(super.hashCode());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -112,19 +67,6 @@ public class RolloverStep extends AsyncWaitStep {
|
|||
return false;
|
||||
}
|
||||
RolloverStep other = (RolloverStep) obj;
|
||||
return super.equals(obj) &&
|
||||
Objects.equals(maxSize, other.maxSize) &&
|
||||
Objects.equals(maxAge, other.maxAge) &&
|
||||
Objects.equals(maxDocs, other.maxDocs);
|
||||
}
|
||||
|
||||
// We currently have no information to provide for this AsyncWaitStep, so this is an empty object
|
||||
private class EmptyInfo implements ToXContentObject {
|
||||
private EmptyInfo() {}
|
||||
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
return builder;
|
||||
}
|
||||
return super.equals(obj);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,8 +32,8 @@ public class UpdateRolloverLifecycleDateStep extends ClusterStateActionStep {
|
|||
}
|
||||
RolloverInfo rolloverInfo = indexMetaData.getRolloverInfos().get(rolloverAlias);
|
||||
if (rolloverInfo == null) {
|
||||
throw new IllegalStateException("no rollover info found for [" + indexMetaData.getIndex().getName() + "], either the index " +
|
||||
"has not yet rolled over or a subsequent index was created outside of Index Lifecycle Management");
|
||||
throw new IllegalStateException("no rollover info found for [" + indexMetaData.getIndex().getName() + "] with alias [" +
|
||||
rolloverAlias + "], the index has not yet rolled over with that alias");
|
||||
}
|
||||
|
||||
LifecycleExecutionState.Builder newLifecycleState = LifecycleExecutionState
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.xpack.core.indexlifecycle;
|
||||
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.action.admin.indices.rollover.RolloverRequest;
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.cluster.metadata.IndexMetaData;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.unit.ByteSizeValue;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.common.xcontent.ToXContentObject;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Waits for at least one rollover condition to be satisfied, using the Rollover API's dry_run option.
|
||||
*/
|
||||
public class WaitForRolloverReadyStep extends AsyncWaitStep {
|
||||
|
||||
public static final String NAME = "check-rollover-ready";
|
||||
|
||||
private final ByteSizeValue maxSize;
|
||||
private final TimeValue maxAge;
|
||||
private final Long maxDocs;
|
||||
|
||||
public WaitForRolloverReadyStep(StepKey key, StepKey nextStepKey, Client client, ByteSizeValue maxSize, TimeValue maxAge,
|
||||
Long maxDocs) {
|
||||
super(key, nextStepKey, client);
|
||||
this.maxSize = maxSize;
|
||||
this.maxAge = maxAge;
|
||||
this.maxDocs = maxDocs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evaluateCondition(IndexMetaData indexMetaData, Listener listener) {
|
||||
String rolloverAlias = RolloverAction.LIFECYCLE_ROLLOVER_ALIAS_SETTING.get(indexMetaData.getSettings());
|
||||
|
||||
if (Strings.isNullOrEmpty(rolloverAlias)) {
|
||||
listener.onFailure(new IllegalArgumentException(String.format(Locale.ROOT,
|
||||
"setting [%s] for index [%s] is empty or not defined", RolloverAction.LIFECYCLE_ROLLOVER_ALIAS,
|
||||
indexMetaData.getIndex().getName())));
|
||||
return;
|
||||
}
|
||||
|
||||
if (indexMetaData.getAliases().containsKey(rolloverAlias) == false) {
|
||||
listener.onFailure(new IllegalArgumentException(String.format(Locale.ROOT,
|
||||
"%s [%s] does not point to index [%s]", RolloverAction.LIFECYCLE_ROLLOVER_ALIAS, rolloverAlias,
|
||||
indexMetaData.getIndex().getName())));
|
||||
return;
|
||||
}
|
||||
|
||||
RolloverRequest rolloverRequest = new RolloverRequest(rolloverAlias, null);
|
||||
rolloverRequest.dryRun(true);
|
||||
if (maxAge != null) {
|
||||
rolloverRequest.addMaxIndexAgeCondition(maxAge);
|
||||
}
|
||||
if (maxSize != null) {
|
||||
rolloverRequest.addMaxIndexSizeCondition(maxSize);
|
||||
}
|
||||
if (maxDocs != null) {
|
||||
rolloverRequest.addMaxIndexDocsCondition(maxDocs);
|
||||
}
|
||||
getClient().admin().indices().rolloverIndex(rolloverRequest,
|
||||
ActionListener.wrap(response -> listener.onResponse(response.getConditionStatus().values().stream().anyMatch(i -> i),
|
||||
new WaitForRolloverReadyStep.EmptyInfo()), listener::onFailure));
|
||||
}
|
||||
|
||||
ByteSizeValue getMaxSize() {
|
||||
return maxSize;
|
||||
}
|
||||
|
||||
TimeValue getMaxAge() {
|
||||
return maxAge;
|
||||
}
|
||||
|
||||
Long getMaxDocs() {
|
||||
return maxDocs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(super.hashCode(), maxSize, maxAge, maxDocs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
WaitForRolloverReadyStep other = (WaitForRolloverReadyStep) obj;
|
||||
return super.equals(obj) &&
|
||||
Objects.equals(maxSize, other.maxSize) &&
|
||||
Objects.equals(maxAge, other.maxAge) &&
|
||||
Objects.equals(maxDocs, other.maxDocs);
|
||||
}
|
||||
|
||||
// We currently have no information to provide for this AsyncWaitStep, so this is an empty object
|
||||
private class EmptyInfo implements ToXContentObject {
|
||||
private EmptyInfo() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -80,17 +80,21 @@ public class RolloverActionTests extends AbstractActionTestCase<RolloverAction>
|
|||
randomAlphaOfLengthBetween(1, 10));
|
||||
List<Step> steps = action.toSteps(null, phase, nextStepKey);
|
||||
assertNotNull(steps);
|
||||
assertEquals(2, steps.size());
|
||||
StepKey expectedFirstStepKey = new StepKey(phase, RolloverAction.NAME, RolloverStep.NAME);
|
||||
StepKey expectedSecondStepKey = new StepKey(phase, RolloverAction.NAME, UpdateRolloverLifecycleDateStep.NAME);
|
||||
RolloverStep firstStep = (RolloverStep) steps.get(0);
|
||||
UpdateRolloverLifecycleDateStep secondStep = (UpdateRolloverLifecycleDateStep) steps.get(1);
|
||||
assertEquals(3, steps.size());
|
||||
StepKey expectedFirstStepKey = new StepKey(phase, RolloverAction.NAME, WaitForRolloverReadyStep.NAME);
|
||||
StepKey expectedSecondStepKey = new StepKey(phase, RolloverAction.NAME, RolloverStep.NAME);
|
||||
StepKey expectedThirdStepKey = new StepKey(phase, RolloverAction.NAME, UpdateRolloverLifecycleDateStep.NAME);
|
||||
WaitForRolloverReadyStep firstStep = (WaitForRolloverReadyStep) steps.get(0);
|
||||
RolloverStep secondStep = (RolloverStep) steps.get(1);
|
||||
UpdateRolloverLifecycleDateStep thirdStep = (UpdateRolloverLifecycleDateStep) steps.get(2);
|
||||
assertEquals(expectedFirstStepKey, firstStep.getKey());
|
||||
assertEquals(expectedSecondStepKey, secondStep.getKey());
|
||||
assertEquals(expectedThirdStepKey, thirdStep.getKey());
|
||||
assertEquals(secondStep.getKey(), firstStep.getNextStepKey());
|
||||
assertEquals(thirdStep.getKey(), secondStep.getNextStepKey());
|
||||
assertEquals(action.getMaxSize(), firstStep.getMaxSize());
|
||||
assertEquals(action.getMaxAge(), firstStep.getMaxAge());
|
||||
assertEquals(action.getMaxDocs(), firstStep.getMaxDocs());
|
||||
assertEquals(nextStepKey, secondStep.getNextStepKey());
|
||||
assertEquals(nextStepKey, thirdStep.getNextStepKey());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,10 +8,6 @@ package org.elasticsearch.xpack.core.indexlifecycle;
|
|||
import org.apache.lucene.util.SetOnce;
|
||||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.action.admin.indices.rollover.Condition;
|
||||
import org.elasticsearch.action.admin.indices.rollover.MaxAgeCondition;
|
||||
import org.elasticsearch.action.admin.indices.rollover.MaxDocsCondition;
|
||||
import org.elasticsearch.action.admin.indices.rollover.MaxSizeCondition;
|
||||
import org.elasticsearch.action.admin.indices.rollover.RolloverRequest;
|
||||
import org.elasticsearch.action.admin.indices.rollover.RolloverResponse;
|
||||
import org.elasticsearch.client.AdminClient;
|
||||
|
@ -19,10 +15,6 @@ import org.elasticsearch.client.Client;
|
|||
import org.elasticsearch.client.IndicesAdminClient;
|
||||
import org.elasticsearch.cluster.metadata.AliasMetaData;
|
||||
import org.elasticsearch.cluster.metadata.IndexMetaData;
|
||||
import org.elasticsearch.common.unit.ByteSizeUnit;
|
||||
import org.elasticsearch.common.unit.ByteSizeValue;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.common.xcontent.ToXContentObject;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.Step.StepKey;
|
||||
import org.junit.Before;
|
||||
import org.mockito.Mockito;
|
||||
|
@ -30,10 +22,7 @@ import org.mockito.invocation.InvocationOnMock;
|
|||
import org.mockito.stubbing.Answer;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
|
@ -50,65 +39,42 @@ public class RolloverStepTests extends AbstractStepTestCase<RolloverStep> {
|
|||
public RolloverStep createRandomInstance() {
|
||||
StepKey stepKey = randomStepKey();
|
||||
StepKey nextStepKey = randomStepKey();
|
||||
ByteSizeUnit maxSizeUnit = randomFrom(ByteSizeUnit.values());
|
||||
ByteSizeValue maxSize = randomBoolean() ? null : new ByteSizeValue(randomNonNegativeLong() / maxSizeUnit.toBytes(1), maxSizeUnit);
|
||||
Long maxDocs = randomBoolean() ? null : randomNonNegativeLong();
|
||||
TimeValue maxAge = (maxDocs == null && maxSize == null || randomBoolean())
|
||||
? TimeValue.parseTimeValue(randomPositiveTimeValue(), "rollover_action_test")
|
||||
: null;
|
||||
return new RolloverStep(stepKey, nextStepKey, client, maxSize, maxAge, maxDocs);
|
||||
|
||||
return new RolloverStep(stepKey, nextStepKey, client);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RolloverStep mutateInstance(RolloverStep instance) {
|
||||
StepKey key = instance.getKey();
|
||||
StepKey nextKey = instance.getNextStepKey();
|
||||
ByteSizeValue maxSize = instance.getMaxSize();
|
||||
TimeValue maxAge = instance.getMaxAge();
|
||||
Long maxDocs = instance.getMaxDocs();
|
||||
|
||||
switch (between(0, 4)) {
|
||||
|
||||
switch (between(0, 1)) {
|
||||
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:
|
||||
maxSize = randomValueOtherThan(maxSize, () -> {
|
||||
ByteSizeUnit maxSizeUnit = randomFrom(ByteSizeUnit.values());
|
||||
return new ByteSizeValue(randomNonNegativeLong() / maxSizeUnit.toBytes(1), maxSizeUnit);
|
||||
});
|
||||
break;
|
||||
case 3:
|
||||
maxAge = TimeValue.parseTimeValue(randomPositiveTimeValue(), "rollover_action_test");
|
||||
break;
|
||||
case 4:
|
||||
maxDocs = randomNonNegativeLong();
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError("Illegal randomisation branch");
|
||||
}
|
||||
|
||||
return new RolloverStep(key, nextKey, instance.getClient(), maxSize, maxAge, maxDocs);
|
||||
return new RolloverStep(key, nextKey, instance.getClient());
|
||||
}
|
||||
|
||||
@Override
|
||||
public RolloverStep copyInstance(RolloverStep instance) {
|
||||
return new RolloverStep(instance.getKey(), instance.getNextStepKey(), instance.getClient(),
|
||||
instance.getMaxSize(), instance.getMaxAge(), instance.getMaxDocs());
|
||||
return new RolloverStep(instance.getKey(), instance.getNextStepKey(), instance.getClient());
|
||||
}
|
||||
|
||||
private static void assertRolloverIndexRequest(RolloverRequest request, String alias, Set<Condition<?>> expectedConditions) {
|
||||
private static void assertRolloverIndexRequest(RolloverRequest request, String alias) {
|
||||
assertNotNull(request);
|
||||
assertEquals(1, request.indices().length);
|
||||
assertEquals(alias, request.indices()[0]);
|
||||
assertEquals(alias, request.getAlias());
|
||||
assertEquals(expectedConditions.size(), request.getConditions().size());
|
||||
Set<Object> expectedConditionValues = expectedConditions.stream().map(Condition::value).collect(Collectors.toSet());
|
||||
Set<Object> actualConditionValues = request.getConditions().values().stream()
|
||||
.map(Condition::value).collect(Collectors.toSet());
|
||||
assertEquals(expectedConditionValues, actualConditionValues);
|
||||
assertFalse(request.isDryRun());
|
||||
assertEquals(0, request.getConditions().size());
|
||||
}
|
||||
|
||||
public void testPerformAction() {
|
||||
|
@ -132,17 +98,7 @@ public class RolloverStepTests extends AbstractStepTestCase<RolloverStep> {
|
|||
RolloverRequest request = (RolloverRequest) invocation.getArguments()[0];
|
||||
@SuppressWarnings("unchecked")
|
||||
ActionListener<RolloverResponse> listener = (ActionListener<RolloverResponse>) invocation.getArguments()[1];
|
||||
Set<Condition<?>> expectedConditions = new HashSet<>();
|
||||
if (step.getMaxAge() != null) {
|
||||
expectedConditions.add(new MaxAgeCondition(step.getMaxAge()));
|
||||
}
|
||||
if (step.getMaxSize() != null) {
|
||||
expectedConditions.add(new MaxSizeCondition(step.getMaxSize()));
|
||||
}
|
||||
if (step.getMaxDocs() != null) {
|
||||
expectedConditions.add(new MaxDocsCondition(step.getMaxDocs()));
|
||||
}
|
||||
assertRolloverIndexRequest(request, alias, expectedConditions);
|
||||
assertRolloverIndexRequest(request, alias);
|
||||
listener.onResponse(new RolloverResponse(null, null, Collections.emptyMap(), request.isDryRun(), true, true, true));
|
||||
return null;
|
||||
}
|
||||
|
@ -150,10 +106,10 @@ public class RolloverStepTests extends AbstractStepTestCase<RolloverStep> {
|
|||
}).when(indicesClient).rolloverIndex(Mockito.any(), Mockito.any());
|
||||
|
||||
SetOnce<Boolean> actionCompleted = new SetOnce<>();
|
||||
step.evaluateCondition(indexMetaData, new AsyncWaitStep.Listener() {
|
||||
step.performAction(indexMetaData, null, new AsyncActionStep.Listener() {
|
||||
|
||||
@Override
|
||||
public void onResponse(boolean complete, ToXContentObject obj) {
|
||||
public void onResponse(boolean complete) {
|
||||
actionCompleted.set(complete);
|
||||
}
|
||||
|
||||
|
@ -170,64 +126,6 @@ public class RolloverStepTests extends AbstractStepTestCase<RolloverStep> {
|
|||
Mockito.verify(indicesClient, Mockito.only()).rolloverIndex(Mockito.any(), Mockito.any());
|
||||
}
|
||||
|
||||
public void testPerformActionNotComplete() {
|
||||
String alias = randomAlphaOfLength(5);
|
||||
IndexMetaData indexMetaData = IndexMetaData.builder(randomAlphaOfLength(10))
|
||||
.putAlias(AliasMetaData.builder(alias))
|
||||
.settings(settings(Version.CURRENT).put(RolloverAction.LIFECYCLE_ROLLOVER_ALIAS, alias))
|
||||
.numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
RolloverStep step = createRandomInstance();
|
||||
|
||||
AdminClient adminClient = Mockito.mock(AdminClient.class);
|
||||
IndicesAdminClient indicesClient = Mockito.mock(IndicesAdminClient.class);
|
||||
|
||||
Mockito.when(client.admin()).thenReturn(adminClient);
|
||||
Mockito.when(adminClient.indices()).thenReturn(indicesClient);
|
||||
Mockito.doAnswer(new Answer<Void>() {
|
||||
|
||||
@Override
|
||||
public Void answer(InvocationOnMock invocation) throws Throwable {
|
||||
RolloverRequest request = (RolloverRequest) invocation.getArguments()[0];
|
||||
@SuppressWarnings("unchecked")
|
||||
ActionListener<RolloverResponse> listener = (ActionListener<RolloverResponse>) invocation.getArguments()[1];
|
||||
Set<Condition<?>> expectedConditions = new HashSet<>();
|
||||
if (step.getMaxAge() != null) {
|
||||
expectedConditions.add(new MaxAgeCondition(step.getMaxAge()));
|
||||
}
|
||||
if (step.getMaxSize() != null) {
|
||||
expectedConditions.add(new MaxSizeCondition(step.getMaxSize()));
|
||||
}
|
||||
if (step.getMaxDocs() != null) {
|
||||
expectedConditions.add(new MaxDocsCondition(step.getMaxDocs()));
|
||||
}
|
||||
assertRolloverIndexRequest(request, alias, expectedConditions);
|
||||
listener.onResponse(new RolloverResponse(null, null, Collections.emptyMap(), request.isDryRun(), false, true, true));
|
||||
return null;
|
||||
}
|
||||
|
||||
}).when(indicesClient).rolloverIndex(Mockito.any(), Mockito.any());
|
||||
|
||||
SetOnce<Boolean> actionCompleted = new SetOnce<>();
|
||||
step.evaluateCondition(indexMetaData, new AsyncWaitStep.Listener() {
|
||||
|
||||
@Override
|
||||
public void onResponse(boolean complete, ToXContentObject obj) {
|
||||
actionCompleted.set(complete);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
throw new AssertionError("Unexpected method call", e);
|
||||
}
|
||||
});
|
||||
|
||||
assertEquals(false, actionCompleted.get());
|
||||
|
||||
Mockito.verify(client, Mockito.only()).admin();
|
||||
Mockito.verify(adminClient, Mockito.only()).indices();
|
||||
Mockito.verify(indicesClient, Mockito.only()).rolloverIndex(Mockito.any(), Mockito.any());
|
||||
}
|
||||
|
||||
public void testPerformActionFailure() {
|
||||
String alias = randomAlphaOfLength(5);
|
||||
IndexMetaData indexMetaData = IndexMetaData.builder(randomAlphaOfLength(10))
|
||||
|
@ -249,17 +147,7 @@ public class RolloverStepTests extends AbstractStepTestCase<RolloverStep> {
|
|||
RolloverRequest request = (RolloverRequest) invocation.getArguments()[0];
|
||||
@SuppressWarnings("unchecked")
|
||||
ActionListener<RolloverResponse> listener = (ActionListener<RolloverResponse>) invocation.getArguments()[1];
|
||||
Set<Condition<?>> expectedConditions = new HashSet<>();
|
||||
if (step.getMaxAge() != null) {
|
||||
expectedConditions.add(new MaxAgeCondition(step.getMaxAge()));
|
||||
}
|
||||
if (step.getMaxSize() != null) {
|
||||
expectedConditions.add(new MaxSizeCondition(step.getMaxSize()));
|
||||
}
|
||||
if (step.getMaxDocs() != null) {
|
||||
expectedConditions.add(new MaxDocsCondition(step.getMaxDocs()));
|
||||
}
|
||||
assertRolloverIndexRequest(request, alias, expectedConditions);
|
||||
assertRolloverIndexRequest(request, alias);
|
||||
listener.onFailure(exception);
|
||||
return null;
|
||||
}
|
||||
|
@ -267,10 +155,10 @@ public class RolloverStepTests extends AbstractStepTestCase<RolloverStep> {
|
|||
}).when(indicesClient).rolloverIndex(Mockito.any(), Mockito.any());
|
||||
|
||||
SetOnce<Boolean> exceptionThrown = new SetOnce<>();
|
||||
step.evaluateCondition(indexMetaData, new AsyncWaitStep.Listener() {
|
||||
step.performAction(indexMetaData, null, new AsyncActionStep.Listener() {
|
||||
|
||||
@Override
|
||||
public void onResponse(boolean complete, ToXContentObject obj) {
|
||||
public void onResponse(boolean complete) {
|
||||
throw new AssertionError("Unexpected method call");
|
||||
}
|
||||
|
||||
|
@ -296,9 +184,9 @@ public class RolloverStepTests extends AbstractStepTestCase<RolloverStep> {
|
|||
RolloverStep step = createRandomInstance();
|
||||
|
||||
SetOnce<Exception> exceptionThrown = new SetOnce<>();
|
||||
step.evaluateCondition(indexMetaData, new AsyncWaitStep.Listener() {
|
||||
step.performAction(indexMetaData, null, new AsyncActionStep.Listener() {
|
||||
@Override
|
||||
public void onResponse(boolean complete, ToXContentObject obj) {
|
||||
public void onResponse(boolean complete) {
|
||||
throw new AssertionError("Unexpected method call");
|
||||
}
|
||||
|
||||
|
@ -321,9 +209,9 @@ public class RolloverStepTests extends AbstractStepTestCase<RolloverStep> {
|
|||
RolloverStep step = createRandomInstance();
|
||||
|
||||
SetOnce<Exception> exceptionThrown = new SetOnce<>();
|
||||
step.evaluateCondition(indexMetaData, new AsyncWaitStep.Listener() {
|
||||
step.performAction(indexMetaData, null, new AsyncActionStep.Listener() {
|
||||
@Override
|
||||
public void onResponse(boolean complete, ToXContentObject obj) {
|
||||
public void onResponse(boolean complete) {
|
||||
throw new AssertionError("Unexpected method call");
|
||||
}
|
||||
|
||||
|
@ -336,6 +224,5 @@ public class RolloverStepTests extends AbstractStepTestCase<RolloverStep> {
|
|||
assertThat(exceptionThrown.get().getMessage(), equalTo(String.format(Locale.ROOT,
|
||||
"%s [%s] does not point to index [%s]", RolloverAction.LIFECYCLE_ROLLOVER_ALIAS, alias,
|
||||
indexMetaData.getIndex().getName())));
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,8 +87,8 @@ public class UpdateRolloverLifecycleDateStepTests extends AbstractStepTestCase<U
|
|||
IllegalStateException exceptionThrown = expectThrows(IllegalStateException.class,
|
||||
() -> step.performAction(indexMetaData.getIndex(), clusterState));
|
||||
assertThat(exceptionThrown.getMessage(),
|
||||
equalTo("no rollover info found for [" + indexMetaData.getIndex().getName() + "], either the index " +
|
||||
"has not yet rolled over or a subsequent index was created outside of Index Lifecycle Management"));
|
||||
equalTo("no rollover info found for [" + indexMetaData.getIndex().getName() + "] with alias [" + alias + "], the index " +
|
||||
"has not yet rolled over with that alias"));
|
||||
}
|
||||
|
||||
public void testPerformActionWithNoRolloverAliasSetting() {
|
||||
|
|
|
@ -0,0 +1,345 @@
|
|||
/*
|
||||
* 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.apache.lucene.util.SetOnce;
|
||||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.action.admin.indices.rollover.Condition;
|
||||
import org.elasticsearch.action.admin.indices.rollover.MaxAgeCondition;
|
||||
import org.elasticsearch.action.admin.indices.rollover.MaxDocsCondition;
|
||||
import org.elasticsearch.action.admin.indices.rollover.MaxSizeCondition;
|
||||
import org.elasticsearch.action.admin.indices.rollover.RolloverRequest;
|
||||
import org.elasticsearch.action.admin.indices.rollover.RolloverResponse;
|
||||
import org.elasticsearch.client.AdminClient;
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.client.IndicesAdminClient;
|
||||
import org.elasticsearch.cluster.metadata.AliasMetaData;
|
||||
import org.elasticsearch.cluster.metadata.IndexMetaData;
|
||||
import org.elasticsearch.common.unit.ByteSizeUnit;
|
||||
import org.elasticsearch.common.unit.ByteSizeValue;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.common.xcontent.ToXContentObject;
|
||||
import org.junit.Before;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
public class WaitForRolloverReadyStepTests extends AbstractStepTestCase<WaitForRolloverReadyStep> {
|
||||
|
||||
private Client client;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
client = Mockito.mock(Client.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected WaitForRolloverReadyStep createRandomInstance() {
|
||||
Step.StepKey stepKey = randomStepKey();
|
||||
Step.StepKey nextStepKey = randomStepKey();
|
||||
ByteSizeUnit maxSizeUnit = randomFrom(ByteSizeUnit.values());
|
||||
ByteSizeValue maxSize = randomBoolean() ? null : new ByteSizeValue(randomNonNegativeLong() / maxSizeUnit.toBytes(1), maxSizeUnit);
|
||||
Long maxDocs = randomBoolean() ? null : randomNonNegativeLong();
|
||||
TimeValue maxAge = (maxDocs == null && maxSize == null || randomBoolean())
|
||||
? TimeValue.parseTimeValue(randomPositiveTimeValue(), "rollover_action_test")
|
||||
: null;
|
||||
return new WaitForRolloverReadyStep(stepKey, nextStepKey, client, maxSize, maxAge, maxDocs);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected WaitForRolloverReadyStep mutateInstance(WaitForRolloverReadyStep instance) {
|
||||
Step.StepKey key = instance.getKey();
|
||||
Step.StepKey nextKey = instance.getNextStepKey();
|
||||
ByteSizeValue maxSize = instance.getMaxSize();
|
||||
TimeValue maxAge = instance.getMaxAge();
|
||||
Long maxDocs = instance.getMaxDocs();
|
||||
|
||||
switch (between(0, 4)) {
|
||||
case 0:
|
||||
key = new Step.StepKey(key.getPhase(), key.getAction(), key.getName() + randomAlphaOfLength(5));
|
||||
break;
|
||||
case 1:
|
||||
nextKey = new Step.StepKey(key.getPhase(), key.getAction(), key.getName() + randomAlphaOfLength(5));
|
||||
break;
|
||||
case 2:
|
||||
maxSize = randomValueOtherThan(maxSize, () -> {
|
||||
ByteSizeUnit maxSizeUnit = randomFrom(ByteSizeUnit.values());
|
||||
return new ByteSizeValue(randomNonNegativeLong() / maxSizeUnit.toBytes(1), maxSizeUnit);
|
||||
});
|
||||
break;
|
||||
case 3:
|
||||
maxAge = TimeValue.parseTimeValue(randomPositiveTimeValue(), "rollover_action_test");
|
||||
break;
|
||||
case 4:
|
||||
maxDocs = randomNonNegativeLong();
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError("Illegal randomisation branch");
|
||||
}
|
||||
return new WaitForRolloverReadyStep(key, nextKey, instance.getClient(), maxSize, maxAge, maxDocs);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected WaitForRolloverReadyStep copyInstance(WaitForRolloverReadyStep instance) {
|
||||
return new WaitForRolloverReadyStep(instance.getKey(), instance.getNextStepKey(), instance.getClient(),
|
||||
instance.getMaxSize(), instance.getMaxAge(), instance.getMaxDocs());
|
||||
}
|
||||
|
||||
private static void assertRolloverIndexRequest(RolloverRequest request, String alias, Set<Condition<?>> expectedConditions) {
|
||||
assertNotNull(request);
|
||||
assertEquals(1, request.indices().length);
|
||||
assertEquals(alias, request.indices()[0]);
|
||||
assertEquals(alias, request.getAlias());
|
||||
assertEquals(expectedConditions.size(), request.getConditions().size());
|
||||
assertTrue(request.isDryRun());
|
||||
Set<Object> expectedConditionValues = expectedConditions.stream().map(Condition::value).collect(Collectors.toSet());
|
||||
Set<Object> actualConditionValues = request.getConditions().values().stream()
|
||||
.map(Condition::value).collect(Collectors.toSet());
|
||||
assertEquals(expectedConditionValues, actualConditionValues);
|
||||
}
|
||||
|
||||
|
||||
public void testEvaluateCondition() {
|
||||
String alias = randomAlphaOfLength(5);
|
||||
IndexMetaData indexMetaData = IndexMetaData.builder(randomAlphaOfLength(10))
|
||||
.putAlias(AliasMetaData.builder(alias))
|
||||
.settings(settings(Version.CURRENT).put(RolloverAction.LIFECYCLE_ROLLOVER_ALIAS, alias))
|
||||
.numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
|
||||
WaitForRolloverReadyStep step = createRandomInstance();
|
||||
|
||||
AdminClient adminClient = Mockito.mock(AdminClient.class);
|
||||
IndicesAdminClient indicesClient = Mockito.mock(IndicesAdminClient.class);
|
||||
|
||||
Mockito.when(client.admin()).thenReturn(adminClient);
|
||||
Mockito.when(adminClient.indices()).thenReturn(indicesClient);
|
||||
Mockito.doAnswer(new Answer<Void>() {
|
||||
|
||||
@Override
|
||||
public Void answer(InvocationOnMock invocation) throws Throwable {
|
||||
RolloverRequest request = (RolloverRequest) invocation.getArguments()[0];
|
||||
@SuppressWarnings("unchecked")
|
||||
ActionListener<RolloverResponse> listener = (ActionListener<RolloverResponse>) invocation.getArguments()[1];
|
||||
Set<Condition<?>> expectedConditions = new HashSet<>();
|
||||
if (step.getMaxAge() != null) {
|
||||
expectedConditions.add(new MaxAgeCondition(step.getMaxAge()));
|
||||
}
|
||||
if (step.getMaxSize() != null) {
|
||||
expectedConditions.add(new MaxSizeCondition(step.getMaxSize()));
|
||||
}
|
||||
if (step.getMaxDocs() != null) {
|
||||
expectedConditions.add(new MaxDocsCondition(step.getMaxDocs()));
|
||||
}
|
||||
assertRolloverIndexRequest(request, alias, expectedConditions);
|
||||
Map<String, Boolean> conditionResults = expectedConditions.stream()
|
||||
.collect(Collectors.toMap(Condition::toString, condition -> true));
|
||||
listener.onResponse(new RolloverResponse(null, null, conditionResults, request.isDryRun(), false, false, false));
|
||||
return null;
|
||||
}
|
||||
|
||||
}).when(indicesClient).rolloverIndex(Mockito.any(), Mockito.any());
|
||||
|
||||
SetOnce<Boolean> conditionsMet = new SetOnce<>();
|
||||
step.evaluateCondition(indexMetaData, new AsyncWaitStep.Listener() {
|
||||
|
||||
@Override
|
||||
public void onResponse(boolean complete, ToXContentObject infomationContext) {
|
||||
conditionsMet.set(complete);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
throw new AssertionError("Unexpected method call", e);
|
||||
}
|
||||
});
|
||||
|
||||
assertEquals(true, conditionsMet.get());
|
||||
|
||||
Mockito.verify(client, Mockito.only()).admin();
|
||||
Mockito.verify(adminClient, Mockito.only()).indices();
|
||||
Mockito.verify(indicesClient, Mockito.only()).rolloverIndex(Mockito.any(), Mockito.any());
|
||||
}
|
||||
|
||||
public void testPerformActionNotComplete() {
|
||||
String alias = randomAlphaOfLength(5);
|
||||
IndexMetaData indexMetaData = IndexMetaData.builder(randomAlphaOfLength(10))
|
||||
.putAlias(AliasMetaData.builder(alias))
|
||||
.settings(settings(Version.CURRENT).put(RolloverAction.LIFECYCLE_ROLLOVER_ALIAS, alias))
|
||||
.numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
WaitForRolloverReadyStep step = createRandomInstance();
|
||||
|
||||
AdminClient adminClient = Mockito.mock(AdminClient.class);
|
||||
IndicesAdminClient indicesClient = Mockito.mock(IndicesAdminClient.class);
|
||||
|
||||
Mockito.when(client.admin()).thenReturn(adminClient);
|
||||
Mockito.when(adminClient.indices()).thenReturn(indicesClient);
|
||||
Mockito.doAnswer(new Answer<Void>() {
|
||||
|
||||
@Override
|
||||
public Void answer(InvocationOnMock invocation) throws Throwable {
|
||||
RolloverRequest request = (RolloverRequest) invocation.getArguments()[0];
|
||||
@SuppressWarnings("unchecked")
|
||||
ActionListener<RolloverResponse> listener = (ActionListener<RolloverResponse>) invocation.getArguments()[1];
|
||||
Set<Condition<?>> expectedConditions = new HashSet<>();
|
||||
if (step.getMaxAge() != null) {
|
||||
expectedConditions.add(new MaxAgeCondition(step.getMaxAge()));
|
||||
}
|
||||
if (step.getMaxSize() != null) {
|
||||
expectedConditions.add(new MaxSizeCondition(step.getMaxSize()));
|
||||
}
|
||||
if (step.getMaxDocs() != null) {
|
||||
expectedConditions.add(new MaxDocsCondition(step.getMaxDocs()));
|
||||
}
|
||||
assertRolloverIndexRequest(request, alias, expectedConditions);
|
||||
Map<String, Boolean> conditionResults = expectedConditions.stream()
|
||||
.collect(Collectors.toMap(Condition::toString, condition -> false));
|
||||
listener.onResponse(new RolloverResponse(null, null, conditionResults, request.isDryRun(), false, false, false));
|
||||
return null;
|
||||
}
|
||||
|
||||
}).when(indicesClient).rolloverIndex(Mockito.any(), Mockito.any());
|
||||
|
||||
SetOnce<Boolean> actionCompleted = new SetOnce<>();
|
||||
step.evaluateCondition(indexMetaData, new AsyncWaitStep.Listener() {
|
||||
|
||||
@Override
|
||||
public void onResponse(boolean complete, ToXContentObject infomationContext) {
|
||||
actionCompleted.set(complete);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
throw new AssertionError("Unexpected method call", e);
|
||||
}
|
||||
});
|
||||
|
||||
assertEquals(false, actionCompleted.get());
|
||||
|
||||
Mockito.verify(client, Mockito.only()).admin();
|
||||
Mockito.verify(adminClient, Mockito.only()).indices();
|
||||
Mockito.verify(indicesClient, Mockito.only()).rolloverIndex(Mockito.any(), Mockito.any());
|
||||
}
|
||||
|
||||
public void testPerformActionFailure() {
|
||||
String alias = randomAlphaOfLength(5);
|
||||
IndexMetaData indexMetaData = IndexMetaData.builder(randomAlphaOfLength(10))
|
||||
.putAlias(AliasMetaData.builder(alias))
|
||||
.settings(settings(Version.CURRENT).put(RolloverAction.LIFECYCLE_ROLLOVER_ALIAS, alias))
|
||||
.numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
Exception exception = new RuntimeException();
|
||||
WaitForRolloverReadyStep step = createRandomInstance();
|
||||
|
||||
AdminClient adminClient = Mockito.mock(AdminClient.class);
|
||||
IndicesAdminClient indicesClient = Mockito.mock(IndicesAdminClient.class);
|
||||
|
||||
Mockito.when(client.admin()).thenReturn(adminClient);
|
||||
Mockito.when(adminClient.indices()).thenReturn(indicesClient);
|
||||
Mockito.doAnswer(new Answer<Void>() {
|
||||
|
||||
@Override
|
||||
public Void answer(InvocationOnMock invocation) throws Throwable {
|
||||
RolloverRequest request = (RolloverRequest) invocation.getArguments()[0];
|
||||
@SuppressWarnings("unchecked")
|
||||
ActionListener<RolloverResponse> listener = (ActionListener<RolloverResponse>) invocation.getArguments()[1];
|
||||
Set<Condition<?>> expectedConditions = new HashSet<>();
|
||||
if (step.getMaxAge() != null) {
|
||||
expectedConditions.add(new MaxAgeCondition(step.getMaxAge()));
|
||||
}
|
||||
if (step.getMaxSize() != null) {
|
||||
expectedConditions.add(new MaxSizeCondition(step.getMaxSize()));
|
||||
}
|
||||
if (step.getMaxDocs() != null) {
|
||||
expectedConditions.add(new MaxDocsCondition(step.getMaxDocs()));
|
||||
}
|
||||
assertRolloverIndexRequest(request, alias, expectedConditions);
|
||||
listener.onFailure(exception);
|
||||
return null;
|
||||
}
|
||||
|
||||
}).when(indicesClient).rolloverIndex(Mockito.any(), Mockito.any());
|
||||
|
||||
SetOnce<Boolean> exceptionThrown = new SetOnce<>();
|
||||
step.evaluateCondition(indexMetaData, new AsyncWaitStep.Listener() {
|
||||
|
||||
@Override
|
||||
public void onResponse(boolean complete, ToXContentObject infomationContext) {
|
||||
throw new AssertionError("Unexpected method call");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
assertSame(exception, e);
|
||||
exceptionThrown.set(true);
|
||||
}
|
||||
});
|
||||
|
||||
assertEquals(true, exceptionThrown.get());
|
||||
|
||||
Mockito.verify(client, Mockito.only()).admin();
|
||||
Mockito.verify(adminClient, Mockito.only()).indices();
|
||||
Mockito.verify(indicesClient, Mockito.only()).rolloverIndex(Mockito.any(), Mockito.any());
|
||||
}
|
||||
|
||||
public void testPerformActionInvalidNullOrEmptyAlias() {
|
||||
String alias = randomBoolean() ? "" : null;
|
||||
IndexMetaData indexMetaData = IndexMetaData.builder(randomAlphaOfLength(10))
|
||||
.settings(settings(Version.CURRENT).put(RolloverAction.LIFECYCLE_ROLLOVER_ALIAS, alias))
|
||||
.numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
WaitForRolloverReadyStep step = createRandomInstance();
|
||||
|
||||
SetOnce<Exception> exceptionThrown = new SetOnce<>();
|
||||
step.evaluateCondition(indexMetaData, new AsyncWaitStep.Listener() {
|
||||
@Override
|
||||
public void onResponse(boolean complete, ToXContentObject infomationContext) {
|
||||
throw new AssertionError("Unexpected method call");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
exceptionThrown.set(e);
|
||||
}
|
||||
});
|
||||
assertThat(exceptionThrown.get().getClass(), equalTo(IllegalArgumentException.class));
|
||||
assertThat(exceptionThrown.get().getMessage(), equalTo(String.format(Locale.ROOT,
|
||||
"setting [%s] for index [%s] is empty or not defined", RolloverAction.LIFECYCLE_ROLLOVER_ALIAS,
|
||||
indexMetaData.getIndex().getName())));
|
||||
}
|
||||
|
||||
public void testPerformActionAliasDoesNotPointToIndex() {
|
||||
String alias = randomAlphaOfLength(5);
|
||||
IndexMetaData indexMetaData = IndexMetaData.builder(randomAlphaOfLength(10))
|
||||
.settings(settings(Version.CURRENT).put(RolloverAction.LIFECYCLE_ROLLOVER_ALIAS, alias))
|
||||
.numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
WaitForRolloverReadyStep step = createRandomInstance();
|
||||
|
||||
SetOnce<Exception> exceptionThrown = new SetOnce<>();
|
||||
step.evaluateCondition(indexMetaData, new AsyncWaitStep.Listener() {
|
||||
@Override
|
||||
public void onResponse(boolean complete, ToXContentObject infomationContext) {
|
||||
throw new AssertionError("Unexpected method call");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
exceptionThrown.set(e);
|
||||
}
|
||||
});
|
||||
assertThat(exceptionThrown.get().getClass(), equalTo(IllegalArgumentException.class));
|
||||
assertThat(exceptionThrown.get().getMessage(), equalTo(String.format(Locale.ROOT,
|
||||
"%s [%s] does not point to index [%s]", RolloverAction.LIFECYCLE_ROLLOVER_ALIAS, alias,
|
||||
indexMetaData.getIndex().getName())));
|
||||
}
|
||||
}
|
|
@ -21,9 +21,9 @@ import org.elasticsearch.xpack.core.indexlifecycle.LifecyclePolicy;
|
|||
import org.elasticsearch.xpack.core.indexlifecycle.LifecycleSettings;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.Phase;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.RolloverAction;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.RolloverStep;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.Step.StepKey;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.TerminalPolicyStep;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.WaitForRolloverReadyStep;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
|
@ -52,7 +52,6 @@ public class ChangePolicyforIndexIT extends ESRestTestCase {
|
|||
* settings from the second policy are set ont he index (proving the second
|
||||
* policy was used for the warm phase)
|
||||
*/
|
||||
@AwaitsFix(bugUrl="https://github.com/elastic/elasticsearch/issues/35244")
|
||||
public void testChangePolicyForIndex() throws Exception {
|
||||
String indexName = "test-000001";
|
||||
// create policy_1 and policy_2
|
||||
|
@ -92,7 +91,7 @@ public class ChangePolicyforIndexIT extends ESRestTestCase {
|
|||
ensureGreen(indexName);
|
||||
|
||||
// Check the index is on the attempt rollover step
|
||||
assertBusy(() -> assertStep(indexName, new StepKey("hot", RolloverAction.NAME, RolloverStep.NAME)));
|
||||
assertBusy(() -> assertStep(indexName, new StepKey("hot", RolloverAction.NAME, WaitForRolloverReadyStep.NAME)));
|
||||
|
||||
// Change the policy to policy_2
|
||||
Request changePolicyRequest = new Request("PUT", "/" + indexName + "/_settings");
|
||||
|
@ -102,7 +101,7 @@ public class ChangePolicyforIndexIT extends ESRestTestCase {
|
|||
assertOK(client().performRequest(changePolicyRequest));
|
||||
|
||||
// Check the index is still on the attempt rollover step
|
||||
assertBusy(() -> assertStep(indexName, new StepKey("hot", RolloverAction.NAME, RolloverStep.NAME)));
|
||||
assertBusy(() -> assertStep(indexName, new StepKey("hot", RolloverAction.NAME, WaitForRolloverReadyStep.NAME)));
|
||||
|
||||
// Index a single document
|
||||
XContentBuilder document = jsonBuilder().startObject();
|
||||
|
@ -131,11 +130,6 @@ public class ChangePolicyforIndexIT extends ESRestTestCase {
|
|||
assertEquals("node-1,node-2", includesAllocation);
|
||||
}
|
||||
|
||||
public void testTempAwaitFix() {
|
||||
// this is a test stub since there is only one test in this class and it is
|
||||
// awaits-fixed. This test is to be removed once testChangePolicyForIndex is resolved
|
||||
}
|
||||
|
||||
private void assertStep(String indexName, StepKey expectedStep) throws IOException {
|
||||
Response explainResponse = client().performRequest(new Request("GET", "/" + indexName + "/_ilm/explain"));
|
||||
assertOK(explainResponse);
|
||||
|
|
|
@ -33,6 +33,7 @@ import org.elasticsearch.xpack.core.indexlifecycle.ShrinkAction;
|
|||
import org.elasticsearch.xpack.core.indexlifecycle.ShrinkStep;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.Step.StepKey;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.TerminalPolicyStep;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.WaitForRolloverReadyStep;
|
||||
import org.junit.Before;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -237,12 +238,10 @@ public class TimeSeriesLifecycleActionsIT extends ESRestTestCase {
|
|||
createIndexWithSettings(originalIndex, Settings.builder().put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, 1)
|
||||
.put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, 0)
|
||||
.put(RolloverAction.LIFECYCLE_ROLLOVER_ALIAS, "alias"));
|
||||
|
||||
// create policy
|
||||
createNewSingletonPolicy("hot", new RolloverAction(null, null, 1L));
|
||||
// update policy on index
|
||||
updatePolicy(originalIndex, policy);
|
||||
|
||||
// Manually create the new index
|
||||
Request request = new Request("PUT", "/" + secondIndex);
|
||||
request.setJsonEntity("{\n \"settings\": " + Strings.toString(Settings.builder().put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, 1)
|
||||
|
@ -250,17 +249,14 @@ public class TimeSeriesLifecycleActionsIT extends ESRestTestCase {
|
|||
client().performRequest(request);
|
||||
// wait for the shards to initialize
|
||||
ensureGreen(secondIndex);
|
||||
|
||||
// index another doc to trigger the policy
|
||||
index(client(), originalIndex, "_id", "foo", "bar");
|
||||
|
||||
assertBusy(() -> {
|
||||
logger.info(originalIndex + ": " + getStepKeyForIndex(originalIndex));
|
||||
logger.info(secondIndex + ": " + getStepKeyForIndex(secondIndex));
|
||||
assertThat(getStepKeyForIndex(originalIndex), equalTo(new StepKey("hot", RolloverAction.NAME, ErrorStep.NAME)));
|
||||
assertThat(getFailedStepForIndex(originalIndex), equalTo("update-rollover-lifecycle-date"));
|
||||
assertThat(getReasonForIndex(originalIndex), equalTo("no rollover info found for [" + originalIndex + "], either the index " +
|
||||
"has not yet rolled over or a subsequent index was created outside of Index Lifecycle Management"));
|
||||
assertThat(getFailedStepForIndex(originalIndex), equalTo(WaitForRolloverReadyStep.NAME));
|
||||
assertThat(getReasonForIndex(originalIndex), containsString("already exists"));
|
||||
});
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue