diff --git a/x-pack/plugin/src/main/java/org/elasticsearch/xpack/indexlifecycle/IndexLifecycle.java b/x-pack/plugin/src/main/java/org/elasticsearch/xpack/indexlifecycle/IndexLifecycle.java index 98f618bbad6..0647051359a 100644 --- a/x-pack/plugin/src/main/java/org/elasticsearch/xpack/indexlifecycle/IndexLifecycle.java +++ b/x-pack/plugin/src/main/java/org/elasticsearch/xpack/indexlifecycle/IndexLifecycle.java @@ -119,9 +119,9 @@ public class IndexLifecycle extends Plugin { new NamedWriteableRegistry.Entry(NamedDiff.class, IndexLifecycleMetadata.TYPE, IndexLifecycleMetadata.IndexLifecycleMetadataDiff::new), - // Lifecycle policies - new NamedWriteableRegistry.Entry(LifecyclePolicy.class, TimeseriesLifecyclePolicy.TYPE, - TimeseriesLifecyclePolicy::new), + // Lifecycle types + new NamedWriteableRegistry.Entry(LifecycleType.class, TimeseriesLifecycleType.TYPE, + (in) -> TimeseriesLifecycleType.INSTANCE), // Lifecycle actions new NamedWriteableRegistry.Entry(LifecycleAction.class, AllocateAction.NAME, AllocateAction::new), @@ -138,9 +138,9 @@ public class IndexLifecycle extends Plugin { // Custom metadata new NamedXContentRegistry.Entry(MetaData.Custom.class, new ParseField(IndexLifecycleMetadata.TYPE), parser -> IndexLifecycleMetadata.PARSER.parse(parser, null)), - // Lifecycle Policy - new NamedXContentRegistry.Entry(LifecyclePolicy.class, new ParseField(TimeseriesLifecyclePolicy.TYPE), - (p, c) -> TimeseriesLifecyclePolicy.parse(p, c)), + // Lifecycle Types + new NamedXContentRegistry.Entry(LifecycleType.class, new ParseField(TimeseriesLifecycleType.TYPE), + (p, c) -> TimeseriesLifecycleType.INSTANCE), // Lifecycle actions new NamedXContentRegistry.Entry(LifecycleAction.class, new ParseField(AllocateAction.NAME), AllocateAction::parse), new NamedXContentRegistry.Entry(LifecycleAction.class, new ParseField(ForceMergeAction.NAME), ForceMergeAction::parse), diff --git a/x-pack/plugin/src/main/java/org/elasticsearch/xpack/indexlifecycle/IndexLifecycleMetadata.java b/x-pack/plugin/src/main/java/org/elasticsearch/xpack/indexlifecycle/IndexLifecycleMetadata.java index 583994651bc..384e2695b02 100644 --- a/x-pack/plugin/src/main/java/org/elasticsearch/xpack/indexlifecycle/IndexLifecycleMetadata.java +++ b/x-pack/plugin/src/main/java/org/elasticsearch/xpack/indexlifecycle/IndexLifecycleMetadata.java @@ -38,7 +38,7 @@ public class IndexLifecycleMetadata implements MetaData.Custom { @SuppressWarnings("unchecked") public static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>( TYPE, a -> new IndexLifecycleMetadata( - ObjectParserUtils.convertListToMapValues(LifecyclePolicy::getName, (List) a[0]))); + ObjectParserUtils.convertListToMapValues(LifecyclePolicy::getName, (List) a[0]))); static { PARSER.declareNamedObjects(ConstructingObjectParser.constructorArg(), (p, c, n) -> LifecyclePolicy.parse(p, new Tuple<>(n, c)), v -> { @@ -56,7 +56,7 @@ public class IndexLifecycleMetadata implements MetaData.Custom { int size = in.readVInt(); TreeMap policies = new TreeMap<>(); for (int i = 0; i < size; i++) { - policies.put(in.readString(), in.readNamedWriteable(LifecyclePolicy.class)); + policies.put(in.readString(), new LifecyclePolicy(in)); } this.policies = policies; } @@ -66,7 +66,7 @@ public class IndexLifecycleMetadata implements MetaData.Custom { out.writeVInt(policies.size()); for (Map.Entry entry : policies.entrySet()) { out.writeString(entry.getKey()); - out.writeNamedWriteable(entry.getValue()); + entry.getValue().writeTo(out); } } @@ -127,44 +127,12 @@ public class IndexLifecycleMetadata implements MetaData.Custom { final Diff> policies; IndexLifecycleMetadataDiff(IndexLifecycleMetadata before, IndexLifecycleMetadata after) { - this.policies = DiffableUtils.diff(before.policies, after.policies, DiffableUtils.getStringKeySerializer(), - new DiffableUtils.ValueSerializer() { - @Override - public void write(LifecyclePolicy value, StreamOutput out) throws IOException { - out.writeNamedWriteable(value); - } - - @Override - public LifecyclePolicy read(StreamInput in, String key) throws IOException { - throw new UnsupportedOperationException(); - } - - @Override - public Diff readDiff(StreamInput in, String key) throws IOException { - throw new UnsupportedOperationException(); - } - - @Override - public boolean supportsDiffableValues() { - return true; - } - - @Override - public Diff diff(LifecyclePolicy value, LifecyclePolicy beforePart) { - return value.diff(beforePart); - } - - @Override - public void writeDiff(Diff value, StreamOutput out) throws IOException { - value.writeTo(out); - } - - }); + this.policies = DiffableUtils.diff(before.policies, after.policies, DiffableUtils.getStringKeySerializer()); } public IndexLifecycleMetadataDiff(StreamInput in) throws IOException { - this.policies = DiffableUtils.readJdkMapDiff(in, DiffableUtils.getStringKeySerializer(), - (i) -> i.readNamedWriteable(LifecyclePolicy.class), IndexLifecycleMetadataDiff::readLifecyclePolicyDiffFrom); + this.policies = DiffableUtils.readJdkMapDiff(in, DiffableUtils.getStringKeySerializer(), LifecyclePolicy::new, + IndexLifecycleMetadataDiff::readLifecyclePolicyDiffFrom); } @Override @@ -184,7 +152,7 @@ public class IndexLifecycleMetadata implements MetaData.Custom { } static Diff readLifecyclePolicyDiffFrom(StreamInput in) throws IOException { - return AbstractDiffable.readDiffFrom((i) -> i.readNamedWriteable(LifecyclePolicy.class), in); + return AbstractDiffable.readDiffFrom(LifecyclePolicy::new, in); } } } diff --git a/x-pack/plugin/src/main/java/org/elasticsearch/xpack/indexlifecycle/LifecyclePolicy.java b/x-pack/plugin/src/main/java/org/elasticsearch/xpack/indexlifecycle/LifecyclePolicy.java index 15a58afe97d..6493b318fdd 100644 --- a/x-pack/plugin/src/main/java/org/elasticsearch/xpack/indexlifecycle/LifecyclePolicy.java +++ b/x-pack/plugin/src/main/java/org/elasticsearch/xpack/indexlifecycle/LifecyclePolicy.java @@ -7,8 +7,7 @@ package org.elasticsearch.xpack.indexlifecycle; import org.apache.logging.log4j.Logger; import org.elasticsearch.cluster.AbstractDiffable; -import org.elasticsearch.cluster.NamedDiffable; -import org.elasticsearch.common.Nullable; +import org.elasticsearch.cluster.Diffable; import org.elasticsearch.common.ParseField; import org.elasticsearch.common.Strings; import org.elasticsearch.common.collect.Tuple; @@ -17,13 +16,13 @@ import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.logging.ESLoggerFactory; import org.elasticsearch.common.xcontent.ConstructingObjectParser; import org.elasticsearch.common.xcontent.NamedXContentRegistry; +import org.elasticsearch.common.xcontent.ObjectParser.ValueType; import org.elasticsearch.common.xcontent.ToXContentObject; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentParser; import org.elasticsearch.xpack.indexlifecycle.IndexLifecycleContext.Listener; import java.io.IOException; -import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; @@ -41,14 +40,32 @@ import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constru * dictate the order in which the {@link Phase}s are executed and will define * which {@link LifecycleAction}s are allowed in each phase. */ -public abstract class LifecyclePolicy extends AbstractDiffable - implements ToXContentObject, NamedDiffable { +public class LifecyclePolicy extends AbstractDiffable + implements ToXContentObject, Diffable { private static final Logger logger = ESLoggerFactory.getLogger(LifecyclePolicy.class); public static final ParseField PHASES_FIELD = new ParseField("phases"); public static final ParseField TYPE_FIELD = new ParseField("type"); + @SuppressWarnings("unchecked") + public static ConstructingObjectParser> PARSER = new ConstructingObjectParser<>( + "lifecycle_policy", false, (a, c) -> { + String name = c.v1(); + LifecycleType type = (LifecycleType) a[0]; + List phases = (List) a[1]; + Map phaseMap = phases.stream().collect(Collectors.toMap(Phase::getName, Function.identity())); + return new LifecyclePolicy(type, name, phaseMap); + }); + static { + PARSER.declareField(constructorArg(), (p, c) -> c.v2().parseNamedObject(LifecycleType.class, p.text(), p, null), TYPE_FIELD, + ValueType.STRING); + PARSER.declareNamedObjects(constructorArg(), (p, c, n) -> Phase.parse(p, new Tuple<>(n, c.v2())), v -> { + throw new IllegalArgumentException("ordered " + PHASES_FIELD.getPreferredName() + " are not supported"); + }, PHASES_FIELD); + } + protected final String name; + protected final LifecycleType type; protected final Map phases; /** @@ -58,35 +75,33 @@ public abstract class LifecyclePolicy extends AbstractDiffable * a {@link Map} of {@link Phase}s which make up this * {@link LifecyclePolicy}. */ - public LifecyclePolicy(String name, Map phases) { + public LifecyclePolicy(LifecycleType type, String name, Map phases) { + this.type = type; this.name = name; this.phases = phases; - validate(phases.values()); + type.validate(phases.values()); } /** * For Serialization */ public LifecyclePolicy(StreamInput in) throws IOException { + type = in.readNamedWriteable(LifecycleType.class); name = in.readString(); phases = Collections.unmodifiableMap(in.readMap(StreamInput::readString, Phase::new)); } public static LifecyclePolicy parse(XContentParser parser, Tuple context) { - return ToXContentContext.PARSER.apply(parser, context); + return PARSER.apply(parser, context); } @Override public void writeTo(StreamOutput out) throws IOException { + out.writeNamedWriteable(type); out.writeString(name); out.writeMap(phases, StreamOutput::writeString, (o, val) -> val.writeTo(o)); } - @Override - public String getWriteableName() { - return getType(); - } - /** * @return the name of this {@link LifecyclePolicy} */ @@ -105,7 +120,7 @@ public abstract class LifecyclePolicy extends AbstractDiffable @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { builder.startObject(); - builder.field(TYPE_FIELD.getPreferredName(), getType()); + builder.field(TYPE_FIELD.getPreferredName(), type.getType()); builder.startObject(PHASES_FIELD.getPreferredName()); for (Phase phase : phases.values()) { builder.field(phase.getName(), phase); @@ -128,7 +143,7 @@ public abstract class LifecyclePolicy extends AbstractDiffable String indexName = context.getLifecycleTarget(); Phase currentPhase = phases.get(currentPhaseName); if (Strings.isNullOrEmpty(currentPhaseName) || currentPhaseActionsComplete) { - Phase nextPhase = nextPhase(currentPhase); + Phase nextPhase = type.nextPhase(phases, currentPhase); // We only want to execute the phase if the conditions for executing are met (e.g. the index is old enough) if (nextPhase != null && context.canExecute(nextPhase)) { String nextPhaseName = nextPhase.getName(); @@ -139,7 +154,7 @@ public abstract class LifecyclePolicy extends AbstractDiffable public void onSuccess() { logger.info("Successfully initialised phase [" + nextPhaseName + "] for index [" + indexName + "]"); // We might as well execute the phase now rather than waiting for execute to be called again - nextPhase.execute(context, getActionProvider(context, nextPhase)); + nextPhase.execute(context, type.getActionProvider(context, nextPhase)); } @Override @@ -154,7 +169,7 @@ public abstract class LifecyclePolicy extends AbstractDiffable throw new IllegalStateException("Current phase [" + currentPhaseName + "] not found in lifecycle [" + getName() + "] for index [" + indexName + "]"); } else { - currentPhase.execute(context, getActionProvider(context, currentPhase)); + currentPhase.execute(context, type.getActionProvider(context, currentPhase)); } } } @@ -183,100 +198,23 @@ public abstract class LifecyclePolicy extends AbstractDiffable } /** - * @return the first phase of this policy to execute - */ - protected abstract Phase getFirstPhase(); - - /** - * @param currentPhase the current phase that is or was just executed - * @return the next phase after currentPhase to be execute. If it is `null`, the first - * phase to be executed is returned. If it is the last phase, then no next phase is to be - * executed and `null` is returned. - */ - protected abstract Phase nextPhase(@Nullable Phase currentPhase); - - /** - * validates whether the specified phases are valid for this policy instance. - * @param phases the phases to verify validity against - * @throws IllegalArgumentException if a specific phase or lack of a specific phase is invalid. - */ - protected abstract void validate(Collection phases); - - /** - * Each {@link LifecyclePolicy} has a specific type to differentiate themselves. Every implementation - * is responsible to providing its specific type. - * @return the {@link LifecyclePolicy} type. - */ - protected abstract String getType(); - - /** - * @param context the index lifecycle context for this phase at the time of execution - * @param phase the current phase for which to provide an action provider - * @return the action provider - */ - protected abstract NextActionProvider getActionProvider(IndexLifecycleContext context, Phase phase); - - /** - * Reference to a method that determines which {@link LifecycleAction} to execute next after - * a specific action. + * Reference to a method that determines which {@link LifecycleAction} to + * execute next after a specific action. * *

- * Concrete {@link LifecyclePolicy} classes will implement this to help determine their specific - * ordering of actions for the phases they allow. + * Concrete {@link LifecyclePolicy} classes will implement this to help + * determine their specific ordering of actions for the phases they allow. */ @FunctionalInterface interface NextActionProvider { /** - * @param current The current action which is being or was executed + * @param current + * The current action which is being or was executed * @return the action following {@code current} to execute */ LifecycleAction next(LifecycleAction current); } - /** - * This class is here to assist in creating a context from which the specific LifecyclePolicy sub-classes can inherit - * all the previously parsed values - */ - public static class ToXContentContext { - private final Map phases; - private final String name; - - @SuppressWarnings("unchecked") - public static ConstructingObjectParser> PARSER = - new ConstructingObjectParser<>("lifecycle_policy", false, (a, c) -> { - String lifecycleType = (String) a[0]; - List phases = (List) a[1]; - Map phaseMap = phases.stream().collect(Collectors.toMap(Phase::getName, Function.identity())); - NamedXContentRegistry registry = c.v2(); - ToXContentContext factory = new ToXContentContext(c.v1(), phaseMap); - try { - return registry.parseNamedObject(LifecyclePolicy.class, lifecycleType, null, factory); - } catch (IOException e) { - throw new IllegalArgumentException(e); - } - }); - static { - PARSER.declareString(constructorArg(), TYPE_FIELD); - PARSER.declareNamedObjects(constructorArg(), (p, c, n) -> Phase.parse(p, new Tuple<>(n, c.v2())), - v -> { - throw new IllegalArgumentException("ordered " + PHASES_FIELD.getPreferredName() + " are not supported"); - }, PHASES_FIELD); - } - - ToXContentContext(String name, Map phases) { - this.name = name; - this.phases = phases; - } - - public String getName() { - return name; - } - - public Map getPhases() { - return phases; - } - } - } diff --git a/x-pack/plugin/src/main/java/org/elasticsearch/xpack/indexlifecycle/LifecycleType.java b/x-pack/plugin/src/main/java/org/elasticsearch/xpack/indexlifecycle/LifecycleType.java new file mode 100644 index 00000000000..fad0ef0b1ce --- /dev/null +++ b/x-pack/plugin/src/main/java/org/elasticsearch/xpack/indexlifecycle/LifecycleType.java @@ -0,0 +1,61 @@ +/* + * 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.indexlifecycle; + +import org.elasticsearch.common.Nullable; +import org.elasticsearch.common.io.stream.NamedWriteable; +import org.elasticsearch.xpack.indexlifecycle.LifecyclePolicy.NextActionProvider; + +import java.util.Collection; +import java.util.Map; + +public interface LifecycleType extends NamedWriteable { + + /** + * @return the first phase of this policy to execute + */ + Phase getFirstPhase(Map phases); + + /** + * @param currentPhase + * the current phase that is or was just executed + * @return the next phase after currentPhase to be execute. If + * it is `null`, the first phase to be executed is returned. If it + * is the last phase, then no next phase is to be executed and + * `null` is returned. + */ + Phase nextPhase(Map phases, @Nullable Phase currentPhase); + + /** + * validates whether the specified phases are valid for this + * policy instance. + * + * @param phases + * the phases to verify validity against + * @throws IllegalArgumentException + * if a specific phase or lack of a specific phase is invalid. + */ + void validate(Collection phases); + + /** + * Each {@link LifecyclePolicy} has a specific type to differentiate + * themselves. Every implementation is responsible to providing its specific + * type. + * + * @return the {@link LifecyclePolicy} type. + */ + String getType(); + + /** + * @param context + * the index lifecycle context for this phase at the time of + * execution + * @param phase + * the current phase for which to provide an action provider + * @return the action provider + */ + NextActionProvider getActionProvider(IndexLifecycleContext context, Phase phase); +} diff --git a/x-pack/plugin/src/main/java/org/elasticsearch/xpack/indexlifecycle/ObjectParserUtils.java b/x-pack/plugin/src/main/java/org/elasticsearch/xpack/indexlifecycle/ObjectParserUtils.java index 7f31b3af4d8..be8bd323145 100644 --- a/x-pack/plugin/src/main/java/org/elasticsearch/xpack/indexlifecycle/ObjectParserUtils.java +++ b/x-pack/plugin/src/main/java/org/elasticsearch/xpack/indexlifecycle/ObjectParserUtils.java @@ -5,7 +5,7 @@ */ package org.elasticsearch.xpack.indexlifecycle; -import org.elasticsearch.common.io.stream.NamedWriteable; +import org.elasticsearch.common.io.stream.Writeable; import java.util.List; import java.util.SortedMap; @@ -17,11 +17,11 @@ import java.util.function.Function; * parsing namedWriteables */ public class ObjectParserUtils { - public static SortedMap convertListToMapValues(Function keyFunction, + public static SortedMap convertListToMapValues(Function keyFunction, List list) { SortedMap map = new TreeMap<>(); - for (V namedWriteable : list) { - map.put(keyFunction.apply(namedWriteable), namedWriteable); + for (V writeable : list) { + map.put(keyFunction.apply(writeable), writeable); } return map; } diff --git a/x-pack/plugin/src/main/java/org/elasticsearch/xpack/indexlifecycle/TimeseriesLifecyclePolicy.java b/x-pack/plugin/src/main/java/org/elasticsearch/xpack/indexlifecycle/TimeseriesLifecycleType.java similarity index 87% rename from x-pack/plugin/src/main/java/org/elasticsearch/xpack/indexlifecycle/TimeseriesLifecyclePolicy.java rename to x-pack/plugin/src/main/java/org/elasticsearch/xpack/indexlifecycle/TimeseriesLifecycleType.java index 6693d1f3f57..5a242db9c54 100644 --- a/x-pack/plugin/src/main/java/org/elasticsearch/xpack/indexlifecycle/TimeseriesLifecyclePolicy.java +++ b/x-pack/plugin/src/main/java/org/elasticsearch/xpack/indexlifecycle/TimeseriesLifecycleType.java @@ -6,9 +6,9 @@ package org.elasticsearch.xpack.indexlifecycle; import org.elasticsearch.common.Nullable; -import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.util.set.Sets; -import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.xpack.indexlifecycle.LifecyclePolicy.NextActionProvider; import java.io.IOException; import java.util.Arrays; @@ -23,13 +23,15 @@ import java.util.stream.Stream; /** * Represents the lifecycle of an index from creation to deletion. A - * {@link TimeseriesLifecyclePolicy} is made up of a set of {@link Phase}s which it will + * {@link TimeseriesLifecycleType} is made up of a set of {@link Phase}s which it will * move through. Soon we will constrain the phases using some kinda of lifecycle * type which will allow only particular {@link Phase}s to be defined, will * dictate the order in which the {@link Phase}s are executed and will define * which {@link LifecycleAction}s are allowed in each phase. */ -public class TimeseriesLifecyclePolicy extends LifecyclePolicy { +public class TimeseriesLifecycleType implements LifecycleType { + public static final TimeseriesLifecycleType INSTANCE = new TimeseriesLifecycleType(); + public static final String TYPE = "timeseries"; static final List VALID_PHASES = Arrays.asList("hot", "warm", "cold", "delete"); static final Set VALID_HOT_ACTIONS = Sets.newHashSet(RolloverAction.NAME); @@ -38,36 +40,25 @@ public class TimeseriesLifecyclePolicy extends LifecyclePolicy { static final Set VALID_COLD_ACTIONS = Sets.newHashSet(AllocateAction.NAME, ReplicasAction.NAME); static final Set VALID_DELETE_ACTIONS = Sets.newHashSet(DeleteAction.NAME); - /** - * @param name - * the name of this {@link TimeseriesLifecyclePolicy} - * @param phases - * a {@link Map} of {@link Phase}s which make up this - * {@link TimeseriesLifecyclePolicy}. - */ - public TimeseriesLifecyclePolicy(String name, Map phases) { - super(name, phases); - } - - /** - * For Serialization - */ - public TimeseriesLifecyclePolicy(StreamInput in) throws IOException { - super(in); - } - - public static TimeseriesLifecyclePolicy parse(XContentParser parser, Object context) { - ToXContentContext factory = (ToXContentContext) context; - return new TimeseriesLifecyclePolicy(factory.getName(), factory.getPhases()); + private TimeseriesLifecycleType() { } @Override - protected String getType() { + public void writeTo(StreamOutput out) throws IOException { + } + + @Override + public String getType() { return TYPE; } @Override - protected Phase getFirstPhase() { + public String getWriteableName() { + return TYPE; + } + + @Override + public Phase getFirstPhase(Map phases) { Phase firstPhase = phases.get("hot"); if (firstPhase == null) { firstPhase = phases.get("warm"); @@ -82,9 +73,9 @@ public class TimeseriesLifecyclePolicy extends LifecyclePolicy { } @Override - protected Phase nextPhase(@Nullable Phase currentPhase) { + public Phase nextPhase(Map phases, @Nullable Phase currentPhase) { if (currentPhase == null) { - return getFirstPhase(); + return getFirstPhase(phases); } // VALID_PHASES is in order of execution @@ -124,7 +115,7 @@ public class TimeseriesLifecyclePolicy extends LifecyclePolicy { * @return the {@link org.elasticsearch.xpack.indexlifecycle.LifecyclePolicy.NextActionProvider} for {@code phase}. */ @Override - protected NextActionProvider getActionProvider(IndexLifecycleContext context, Phase phase) { + public NextActionProvider getActionProvider(IndexLifecycleContext context, Phase phase) { Map actions = phase.getActions(); switch (phase.getName()) { case "hot": diff --git a/x-pack/plugin/src/main/java/org/elasticsearch/xpack/indexlifecycle/action/GetLifecycleAction.java b/x-pack/plugin/src/main/java/org/elasticsearch/xpack/indexlifecycle/action/GetLifecycleAction.java index 4bd03e22dc7..1b4d71c2c85 100644 --- a/x-pack/plugin/src/main/java/org/elasticsearch/xpack/indexlifecycle/action/GetLifecycleAction.java +++ b/x-pack/plugin/src/main/java/org/elasticsearch/xpack/indexlifecycle/action/GetLifecycleAction.java @@ -86,12 +86,12 @@ public class GetLifecycleAction @Override public void readFrom(StreamInput in) throws IOException { - policy = in.readNamedWriteable(LifecyclePolicy.class); + policy = new LifecyclePolicy(in); } @Override public void writeTo(StreamOutput out) throws IOException { - out.writeNamedWriteable(policy); + policy.writeTo(out); } @Override diff --git a/x-pack/plugin/src/main/java/org/elasticsearch/xpack/indexlifecycle/action/PutLifecycleAction.java b/x-pack/plugin/src/main/java/org/elasticsearch/xpack/indexlifecycle/action/PutLifecycleAction.java index 810625ff8a9..689efd014b7 100644 --- a/x-pack/plugin/src/main/java/org/elasticsearch/xpack/indexlifecycle/action/PutLifecycleAction.java +++ b/x-pack/plugin/src/main/java/org/elasticsearch/xpack/indexlifecycle/action/PutLifecycleAction.java @@ -163,13 +163,13 @@ public class PutLifecycleAction extends Action deletePhaseActions = Collections.singletonMap(DeleteAction.NAME, new DeleteAction()); Map phases = Collections.singletonMap("delete", new Phase("delete", TimeValue.timeValueSeconds(3), deletePhaseActions)); - lifecyclePolicy = new TimeseriesLifecyclePolicy("test", phases); + lifecyclePolicy = new LifecyclePolicy(TimeseriesLifecycleType.INSTANCE, "test", phases); } public void testSingleNodeCluster() throws Exception { diff --git a/x-pack/plugin/src/test/java/org/elasticsearch/xpack/indexlifecycle/IndexLifecycleMetadataTests.java b/x-pack/plugin/src/test/java/org/elasticsearch/xpack/indexlifecycle/IndexLifecycleMetadataTests.java index 3c19e8c763f..9adbabec905 100644 --- a/x-pack/plugin/src/test/java/org/elasticsearch/xpack/indexlifecycle/IndexLifecycleMetadataTests.java +++ b/x-pack/plugin/src/test/java/org/elasticsearch/xpack/indexlifecycle/IndexLifecycleMetadataTests.java @@ -20,9 +20,9 @@ import org.elasticsearch.xpack.indexlifecycle.IndexLifecycleMetadata.IndexLifecy import org.junit.Before; import java.io.IOException; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.SortedMap; @@ -35,8 +35,9 @@ public class IndexLifecycleMetadataTests extends AbstractDiffableSerializationTe @Before public void setup() { List entries = Arrays - .asList(new NamedXContentRegistry.Entry(LifecycleAction.class, new ParseField(DeleteAction.NAME), DeleteAction::parse), - new NamedXContentRegistry.Entry(LifecyclePolicy.class, new ParseField("test"), TestLifecyclePolicy::parse)); + .asList(new NamedXContentRegistry.Entry(LifecycleAction.class, new ParseField(DeleteAction.NAME), DeleteAction::parse), + new NamedXContentRegistry.Entry(LifecycleType.class, new ParseField(TestLifecycleType.TYPE), + (p) -> TestLifecycleType.INSTANCE)); registry = new NamedXContentRegistry(entries); } @@ -46,17 +47,18 @@ public class IndexLifecycleMetadataTests extends AbstractDiffableSerializationTe SortedMap policies = new TreeMap<>(); for (int i = 0; i < numPolicies; i++) { int numberPhases = randomInt(5); - List phases = new ArrayList<>(numberPhases); + Map phases = new HashMap<>(numberPhases); for (int j = 0; j < numberPhases; j++) { TimeValue after = TimeValue.parseTimeValue(randomTimeValue(0, 1000000000, "s", "m", "h", "d"), "test_after"); Map actions = Collections.emptyMap(); if (randomBoolean()) { actions = Collections.singletonMap(DeleteAction.NAME, new DeleteAction()); } - phases.add(new Phase(randomAlphaOfLength(10), after, actions)); + String phaseName = randomAlphaOfLength(10); + phases.put(phaseName, new Phase(phaseName, after, actions)); } String policyName = randomAlphaOfLength(10); - policies.put(policyName, new TestLifecyclePolicy(policyName, phases)); + policies.put(policyName, new LifecyclePolicy(TestLifecycleType.INSTANCE, policyName, phases)); } return new IndexLifecycleMetadata(policies); } @@ -75,8 +77,7 @@ public class IndexLifecycleMetadataTests extends AbstractDiffableSerializationTe protected NamedWriteableRegistry getNamedWriteableRegistry() { return new NamedWriteableRegistry( Arrays.asList(new NamedWriteableRegistry.Entry(LifecycleAction.class, DeleteAction.NAME, DeleteAction::new), - new NamedWriteableRegistry.Entry(LifecyclePolicy.class, TestLifecyclePolicy.TYPE, - TestLifecyclePolicy::new))); + new NamedWriteableRegistry.Entry(LifecycleType.class, TestLifecycleType.TYPE, (in) -> TestLifecycleType.INSTANCE))); } @Override @@ -85,7 +86,7 @@ public class IndexLifecycleMetadataTests extends AbstractDiffableSerializationTe SortedMap policies = metadata.getPolicies(); policies = new TreeMap<>(policies); String policyName = randomAlphaOfLength(10); - policies.put(policyName, new TestLifecyclePolicy(policyName, Collections.emptyList())); + policies.put(policyName, new LifecyclePolicy(TestLifecycleType.INSTANCE, policyName, Collections.emptyMap())); return new IndexLifecycleMetadata(policies); } diff --git a/x-pack/plugin/src/test/java/org/elasticsearch/xpack/indexlifecycle/IndexLifecycleServiceTests.java b/x-pack/plugin/src/test/java/org/elasticsearch/xpack/indexlifecycle/IndexLifecycleServiceTests.java index 040d2564443..941d1acd446 100644 --- a/x-pack/plugin/src/test/java/org/elasticsearch/xpack/indexlifecycle/IndexLifecycleServiceTests.java +++ b/x-pack/plugin/src/test/java/org/elasticsearch/xpack/indexlifecycle/IndexLifecycleServiceTests.java @@ -8,10 +8,8 @@ package org.elasticsearch.xpack.indexlifecycle; import org.apache.lucene.util.SetOnce; import org.elasticsearch.Version; import org.elasticsearch.action.ActionListener; -import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsAction; import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsResponse; import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsTestHelper; -import org.elasticsearch.action.support.master.AcknowledgedResponse; import org.elasticsearch.client.AdminClient; import org.elasticsearch.client.Client; import org.elasticsearch.client.IndicesAdminClient; @@ -25,7 +23,6 @@ import org.elasticsearch.cluster.node.DiscoveryNode; import org.elasticsearch.cluster.node.DiscoveryNodes; import org.elasticsearch.cluster.service.ClusterService; import org.elasticsearch.common.collect.ImmutableOpenMap; -import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.transport.TransportAddress; import org.elasticsearch.common.unit.TimeValue; @@ -48,8 +45,8 @@ import java.util.concurrent.ExecutorService; import static org.elasticsearch.node.Node.NODE_MASTER_SETTING; import static org.hamcrest.Matchers.equalTo; -import static org.mockito.Mockito.anyString; -import static org.mockito.Mockito.any; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; @@ -201,7 +198,8 @@ public class IndexLifecycleServiceTests extends ESTestCase { String policyName = randomAlphaOfLengthBetween(1, 20); MockAction mockAction = new MockAction(); Phase phase = new Phase("phase", TimeValue.ZERO, Collections.singletonMap("action", mockAction)); - LifecyclePolicy policy = new TestLifecyclePolicy(policyName, Collections.singletonList(phase)); + LifecyclePolicy policy = new LifecyclePolicy(TestLifecycleType.INSTANCE, policyName, + Collections.singletonMap(phase.getName(), phase)); SortedMap policyMap = new TreeMap<>(); policyMap.put(policyName, policy); Index index = new Index(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20)); diff --git a/x-pack/plugin/src/test/java/org/elasticsearch/xpack/indexlifecycle/LifecyclePolicyTests.java b/x-pack/plugin/src/test/java/org/elasticsearch/xpack/indexlifecycle/LifecyclePolicyTests.java index 77b18d251ef..c3872c7b594 100644 --- a/x-pack/plugin/src/test/java/org/elasticsearch/xpack/indexlifecycle/LifecyclePolicyTests.java +++ b/x-pack/plugin/src/test/java/org/elasticsearch/xpack/indexlifecycle/LifecyclePolicyTests.java @@ -5,16 +5,25 @@ */ package org.elasticsearch.xpack.indexlifecycle; +import org.elasticsearch.common.ParseField; +import org.elasticsearch.common.collect.Tuple; +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.Writeable.Reader; import org.elasticsearch.common.unit.TimeValue; -import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.common.xcontent.NamedXContentRegistry; +import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.test.AbstractSerializingTestCase; import org.junit.Before; -import java.util.ArrayList; +import java.io.IOException; +import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -public class LifecyclePolicyTests extends ESTestCase { +public class LifecyclePolicyTests extends AbstractSerializingTestCase { private String indexName; private String lifecycleName; @@ -25,28 +34,87 @@ public class LifecyclePolicyTests extends ESTestCase { private Phase secondPhase; private Phase thirdPhase; private LifecyclePolicy policy; + private NamedXContentRegistry registry; + + @Override + protected LifecyclePolicy doParseInstance(XContentParser parser) throws IOException { + return LifecyclePolicy.parse(parser, new Tuple(lifecycleName, registry)); + } + + @Override + protected NamedWriteableRegistry getNamedWriteableRegistry() { + return new NamedWriteableRegistry( + Arrays.asList(new NamedWriteableRegistry.Entry(LifecycleAction.class, DeleteAction.NAME, DeleteAction::new), + new NamedWriteableRegistry.Entry(LifecycleType.class, TestLifecycleType.TYPE, (in) -> TestLifecycleType.INSTANCE))); + } + + @Override + protected LifecyclePolicy createTestInstance() { + int numberPhases = randomInt(5); + Map phases = new HashMap<>(numberPhases); + for (int i = 0; i < numberPhases; i++) { + TimeValue after = TimeValue.parseTimeValue(randomTimeValue(0, 1000000000, "s", "m", "h", "d"), "test_after"); + Map actions = new HashMap<>(); + if (randomBoolean()) { + DeleteAction action = new DeleteAction(); + actions.put(action.getWriteableName(), action); + } + String phaseName = randomAlphaOfLength(10); + phases.put(phaseName, new Phase(phaseName, after, actions)); + } + return new LifecyclePolicy(TestLifecycleType.INSTANCE, lifecycleName, phases); + } + + @Override + protected LifecyclePolicy mutateInstance(LifecyclePolicy instance) throws IOException { + String name = instance.getName(); + Map phases = instance.getPhases(); + switch (between(0, 1)) { + case 0: + name = name + randomAlphaOfLengthBetween(1, 5); + break; + case 1: + phases = new LinkedHashMap<>(phases); + String phaseName = randomAlphaOfLengthBetween(1, 10); + phases.put(phaseName, new Phase(phaseName, TimeValue.timeValueSeconds(randomIntBetween(1, 1000)), Collections.emptyMap())); + break; + default: + throw new AssertionError("Illegal randomisation branch"); + } + return new LifecyclePolicy(TestLifecycleType.INSTANCE, name, phases); + } + + @Override + protected Reader instanceReader() { + return LifecyclePolicy::new; + } @Before public void setupPolicy() { + List entries = Arrays + .asList(new NamedXContentRegistry.Entry(LifecycleAction.class, new ParseField(DeleteAction.NAME), DeleteAction::parse), + new NamedXContentRegistry.Entry(LifecycleType.class, new ParseField(TestLifecycleType.TYPE), + (p) -> TestLifecycleType.INSTANCE)); + registry = new NamedXContentRegistry(entries); indexName = randomAlphaOfLengthBetween(1, 20); lifecycleName = randomAlphaOfLengthBetween(1, 20); - List phases = new ArrayList<>(); + Map phases = new LinkedHashMap<>(); firstAction = new MockAction(); Map actions = Collections.singletonMap(MockAction.NAME, firstAction); TimeValue after = TimeValue.timeValueSeconds(0); firstPhase = new Phase("first_phase", after, actions); - phases.add(firstPhase); + phases.put(firstPhase.getName(), firstPhase); secondAction = new MockAction(); actions = Collections.singletonMap(MockAction.NAME, secondAction); after = TimeValue.timeValueSeconds(10); secondPhase = new Phase("second_phase", after, actions); - phases.add(secondPhase); + phases.put(secondPhase.getName(), secondPhase); thirdAction = new MockAction(); actions = Collections.singletonMap(MockAction.NAME, thirdAction); after = TimeValue.timeValueSeconds(20); thirdPhase = new Phase("third_phase", after, actions); - phases.add(thirdPhase); - policy = new TestLifecyclePolicy(lifecycleName, phases); + phases.put(thirdPhase.getName(), thirdPhase); + policy = new LifecyclePolicy(TestLifecycleType.INSTANCE, lifecycleName, phases); } public void testExecuteNewIndexBeforeTrigger() throws Exception { diff --git a/x-pack/plugin/src/test/java/org/elasticsearch/xpack/indexlifecycle/TestLifecyclePolicy.java b/x-pack/plugin/src/test/java/org/elasticsearch/xpack/indexlifecycle/TestLifecyclePolicy.java deleted file mode 100644 index 87171bf1799..00000000000 --- a/x-pack/plugin/src/test/java/org/elasticsearch/xpack/indexlifecycle/TestLifecyclePolicy.java +++ /dev/null @@ -1,74 +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.indexlifecycle; - -import org.elasticsearch.common.Nullable; -import org.elasticsearch.common.io.stream.StreamInput; -import org.elasticsearch.common.xcontent.XContentParser; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.function.Function; -import java.util.stream.Collectors; - -public class TestLifecyclePolicy extends LifecyclePolicy { - - public static final String TYPE = "test"; - private List phasesList; - - public TestLifecyclePolicy(String name, List phasesList) { - super(name, phasesList.stream().collect(Collectors.toMap(Phase::getName, Function.identity()))); - this.phasesList = phasesList; - } - - public TestLifecyclePolicy(StreamInput in) throws IOException { - super(in); - } - - public static TestLifecyclePolicy parse(XContentParser parser, Object context) { - ToXContentContext factory = (ToXContentContext) context; - return new TestLifecyclePolicy(factory.getName(), new ArrayList<>(factory.getPhases().values())); - } - - @Override - protected String getType() { - return TYPE; - } - - @Override - protected NextActionProvider getActionProvider(IndexLifecycleContext context, Phase phase) { - return a -> Optional.ofNullable(phase.getActions().entrySet().iterator().next()).map(Map.Entry::getValue).orElse(null); - } - - @Override - protected Phase getFirstPhase() { - return phasesList.get(0); - } - - @Override - protected Phase nextPhase(@Nullable Phase currentPhase) { - if (currentPhase == null) { - return getFirstPhase(); - } - - for(int i=0; i < phasesList.size() - 1; i++) { - if (phasesList.get(i).equals(currentPhase)) { - return phasesList.get(i + 1); - } - } - - return null; - } - - @Override - protected void validate(Collection phases) { - // always valid - } -} diff --git a/x-pack/plugin/src/test/java/org/elasticsearch/xpack/indexlifecycle/TestLifecycleType.java b/x-pack/plugin/src/test/java/org/elasticsearch/xpack/indexlifecycle/TestLifecycleType.java new file mode 100644 index 00000000000..e6e729f0e15 --- /dev/null +++ b/x-pack/plugin/src/test/java/org/elasticsearch/xpack/indexlifecycle/TestLifecycleType.java @@ -0,0 +1,71 @@ +/* + * 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.indexlifecycle; + +import org.elasticsearch.common.Nullable; +import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.xpack.indexlifecycle.LifecyclePolicy.NextActionProvider; + +import java.io.IOException; +import java.util.Collection; +import java.util.Map; +import java.util.Optional; + +public class TestLifecycleType implements LifecycleType { + public static final TestLifecycleType INSTANCE = new TestLifecycleType(); + + public static final String TYPE = "test"; + + private TestLifecycleType() { + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + } + + @Override + public String getType() { + return TYPE; + } + + @Override + public String getWriteableName() { + return TYPE; + } + + @Override + public NextActionProvider getActionProvider(IndexLifecycleContext context, Phase phase) { + return a -> Optional.ofNullable(phase.getActions().entrySet().iterator().next()).map(Map.Entry::getValue).orElse(null); + } + + @Override + public Phase getFirstPhase(Map phases) { + return phases.values().iterator().next(); + } + + @Override + public Phase nextPhase(Map phases, @Nullable Phase currentPhase) { + if (currentPhase == null) { + return getFirstPhase(phases); + } + + boolean foundPhase = false; + for (Phase phase : phases.values()) { + if (foundPhase) { + return phase; + } else if (phase.equals(currentPhase)) { + foundPhase = true; + } + } + + return null; + } + + @Override + public void validate(Collection phases) { + // always valid + } +} diff --git a/x-pack/plugin/src/test/java/org/elasticsearch/xpack/indexlifecycle/TimeseriesLifecyclePolicyTests.java b/x-pack/plugin/src/test/java/org/elasticsearch/xpack/indexlifecycle/TimeseriesLifecycleTypeTests.java similarity index 66% rename from x-pack/plugin/src/test/java/org/elasticsearch/xpack/indexlifecycle/TimeseriesLifecyclePolicyTests.java rename to x-pack/plugin/src/test/java/org/elasticsearch/xpack/indexlifecycle/TimeseriesLifecycleTypeTests.java index 2d503610054..a15067dc627 100644 --- a/x-pack/plugin/src/test/java/org/elasticsearch/xpack/indexlifecycle/TimeseriesLifecyclePolicyTests.java +++ b/x-pack/plugin/src/test/java/org/elasticsearch/xpack/indexlifecycle/TimeseriesLifecycleTypeTests.java @@ -5,18 +5,10 @@ */ package org.elasticsearch.xpack.indexlifecycle; -import org.elasticsearch.common.ParseField; -import org.elasticsearch.common.collect.Tuple; -import org.elasticsearch.common.io.stream.NamedWriteableRegistry; -import org.elasticsearch.common.io.stream.Writeable.Reader; import org.elasticsearch.common.unit.ByteSizeValue; import org.elasticsearch.common.unit.TimeValue; -import org.elasticsearch.common.xcontent.NamedXContentRegistry; -import org.elasticsearch.common.xcontent.XContentParser; -import org.elasticsearch.test.AbstractSerializingTestCase; -import org.junit.Before; +import org.elasticsearch.test.ESTestCase; -import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -26,92 +18,22 @@ import java.util.Map; import java.util.function.Function; import java.util.stream.Collectors; -import static org.elasticsearch.xpack.indexlifecycle.TimeseriesLifecyclePolicy.VALID_COLD_ACTIONS; -import static org.elasticsearch.xpack.indexlifecycle.TimeseriesLifecyclePolicy.VALID_DELETE_ACTIONS; -import static org.elasticsearch.xpack.indexlifecycle.TimeseriesLifecyclePolicy.VALID_HOT_ACTIONS; -import static org.elasticsearch.xpack.indexlifecycle.TimeseriesLifecyclePolicy.VALID_PHASES; -import static org.elasticsearch.xpack.indexlifecycle.TimeseriesLifecyclePolicy.VALID_WARM_ACTIONS; +import static org.elasticsearch.xpack.indexlifecycle.TimeseriesLifecycleType.VALID_COLD_ACTIONS; +import static org.elasticsearch.xpack.indexlifecycle.TimeseriesLifecycleType.VALID_DELETE_ACTIONS; +import static org.elasticsearch.xpack.indexlifecycle.TimeseriesLifecycleType.VALID_HOT_ACTIONS; +import static org.elasticsearch.xpack.indexlifecycle.TimeseriesLifecycleType.VALID_PHASES; +import static org.elasticsearch.xpack.indexlifecycle.TimeseriesLifecycleType.VALID_WARM_ACTIONS; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.not; -public class TimeseriesLifecyclePolicyTests extends AbstractSerializingTestCase { +public class TimeseriesLifecycleTypeTests extends ESTestCase { - private NamedXContentRegistry registry; - private String lifecycleName; private static final AllocateAction TEST_ALLOCATE_ACTION = new AllocateAction(); private static final DeleteAction TEST_DELETE_ACTION = new DeleteAction(); private static final ForceMergeAction TEST_FORCE_MERGE_ACTION = new ForceMergeAction(); 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(); - private static final List VALID_PHASE_NAMES = Arrays.asList(); - - @Before - public void setup() { - List entries = Arrays - .asList(new NamedXContentRegistry.Entry(LifecycleAction.class, new ParseField(DeleteAction.NAME), DeleteAction::parse), - new NamedXContentRegistry.Entry(LifecyclePolicy.class, new ParseField(TimeseriesLifecyclePolicy.TYPE), - TimeseriesLifecyclePolicy::parse), - 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(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)); - registry = new NamedXContentRegistry(entries); - lifecycleName = randomAlphaOfLength(20); // NORELEASE we need to randomise the lifecycle name rather - // than use the same name for all instances - } - - @Override - protected LifecyclePolicy createTestInstance() { - Map phases = TimeseriesLifecyclePolicy.VALID_PHASES.stream() - .map(phaseName -> new Phase(phaseName, - TimeValue.parseTimeValue(randomTimeValue(0, 1000000000, "s", "m", "h", "d"), "test_after"), Collections.emptyMap())) - .collect(Collectors.toMap(Phase::getName, Function.identity())); - return new TimeseriesLifecyclePolicy(lifecycleName, phases); - } - - @Override - protected LifecyclePolicy mutateInstance(LifecyclePolicy instance) throws IOException { - String name = instance.getName(); - Map phases = instance.getPhases(); - switch (between(0, 1)) { - case 0: - name = name + randomAlphaOfLengthBetween(1, 5); - break; - case 1: - phases = randomValueOtherThan(phases, - () -> TimeseriesLifecyclePolicy.VALID_PHASES.stream() - .map(phaseName -> new Phase(phaseName, - TimeValue.parseTimeValue(randomTimeValue(0, 1000000000, "s", "m", "h", "d"), "test_after"), - Collections.emptyMap())) - .collect(Collectors.toMap(Phase::getName, Function.identity()))); - break; - default: - throw new AssertionError("Illegal randomisation branch"); - } - return new TimeseriesLifecyclePolicy(name, phases); - } - - @Override - protected LifecyclePolicy doParseInstance(XContentParser parser) throws IOException { - return LifecyclePolicy.parse(parser, new Tuple<>(lifecycleName, registry)); - } - - @Override - protected Reader instanceReader() { - return TimeseriesLifecyclePolicy::new; - } - - protected NamedWriteableRegistry getNamedWriteableRegistry() { - return new NamedWriteableRegistry( - Arrays.asList(new NamedWriteableRegistry.Entry(LifecycleAction.class, DeleteAction.NAME, DeleteAction::new), - new NamedWriteableRegistry.Entry(LifecycleAction.class, AllocateAction.NAME, AllocateAction::new), - new NamedWriteableRegistry.Entry(LifecycleAction.class, ForceMergeAction.NAME, ForceMergeAction::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))); - } public void testGetFirstPhase() { Map phases = new HashMap<>(); @@ -125,12 +47,12 @@ public class TimeseriesLifecyclePolicyTests extends AbstractSerializingTestCase< } } } - TimeseriesLifecyclePolicy policy = new TimeseriesLifecyclePolicy(lifecycleName, phases); - assertThat(policy.getFirstPhase(), equalTo(expectedFirstPhase)); + TimeseriesLifecycleType policy = TimeseriesLifecycleType.INSTANCE; + assertThat(policy.getFirstPhase(phases), equalTo(expectedFirstPhase)); } public void testGetNextPhase() { - for (int runs = 0; runs < NUMBER_OF_TEST_RUNS; runs++) { + for (int runs = 0; runs < 20; runs++) { Map phases = new HashMap<>(); List phasesInOrder = new ArrayList<>(); for (String phase : VALID_PHASES) { @@ -140,13 +62,13 @@ public class TimeseriesLifecyclePolicyTests extends AbstractSerializingTestCase< phasesInOrder.add(phaseToAdd); } } - TimeseriesLifecyclePolicy policy = new TimeseriesLifecyclePolicy(lifecycleName, phases); - assertThat(policy.nextPhase(null), equalTo(policy.getFirstPhase())); + TimeseriesLifecycleType policy = TimeseriesLifecycleType.INSTANCE; + assertThat(policy.nextPhase(phases, null), equalTo(policy.getFirstPhase(phases))); for (int i = 0; i < phasesInOrder.size() - 1; i++) { - assertThat(policy.nextPhase(phasesInOrder.get(i)), equalTo(phasesInOrder.get(i + 1))); + assertThat(policy.nextPhase(phases, phasesInOrder.get(i)), equalTo(phasesInOrder.get(i + 1))); } if (phasesInOrder.isEmpty() == false) { - assertNull(policy.nextPhase(phasesInOrder.get(phasesInOrder.size() - 1))); + assertNull(policy.nextPhase(phases, phasesInOrder.get(phasesInOrder.size() - 1))); } } } @@ -160,10 +82,10 @@ public class TimeseriesLifecyclePolicyTests extends AbstractSerializingTestCase< Map phases = Collections.singletonMap(phaseName, new Phase(phaseName, TimeValue.ZERO, Collections.emptyMap())); if (invalid) { - Exception e = expectThrows(IllegalArgumentException.class, () -> new TimeseriesLifecyclePolicy(lifecycleName, phases)); + Exception e = expectThrows(IllegalArgumentException.class, () -> TimeseriesLifecycleType.INSTANCE.validate(phases.values())); assertThat(e.getMessage(), equalTo("Timeseries lifecycle does not support phase [" + phaseName + "]")); } else { - new TimeseriesLifecyclePolicy(lifecycleName, phases); + TimeseriesLifecycleType.INSTANCE.validate(phases.values()); } } @@ -180,11 +102,11 @@ public class TimeseriesLifecyclePolicyTests extends AbstractSerializingTestCase< if (invalidAction != null) { Exception e = expectThrows(IllegalArgumentException.class, - () -> new TimeseriesLifecyclePolicy(lifecycleName, hotPhase)); + () -> TimeseriesLifecycleType.INSTANCE.validate(hotPhase.values())); assertThat(e.getMessage(), equalTo("invalid action [" + invalidAction.getWriteableName() + "] defined in phase [hot]")); } else { - new TimeseriesLifecyclePolicy(lifecycleName, hotPhase); + TimeseriesLifecycleType.INSTANCE.validate(hotPhase.values()); } } @@ -201,11 +123,11 @@ public class TimeseriesLifecyclePolicyTests extends AbstractSerializingTestCase< if (invalidAction != null) { Exception e = expectThrows(IllegalArgumentException.class, - () -> new TimeseriesLifecyclePolicy(lifecycleName, warmPhase)); + () -> TimeseriesLifecycleType.INSTANCE.validate(warmPhase.values())); assertThat(e.getMessage(), equalTo("invalid action [" + invalidAction.getWriteableName() + "] defined in phase [warm]")); } else { - new TimeseriesLifecyclePolicy(lifecycleName, warmPhase); + TimeseriesLifecycleType.INSTANCE.validate(warmPhase.values()); } } @@ -222,11 +144,11 @@ public class TimeseriesLifecyclePolicyTests extends AbstractSerializingTestCase< if (invalidAction != null) { Exception e = expectThrows(IllegalArgumentException.class, - () -> new TimeseriesLifecyclePolicy(lifecycleName, coldPhase)); + () -> TimeseriesLifecycleType.INSTANCE.validate(coldPhase.values())); assertThat(e.getMessage(), equalTo("invalid action [" + invalidAction.getWriteableName() + "] defined in phase [cold]")); } else { - new TimeseriesLifecyclePolicy(lifecycleName, coldPhase); + TimeseriesLifecycleType.INSTANCE.validate(coldPhase.values()); } } @@ -243,11 +165,11 @@ public class TimeseriesLifecyclePolicyTests extends AbstractSerializingTestCase< if (invalidAction != null) { Exception e = expectThrows(IllegalArgumentException.class, - () -> new TimeseriesLifecyclePolicy(lifecycleName, deletePhase)); + () -> TimeseriesLifecycleType.INSTANCE.validate(deletePhase.values())); assertThat(e.getMessage(), equalTo("invalid action [" + invalidAction.getWriteableName() + "] defined in phase [delete]")); } else { - new TimeseriesLifecyclePolicy(lifecycleName, deletePhase); + TimeseriesLifecycleType.INSTANCE.validate(deletePhase.values()); } } @@ -264,7 +186,7 @@ public class TimeseriesLifecyclePolicyTests extends AbstractSerializingTestCase< return true; } }; - TimeseriesLifecyclePolicy policy = new TimeseriesLifecyclePolicy(lifecycleName, Collections.singletonMap("hot", hotPhase)); + TimeseriesLifecycleType policy = TimeseriesLifecycleType.INSTANCE; LifecyclePolicy.NextActionProvider provider = policy.getActionProvider(context, hotPhase); assertThat(provider.next(null), equalTo(TEST_ROLLOVER_ACTION)); assertNull(provider.next(TEST_ROLLOVER_ACTION)); @@ -286,7 +208,7 @@ public class TimeseriesLifecyclePolicyTests extends AbstractSerializingTestCase< return true; } }; - TimeseriesLifecyclePolicy policy = new TimeseriesLifecyclePolicy(lifecycleName, Collections.singletonMap("warm", warmPhase)); + TimeseriesLifecycleType policy = TimeseriesLifecycleType.INSTANCE; LifecyclePolicy.NextActionProvider provider = policy.getActionProvider(context, warmPhase); assertThat(provider.next(null), equalTo(TEST_REPLICAS_ACTION)); context = new MockIndexLifecycleContext(indexName, "", "", @@ -334,7 +256,7 @@ public class TimeseriesLifecyclePolicyTests extends AbstractSerializingTestCase< return true; } }; - TimeseriesLifecyclePolicy policy = new TimeseriesLifecyclePolicy(lifecycleName, Collections.singletonMap("cold", coldPhase)); + TimeseriesLifecycleType policy = TimeseriesLifecycleType.INSTANCE; LifecyclePolicy.NextActionProvider provider = policy.getActionProvider(context, coldPhase); assertThat(provider.next(null), equalTo(TEST_REPLICAS_ACTION)); context = new MockIndexLifecycleContext(indexName, "", "", @@ -370,7 +292,7 @@ public class TimeseriesLifecyclePolicyTests extends AbstractSerializingTestCase< return true; } }; - TimeseriesLifecyclePolicy policy = new TimeseriesLifecyclePolicy(lifecycleName, Collections.singletonMap("delete", deletePhase)); + TimeseriesLifecycleType policy = TimeseriesLifecycleType.INSTANCE; LifecyclePolicy.NextActionProvider provider = policy.getActionProvider(context, deletePhase); assertThat(provider.next(null), equalTo(TEST_DELETE_ACTION)); assertNull(provider.next(TEST_DELETE_ACTION)); diff --git a/x-pack/plugin/src/test/java/org/elasticsearch/xpack/indexlifecycle/action/GetLifecycleResponseTests.java b/x-pack/plugin/src/test/java/org/elasticsearch/xpack/indexlifecycle/action/GetLifecycleResponseTests.java index 8fa1f329c85..14fe122a8f6 100644 --- a/x-pack/plugin/src/test/java/org/elasticsearch/xpack/indexlifecycle/action/GetLifecycleResponseTests.java +++ b/x-pack/plugin/src/test/java/org/elasticsearch/xpack/indexlifecycle/action/GetLifecycleResponseTests.java @@ -12,12 +12,12 @@ import org.elasticsearch.test.EqualsHashCodeTestUtils.MutateFunction; import org.elasticsearch.xpack.indexlifecycle.DeleteAction; import org.elasticsearch.xpack.indexlifecycle.LifecycleAction; import org.elasticsearch.xpack.indexlifecycle.LifecyclePolicy; +import org.elasticsearch.xpack.indexlifecycle.LifecycleType; import org.elasticsearch.xpack.indexlifecycle.Phase; -import org.elasticsearch.xpack.indexlifecycle.TestLifecyclePolicy; +import org.elasticsearch.xpack.indexlifecycle.TestLifecycleType; import org.elasticsearch.xpack.indexlifecycle.action.GetLifecycleAction.Response; import org.junit.Before; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; @@ -35,7 +35,7 @@ public class GetLifecycleResponseTests extends AbstractStreamableTestCase TestLifecycleType.INSTANCE))); } @Override @@ -68,7 +68,7 @@ public class GetLifecycleResponseTests extends AbstractStreamableTestCase(phases.values()))); + return new Response(new LifecyclePolicy(TestLifecycleType.INSTANCE, name, phases)); }; } } diff --git a/x-pack/plugin/src/test/java/org/elasticsearch/xpack/indexlifecycle/action/PutLifecycleRequestTests.java b/x-pack/plugin/src/test/java/org/elasticsearch/xpack/indexlifecycle/action/PutLifecycleRequestTests.java index 62cb09d0678..c07f3623e22 100644 --- a/x-pack/plugin/src/test/java/org/elasticsearch/xpack/indexlifecycle/action/PutLifecycleRequestTests.java +++ b/x-pack/plugin/src/test/java/org/elasticsearch/xpack/indexlifecycle/action/PutLifecycleRequestTests.java @@ -15,12 +15,12 @@ import org.elasticsearch.test.EqualsHashCodeTestUtils.MutateFunction; import org.elasticsearch.xpack.indexlifecycle.DeleteAction; import org.elasticsearch.xpack.indexlifecycle.LifecycleAction; import org.elasticsearch.xpack.indexlifecycle.LifecyclePolicy; +import org.elasticsearch.xpack.indexlifecycle.LifecycleType; import org.elasticsearch.xpack.indexlifecycle.Phase; -import org.elasticsearch.xpack.indexlifecycle.TestLifecyclePolicy; +import org.elasticsearch.xpack.indexlifecycle.TestLifecycleType; import org.elasticsearch.xpack.indexlifecycle.action.PutLifecycleAction.Request; import org.junit.Before; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; @@ -34,11 +34,10 @@ public class PutLifecycleRequestTests extends AbstractStreamableXContentTestCase @Before public void setup() { - List entries = Arrays - .asList(new NamedXContentRegistry.Entry(LifecycleAction.class, - new ParseField(DeleteAction.NAME), DeleteAction::parse), - new NamedXContentRegistry.Entry(LifecyclePolicy.class, - new ParseField(TestLifecyclePolicy.TYPE), TestLifecyclePolicy::parse)); + List entries = Arrays.asList( + new NamedXContentRegistry.Entry(LifecycleAction.class, new ParseField(DeleteAction.NAME), DeleteAction::parse), + new NamedXContentRegistry.Entry(LifecycleType.class, new ParseField(TestLifecycleType.TYPE), + (p) -> TestLifecycleType.INSTANCE)); registry = new NamedXContentRegistry(entries); lifecycleName = randomAlphaOfLength(20); // NORELEASE we need to randomise the lifecycle name rather // than use the same name for all instances @@ -46,7 +45,7 @@ public class PutLifecycleRequestTests extends AbstractStreamableXContentTestCase @Override protected Request createTestInstance() { - return new Request(new TestLifecyclePolicy(lifecycleName, Collections.emptyList())); + return new Request(new LifecyclePolicy(TestLifecycleType.INSTANCE, lifecycleName, Collections.emptyMap())); } @Override @@ -62,7 +61,7 @@ public class PutLifecycleRequestTests extends AbstractStreamableXContentTestCase protected NamedWriteableRegistry getNamedWriteableRegistry() { return new NamedWriteableRegistry( Arrays.asList(new NamedWriteableRegistry.Entry(LifecycleAction.class, DeleteAction.NAME, DeleteAction::new), - new NamedWriteableRegistry.Entry(LifecyclePolicy.class, TestLifecyclePolicy.TYPE, TestLifecyclePolicy::new))); + new NamedWriteableRegistry.Entry(LifecycleType.class, TestLifecycleType.TYPE, in -> TestLifecycleType.INSTANCE))); } protected boolean supportsUnknownFields() { @@ -88,7 +87,7 @@ public class PutLifecycleRequestTests extends AbstractStreamableXContentTestCase default: throw new AssertionError("Illegal randomisation branch"); } - return new Request(new TestLifecyclePolicy(name, new ArrayList<>(phases.values()))); + return new Request(new LifecyclePolicy(TestLifecycleType.INSTANCE, name, phases)); }; }