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 ac50fa745d7..15abe6b524b 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 @@ -68,7 +68,7 @@ public class IndexLifecycleIT extends ESRestHighLevelClientTestCase { " \"cold\": {\n" + " \"after\": \"2000s\",\n" + " \"actions\": {\n" + - " \"replicas\": {\n" + + " \"allocate\": {\n" + " \"number_of_replicas\": 0\n" + " }\n" + " }\n" + diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/XPackClientPlugin.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/XPackClientPlugin.java index 76df45d8a5e..dc097665633 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/XPackClientPlugin.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/XPackClientPlugin.java @@ -49,7 +49,6 @@ import org.elasticsearch.xpack.core.indexlifecycle.IndexLifecycleMetadata; import org.elasticsearch.xpack.core.indexlifecycle.LifecycleAction; import org.elasticsearch.xpack.core.indexlifecycle.LifecycleType; import org.elasticsearch.xpack.core.indexlifecycle.ReadOnlyAction; -import org.elasticsearch.xpack.core.indexlifecycle.ReplicasAction; import org.elasticsearch.xpack.core.indexlifecycle.RolloverAction; import org.elasticsearch.xpack.core.indexlifecycle.ShrinkAction; import org.elasticsearch.xpack.core.indexlifecycle.TimeseriesLifecycleType; @@ -408,7 +407,6 @@ public class XPackClientPlugin extends Plugin implements ActionPlugin, NetworkPl new NamedWriteableRegistry.Entry(LifecycleAction.class, AllocateAction.NAME, AllocateAction::new), new NamedWriteableRegistry.Entry(LifecycleAction.class, ForceMergeAction.NAME, ForceMergeAction::new), new NamedWriteableRegistry.Entry(LifecycleAction.class, ReadOnlyAction.NAME, ReadOnlyAction::new), - new NamedWriteableRegistry.Entry(LifecycleAction.class, ReplicasAction.NAME, ReplicasAction::new), new NamedWriteableRegistry.Entry(LifecycleAction.class, RolloverAction.NAME, RolloverAction::new), new NamedWriteableRegistry.Entry(LifecycleAction.class, ShrinkAction.NAME, ShrinkAction::new), new NamedWriteableRegistry.Entry(LifecycleAction.class, DeleteAction.NAME, DeleteAction::new) @@ -452,7 +450,6 @@ public class XPackClientPlugin extends Plugin implements ActionPlugin, NetworkPl new NamedXContentRegistry.Entry(LifecycleAction.class, new ParseField(AllocateAction.NAME), AllocateAction::parse), new NamedXContentRegistry.Entry(LifecycleAction.class, new ParseField(ForceMergeAction.NAME), ForceMergeAction::parse), new NamedXContentRegistry.Entry(LifecycleAction.class, new ParseField(ReadOnlyAction.NAME), ReadOnlyAction::parse), - new NamedXContentRegistry.Entry(LifecycleAction.class, new ParseField(ReplicasAction.NAME), ReplicasAction::parse), new NamedXContentRegistry.Entry(LifecycleAction.class, new ParseField(RolloverAction.NAME), RolloverAction::parse), new NamedXContentRegistry.Entry(LifecycleAction.class, new ParseField(ShrinkAction.NAME), ShrinkAction::parse), new NamedXContentRegistry.Entry(LifecycleAction.class, new ParseField(DeleteAction.NAME), DeleteAction::parse) diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/AllocateAction.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/AllocateAction.java index 2e4ebbf4ac1..9cd74353237 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/AllocateAction.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/AllocateAction.java @@ -27,20 +27,23 @@ import java.util.Objects; public class AllocateAction implements LifecycleAction { public static final String NAME = "allocate"; + public static final ParseField NUMBER_OF_REPLICAS_FIELD = new ParseField("number_of_replicas"); public static final ParseField INCLUDE_FIELD = new ParseField("include"); public static final ParseField EXCLUDE_FIELD = new ParseField("exclude"); public static final ParseField REQUIRE_FIELD = new ParseField("require"); @SuppressWarnings("unchecked") private static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>(NAME, - a -> new AllocateAction((Map) a[0], (Map) a[1], (Map) a[2])); + a -> new AllocateAction((Integer) a[0], (Map) a[1], (Map) a[2], (Map) a[3])); static { + PARSER.declareInt(ConstructingObjectParser.optionalConstructorArg(), NUMBER_OF_REPLICAS_FIELD); PARSER.declareObject(ConstructingObjectParser.optionalConstructorArg(), (p, c) -> p.mapStrings(), INCLUDE_FIELD); PARSER.declareObject(ConstructingObjectParser.optionalConstructorArg(), (p, c) -> p.mapStrings(), EXCLUDE_FIELD); PARSER.declareObject(ConstructingObjectParser.optionalConstructorArg(), (p, c) -> p.mapStrings(), REQUIRE_FIELD); } + private final Integer numberOfReplicas; private final Map include; private final Map exclude; private final Map require; @@ -49,7 +52,7 @@ public class AllocateAction implements LifecycleAction { return PARSER.apply(parser, null); } - public AllocateAction(Map include, Map exclude, Map require) { + public AllocateAction(Integer numberOfReplicas, Map include, Map exclude, Map require) { if (include == null) { this.include = Collections.emptyMap(); } else { @@ -65,19 +68,27 @@ public class AllocateAction implements LifecycleAction { } else { this.require = require; } - if (this.include.isEmpty() && this.exclude.isEmpty() && this.require.isEmpty()) { + if (this.include.isEmpty() && this.exclude.isEmpty() && this.require.isEmpty() && numberOfReplicas == null) { throw new IllegalArgumentException( "At least one of " + INCLUDE_FIELD.getPreferredName() + ", " + EXCLUDE_FIELD.getPreferredName() + " or " + REQUIRE_FIELD.getPreferredName() + "must contain attributes for action " + NAME); } + if (numberOfReplicas != null && numberOfReplicas < 0) { + throw new IllegalArgumentException("[" + NUMBER_OF_REPLICAS_FIELD.getPreferredName() + "] must be >= 0"); + } + this.numberOfReplicas = numberOfReplicas; } @SuppressWarnings("unchecked") public AllocateAction(StreamInput in) throws IOException { - this((Map) in.readGenericValue(), (Map) in.readGenericValue(), + this(in.readOptionalVInt(), (Map) in.readGenericValue(), (Map) in.readGenericValue(), (Map) in.readGenericValue()); } + public Integer getNumberOfReplicas() { + return numberOfReplicas; + } + public Map getInclude() { return include; } @@ -92,6 +103,7 @@ public class AllocateAction implements LifecycleAction { @Override public void writeTo(StreamOutput out) throws IOException { + out.writeOptionalVInt(numberOfReplicas); out.writeGenericValue(include); out.writeGenericValue(exclude); out.writeGenericValue(require); @@ -105,6 +117,9 @@ public class AllocateAction implements LifecycleAction { @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { builder.startObject(); + if (numberOfReplicas != null) { + builder.field(NUMBER_OF_REPLICAS_FIELD.getPreferredName(), numberOfReplicas); + } builder.field(INCLUDE_FIELD.getPreferredName(), include); builder.field(EXCLUDE_FIELD.getPreferredName(), exclude); builder.field(REQUIRE_FIELD.getPreferredName(), require); @@ -123,6 +138,9 @@ public class AllocateAction implements LifecycleAction { StepKey allocationRoutedKey = new StepKey(phase, NAME, AllocationRoutedStep.NAME); Settings.Builder newSettings = Settings.builder(); + if (numberOfReplicas != null) { + newSettings.put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, numberOfReplicas); + } include.forEach((key, value) -> newSettings.put(IndexMetaData.INDEX_ROUTING_INCLUDE_GROUP_SETTING.getKey() + key, value)); exclude.forEach((key, value) -> newSettings.put(IndexMetaData.INDEX_ROUTING_EXCLUDE_GROUP_SETTING.getKey() + key, value)); require.forEach((key, value) -> newSettings.put(IndexMetaData.INDEX_ROUTING_REQUIRE_GROUP_SETTING.getKey() + key, value)); @@ -140,7 +158,7 @@ public class AllocateAction implements LifecycleAction { @Override public int hashCode() { - return Objects.hash(include, exclude, require); + return Objects.hash(numberOfReplicas, include, exclude, require); } @Override @@ -152,7 +170,10 @@ public class AllocateAction implements LifecycleAction { return false; } AllocateAction other = (AllocateAction) obj; - return Objects.equals(include, other.include) && Objects.equals(exclude, other.exclude) && Objects.equals(require, other.require); + return Objects.equals(numberOfReplicas, other.numberOfReplicas) && + Objects.equals(include, other.include) && + Objects.equals(exclude, other.exclude) && + Objects.equals(require, other.require); } @Override diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/AllocationRoutedStep.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/AllocationRoutedStep.java index 7ee7868ba85..560029ba857 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/AllocationRoutedStep.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/AllocationRoutedStep.java @@ -54,15 +54,15 @@ public class AllocationRoutedStep extends ClusterStateWaitStep { @Override public Result isConditionMet(Index index, ClusterState clusterState) { - if (ActiveShardCount.ALL.enoughShardsActive(clusterState, index.getName()) == false) { - logger.debug("[{}] lifecycle action for index [{}] cannot make progress because not all shards are active", - getKey().getAction(), index.getName()); - return new Result(false, new Info(-1, false)); - } IndexMetaData idxMeta = clusterState.metaData().index(index); if (idxMeta == null) { throw new IndexNotFoundException("Index not found when executing " + getKey().getAction() + " lifecycle action.", - index.getName()); + index.getName()); + } + if (ActiveShardCount.ALL.enoughShardsActive(clusterState, index.getName()) == false) { + logger.debug("[{}] lifecycle action for index [{}] cannot make progress because not all shards are active", + getKey().getAction(), index.getName()); + return new Result(false, new Info(idxMeta.getNumberOfReplicas(), -1, false)); } // All the allocation attributes are already set so just need to check // if the allocation has happened @@ -94,7 +94,7 @@ public class AllocationRoutedStep extends ClusterStateWaitStep { logger.debug( "[{}] lifecycle action for index [{}] waiting for [{}] shards " + "to be allocated to nodes matching the given filters", getKey().getAction(), index, allocationPendingAllShards); - return new Result(false, new Info(allocationPendingAllShards, true)); + return new Result(false, new Info(idxMeta.getNumberOfReplicas(), allocationPendingAllShards, true)); } else { logger.debug("[{}] lifecycle action for index [{}] complete", getKey().getAction(), index); return new Result(true, null); @@ -105,7 +105,7 @@ public class AllocationRoutedStep extends ClusterStateWaitStep { public int hashCode() { return Objects.hash(super.hashCode(), waitOnAllShardCopies); } - + @Override public boolean equals(Object obj) { if (obj == null) { @@ -115,29 +115,33 @@ public class AllocationRoutedStep extends ClusterStateWaitStep { return false; } AllocationRoutedStep other = (AllocationRoutedStep) obj; - return super.equals(obj) && + return super.equals(obj) && Objects.equals(waitOnAllShardCopies, other.waitOnAllShardCopies); } - + public static final class Info implements ToXContentObject { + private final long actualReplicas; private final long numberShardsLeftToAllocate; private final boolean allShardsActive; private final String message; + static final ParseField ACTUAL_REPLICAS = new ParseField("actual_replicas"); static final ParseField SHARDS_TO_ALLOCATE = new ParseField("shards_left_to_allocate"); static final ParseField ALL_SHARDS_ACTIVE = new ParseField("all_shards_active"); static final ParseField MESSAGE = new ParseField("message"); static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>("allocation_routed_step_info", - a -> new Info((long) a[0], (boolean) a[1])); + a -> new Info((long) a[0], (long) a[1], (boolean) a[2])); static { + PARSER.declareLong(ConstructingObjectParser.constructorArg(), ACTUAL_REPLICAS); PARSER.declareLong(ConstructingObjectParser.constructorArg(), SHARDS_TO_ALLOCATE); PARSER.declareBoolean(ConstructingObjectParser.constructorArg(), ALL_SHARDS_ACTIVE); PARSER.declareString((i, s) -> {}, MESSAGE); } - public Info(long numberShardsLeftToMerge, boolean allShardsActive) { - this.numberShardsLeftToAllocate = numberShardsLeftToMerge; + public Info(long actualReplicas, long numberShardsLeftToAllocate, boolean allShardsActive) { + this.actualReplicas = actualReplicas; + this.numberShardsLeftToAllocate = numberShardsLeftToAllocate; this.allShardsActive = allShardsActive; if (allShardsActive == false) { message = "Waiting for all shard copies to be active"; @@ -147,10 +151,14 @@ public class AllocationRoutedStep extends ClusterStateWaitStep { } } + public long getActualReplicas() { + return actualReplicas; + } + public long getNumberShardsLeftToAllocate() { return numberShardsLeftToAllocate; } - + public boolean allShardsActive() { return allShardsActive; } @@ -161,13 +169,14 @@ public class AllocationRoutedStep extends ClusterStateWaitStep { builder.field(MESSAGE.getPreferredName(), message); builder.field(SHARDS_TO_ALLOCATE.getPreferredName(), numberShardsLeftToAllocate); builder.field(ALL_SHARDS_ACTIVE.getPreferredName(), allShardsActive); + builder.field(ACTUAL_REPLICAS.getPreferredName(), actualReplicas); builder.endObject(); return builder; } @Override public int hashCode() { - return Objects.hash(numberShardsLeftToAllocate, allShardsActive); + return Objects.hash(actualReplicas, numberShardsLeftToAllocate, allShardsActive); } @Override @@ -179,8 +188,9 @@ public class AllocationRoutedStep extends ClusterStateWaitStep { return false; } Info other = (Info) obj; - return Objects.equals(numberShardsLeftToAllocate, other.numberShardsLeftToAllocate) && - Objects.equals(allShardsActive, other.allShardsActive); + return Objects.equals(actualReplicas, other.actualReplicas) && + Objects.equals(numberShardsLeftToAllocate, other.numberShardsLeftToAllocate) && + Objects.equals(allShardsActive, other.allShardsActive); } @Override diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/ReplicasAction.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/ReplicasAction.java deleted file mode 100644 index 4d45f1aa89a..00000000000 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/ReplicasAction.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -package org.elasticsearch.xpack.core.indexlifecycle; - -import org.elasticsearch.client.Client; -import org.elasticsearch.cluster.metadata.IndexMetaData; -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.Settings; -import org.elasticsearch.common.xcontent.ConstructingObjectParser; -import org.elasticsearch.common.xcontent.XContentBuilder; -import org.elasticsearch.common.xcontent.XContentParser; -import org.elasticsearch.xpack.core.indexlifecycle.Step.StepKey; - -import java.io.IOException; -import java.util.Arrays; -import java.util.List; -import java.util.Objects; - -import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg; - -/** - * A {@link LifecycleAction} that changes the number of replicas for the index. - */ -public class ReplicasAction implements LifecycleAction { - public static final String NAME = "replicas"; - - public static final ParseField NUMBER_OF_REPLICAS_FIELD = new ParseField("number_of_replicas"); - private static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>(NAME, - false, a -> new ReplicasAction((Integer) a[0])); - - static { - PARSER.declareInt(constructorArg(), NUMBER_OF_REPLICAS_FIELD); - } - - private int numberOfReplicas; - - public static ReplicasAction parse(XContentParser parser) { - return PARSER.apply(parser, null); - } - - public ReplicasAction(int numberOfReplicas) { - if (numberOfReplicas < 0) { - throw new IllegalArgumentException("[" + NUMBER_OF_REPLICAS_FIELD.getPreferredName() + "] must be >= 0"); - } - this.numberOfReplicas = numberOfReplicas; - } - - public ReplicasAction(StreamInput in) throws IOException { - this.numberOfReplicas = in.readVInt(); - } - - @Override - public void writeTo(StreamOutput out) throws IOException { - out.writeVInt(numberOfReplicas); - } - - @Override - public String getWriteableName() { - return NAME; - } - - @Override - public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.startObject(); - builder.field(NUMBER_OF_REPLICAS_FIELD.getPreferredName(), numberOfReplicas); - builder.endObject(); - return builder; - } - - @Override - public boolean isSafeAction() { - return true; - } - - @Override - public List toSteps(Client client, String phase, Step.StepKey nextStepKey) { - StepKey updateReplicasKey = new StepKey(phase, NAME, UpdateSettingsStep.NAME); - StepKey enoughKey = new StepKey(phase, NAME, ReplicasAllocatedStep.NAME); - Settings replicaSettings = Settings.builder().put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, numberOfReplicas).build(); - return Arrays.asList(new UpdateSettingsStep(updateReplicasKey, enoughKey, client, replicaSettings), - new ReplicasAllocatedStep(enoughKey, nextStepKey)); - } - - @Override - public List toStepKeys(String phase) { - StepKey updateReplicasKey = new StepKey(phase, NAME, UpdateSettingsStep.NAME); - StepKey enoughKey = new StepKey(phase, NAME, ReplicasAllocatedStep.NAME); - return Arrays.asList(updateReplicasKey, enoughKey); - } - - public int getNumberOfReplicas() { - return numberOfReplicas; - } - - @Override - public int hashCode() { - return Objects.hashCode(numberOfReplicas); - } - - @Override - public boolean equals(Object obj) { - if (obj == null) { - return false; - } - if (obj.getClass() != getClass()) { - return false; - } - ReplicasAction other = (ReplicasAction) obj; - return Objects.equals(numberOfReplicas, other.numberOfReplicas); - } - - @Override - public String toString() { - return Strings.toString(this); - } - -} diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/ReplicasAllocatedStep.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/ReplicasAllocatedStep.java deleted file mode 100644 index 012a2c4515d..00000000000 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/ReplicasAllocatedStep.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -package org.elasticsearch.xpack.core.indexlifecycle; - -import org.elasticsearch.action.support.ActiveShardCount; -import org.elasticsearch.cluster.ClusterState; -import org.elasticsearch.cluster.metadata.IndexMetaData; -import org.elasticsearch.common.ParseField; -import org.elasticsearch.common.Strings; -import org.elasticsearch.common.xcontent.ConstructingObjectParser; -import org.elasticsearch.common.xcontent.ToXContentObject; -import org.elasticsearch.common.xcontent.XContentBuilder; -import org.elasticsearch.index.Index; -import org.elasticsearch.index.IndexNotFoundException; - -import java.io.IOException; -import java.util.Objects; - -public class ReplicasAllocatedStep extends ClusterStateWaitStep { - public static final String NAME = "enough-shards-allocated"; - - public ReplicasAllocatedStep(StepKey key, StepKey nextStepKey) { - super(key, nextStepKey); - } - - @Override - public Result isConditionMet(Index index, ClusterState clusterState) { - IndexMetaData idxMeta = clusterState.metaData().index(index); - if (idxMeta == null) { - throw new IndexNotFoundException("Index not found when executing " + getKey().getAction() + " lifecycle action.", - index.getName()); - } - // We only want to make progress if the cluster state reflects the number of replicas change and all shards are active - boolean allShardsActive = ActiveShardCount.ALL.enoughShardsActive(clusterState, index.getName()); - if (allShardsActive) { - return new Result(true, null); - } else { - return new Result(false, new Info(idxMeta.getNumberOfReplicas(), allShardsActive)); - } - } - - @Override - public int hashCode() { - return super.hashCode(); - } - - @Override - public boolean equals(Object obj) { - return obj != null && getClass() == obj.getClass() && super.equals(obj); - } - - public static final class Info implements ToXContentObject { - - private final long actualReplicas; - private final boolean allShardsActive; - private final String message; - - static final ParseField ACTUAL_REPLICAS = new ParseField("actual_replicas"); - static final ParseField ALL_SHARDS_ACTIVE = new ParseField("all_shards_active"); - static final ParseField MESSAGE = new ParseField("message"); - static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>("replicas_allocated_step_info", - a -> new Info((long) a[0], (boolean) a[1])); - static { - PARSER.declareLong(ConstructingObjectParser.constructorArg(), ACTUAL_REPLICAS); - PARSER.declareBoolean(ConstructingObjectParser.constructorArg(), ALL_SHARDS_ACTIVE); - PARSER.declareString((i, s) -> {}, MESSAGE); - } - - public Info(long actualReplicas, boolean allShardsActive) { - this.actualReplicas = actualReplicas; - this.allShardsActive = allShardsActive; - if (allShardsActive == false) { - message = "Waiting for all shard copies to be active"; - } else { - message = ""; - } - } - - public long getActualReplicas() { - return actualReplicas; - } - - public boolean allShardsActive() { - return allShardsActive; - } - - @Override - public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - builder.startObject(); - builder.field(MESSAGE.getPreferredName(), message); - builder.field(ACTUAL_REPLICAS.getPreferredName(), actualReplicas); - builder.field(ALL_SHARDS_ACTIVE.getPreferredName(), allShardsActive); - builder.endObject(); - return builder; - } - - @Override - public int hashCode() { - return Objects.hash(actualReplicas, allShardsActive); - } - - @Override - public boolean equals(Object obj) { - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - Info other = (Info) obj; - return Objects.equals(actualReplicas, other.actualReplicas) && - Objects.equals(allShardsActive, other.allShardsActive); - } - - @Override - public String toString() { - return Strings.toString(this); - } - } -} diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/TimeseriesLifecycleType.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/TimeseriesLifecycleType.java index fb5fcf52956..8ace07e3a9a 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/TimeseriesLifecycleType.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/indexlifecycle/TimeseriesLifecycleType.java @@ -37,8 +37,8 @@ public class TimeseriesLifecycleType implements LifecycleType { static final List VALID_PHASES = Arrays.asList("hot", "warm", "cold", "delete"); static final List ORDERED_VALID_HOT_ACTIONS = Collections.singletonList(RolloverAction.NAME); static final List ORDERED_VALID_WARM_ACTIONS = Arrays.asList(ReadOnlyAction.NAME, AllocateAction.NAME, - ReplicasAction.NAME, ShrinkAction.NAME, ForceMergeAction.NAME); - static final List ORDERED_VALID_COLD_ACTIONS = Arrays.asList(AllocateAction.NAME, ReplicasAction.NAME); + ShrinkAction.NAME, ForceMergeAction.NAME); + static final List ORDERED_VALID_COLD_ACTIONS = Arrays.asList(AllocateAction.NAME); static final List ORDERED_VALID_DELETE_ACTIONS = Arrays.asList(DeleteAction.NAME); static final Set VALID_HOT_ACTIONS = Sets.newHashSet(ORDERED_VALID_HOT_ACTIONS); static final Set VALID_WARM_ACTIONS = Sets.newHashSet(ORDERED_VALID_WARM_ACTIONS); @@ -140,7 +140,7 @@ public class TimeseriesLifecycleType implements LifecycleType { throw new IllegalArgumentException("lifecycle type[" + TYPE + "] does not support phase[" + phase.getName() + "]"); } } - + @Override public String getNextActionName(String currentActionName, Phase phase) { List orderedActionNames; diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/indexlifecycle/AllocateActionTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/indexlifecycle/AllocateActionTests.java index 55d68b41610..147e1b7671c 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/indexlifecycle/AllocateActionTests.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/indexlifecycle/AllocateActionTests.java @@ -48,7 +48,8 @@ public class AllocateActionTests extends AbstractActionTestCase } else { requires = randomBoolean() ? null : Collections.emptyMap(); } - return new AllocateAction(includes, excludes, requires); + Integer numberOfReplicas = randomBoolean() ? null : randomIntBetween(0, 10); + return new AllocateAction(numberOfReplicas, includes, excludes, requires); } @Override @@ -61,7 +62,8 @@ public class AllocateActionTests extends AbstractActionTestCase Map include = instance.getInclude(); Map exclude = instance.getExclude(); Map require = instance.getRequire(); - switch (randomIntBetween(0, 2)) { + Integer numberOfReplicas = instance.getNumberOfReplicas(); + switch (randomIntBetween(0, 3)) { case 0: include = new HashMap<>(include); include.put(randomAlphaOfLengthBetween(11, 15), randomAlphaOfLengthBetween(1, 20)); @@ -74,10 +76,13 @@ public class AllocateActionTests extends AbstractActionTestCase require = new HashMap<>(require); require.put(randomAlphaOfLengthBetween(11, 15), randomAlphaOfLengthBetween(1, 20)); break; + case 3: + numberOfReplicas = randomIntBetween(11, 20); + break; default: throw new AssertionError("Illegal randomisation branch"); } - return new AllocateAction(include, exclude, require); + return new AllocateAction(numberOfReplicas, include, exclude, require); } public void testAllMapsNullOrEmpty() { @@ -85,12 +90,21 @@ public class AllocateActionTests extends AbstractActionTestCase Map exclude = randomBoolean() ? null : Collections.emptyMap(); Map require = randomBoolean() ? null : Collections.emptyMap(); IllegalArgumentException exception = expectThrows(IllegalArgumentException.class, - () -> new AllocateAction(include, exclude, require)); + () -> new AllocateAction(null, include, exclude, require)); assertEquals("At least one of " + AllocateAction.INCLUDE_FIELD.getPreferredName() + ", " + AllocateAction.EXCLUDE_FIELD.getPreferredName() + " or " + AllocateAction.REQUIRE_FIELD.getPreferredName() + "must contain attributes for action " + AllocateAction.NAME, exception.getMessage()); } + public void testInvalidNumberOfReplicas() { + Map include = randomMap(1, 5); + Map exclude = randomBoolean() ? null : Collections.emptyMap(); + Map require = randomBoolean() ? null : Collections.emptyMap(); + IllegalArgumentException exception = expectThrows(IllegalArgumentException.class, + () -> new AllocateAction(randomIntBetween(-1000, -1), include, exclude, require)); + assertEquals("[" + AllocateAction.NUMBER_OF_REPLICAS_FIELD.getPreferredName() + "] must be >= 0", exception.getMessage()); + } + public static Map randomMap(int minEntries, int maxEntries) { Map map = new HashMap<>(); int numIncludes = randomIntBetween(minEntries, maxEntries); @@ -114,6 +128,9 @@ public class AllocateActionTests extends AbstractActionTestCase assertEquals(expectedFirstStepKey, firstStep.getKey()); assertEquals(expectedSecondStepKey, firstStep.getNextStepKey()); Settings.Builder expectedSettings = Settings.builder(); + if (action.getNumberOfReplicas() != null) { + expectedSettings.put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, action.getNumberOfReplicas()); + } action.getInclude().forEach( (key, value) -> expectedSettings.put(IndexMetaData.INDEX_ROUTING_INCLUDE_GROUP_SETTING.getKey() + key, value)); action.getExclude().forEach( diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/indexlifecycle/AllocationRoutedStepInfoTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/indexlifecycle/AllocationRoutedStepInfoTests.java index 8979e0e31f3..80eb89c45b9 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/indexlifecycle/AllocationRoutedStepInfoTests.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/indexlifecycle/AllocationRoutedStepInfoTests.java @@ -17,7 +17,7 @@ public class AllocationRoutedStepInfoTests extends AbstractXContentTestCase { @@ -168,7 +169,7 @@ public class AllocationRoutedStepTests extends AbstractStepTestCase requires = Collections.singletonMap("_name", "node1"); + Settings.Builder existingSettings = Settings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT.id) + .put(IndexMetaData.SETTING_INDEX_UUID, index.getUUID()); + Settings.Builder expectedSettings = Settings.builder(); + Settings.Builder node1Settings = Settings.builder(); + Settings.Builder node2Settings = Settings.builder(); + requires.forEach((k, v) -> { + expectedSettings.put(IndexMetaData.INDEX_ROUTING_REQUIRE_GROUP_SETTING.getKey() + k, v); + }); + + IndexRoutingTable.Builder indexRoutingTable = IndexRoutingTable.builder(index) + .addShard(TestShardRouting.newShardRouting(new ShardId(index, 0), "node1", true, ShardRoutingState.STARTED)) + .addShard(TestShardRouting.newShardRouting(new ShardId(index, 0), null, null, false, ShardRoutingState.UNASSIGNED, + new UnassignedInfo(Reason.REPLICA_ADDED, "no attempt"))); + + AllocationRoutedStep step = createRandomInstance(); + assertAllocateStatus(index, 1, 1, step, existingSettings, node1Settings, node2Settings, indexRoutingTable, + new ClusterStateWaitStep.Result(false, new AllocationRoutedStep.Info(1, -1, false))); } public void testExecuteIndexMissing() throws Exception { diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/indexlifecycle/ReplicasActionTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/indexlifecycle/ReplicasActionTests.java deleted file mode 100644 index db0d08a401f..00000000000 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/indexlifecycle/ReplicasActionTests.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -package org.elasticsearch.xpack.core.indexlifecycle; - -import org.elasticsearch.cluster.metadata.IndexMetaData; -import org.elasticsearch.common.io.stream.Writeable.Reader; -import org.elasticsearch.common.xcontent.XContentParser; -import org.elasticsearch.xpack.core.indexlifecycle.Step.StepKey; - -import java.io.IOException; -import java.util.List; - -public class ReplicasActionTests extends AbstractActionTestCase { - - @Override - protected ReplicasAction doParseInstance(XContentParser parser) { - return ReplicasAction.parse(parser); - } - - @Override - protected ReplicasAction createTestInstance() { - return new ReplicasAction(randomIntBetween(0, 10)); - } - - @Override - protected Reader instanceReader() { - return ReplicasAction::new; - } - - @Override - protected ReplicasAction mutateInstance(ReplicasAction instance) throws IOException { - return new ReplicasAction(instance.getNumberOfReplicas() + randomIntBetween(1, 5)); - } - - public void testInvalidNumReplicas() { - IllegalArgumentException exception = expectThrows(IllegalArgumentException.class, - () -> new ReplicasAction(randomIntBetween(-1000, -1))); - assertEquals("[" + ReplicasAction.NUMBER_OF_REPLICAS_FIELD.getPreferredName() + "] must be >= 0", exception.getMessage()); - } - - public void testToSteps() { - ReplicasAction action = createTestInstance(); - String phase = randomAlphaOfLengthBetween(1, 10); - StepKey nextStepKey = new StepKey(randomAlphaOfLengthBetween(1, 10), randomAlphaOfLengthBetween(1, 10), - randomAlphaOfLengthBetween(1, 10)); - List steps = action.toSteps(null, phase, nextStepKey); - assertNotNull(steps); - assertEquals(2, steps.size()); - StepKey expectedFirstStepKey = new StepKey(phase, ReplicasAction.NAME, UpdateSettingsStep.NAME); - StepKey expectedSecondStepKey = new StepKey(phase, ReplicasAction.NAME, ReplicasAllocatedStep.NAME); - UpdateSettingsStep firstStep = (UpdateSettingsStep) steps.get(0); - assertEquals(expectedFirstStepKey, firstStep.getKey()); - assertEquals(expectedSecondStepKey, firstStep.getNextStepKey()); - assertEquals(1, firstStep.getSettings().size()); - assertEquals(action.getNumberOfReplicas(), IndexMetaData.INDEX_NUMBER_OF_REPLICAS_SETTING.get(firstStep.getSettings()).intValue()); - ReplicasAllocatedStep secondStep = (ReplicasAllocatedStep) steps.get(1); - assertEquals(expectedSecondStepKey, secondStep.getKey()); - assertEquals(nextStepKey, secondStep.getNextStepKey()); - } -} diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/indexlifecycle/ReplicasAllocatedStepInfoTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/indexlifecycle/ReplicasAllocatedStepInfoTests.java deleted file mode 100644 index 9769fd40e23..00000000000 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/indexlifecycle/ReplicasAllocatedStepInfoTests.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ - -package org.elasticsearch.xpack.core.indexlifecycle; - -import org.elasticsearch.common.xcontent.XContentParser; -import org.elasticsearch.test.AbstractXContentTestCase; -import org.elasticsearch.test.EqualsHashCodeTestUtils; -import org.elasticsearch.xpack.core.indexlifecycle.ReplicasAllocatedStep.Info; - -import java.io.IOException; - -public class ReplicasAllocatedStepInfoTests extends AbstractXContentTestCase { - - @Override - protected Info createTestInstance() { - return new Info(randomNonNegativeLong(), randomBoolean()); - } - - @Override - protected Info doParseInstance(XContentParser parser) throws IOException { - return Info.PARSER.apply(parser, null); - } - - @Override - protected boolean supportsUnknownFields() { - return false; - } - - public final void testEqualsAndHashcode() { - for (int runs = 0; runs < NUMBER_OF_TEST_RUNS; runs++) { - EqualsHashCodeTestUtils.checkEqualsAndHashCode(createTestInstance(), this::copyInstance, this::mutateInstance); - } - } - - protected final Info copyInstance(Info instance) throws IOException { - return new Info(instance.getActualReplicas(), instance.allShardsActive()); - } - - protected Info mutateInstance(Info instance) throws IOException { - long actualReplicas = instance.getActualReplicas(); - boolean allShardsActive = instance.allShardsActive(); - if (randomBoolean()) { - actualReplicas += between(1, 20); - } else { - allShardsActive = allShardsActive == false; - } - return new Info(actualReplicas, allShardsActive); - } - -} diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/indexlifecycle/ReplicasAllocatedStepTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/indexlifecycle/ReplicasAllocatedStepTests.java deleted file mode 100644 index 325060cf64d..00000000000 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/indexlifecycle/ReplicasAllocatedStepTests.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License; - * you may not use this file except in compliance with the Elastic License. - */ -package org.elasticsearch.xpack.core.indexlifecycle; - - -import org.elasticsearch.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.cluster.node.DiscoveryNode; -import org.elasticsearch.cluster.node.DiscoveryNodes; -import org.elasticsearch.cluster.routing.IndexRoutingTable; -import org.elasticsearch.cluster.routing.RoutingTable; -import org.elasticsearch.cluster.routing.ShardRoutingState; -import org.elasticsearch.cluster.routing.TestShardRouting; -import org.elasticsearch.common.transport.TransportAddress; -import org.elasticsearch.index.Index; -import org.elasticsearch.index.IndexNotFoundException; -import org.elasticsearch.index.shard.ShardId; -import org.elasticsearch.node.Node; -import org.elasticsearch.xpack.core.indexlifecycle.ClusterStateWaitStep.Result; -import org.elasticsearch.xpack.core.indexlifecycle.Step.StepKey; - -public class ReplicasAllocatedStepTests extends AbstractStepTestCase { - - @Override - public ReplicasAllocatedStep createRandomInstance() { - StepKey stepKey = randomStepKey(); - StepKey nextStepKey = randomStepKey(); - return new ReplicasAllocatedStep(stepKey, nextStepKey); - } - - @Override - public ReplicasAllocatedStep mutateInstance(ReplicasAllocatedStep instance) { - StepKey key = instance.getKey(); - StepKey nextKey = instance.getNextStepKey(); - if (randomBoolean()) { - key = new StepKey(key.getPhase(), key.getAction(), key.getName() + randomAlphaOfLength(5)); - } else { - nextKey = new StepKey(key.getPhase(), key.getAction(), key.getName() + randomAlphaOfLength(5)); - } - return new ReplicasAllocatedStep(key, nextKey); - } - - @Override - public ReplicasAllocatedStep copyInstance(ReplicasAllocatedStep instance) { - return new ReplicasAllocatedStep(instance.getKey(), instance.getNextStepKey()); - } - - public void testConditionMet() { - ReplicasAllocatedStep step = createRandomInstance(); - IndexMetaData indexMetadata = IndexMetaData.builder(randomAlphaOfLength(5)) - .settings(settings(Version.CURRENT)) - .numberOfShards(1) - .numberOfReplicas(randomIntBetween(0, 5)).build(); - MetaData metaData = MetaData.builder() - .persistentSettings(settings(Version.CURRENT).build()) - .put(IndexMetaData.builder(indexMetadata)) - .build(); - Index index = indexMetadata.getIndex(); - - String nodeId = randomAlphaOfLength(10); - DiscoveryNode masterNode = DiscoveryNode.createLocal(settings(Version.CURRENT) - .put(Node.NODE_MASTER_SETTING.getKey(), true).build(), - new TransportAddress(TransportAddress.META_ADDRESS, 9300), nodeId); - - ClusterState clusterState = ClusterState.builder(ClusterName.DEFAULT) - .metaData(metaData) - .nodes(DiscoveryNodes.builder().localNodeId(nodeId).masterNodeId(nodeId).add(masterNode).build()) - .routingTable(RoutingTable.builder() - .add(IndexRoutingTable.builder(index).addShard( - TestShardRouting.newShardRouting(new ShardId(index, 0), - nodeId, true, ShardRoutingState.STARTED))) - .build()) - .build(); - Result result = step.isConditionMet(indexMetadata.getIndex(), clusterState); - assertTrue(result.isComplete()); - assertNull(result.getInfomationContext()); - } - - public void testConditionNotMetAllocation() { - ReplicasAllocatedStep step = createRandomInstance(); - IndexMetaData indexMetadata = IndexMetaData.builder(randomAlphaOfLength(5)) - .settings(settings(Version.CURRENT)) - .numberOfShards(1) - .numberOfReplicas(randomIntBetween(0, 5)).build(); - MetaData metaData = MetaData.builder() - .persistentSettings(settings(Version.CURRENT).build()) - .put(IndexMetaData.builder(indexMetadata)) - .build(); - Index index = indexMetadata.getIndex(); - - String nodeId = randomAlphaOfLength(10); - DiscoveryNode masterNode = DiscoveryNode.createLocal(settings(Version.CURRENT) - .put(Node.NODE_MASTER_SETTING.getKey(), true).build(), - new TransportAddress(TransportAddress.META_ADDRESS, 9300), nodeId); - - ClusterState clusterState = ClusterState.builder(ClusterName.DEFAULT) - .metaData(metaData) - .nodes(DiscoveryNodes.builder().localNodeId(nodeId).masterNodeId(nodeId).add(masterNode).build()) - .routingTable(RoutingTable.builder() - .add(IndexRoutingTable.builder(index).addShard( - TestShardRouting.newShardRouting(new ShardId(index, 0), - nodeId, true, ShardRoutingState.INITIALIZING))) - .build()) - .build(); - - Result result = step.isConditionMet(indexMetadata.getIndex(), clusterState); - assertFalse(result.isComplete()); - assertEquals(new ReplicasAllocatedStep.Info(indexMetadata.getNumberOfReplicas(), false), - result.getInfomationContext()); - } - - public void testConditionIndexMissing() throws Exception { - Index index = new Index(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20)); - ClusterState clusterState = ClusterState.builder(ClusterState.EMPTY_STATE).build(); - - ReplicasAllocatedStep step = createRandomInstance(); - - IndexNotFoundException thrownException = expectThrows(IndexNotFoundException.class, () -> step.isConditionMet(index, clusterState)); - assertEquals("Index not found when executing " + step.getKey().getAction() + " lifecycle action.", thrownException.getMessage()); - assertEquals(index.getName(), thrownException.getIndex().getName()); - } -} diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/indexlifecycle/TimeseriesLifecycleTypeTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/indexlifecycle/TimeseriesLifecycleTypeTests.java index d1af22172a4..511aa56c399 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/indexlifecycle/TimeseriesLifecycleTypeTests.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/indexlifecycle/TimeseriesLifecycleTypeTests.java @@ -31,10 +31,10 @@ import static org.hamcrest.Matchers.equalTo; public class TimeseriesLifecycleTypeTests extends ESTestCase { - private static final AllocateAction TEST_ALLOCATE_ACTION = new AllocateAction(Collections.singletonMap("node", "node1"),null, null); + private static final AllocateAction TEST_ALLOCATE_ACTION = + new AllocateAction(2, Collections.singletonMap("node", "node1"),null, null); private static final DeleteAction TEST_DELETE_ACTION = new DeleteAction(); private static final ForceMergeAction TEST_FORCE_MERGE_ACTION = new ForceMergeAction(1); - 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 ShrinkAction TEST_SHRINK_ACTION = new ShrinkAction(1); private static final ReadOnlyAction TEST_READ_ONLY_ACTION = new ReadOnlyAction(); @@ -307,14 +307,11 @@ public class TimeseriesLifecycleTypeTests extends ESTestCase { assertInvalidAction("hot", DeleteAction.NAME, new String[] { RolloverAction.NAME }); assertInvalidAction("hot", ForceMergeAction.NAME, new String[] { RolloverAction.NAME }); assertInvalidAction("hot", ReadOnlyAction.NAME, new String[] { RolloverAction.NAME }); - assertInvalidAction("hot", ReplicasAction.NAME, new String[] { RolloverAction.NAME }); assertInvalidAction("hot", ShrinkAction.NAME, new String[] { RolloverAction.NAME }); // Warm Phase assertNextActionName("warm", ReadOnlyAction.NAME, AllocateAction.NAME, - new String[] { ReadOnlyAction.NAME, AllocateAction.NAME, ReplicasAction.NAME, ShrinkAction.NAME, ForceMergeAction.NAME }); - assertNextActionName("warm", ReadOnlyAction.NAME, ReplicasAction.NAME, - new String[] { ReadOnlyAction.NAME, ReplicasAction.NAME, ShrinkAction.NAME, ForceMergeAction.NAME }); + new String[] { ReadOnlyAction.NAME, AllocateAction.NAME, ShrinkAction.NAME, ForceMergeAction.NAME }); assertNextActionName("warm", ReadOnlyAction.NAME, ShrinkAction.NAME, new String[] { ReadOnlyAction.NAME, ShrinkAction.NAME, ForceMergeAction.NAME }); assertNextActionName("warm", ReadOnlyAction.NAME, ForceMergeAction.NAME, @@ -322,73 +319,53 @@ public class TimeseriesLifecycleTypeTests extends ESTestCase { assertNextActionName("warm", ReadOnlyAction.NAME, null, new String[] { ReadOnlyAction.NAME }); assertNextActionName("warm", ReadOnlyAction.NAME, AllocateAction.NAME, - new String[] { AllocateAction.NAME, ReplicasAction.NAME, ShrinkAction.NAME, ForceMergeAction.NAME }); - assertNextActionName("warm", ReadOnlyAction.NAME, ReplicasAction.NAME, - new String[] { ReplicasAction.NAME, ShrinkAction.NAME, ForceMergeAction.NAME }); + new String[] { AllocateAction.NAME, ShrinkAction.NAME, ForceMergeAction.NAME }); assertNextActionName("warm", ReadOnlyAction.NAME, ShrinkAction.NAME, new String[] { ShrinkAction.NAME, ForceMergeAction.NAME }); assertNextActionName("warm", ReadOnlyAction.NAME, ForceMergeAction.NAME, new String[] { ForceMergeAction.NAME }); assertNextActionName("warm", ReadOnlyAction.NAME, null, new String[] {}); - assertNextActionName("warm", AllocateAction.NAME, ReplicasAction.NAME, - new String[] { ReadOnlyAction.NAME, AllocateAction.NAME, ReplicasAction.NAME, ShrinkAction.NAME, ForceMergeAction.NAME }); assertNextActionName("warm", AllocateAction.NAME, ShrinkAction.NAME, new String[] { ReadOnlyAction.NAME, AllocateAction.NAME, ShrinkAction.NAME, ForceMergeAction.NAME }); assertNextActionName("warm", AllocateAction.NAME, ForceMergeAction.NAME, new String[] { ReadOnlyAction.NAME, AllocateAction.NAME, ForceMergeAction.NAME }); assertNextActionName("warm", AllocateAction.NAME, null, new String[] { ReadOnlyAction.NAME, AllocateAction.NAME }); - assertNextActionName("warm", AllocateAction.NAME, ReplicasAction.NAME, - new String[] { ReplicasAction.NAME, ShrinkAction.NAME, ForceMergeAction.NAME }); assertNextActionName("warm", AllocateAction.NAME, ShrinkAction.NAME, new String[] { ShrinkAction.NAME, ForceMergeAction.NAME }); assertNextActionName("warm", AllocateAction.NAME, ForceMergeAction.NAME, new String[] { ForceMergeAction.NAME }); assertNextActionName("warm", AllocateAction.NAME, null, new String[] {}); - assertNextActionName("warm", ReplicasAction.NAME, ShrinkAction.NAME, - new String[] { ReadOnlyAction.NAME, AllocateAction.NAME, ReplicasAction.NAME, ShrinkAction.NAME, ForceMergeAction.NAME }); - assertNextActionName("warm", ReplicasAction.NAME, ForceMergeAction.NAME, - new String[] { ReadOnlyAction.NAME, AllocateAction.NAME, ReplicasAction.NAME, ForceMergeAction.NAME }); - assertNextActionName("warm", ReplicasAction.NAME, null, - new String[] { ReadOnlyAction.NAME, AllocateAction.NAME, ReplicasAction.NAME }); - - assertNextActionName("warm", ReplicasAction.NAME, ShrinkAction.NAME, new String[] { ShrinkAction.NAME, ForceMergeAction.NAME }); - assertNextActionName("warm", ReplicasAction.NAME, ForceMergeAction.NAME, new String[] { ForceMergeAction.NAME }); - assertNextActionName("warm", ReplicasAction.NAME, null, new String[] {}); - assertNextActionName("warm", ShrinkAction.NAME, ForceMergeAction.NAME, - new String[] { ReadOnlyAction.NAME, AllocateAction.NAME, ReplicasAction.NAME, ShrinkAction.NAME, ForceMergeAction.NAME }); + new String[] { ReadOnlyAction.NAME, AllocateAction.NAME, ShrinkAction.NAME, ForceMergeAction.NAME }); assertNextActionName("warm", ShrinkAction.NAME, null, - new String[] { ReadOnlyAction.NAME, AllocateAction.NAME, ReplicasAction.NAME, ShrinkAction.NAME }); + new String[] { ReadOnlyAction.NAME, AllocateAction.NAME, ShrinkAction.NAME }); assertNextActionName("warm", ShrinkAction.NAME, ForceMergeAction.NAME, new String[] { ForceMergeAction.NAME }); assertNextActionName("warm", ShrinkAction.NAME, null, new String[] {}); assertNextActionName("warm", ForceMergeAction.NAME, null, - new String[] { ReadOnlyAction.NAME, AllocateAction.NAME, ReplicasAction.NAME, ShrinkAction.NAME, ForceMergeAction.NAME }); + new String[] { ReadOnlyAction.NAME, AllocateAction.NAME, ShrinkAction.NAME, ForceMergeAction.NAME }); assertNextActionName("warm", ForceMergeAction.NAME, null, new String[] {}); assertInvalidAction("warm", "foo", new String[] { RolloverAction.NAME }); assertInvalidAction("warm", DeleteAction.NAME, - new String[] { ReadOnlyAction.NAME, AllocateAction.NAME, ReplicasAction.NAME, ShrinkAction.NAME, ForceMergeAction.NAME }); + new String[] { ReadOnlyAction.NAME, AllocateAction.NAME, ShrinkAction.NAME, ForceMergeAction.NAME }); assertInvalidAction("warm", RolloverAction.NAME, - new String[] { ReadOnlyAction.NAME, AllocateAction.NAME, ReplicasAction.NAME, ShrinkAction.NAME, ForceMergeAction.NAME }); + new String[] { ReadOnlyAction.NAME, AllocateAction.NAME, ShrinkAction.NAME, ForceMergeAction.NAME }); // Cold Phase - assertNextActionName("cold", AllocateAction.NAME, ReplicasAction.NAME, new String[] { AllocateAction.NAME, ReplicasAction.NAME }); assertNextActionName("cold", AllocateAction.NAME, null, new String[] { AllocateAction.NAME }); - assertNextActionName("cold", AllocateAction.NAME, ReplicasAction.NAME, new String[] { ReplicasAction.NAME }); assertNextActionName("cold", AllocateAction.NAME, null, new String[] {}); - assertNextActionName("cold", ReplicasAction.NAME, null, new String[] { AllocateAction.NAME, ReplicasAction.NAME }); assertNextActionName("cold", AllocateAction.NAME, null, new String[] {}); - assertInvalidAction("cold", "foo", new String[] { AllocateAction.NAME, ReplicasAction.NAME }); - assertInvalidAction("cold", DeleteAction.NAME, new String[] { AllocateAction.NAME, ReplicasAction.NAME }); - assertInvalidAction("cold", ForceMergeAction.NAME, new String[] { AllocateAction.NAME, ReplicasAction.NAME }); - assertInvalidAction("cold", ReadOnlyAction.NAME, new String[] { AllocateAction.NAME, ReplicasAction.NAME }); - assertInvalidAction("cold", RolloverAction.NAME, new String[] { AllocateAction.NAME, ReplicasAction.NAME }); - assertInvalidAction("cold", ShrinkAction.NAME, new String[] { AllocateAction.NAME, ReplicasAction.NAME }); + assertInvalidAction("cold", "foo", new String[] { AllocateAction.NAME }); + assertInvalidAction("cold", DeleteAction.NAME, new String[] { AllocateAction.NAME }); + assertInvalidAction("cold", ForceMergeAction.NAME, new String[] { AllocateAction.NAME }); + assertInvalidAction("cold", ReadOnlyAction.NAME, new String[] { AllocateAction.NAME }); + assertInvalidAction("cold", RolloverAction.NAME, new String[] { AllocateAction.NAME }); + assertInvalidAction("cold", ShrinkAction.NAME, new String[] { AllocateAction.NAME }); // Delete Phase assertNextActionName("delete", DeleteAction.NAME, null, new String[] {}); @@ -397,7 +374,6 @@ public class TimeseriesLifecycleTypeTests extends ESTestCase { assertInvalidAction("delete", AllocateAction.NAME, new String[] { DeleteAction.NAME }); assertInvalidAction("delete", ForceMergeAction.NAME, new String[] { DeleteAction.NAME }); assertInvalidAction("delete", ReadOnlyAction.NAME, new String[] { DeleteAction.NAME }); - assertInvalidAction("delete", ReplicasAction.NAME, new String[] { DeleteAction.NAME }); assertInvalidAction("delete", RolloverAction.NAME, new String[] { DeleteAction.NAME }); assertInvalidAction("delete", ShrinkAction.NAME, new String[] { DeleteAction.NAME }); @@ -428,15 +404,13 @@ public class TimeseriesLifecycleTypeTests extends ESTestCase { return Arrays.asList(availableActionNames).stream().map(n -> { switch (n) { case AllocateAction.NAME: - return new AllocateAction(Collections.singletonMap("foo", "bar"), Collections.emptyMap(), Collections.emptyMap()); + return new AllocateAction(null, Collections.singletonMap("foo", "bar"), Collections.emptyMap(), Collections.emptyMap()); case DeleteAction.NAME: return new DeleteAction(); case ForceMergeAction.NAME: return new ForceMergeAction(1); case ReadOnlyAction.NAME: return new ReadOnlyAction(); - case ReplicasAction.NAME: - return new ReplicasAction(1); case RolloverAction.NAME: return new RolloverAction(ByteSizeValue.parseBytesSizeValue("0b", "test"), TimeValue.ZERO, 1L); case ShrinkAction.NAME: @@ -498,8 +472,6 @@ public class TimeseriesLifecycleTypeTests extends ESTestCase { return TEST_FORCE_MERGE_ACTION; case ReadOnlyAction.NAME: return TEST_READ_ONLY_ACTION; - case ReplicasAction.NAME: - return TEST_REPLICAS_ACTION; case RolloverAction.NAME: return TEST_ROLLOVER_ACTION; case ShrinkAction.NAME: 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 fce7f0a2479..dde30ca54e7 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 @@ -24,7 +24,6 @@ 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.ReadOnlyAction; -import org.elasticsearch.xpack.core.indexlifecycle.ReplicasAction; import org.elasticsearch.xpack.core.indexlifecycle.ShrinkAction; import org.elasticsearch.xpack.core.indexlifecycle.Step.StepKey; import org.elasticsearch.xpack.core.indexlifecycle.TerminalPolicyStep; @@ -69,11 +68,11 @@ public class TimeSeriesLifecycleActionsIT extends ESRestTestCase { client().performRequest(request); } - public void testAllocate() throws Exception { + public void testAllocateOnlyAllocation() throws Exception { createIndexWithSettings(index, Settings.builder().put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, 2) .put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, 0)); String allocateNodeName = "node-" + randomFrom(0, 1); - AllocateAction allocateAction = new AllocateAction(null, null, singletonMap("_name", allocateNodeName)); + AllocateAction allocateAction = new AllocateAction(null, null, null, singletonMap("_name", allocateNodeName)); createNewSingletonPolicy(randomFrom("warm", "cold"), allocateAction); updatePolicy(index, policy); assertBusy(() -> { @@ -83,6 +82,22 @@ public class TimeSeriesLifecycleActionsIT extends ESRestTestCase { ensureGreen(index); } + public void testAllocateActionOnlyReplicas() throws Exception { + int numShards = randomFrom(1, 5); + int numReplicas = randomFrom(0, 1); + int finalNumReplicas = (numReplicas + 1) % 2; + createIndexWithSettings(index, Settings.builder().put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, numShards) + .put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, numReplicas)); + AllocateAction allocateAction = new AllocateAction(finalNumReplicas, null, null, null); + createNewSingletonPolicy(randomFrom("warm", "cold"), allocateAction); + updatePolicy(index, policy); + assertBusy(() -> { + Map settings = getOnlyIndexSettings(index); + assertThat(getStepKey(settings), equalTo(TerminalPolicyStep.KEY)); + assertThat(settings.get(IndexMetaData.INDEX_NUMBER_OF_REPLICAS_SETTING.getKey()), equalTo(String.valueOf(finalNumReplicas))); + }); + } + public void testDelete() throws Exception { createIndexWithSettings(index, Settings.builder().put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, 1) .put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, 0)); @@ -137,22 +152,6 @@ public class TimeSeriesLifecycleActionsIT extends ESRestTestCase { }); } - public void testReplicasAction() throws Exception { - int numShards = randomFrom(1, 5); - int numReplicas = randomFrom(0, 1); - int finalNumReplicas = (numReplicas + 1) % 2; - createIndexWithSettings(index, Settings.builder().put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, numShards) - .put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, numReplicas)); - createNewSingletonPolicy(randomFrom("warm", "cold"), new ReplicasAction(finalNumReplicas)); - updatePolicy(index, policy); - - assertBusy(() -> { - Map settings = getOnlyIndexSettings(index); - assertThat(getStepKey(settings), equalTo(TerminalPolicyStep.KEY)); - assertThat(settings.get(IndexMetaData.INDEX_NUMBER_OF_REPLICAS_SETTING.getKey()), equalTo(String.valueOf(finalNumReplicas))); - }); - } - public void testShrinkAction() throws Exception { int numShards = 6; int divisor = randomFrom(2, 3, 6);