update RolloverAction to utilize an index-setting for rollover_alias (#30158)

The purpose of this change is to reflect what is the future way of configuring aliases in
the Rollover action for ILM. With this change, users will be able to edit all desired rollover-related
information in the index's template, so that the index-lifecycle policy does not need to be dependent on it.
This commit is contained in:
Tal Levy 2018-04-26 08:18:23 -07:00 committed by GitHub
parent 26b42dfbf3
commit c10e624c92
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 78 additions and 66 deletions

View File

@ -10,6 +10,7 @@ import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.unit.ByteSizeValue;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
@ -28,15 +29,16 @@ import java.util.Objects;
*/
public class RolloverAction implements LifecycleAction {
public static final String NAME = "rollover";
public static final ParseField ALIAS_FIELD = new ParseField("alias");
public static final ParseField MAX_SIZE_FIELD = new ParseField("max_size");
public static final ParseField MAX_DOCS_FIELD = new ParseField("max_docs");
public static final ParseField MAX_AGE_FIELD = new ParseField("max_age");
public static final String LIFECYCLE_ROLLOVER_ALIAS = "index.lifecycle.rollover_alias";
public static final Setting<String> LIFECYCLE_ROLLOVER_ALIAS_SETTING = Setting.simpleString(LIFECYCLE_ROLLOVER_ALIAS,
Setting.Property.Dynamic, Setting.Property.IndexScope);
private static final ConstructingObjectParser<RolloverAction, Void> PARSER = new ConstructingObjectParser<>(NAME,
a -> new RolloverAction((String) a[0], (ByteSizeValue) a[1], (TimeValue) a[2], (Long) a[3]));
a -> new RolloverAction((ByteSizeValue) a[0], (TimeValue) a[1], (Long) a[2]));
static {
PARSER.declareString(ConstructingObjectParser.constructorArg(), ALIAS_FIELD);
PARSER.declareField(ConstructingObjectParser.optionalConstructorArg(),
(p, c) -> ByteSizeValue.parseBytesSizeValue(p.text(), MAX_SIZE_FIELD.getPreferredName()), MAX_SIZE_FIELD, ValueType.VALUE);
PARSER.declareField(ConstructingObjectParser.optionalConstructorArg(),
@ -44,7 +46,6 @@ public class RolloverAction implements LifecycleAction {
PARSER.declareLong(ConstructingObjectParser.optionalConstructorArg(), MAX_DOCS_FIELD);
}
private final String alias;
private final ByteSizeValue maxSize;
private final Long maxDocs;
private final TimeValue maxAge;
@ -53,21 +54,16 @@ public class RolloverAction implements LifecycleAction {
return PARSER.apply(parser, null);
}
public RolloverAction(String alias, ByteSizeValue maxSize, TimeValue maxAge, Long maxDocs) {
if (alias == null) {
throw new IllegalArgumentException(ALIAS_FIELD.getPreferredName() + " must be not be null");
}
public RolloverAction(ByteSizeValue maxSize, TimeValue maxAge, Long maxDocs) {
if (maxSize == null && maxAge == null && maxDocs == null) {
throw new IllegalArgumentException("At least one rollover condition must be set.");
}
this.alias = alias;
this.maxSize = maxSize;
this.maxAge = maxAge;
this.maxDocs = maxDocs;
}
public RolloverAction(StreamInput in) throws IOException {
alias = in.readString();
if (in.readBoolean()) {
maxSize = new ByteSizeValue(in);
} else {
@ -83,7 +79,6 @@ public class RolloverAction implements LifecycleAction {
@Override
public void writeTo(StreamOutput out) throws IOException {
out.writeString(alias);
boolean hasMaxSize = maxSize != null;
out.writeBoolean(hasMaxSize);
if (hasMaxSize) {
@ -102,10 +97,6 @@ public class RolloverAction implements LifecycleAction {
return NAME;
}
public String getAlias() {
return alias;
}
public ByteSizeValue getMaxSize() {
return maxSize;
}
@ -121,7 +112,6 @@ public class RolloverAction implements LifecycleAction {
@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject();
builder.field(ALIAS_FIELD.getPreferredName(), alias);
if (maxSize != null) {
builder.field(MAX_SIZE_FIELD.getPreferredName(), maxSize.getStringRep());
}
@ -138,12 +128,12 @@ public class RolloverAction implements LifecycleAction {
@Override
public List<Step> toSteps(Client client, String phase, Step.StepKey nextStepKey) {
return Collections.singletonList(
new RolloverStep(new StepKey(phase, NAME, RolloverStep.NAME), nextStepKey, client, alias, maxSize, maxAge, maxDocs));
new RolloverStep(new StepKey(phase, NAME, RolloverStep.NAME), nextStepKey, client, maxSize, maxAge, maxDocs));
}
@Override
public int hashCode() {
return Objects.hash(alias, maxSize, maxAge, maxDocs);
return Objects.hash(maxSize, maxAge, maxDocs);
}
@Override
@ -155,8 +145,7 @@ public class RolloverAction implements LifecycleAction {
return false;
}
RolloverAction other = (RolloverAction) obj;
return Objects.equals(alias, other.alias) &&
Objects.equals(maxSize, other.maxSize) &&
return Objects.equals(maxSize, other.maxSize) &&
Objects.equals(maxAge, other.maxAge) &&
Objects.equals(maxDocs, other.maxDocs);
}

View File

@ -9,23 +9,23 @@ 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 java.util.Locale;
import java.util.Objects;
public class RolloverStep extends AsyncActionStep {
public static final String NAME = "attempt_rollover";
private String alias;
private ByteSizeValue maxSize;
private TimeValue maxAge;
private Long maxDocs;
public RolloverStep(StepKey key, StepKey nextStepKey, Client client, String alias, ByteSizeValue maxSize, TimeValue maxAge,
public RolloverStep(StepKey key, StepKey nextStepKey, Client client, ByteSizeValue maxSize, TimeValue maxAge,
Long maxDocs) {
super(key, nextStepKey, client);
this.alias = alias;
this.maxSize = maxSize;
this.maxAge = maxAge;
this.maxDocs = maxDocs;
@ -33,8 +33,15 @@ public class RolloverStep extends AsyncActionStep {
@Override
public void performAction(IndexMetaData indexMetaData, Listener listener) {
// TODO(talevy): shouldn't we double-check that this alias is managed by us/this-index?
RolloverRequest rolloverRequest = new RolloverRequest(alias, null);
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;
}
RolloverRequest rolloverRequest = new RolloverRequest(rolloverAlias, null);
if (maxAge != null) {
rolloverRequest.addMaxIndexAgeCondition(maxAge);
}
@ -48,10 +55,6 @@ public class RolloverStep extends AsyncActionStep {
ActionListener.wrap(response -> listener.onResponse(response.isRolledOver()), listener::onFailure));
}
String getAlias() {
return alias;
}
ByteSizeValue getMaxSize() {
return maxSize;
}
@ -66,7 +69,7 @@ public class RolloverStep extends AsyncActionStep {
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), alias, maxSize, maxAge, maxDocs);
return Objects.hash(super.hashCode(), maxSize, maxAge, maxDocs);
}
@Override
@ -79,7 +82,6 @@ public class RolloverStep extends AsyncActionStep {
}
RolloverStep other = (RolloverStep) obj;
return super.equals(obj) &&
Objects.equals(alias, other.alias) &&
Objects.equals(maxSize, other.maxSize) &&
Objects.equals(maxAge, other.maxAge) &&
Objects.equals(maxDocs, other.maxDocs);

View File

@ -25,14 +25,13 @@ public class RolloverActionTests extends AbstractSerializingTestCase<RolloverAct
@Override
protected RolloverAction createTestInstance() {
String alias = randomAlphaOfLengthBetween(1, 20);
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 RolloverAction(alias, maxSize, maxAge, maxDocs);
return new RolloverAction(maxSize, maxAge, maxDocs);
}
@Override
@ -42,43 +41,34 @@ public class RolloverActionTests extends AbstractSerializingTestCase<RolloverAct
@Override
protected RolloverAction mutateInstance(RolloverAction instance) throws IOException {
String alias = instance.getAlias();
ByteSizeValue maxSize = instance.getMaxSize();
TimeValue maxAge = instance.getMaxAge();
Long maxDocs = instance.getMaxDocs();
switch (between(0, 3)) {
switch (between(0, 2)) {
case 0:
alias = alias + randomAlphaOfLengthBetween(1, 5);
break;
case 1:
maxSize = randomValueOtherThan(maxSize, () -> {
ByteSizeUnit maxSizeUnit = randomFrom(ByteSizeUnit.values());
return new ByteSizeValue(randomNonNegativeLong() / maxSizeUnit.toBytes(1), maxSizeUnit);
});
break;
case 2:
case 1:
maxAge = TimeValue.parseTimeValue(randomPositiveTimeValue(), "rollover_action_test");
break;
case 3:
case 2:
maxDocs = randomNonNegativeLong();
break;
default:
throw new AssertionError("Illegal randomisation branch");
}
return new RolloverAction(alias, maxSize, maxAge, maxDocs);
return new RolloverAction(maxSize, maxAge, maxDocs);
}
public void testNoConditions() {
IllegalArgumentException exception = expectThrows(IllegalArgumentException.class,
() -> new RolloverAction(randomAlphaOfLengthBetween(1, 20), null, null, null));
() -> new RolloverAction(null, null, null));
assertEquals("At least one rollover condition must be set.", exception.getMessage());
}
public void testNoAlias() {
IllegalArgumentException exception = expectThrows(IllegalArgumentException.class, () -> new RolloverAction(null, null, null, 1L));
assertEquals(RolloverAction.ALIAS_FIELD.getPreferredName() + " must be not be null", exception.getMessage());
}
public void testToSteps() {
RolloverAction action = createTestInstance();
String phase = randomAlphaOfLengthBetween(1, 10);
@ -91,7 +81,6 @@ public class RolloverActionTests extends AbstractSerializingTestCase<RolloverAct
RolloverStep firstStep = (RolloverStep) steps.get(0);
assertEquals(expectedFirstStepKey, firstStep.getKey());
assertEquals(nextStepKey, firstStep.getNextStepKey());
assertEquals(action.getAlias(), firstStep.getAlias());
assertEquals(action.getMaxSize(), firstStep.getMaxSize());
assertEquals(action.getMaxAge(), firstStep.getMaxAge());
assertEquals(action.getMaxDocs(), firstStep.getMaxDocs());

View File

@ -30,8 +30,11 @@ import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
import static org.hamcrest.Matchers.equalTo;
public class RolloverStepTests extends AbstractStepTestCase<RolloverStep> {
private Client client;
@ -52,19 +55,18 @@ public class RolloverStepTests extends AbstractStepTestCase<RolloverStep> {
TimeValue maxAge = (maxDocs == null && maxSize == null || randomBoolean())
? TimeValue.parseTimeValue(randomPositiveTimeValue(), "rollover_action_test")
: null;
return new RolloverStep(stepKey, nextStepKey, client, alias, maxSize, maxAge, maxDocs);
return new RolloverStep(stepKey, nextStepKey, client, maxSize, maxAge, maxDocs);
}
@Override
public RolloverStep mutateInstance(RolloverStep instance) {
StepKey key = instance.getKey();
StepKey nextKey = instance.getNextStepKey();
String alias = instance.getAlias();
ByteSizeValue maxSize = instance.getMaxSize();
TimeValue maxAge = instance.getMaxAge();
Long maxDocs = instance.getMaxDocs();
switch (between(0, 5)) {
switch (between(0, 4)) {
case 0:
key = new StepKey(key.getPhase(), key.getAction(), key.getName() + randomAlphaOfLength(5));
break;
@ -72,35 +74,34 @@ public class RolloverStepTests extends AbstractStepTestCase<RolloverStep> {
nextKey = new StepKey(key.getPhase(), key.getAction(), key.getName() + randomAlphaOfLength(5));
break;
case 2:
alias = alias + randomAlphaOfLengthBetween(1, 5);
break;
case 3:
maxSize = randomValueOtherThan(maxSize, () -> {
ByteSizeUnit maxSizeUnit = randomFrom(ByteSizeUnit.values());
return new ByteSizeValue(randomNonNegativeLong() / maxSizeUnit.toBytes(1), maxSizeUnit);
});
break;
case 4:
case 3:
maxAge = TimeValue.parseTimeValue(randomPositiveTimeValue(), "rollover_action_test");
break;
case 5:
case 4:
maxDocs = randomNonNegativeLong();
break;
default:
throw new AssertionError("Illegal randomisation branch");
}
return new RolloverStep(key, nextKey, instance.getClient(), alias, maxSize, maxAge, maxDocs);
return new RolloverStep(key, nextKey, instance.getClient(), maxSize, maxAge, maxDocs);
}
@Override
public RolloverStep copyInstance(RolloverStep instance) {
return new RolloverStep(instance.getKey(), instance.getNextStepKey(), instance.getClient(),
instance.getAlias(), instance.getMaxSize(), instance.getMaxAge(), instance.getMaxDocs());
instance.getMaxSize(), instance.getMaxAge(), instance.getMaxDocs());
}
public void testPerformAction() throws Exception {
IndexMetaData indexMetaData = IndexMetaData.builder(randomAlphaOfLength(10)).settings(settings(Version.CURRENT))
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();
RolloverStep step = createRandomInstance();
@ -127,7 +128,7 @@ public class RolloverStepTests extends AbstractStepTestCase<RolloverStep> {
if (step.getMaxDocs() != null) {
expectedConditions.add(new MaxDocsCondition(step.getMaxDocs()));
}
RolloverIndexTestHelper.assertRolloverIndexRequest(request, step.getAlias(), expectedConditions);
RolloverIndexTestHelper.assertRolloverIndexRequest(request, alias, expectedConditions);
listener.onResponse(RolloverIndexTestHelper.createMockResponse(request, true));
return null;
}
@ -156,7 +157,9 @@ public class RolloverStepTests extends AbstractStepTestCase<RolloverStep> {
}
public void testPerformActionNotComplete() throws Exception {
IndexMetaData indexMetaData = IndexMetaData.builder(randomAlphaOfLength(10)).settings(settings(Version.CURRENT))
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();
RolloverStep step = createRandomInstance();
@ -182,7 +185,7 @@ public class RolloverStepTests extends AbstractStepTestCase<RolloverStep> {
if (step.getMaxDocs() != null) {
expectedConditions.add(new MaxDocsCondition(step.getMaxDocs()));
}
RolloverIndexTestHelper.assertRolloverIndexRequest(request, step.getAlias(), expectedConditions);
RolloverIndexTestHelper.assertRolloverIndexRequest(request, alias, expectedConditions);
listener.onResponse(RolloverIndexTestHelper.createMockResponse(request, false));
return null;
}
@ -211,7 +214,9 @@ public class RolloverStepTests extends AbstractStepTestCase<RolloverStep> {
}
public void testPerformActionFailure() throws Exception {
IndexMetaData indexMetaData = IndexMetaData.builder(randomAlphaOfLength(10)).settings(settings(Version.CURRENT))
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();
Exception exception = new RuntimeException();
RolloverStep step = createRandomInstance();
@ -238,7 +243,7 @@ public class RolloverStepTests extends AbstractStepTestCase<RolloverStep> {
if (step.getMaxDocs() != null) {
expectedConditions.add(new MaxDocsCondition(step.getMaxDocs()));
}
RolloverIndexTestHelper.assertRolloverIndexRequest(request, step.getAlias(), expectedConditions);
RolloverIndexTestHelper.assertRolloverIndexRequest(request, alias, expectedConditions);
listener.onFailure(exception);
return null;
}
@ -267,4 +272,29 @@ public class RolloverStepTests extends AbstractStepTestCase<RolloverStep> {
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();
RolloverStep step = createRandomInstance();
SetOnce<Exception> exceptionThrown = new SetOnce<>();
step.performAction(indexMetaData, new Listener() {
@Override
public void onResponse(boolean complete) {
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())));
}
}

View File

@ -33,7 +33,7 @@ public class TimeseriesLifecycleTypeTests extends ESTestCase {
private static final DeleteAction TEST_DELETE_ACTION = new DeleteAction();
private static final ForceMergeAction TEST_FORCE_MERGE_ACTION = new ForceMergeAction(1, true);
private static final ReplicasAction TEST_REPLICAS_ACTION = new ReplicasAction(1);
private static final RolloverAction TEST_ROLLOVER_ACTION = new RolloverAction("", new ByteSizeValue(1), null, null);
private static final RolloverAction TEST_ROLLOVER_ACTION = new RolloverAction(new ByteSizeValue(1), null, null);
private static final ShrinkAction TEST_SHRINK_ACTION = new ShrinkAction(1);
private static final ReadOnlyAction TEST_READ_ONLY_ACTION = new ReadOnlyAction();

View File

@ -33,6 +33,7 @@ import org.elasticsearch.watcher.ResourceWatcherService;
import org.elasticsearch.xpack.core.XPackPlugin;
import org.elasticsearch.xpack.core.XPackSettings;
import org.elasticsearch.xpack.core.indexlifecycle.LifecycleSettings;
import org.elasticsearch.xpack.core.indexlifecycle.RolloverAction;
import org.elasticsearch.xpack.core.indexlifecycle.action.DeleteLifecycleAction;
import org.elasticsearch.xpack.core.indexlifecycle.action.GetLifecycleAction;
import org.elasticsearch.xpack.core.indexlifecycle.action.PutLifecycleAction;
@ -95,7 +96,8 @@ public class IndexLifecycle extends Plugin implements ActionPlugin {
LifecycleSettings.LIFECYCLE_ACTION_TIME_SETTING,
LifecycleSettings.LIFECYCLE_ACTION_SETTING,
LifecycleSettings.LIFECYCLE_STEP_TIME_SETTING,
LifecycleSettings.LIFECYCLE_STEP_SETTING);
LifecycleSettings.LIFECYCLE_STEP_SETTING,
RolloverAction.LIFECYCLE_ROLLOVER_ALIAS_SETTING);
}
@Override