diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/indexlifecycle/LifecyclePolicy.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/indexlifecycle/LifecyclePolicy.java index ff0480b2b037..d5124c3bebfc 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/indexlifecycle/LifecyclePolicy.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/indexlifecycle/LifecyclePolicy.java @@ -52,7 +52,18 @@ public class LifecyclePolicy implements ToXContentObject { PHASES_FIELD ); - ALLOWED_ACTIONS.put("hot", Sets.newHashSet(UnfollowAction.NAME, SetPriorityAction.NAME, RolloverAction.NAME)); + ALLOWED_ACTIONS.put( + "hot", + Sets.newHashSet( + UnfollowAction.NAME, + SetPriorityAction.NAME, + RolloverAction.NAME, + ReadOnlyAction.NAME, + ShrinkAction.NAME, + ForceMergeAction.NAME, + SearchableSnapshotAction.NAME + ) + ); ALLOWED_ACTIONS.put( "warm", Sets.newHashSet( @@ -73,9 +84,11 @@ public class LifecyclePolicy implements ToXContentObject { MigrateAction.NAME, AllocateAction.NAME, FreezeAction.NAME, - SearchableSnapshotAction.NAME + SearchableSnapshotAction.NAME, + ReadOnlyAction.NAME ) ); + ALLOWED_ACTIONS.put("frozen", Sets.newHashSet(UnfollowAction.NAME, SearchableSnapshotAction.NAME)); ALLOWED_ACTIONS.put("delete", Sets.newHashSet(DeleteAction.NAME, WaitForSnapshotAction.NAME)); } diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/indexlifecycle/MigrateAction.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/indexlifecycle/MigrateAction.java index 4beea09f2a7b..3888111ac8d4 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/indexlifecycle/MigrateAction.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/indexlifecycle/MigrateAction.java @@ -24,6 +24,7 @@ public class MigrateAction implements LifecycleAction, ToXContentObject { private static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>( NAME, + true, a -> new MigrateAction(a[0] == null ? true : (boolean) a[0]) ); diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/indexlifecycle/GetLifecyclePolicyResponseTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/indexlifecycle/GetLifecyclePolicyResponseTests.java index 0038a1d4cba0..e39bdf96be3c 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/indexlifecycle/GetLifecyclePolicyResponseTests.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/indexlifecycle/GetLifecyclePolicyResponseTests.java @@ -86,7 +86,8 @@ public class GetLifecyclePolicyResponseTests extends AbstractXContentTestCase { - private static final Set VALID_HOT_ACTIONS = Sets.newHashSet(UnfollowAction.NAME, SetPriorityAction.NAME, RolloverAction.NAME); - private static final Set VALID_WARM_ACTIONS = Sets.newHashSet( - UnfollowAction.NAME, - SetPriorityAction.NAME, - AllocateAction.NAME, - ForceMergeAction.NAME, - ReadOnlyAction.NAME, - ShrinkAction.NAME - ); - private static final Set VALID_COLD_ACTIONS = Sets.newHashSet( - UnfollowAction.NAME, - SetPriorityAction.NAME, - AllocateAction.NAME, - SearchableSnapshotAction.NAME - ); - private static final Set VALID_DELETE_ACTIONS = Sets.newHashSet(DeleteAction.NAME, WaitForSnapshotAction.NAME); + private static final Set VALID_HOT_ACTIONS = new HashSet<>(TimeseriesLifecycleType.ORDERED_VALID_HOT_ACTIONS); + private static final Set VALID_WARM_ACTIONS = new HashSet<>(TimeseriesLifecycleType.ORDERED_VALID_WARM_ACTIONS); + private static final Set VALID_COLD_ACTIONS = new HashSet<>(TimeseriesLifecycleType.ORDERED_VALID_COLD_ACTIONS); + private static final Set VALID_FROZEN_ACTIONS = new HashSet<>(TimeseriesLifecycleType.ORDERED_VALID_FROZEN_ACTIONS); + private static final Set VALID_DELETE_ACTIONS = new HashSet<>(TimeseriesLifecycleType.ORDERED_VALID_DELETE_ACTIONS); private String lifecycleName; @@ -87,7 +78,8 @@ public class LifecyclePolicyTests extends AbstractXContentTestCase hotPhase = Collections.singletonMap("hot", new Phase("hot", TimeValue.ZERO, actions)); if (invalidAction != null) { - Exception e = expectThrows(IllegalArgumentException.class, () -> new LifecyclePolicy(lifecycleName, hotPhase)); + Exception e = expectThrows( + IllegalArgumentException.class, + "expected " + invalidAction + " to throw but it didn't", + () -> new LifecyclePolicy(lifecycleName, hotPhase) + ); assertThat(e.getMessage(), equalTo("invalid action [" + invalidAction.getName() + "] defined in phase [hot]")); } else { new LifecyclePolicy(lifecycleName, hotPhase); @@ -146,7 +142,7 @@ public class LifecyclePolicyTests extends AbstractXContentTestCase warmPhase = Collections.singletonMap("warm", new Phase("warm", TimeValue.ZERO, actions)); @@ -178,6 +174,25 @@ public class LifecyclePolicyTests extends AbstractXContentTestCase actions = randomSubsetOf(VALID_FROZEN_ACTIONS).stream() + .map(this::getTestAction) + .collect(Collectors.toMap(LifecycleAction::getName, Function.identity())); + if (randomBoolean()) { + invalidAction = getTestAction(randomFrom("allocate", "rollover", "delete", "forcemerge", "shrink", "readonly")); + actions.put(invalidAction.getName(), invalidAction); + } + Map coldPhase = Collections.singletonMap("cold", new Phase("frozen", TimeValue.ZERO, actions)); + + if (invalidAction != null) { + Exception e = expectThrows(IllegalArgumentException.class, () -> new LifecyclePolicy(lifecycleName, coldPhase)); + assertThat(e.getMessage(), equalTo("invalid action [" + invalidAction.getName() + "] defined in phase [frozen]")); + } else { + new LifecyclePolicy(lifecycleName, coldPhase); + } + } + public void testValidateDeletePhase() { LifecycleAction invalidAction = null; Map actions = VALID_DELETE_ACTIONS.stream() @@ -259,12 +274,15 @@ public class LifecyclePolicyTests extends AbstractXContentTestCase ORDERED_VALID_PHASES = Arrays.asList(HOT_PHASE, WARM_PHASE, COLD_PHASE, FROZEN_PHASE, DELETE_PHASE); + public static final List ORDERED_VALID_PHASES = Arrays.asList(HOT_PHASE, WARM_PHASE, COLD_PHASE, FROZEN_PHASE, DELETE_PHASE); public static final String FREEZE_ACTION_DEPRECATION_WARNING = "the freeze action has been deprecated and will be removed in a future" + " release"; - static final List ORDERED_VALID_HOT_ACTIONS = Stream.of( + public static final List ORDERED_VALID_HOT_ACTIONS = Stream.of( SetPriorityAction.NAME, UnfollowAction.NAME, RolloverAction.NAME, @@ -69,7 +69,7 @@ public class TimeseriesLifecycleType implements LifecycleType { ForceMergeAction.NAME, SearchableSnapshotAction.NAME ).filter(Objects::nonNull).collect(toList()); - static final List ORDERED_VALID_WARM_ACTIONS = Arrays.asList( + public static final List ORDERED_VALID_WARM_ACTIONS = Arrays.asList( SetPriorityAction.NAME, UnfollowAction.NAME, ReadOnlyAction.NAME, @@ -78,7 +78,7 @@ public class TimeseriesLifecycleType implements LifecycleType { ShrinkAction.NAME, ForceMergeAction.NAME ); - static final List ORDERED_VALID_COLD_ACTIONS = Stream.of( + public static final List ORDERED_VALID_COLD_ACTIONS = Stream.of( SetPriorityAction.NAME, UnfollowAction.NAME, ReadOnlyAction.NAME, @@ -88,8 +88,8 @@ public class TimeseriesLifecycleType implements LifecycleType { FreezeAction.NAME, RollupV2.isEnabled() ? RollupILMAction.NAME : null ).filter(Objects::nonNull).collect(toList()); - static final List ORDERED_VALID_FROZEN_ACTIONS = Arrays.asList(UnfollowAction.NAME, SearchableSnapshotAction.NAME); - static final List ORDERED_VALID_DELETE_ACTIONS = Arrays.asList(WaitForSnapshotAction.NAME, DeleteAction.NAME); + public static final List ORDERED_VALID_FROZEN_ACTIONS = Arrays.asList(UnfollowAction.NAME, SearchableSnapshotAction.NAME); + public static final List ORDERED_VALID_DELETE_ACTIONS = Arrays.asList(WaitForSnapshotAction.NAME, 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); @@ -119,8 +119,8 @@ public class TimeseriesLifecycleType implements LifecycleType { ); // Set of actions that cannot be defined (executed) after the managed index has been mounted as searchable snapshot. // It's ordered to produce consistent error messages which can be unit tested. - static final Set ACTIONS_CANNOT_FOLLOW_SEARCHABLE_SNAPSHOT = new LinkedHashSet<>( - Arrays.asList(ForceMergeAction.NAME, FreezeAction.NAME, ShrinkAction.NAME, RollupILMAction.NAME) + public static final Set ACTIONS_CANNOT_FOLLOW_SEARCHABLE_SNAPSHOT = Collections.unmodifiableSet( + new LinkedHashSet<>(Arrays.asList(ForceMergeAction.NAME, FreezeAction.NAME, ShrinkAction.NAME, RollupILMAction.NAME)) ); private TimeseriesLifecycleType() {} diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ilm/TimeseriesLifecycleTypeTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ilm/TimeseriesLifecycleTypeTests.java index c3892100c1d7..3addf9cd6e1d 100644 --- a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ilm/TimeseriesLifecycleTypeTests.java +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/ilm/TimeseriesLifecycleTypeTests.java @@ -203,8 +203,8 @@ public class TimeseriesLifecycleTypeTests extends ESTestCase { Map actions = randomSubsetOf(VALID_FROZEN_ACTIONS).stream() .map(this::getTestAction) .collect(Collectors.toMap(LifecycleAction::getWriteableName, Function.identity())); - // regardless of the randomised actions, we must have a SearchableSnapshotAction in frozen - actions.put(SearchableSnapshotAction.NAME, getTestAction(SearchableSnapshotAction.NAME)); + // Frozen requires the searchable snapshot action to be present + actions.put(SearchableSnapshotAction.NAME, new SearchableSnapshotAction("repo", randomBoolean())); if (randomBoolean()) { invalidAction = getTestAction(randomFrom("rollover", "delete", "forcemerge", "shrink")); actions.put(invalidAction.getWriteableName(), invalidAction);