diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/indexlifecycle/IndexLifecycleNamedXContentProvider.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/indexlifecycle/IndexLifecycleNamedXContentProvider.java index 51f37157637..7630c010c77 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/indexlifecycle/IndexLifecycleNamedXContentProvider.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/indexlifecycle/IndexLifecycleNamedXContentProvider.java @@ -51,6 +51,9 @@ public class IndexLifecycleNamedXContentProvider implements NamedXContentProvide new NamedXContentRegistry.Entry(LifecycleAction.class, new ParseField(ShrinkAction.NAME), ShrinkAction::parse), + new NamedXContentRegistry.Entry(LifecycleAction.class, + new ParseField(WaitForSnapshotAction.NAME), + WaitForSnapshotAction::parse), new NamedXContentRegistry.Entry(LifecycleAction.class, new ParseField(FreezeAction.NAME), FreezeAction::parse), 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 4e6632b577a..c4205a436ee 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 @@ -62,7 +62,7 @@ public class LifecyclePolicy implements ToXContentObject { ForceMergeAction.NAME, ReadOnlyAction.NAME, ShrinkAction.NAME)); ALLOWED_ACTIONS.put("cold", Sets.newHashSet(UnfollowAction.NAME, SetPriorityAction.NAME, MigrateAction.NAME, AllocateAction.NAME, FreezeAction.NAME, SearchableSnapshotAction.NAME)); - ALLOWED_ACTIONS.put("delete", Sets.newHashSet(DeleteAction.NAME)); + ALLOWED_ACTIONS.put("delete", Sets.newHashSet(DeleteAction.NAME, WaitForSnapshotAction.NAME)); } private final String name; diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/indexlifecycle/WaitForSnapshotAction.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/indexlifecycle/WaitForSnapshotAction.java new file mode 100644 index 00000000000..d69c8b58121 --- /dev/null +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/indexlifecycle/WaitForSnapshotAction.java @@ -0,0 +1,86 @@ +/* + * Licensed to Elasticsearch under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.elasticsearch.client.indexlifecycle; + +import org.elasticsearch.common.ParseField; +import org.elasticsearch.common.Strings; +import org.elasticsearch.common.xcontent.ConstructingObjectParser; +import org.elasticsearch.common.xcontent.ToXContent; +import org.elasticsearch.common.xcontent.ToXContentObject; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentParser; + +import java.io.IOException; +import java.util.Objects; + +/** + * A {@link LifecycleAction} which waits for snapshot to be taken (by configured SLM policy). + */ +public class WaitForSnapshotAction implements LifecycleAction, ToXContentObject { + + public static final String NAME = "wait_for_snapshot"; + public static final ParseField POLICY_FIELD = new ParseField("policy"); + + private static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>(NAME, + true, a -> new WaitForSnapshotAction((String) a[0])); + + static { + PARSER.declareString(ConstructingObjectParser.constructorArg(), POLICY_FIELD); + } + + private final String policy; + + public static WaitForSnapshotAction parse(XContentParser parser) { + return PARSER.apply(parser, null); + } + + public WaitForSnapshotAction(String policy) { + if (Strings.hasText(policy) == false) { + throw new IllegalArgumentException("policy name must be specified"); + } + this.policy = policy; + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, ToXContent.Params params) throws IOException { + builder.startObject(); + builder.field(POLICY_FIELD.getPreferredName(), policy); + builder.endObject(); + return builder; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + WaitForSnapshotAction that = (WaitForSnapshotAction) o; + return policy.equals(that.policy); + } + + @Override + public int hashCode() { + return Objects.hash(policy); + } + + @Override + public String getName() { + return NAME; + } +} 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 a429272b7c7..a5fec6f4a8c 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 @@ -50,6 +50,7 @@ import org.elasticsearch.client.indexlifecycle.ShrinkAction; import org.elasticsearch.client.indexlifecycle.StartILMRequest; import org.elasticsearch.client.indexlifecycle.StopILMRequest; import org.elasticsearch.client.indexlifecycle.UnfollowAction; +import org.elasticsearch.client.indexlifecycle.WaitForSnapshotAction; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.unit.TimeValue; import org.hamcrest.Matchers; @@ -164,7 +165,9 @@ public class IndexLifecycleIT extends ESRestHighLevelClientTestCase { coldActions.put(SearchableSnapshotAction.NAME, new SearchableSnapshotAction("repo")); lifecyclePhases.put("cold", new Phase("cold", TimeValue.timeValueSeconds(2000), coldActions)); - Map deleteActions = Collections.singletonMap(DeleteAction.NAME, new DeleteAction()); + Map deleteActions = new HashMap<>(); + deleteActions.put(WaitForSnapshotAction.NAME, new WaitForSnapshotAction("policy")); + deleteActions.put(DeleteAction.NAME, new DeleteAction()); lifecyclePhases.put("delete", new Phase("delete", TimeValue.timeValueSeconds(3000), deleteActions)); LifecyclePolicy policy = new LifecyclePolicy(randomAlphaOfLength(10), lifecyclePhases); diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/RestHighLevelClientTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/RestHighLevelClientTests.java index 403a048410a..063a92ae15d 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/RestHighLevelClientTests.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/RestHighLevelClientTests.java @@ -56,6 +56,7 @@ import org.elasticsearch.client.indexlifecycle.SearchableSnapshotAction; import org.elasticsearch.client.indexlifecycle.SetPriorityAction; import org.elasticsearch.client.indexlifecycle.ShrinkAction; import org.elasticsearch.client.indexlifecycle.UnfollowAction; +import org.elasticsearch.client.indexlifecycle.WaitForSnapshotAction; import org.elasticsearch.client.ml.dataframe.DataFrameAnalysis; import org.elasticsearch.client.ml.dataframe.evaluation.classification.AccuracyMetric; import org.elasticsearch.client.ml.dataframe.evaluation.classification.Classification; @@ -706,7 +707,7 @@ public class RestHighLevelClientTests extends ESTestCase { public void testProvidedNamedXContents() { List namedXContents = RestHighLevelClient.getProvidedNamedXContents(); - assertEquals(72, namedXContents.size()); + assertEquals(73, namedXContents.size()); Map, Integer> categories = new HashMap<>(); List names = new ArrayList<>(); for (NamedXContentRegistry.Entry namedXContent : namedXContents) { @@ -732,13 +733,14 @@ public class RestHighLevelClientTests extends ESTestCase { assertTrue(names.contains(MeanReciprocalRank.NAME)); assertTrue(names.contains(DiscountedCumulativeGain.NAME)); assertTrue(names.contains(ExpectedReciprocalRank.NAME)); - assertEquals(Integer.valueOf(11), categories.get(LifecycleAction.class)); + assertEquals(Integer.valueOf(12), categories.get(LifecycleAction.class)); assertTrue(names.contains(UnfollowAction.NAME)); assertTrue(names.contains(AllocateAction.NAME)); assertTrue(names.contains(DeleteAction.NAME)); assertTrue(names.contains(ForceMergeAction.NAME)); assertTrue(names.contains(ReadOnlyAction.NAME)); assertTrue(names.contains(RolloverAction.NAME)); + assertTrue(names.contains(WaitForSnapshotAction.NAME)); assertTrue(names.contains(ShrinkAction.NAME)); assertTrue(names.contains(FreezeAction.NAME)); assertTrue(names.contains(SetPriorityAction.NAME)); 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 fdae6c3f73f..4b99ce022a6 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 @@ -85,6 +85,8 @@ public class GetLifecyclePolicyResponseTests extends AbstractXContentTestCase VALID_COLD_ACTIONS = Sets.newHashSet(UnfollowAction.NAME, SetPriorityAction.NAME, AllocateAction.NAME, FreezeAction.NAME, SearchableSnapshotAction.NAME); - private static final Set VALID_DELETE_ACTIONS = Sets.newHashSet(DeleteAction.NAME); + private static final Set VALID_DELETE_ACTIONS = Sets.newHashSet(DeleteAction.NAME, WaitForSnapshotAction.NAME); private String lifecycleName; @@ -75,6 +75,8 @@ public class LifecyclePolicyTests extends AbstractXContentTestCase { + + @Override + protected WaitForSnapshotAction doParseInstance(XContentParser parser) { + return WaitForSnapshotAction.parse(parser); + } + + @Override + protected boolean supportsUnknownFields() { + return true; + } + + static WaitForSnapshotAction randomInstance() { + return new WaitForSnapshotAction(randomAlphaOfLength(5)); + } + + @Override + protected WaitForSnapshotAction createTestInstance() { + return randomInstance(); + } + + public void testActionWithEmptyOrNullPolicy() { + { + IllegalArgumentException exception = expectThrows(IllegalArgumentException.class, () -> new WaitForSnapshotAction("")); + assertThat(exception.getMessage(), is("policy name must be specified")); + } + + { + IllegalArgumentException exception = expectThrows(IllegalArgumentException.class, () -> new WaitForSnapshotAction(null)); + assertThat(exception.getMessage(), is("policy name must be specified")); + } + } +}