diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/IndexLifecycleClient.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/IndexLifecycleClient.java index 2e57d93cd10..075e0302696 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/IndexLifecycleClient.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/IndexLifecycleClient.java @@ -22,6 +22,8 @@ package org.elasticsearch.client; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.support.master.AcknowledgedResponse; import org.elasticsearch.client.indexlifecycle.DeleteLifecyclePolicyRequest; +import org.elasticsearch.client.indexlifecycle.GetLifecyclePolicyRequest; +import org.elasticsearch.client.indexlifecycle.GetLifecyclePolicyResponse; import org.elasticsearch.client.indexlifecycle.LifecycleManagementStatusRequest; import org.elasticsearch.client.indexlifecycle.LifecycleManagementStatusResponse; import org.elasticsearch.client.indexlifecycle.PutLifecyclePolicyRequest; @@ -43,6 +45,35 @@ public class IndexLifecycleClient { this.restHighLevelClient = restHighLevelClient; } + /** + * Retrieve one or more lifecycle policy definition + * See + * the docs for more. + * @param request the request + * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized + * @return the response + * @throws IOException in case there is a problem sending the request or parsing back the response + */ + public GetLifecyclePolicyResponse getLifecyclePolicy(GetLifecyclePolicyRequest request, + RequestOptions options) throws IOException { + return restHighLevelClient.performRequestAndParseEntity(request, RequestConverters::getLifecyclePolicy, options, + GetLifecyclePolicyResponse::fromXContent, emptySet()); + } + + /** + * Asynchronously retrieve one or more lifecycle policy definition + * See + * the docs for more. + * @param request the request + * @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized + * @param listener the listener to be notified upon request completion + */ + public void getLifecyclePolicyAsync(GetLifecyclePolicyRequest request, RequestOptions options, + ActionListener listener) { + restHighLevelClient.performRequestAsyncAndParseEntity(request, RequestConverters::getLifecyclePolicy, options, + GetLifecyclePolicyResponse::fromXContent, listener, emptySet()); + } + /** * Create or modify a lifecycle definition * See diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/RequestConverters.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/RequestConverters.java index dfb3be22c3f..1c4388b1bc3 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/RequestConverters.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/RequestConverters.java @@ -84,6 +84,7 @@ import org.elasticsearch.action.support.ActiveShardCount; import org.elasticsearch.action.support.IndicesOptions; import org.elasticsearch.action.support.WriteRequest; import org.elasticsearch.action.update.UpdateRequest; +import org.elasticsearch.client.indexlifecycle.GetLifecyclePolicyRequest; import org.elasticsearch.client.indexlifecycle.LifecycleManagementStatusRequest; import org.elasticsearch.client.indexlifecycle.PutLifecyclePolicyRequest; import org.elasticsearch.client.indexlifecycle.DeleteLifecyclePolicyRequest; @@ -1164,6 +1165,18 @@ final class RequestConverters { return request; } + static Request getLifecyclePolicy(GetLifecyclePolicyRequest getLifecyclePolicyRequest) { + String endpoint = new EndpointBuilder() + .addPathPartAsIs("_ilm") + .addCommaSeparatedPathParts(getLifecyclePolicyRequest.getPolicyNames()) + .build(); + Request request = new Request(HttpGet.METHOD_NAME, endpoint); + Params params = new Params(request); + params.withMasterTimeout(getLifecyclePolicyRequest.masterNodeTimeout()); + params.withTimeout(getLifecyclePolicyRequest.timeout()); + return request; + } + static Request putLifecyclePolicy(PutLifecyclePolicyRequest putLifecycleRequest) throws IOException { String endpoint = new EndpointBuilder() .addPathPartAsIs("_ilm") diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/indexlifecycle/GetLifecyclePolicyRequest.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/indexlifecycle/GetLifecyclePolicyRequest.java new file mode 100644 index 00000000000..af17a3ea48c --- /dev/null +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/indexlifecycle/GetLifecyclePolicyRequest.java @@ -0,0 +1,61 @@ +/* + * 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.client.TimedRequest; +import org.elasticsearch.common.Strings; + +import java.util.Arrays; + +public class GetLifecyclePolicyRequest extends TimedRequest { + + private final String[] policyNames; + + public GetLifecyclePolicyRequest(String... policyNames) { + if (policyNames == null) { + this.policyNames = Strings.EMPTY_ARRAY; + } else { + for (String name : policyNames) { + if (name == null) { + throw new IllegalArgumentException("cannot include null policy name"); + } + } + this.policyNames = policyNames; + } + } + + public String[] getPolicyNames() { + return policyNames; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + GetLifecyclePolicyRequest request = (GetLifecyclePolicyRequest) o; + return Arrays.equals(getPolicyNames(), request.getPolicyNames()); + } + + @Override + public int hashCode() { + return Arrays.hashCode(getPolicyNames()); + } +} diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/indexlifecycle/GetLifecyclePolicyResponse.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/indexlifecycle/GetLifecyclePolicyResponse.java new file mode 100644 index 00000000000..fc007cb5aeb --- /dev/null +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/indexlifecycle/GetLifecyclePolicyResponse.java @@ -0,0 +1,91 @@ +/* + * 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 com.carrotsearch.hppc.cursors.ObjectObjectCursor; +import org.elasticsearch.common.collect.ImmutableOpenMap; +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; + +import static org.elasticsearch.common.xcontent.XContentParserUtils.ensureExpectedToken; + +public class GetLifecyclePolicyResponse implements ToXContentObject { + + private final ImmutableOpenMap policies; + + public GetLifecyclePolicyResponse(ImmutableOpenMap policies) { + this.policies = policies; + } + + public ImmutableOpenMap getPolicies() { + return policies; + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, ToXContent.Params params) throws IOException { + builder.startObject(); + for (ObjectObjectCursor stringLifecyclePolicyObjectObjectCursor : policies) { + builder.field(stringLifecyclePolicyObjectObjectCursor.key, stringLifecyclePolicyObjectObjectCursor.value); + } + builder.endObject(); + return builder; + } + + public static GetLifecyclePolicyResponse fromXContent(XContentParser parser) throws IOException { + ImmutableOpenMap.Builder policies = ImmutableOpenMap.builder(); + + if (parser.currentToken() == null) { + parser.nextToken(); + } + ensureExpectedToken(XContentParser.Token.START_OBJECT, parser.currentToken(), parser::getTokenLocation); + parser.nextToken(); + + while (!parser.isClosed()) { + if (parser.currentToken() == XContentParser.Token.START_OBJECT) { + String policyName = parser.currentName(); + LifecyclePolicyMetadata policyDefinion = LifecyclePolicyMetadata.parse(parser, policyName); + policies.put(policyName, policyDefinion); + } else { + parser.nextToken(); + } + } + + return new GetLifecyclePolicyResponse(policies.build()); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + GetLifecyclePolicyResponse that = (GetLifecyclePolicyResponse) o; + return Objects.equals(getPolicies(), that.getPolicies()); + } + + @Override + public int hashCode() { + return Objects.hash(getPolicies()); + } +} 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 new file mode 100644 index 00000000000..22935f19773 --- /dev/null +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/indexlifecycle/IndexLifecycleNamedXContentProvider.java @@ -0,0 +1,56 @@ +/* + * 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.xcontent.NamedXContentRegistry; +import org.elasticsearch.plugins.spi.NamedXContentProvider; + +import java.util.Arrays; +import java.util.List; + +public class IndexLifecycleNamedXContentProvider implements NamedXContentProvider { + + + @Override + public List getNamedXContentParsers() { + return Arrays.asList( + // ILM + new NamedXContentRegistry.Entry(LifecycleAction.class, + new ParseField(AllocateAction.NAME), + AllocateAction::parse), + new NamedXContentRegistry.Entry(LifecycleAction.class, + new ParseField(DeleteAction.NAME), + DeleteAction::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(RolloverAction.NAME), + RolloverAction::parse), + new NamedXContentRegistry.Entry(LifecycleAction.class, + new ParseField(ShrinkAction.NAME), + ShrinkAction::parse) + ); + } +} diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/indexlifecycle/LifecyclePolicyMetadata.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/indexlifecycle/LifecyclePolicyMetadata.java new file mode 100644 index 00000000000..84de8143706 --- /dev/null +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/indexlifecycle/LifecyclePolicyMetadata.java @@ -0,0 +1,117 @@ +/* + * 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.xcontent.ConstructingObjectParser; +import org.elasticsearch.common.xcontent.ToXContentObject; +import org.elasticsearch.common.xcontent.XContentBuilder; +import org.elasticsearch.common.xcontent.XContentParser; + +import java.io.IOException; +import java.time.Instant; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import java.util.Objects; + +public class LifecyclePolicyMetadata implements ToXContentObject { + + static final ParseField POLICY = new ParseField("policy"); + static final ParseField VERSION = new ParseField("version"); + static final ParseField MODIFIED_DATE = new ParseField("modified_date"); + + @SuppressWarnings("unchecked") + public static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>("policy_metadata", + a -> { + LifecyclePolicy policy = (LifecyclePolicy) a[0]; + return new LifecyclePolicyMetadata(policy, (long) a[1], ZonedDateTime.parse((String) a[2]).toInstant().toEpochMilli()); + }); + static { + PARSER.declareObject(ConstructingObjectParser.constructorArg(), LifecyclePolicy::parse, POLICY); + PARSER.declareLong(ConstructingObjectParser.constructorArg(), VERSION); + PARSER.declareString(ConstructingObjectParser.constructorArg(), MODIFIED_DATE); + } + + public static LifecyclePolicyMetadata parse(XContentParser parser, String name) { + return PARSER.apply(parser, name); + } + + private final LifecyclePolicy policy; + private final long version; + private final long modifiedDate; + + public LifecyclePolicyMetadata(LifecyclePolicy policy, long version, long modifiedDate) { + this.policy = policy; + this.version = version; + this.modifiedDate = modifiedDate; + } + + public LifecyclePolicy getPolicy() { + return policy; + } + + public String getName() { + return policy.getName(); + } + + public long getVersion() { + return version; + } + + public long getModifiedDate() { + return modifiedDate; + } + + public String getModifiedDateString() { + ZonedDateTime modifiedDateTime = ZonedDateTime.ofInstant(Instant.ofEpochMilli(modifiedDate), ZoneOffset.UTC); + return modifiedDateTime.toString(); + } + + @Override + public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { + builder.startObject(); + builder.field(POLICY.getPreferredName(), policy); + builder.field(VERSION.getPreferredName(), version); + builder.field(MODIFIED_DATE.getPreferredName(), + ZonedDateTime.ofInstant(Instant.ofEpochMilli(modifiedDate), ZoneOffset.UTC).toString()); + builder.endObject(); + return builder; + } + + @Override + public int hashCode() { + return Objects.hash(policy, version, modifiedDate); + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + LifecyclePolicyMetadata other = (LifecyclePolicyMetadata) obj; + return Objects.equals(policy, other.policy) && + Objects.equals(version, other.version) && + Objects.equals(modifiedDate, other.modifiedDate); + } + +} diff --git a/client/rest-high-level/src/main/resources/META-INF/services/org.elasticsearch.plugins.spi.NamedXContentProvider b/client/rest-high-level/src/main/resources/META-INF/services/org.elasticsearch.plugins.spi.NamedXContentProvider new file mode 100644 index 00000000000..4204a868246 --- /dev/null +++ b/client/rest-high-level/src/main/resources/META-INF/services/org.elasticsearch.plugins.spi.NamedXContentProvider @@ -0,0 +1 @@ +org.elasticsearch.client.indexlifecycle.IndexLifecycleNamedXContentProvider \ No newline at end of file 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 b8975e66696..2b363c4a45c 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 @@ -19,6 +19,7 @@ package org.elasticsearch.client; +import org.elasticsearch.ElasticsearchStatusException; import org.elasticsearch.action.admin.indices.settings.get.GetSettingsRequest; import org.elasticsearch.action.admin.indices.settings.get.GetSettingsResponse; import org.elasticsearch.action.support.master.AcknowledgedResponse; @@ -26,10 +27,13 @@ import org.elasticsearch.client.indexlifecycle.AllocateAction; import org.elasticsearch.client.indexlifecycle.DeleteAction; import org.elasticsearch.client.indexlifecycle.DeleteLifecyclePolicyRequest; import org.elasticsearch.client.indexlifecycle.ForceMergeAction; +import org.elasticsearch.client.indexlifecycle.GetLifecyclePolicyRequest; +import org.elasticsearch.client.indexlifecycle.GetLifecyclePolicyResponse; import org.elasticsearch.client.indexlifecycle.LifecycleAction; import org.elasticsearch.client.indexlifecycle.LifecycleManagementStatusRequest; import org.elasticsearch.client.indexlifecycle.LifecycleManagementStatusResponse; import org.elasticsearch.client.indexlifecycle.LifecyclePolicy; +import org.elasticsearch.client.indexlifecycle.LifecyclePolicyMetadata; import org.elasticsearch.client.indexlifecycle.OperationMode; import org.elasticsearch.client.indexlifecycle.Phase; import org.elasticsearch.client.indexlifecycle.PutLifecyclePolicyRequest; @@ -47,13 +51,17 @@ import org.elasticsearch.client.indexlifecycle.StopILMRequest; import org.hamcrest.Matchers; import java.io.IOException; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import static org.elasticsearch.client.indexlifecycle.LifecyclePolicyTests.createRandomPolicy; import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked; import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasItems; import static org.hamcrest.Matchers.is; public class IndexLifecycleIT extends ESRestHighLevelClientTestCase { @@ -198,14 +206,11 @@ public class IndexLifecycleIT extends ESRestHighLevelClientTestCase { assertAcked(execute(deleteRequest, highLevelClient().indexLifecycle()::deleteLifecyclePolicy, highLevelClient().indexLifecycle()::deleteLifecyclePolicyAsync)); - // TODO: NORELEASE convert this to using the high level client once there are APIs for it - Request getLifecycle = new Request("GET", "/_ilm/" + policyName); - try { - client().performRequest(getLifecycle); - fail("index should not exist after being deleted"); - } catch (ResponseException ex) { - assertEquals(404, ex.getResponse().getStatusLine().getStatusCode()); - } + GetLifecyclePolicyRequest getRequest = new GetLifecyclePolicyRequest(policyName); + ElasticsearchStatusException ex = expectThrows(ElasticsearchStatusException.class, + () -> execute(getRequest, highLevelClient().indexLifecycle()::getLifecyclePolicy, + highLevelClient().indexLifecycle()::getLifecyclePolicyAsync)); + assertEquals(404, ex.status().getStatus()); } public void testPutLifecycle() throws IOException { @@ -216,9 +221,29 @@ public class IndexLifecycleIT extends ESRestHighLevelClientTestCase { assertAcked(execute(putRequest, highLevelClient().indexLifecycle()::putLifecyclePolicy, highLevelClient().indexLifecycle()::putLifecyclePolicyAsync)); - // TODO: NORELEASE convert this to using the high level client once there are APIs for it - Request getLifecycle = new Request("GET", "/_ilm/" + name); - Response response = client().performRequest(getLifecycle); - assertEquals(200, response.getStatusLine().getStatusCode()); + GetLifecyclePolicyRequest getRequest = new GetLifecyclePolicyRequest(name); + GetLifecyclePolicyResponse response = execute(getRequest, highLevelClient().indexLifecycle()::getLifecyclePolicy, + highLevelClient().indexLifecycle()::getLifecyclePolicyAsync); + assertEquals(policy, response.getPolicies().get(name).getPolicy()); + } + + public void testGetMultipleLifecyclePolicies() throws IOException { + int numPolicies = randomIntBetween(1, 10); + String[] policyNames = new String[numPolicies]; + LifecyclePolicy[] policies = new LifecyclePolicy[numPolicies]; + for (int i = 0; i < numPolicies; i++) { + policyNames[i] = "policy-" + randomAlphaOfLengthBetween(5, 10); + policies[i] = createRandomPolicy(policyNames[i]); + PutLifecyclePolicyRequest putRequest = new PutLifecyclePolicyRequest(policies[i]); + assertAcked(execute(putRequest, highLevelClient().indexLifecycle()::putLifecyclePolicy, + highLevelClient().indexLifecycle()::putLifecyclePolicyAsync)); + } + + GetLifecyclePolicyRequest getRequest = new GetLifecyclePolicyRequest(randomFrom(policyNames, null)); + GetLifecyclePolicyResponse response = execute(getRequest, highLevelClient().indexLifecycle()::getLifecyclePolicy, + highLevelClient().indexLifecycle()::getLifecyclePolicyAsync); + List retrievedPolicies = Arrays.stream(response.getPolicies().values().toArray()) + .map(p -> ((LifecyclePolicyMetadata) p).getPolicy()).collect(Collectors.toList()); + assertThat(retrievedPolicies, hasItems(policies)); } } diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/RequestConvertersTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/RequestConvertersTests.java index 4a839b2f7b2..4e239848aac 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/RequestConvertersTests.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/RequestConvertersTests.java @@ -92,6 +92,7 @@ import org.elasticsearch.action.support.master.MasterNodeRequest; import org.elasticsearch.action.support.replication.ReplicationRequest; import org.elasticsearch.action.update.UpdateRequest; import org.elasticsearch.client.RequestConverters.EndpointBuilder; +import org.elasticsearch.client.indexlifecycle.GetLifecyclePolicyRequest; import org.elasticsearch.client.indexlifecycle.LifecycleManagementStatusRequest; import org.elasticsearch.client.indexlifecycle.LifecyclePolicy; import org.elasticsearch.client.indexlifecycle.PutLifecyclePolicyRequest; @@ -2582,6 +2583,20 @@ public class RequestConvertersTests extends ESTestCase { assertThat(bos.toString("UTF-8"), is(body)); } + public void testGetLifecyclePolicy() { + String[] policies = rarely() ? null : randomIndicesNames(0, 10); + GetLifecyclePolicyRequest req = new GetLifecyclePolicyRequest(policies); + Map expectedParams = new HashMap<>(); + setRandomMasterTimeout(req::setMasterTimeout, TimedRequest.DEFAULT_TIMEOUT, expectedParams); + setRandomTimeoutTimeValue(req::setTimeout, TimedRequest.DEFAULT_MASTER_TIMEOUT, expectedParams); + + Request request = RequestConverters.getLifecyclePolicy(req); + assertEquals(request.getMethod(), HttpGet.METHOD_NAME); + String policiesStr = Strings.arrayToCommaDelimitedString(policies); + assertEquals(request.getEndpoint(), "/_ilm" + (policiesStr.isEmpty() ? "" : ("/" + policiesStr))); + assertEquals(request.getParameters(), expectedParams); + } + public void testPutLifecyclePolicy() throws Exception { String name = randomAlphaOfLengthBetween(2, 20); LifecyclePolicy policy = createRandomPolicy(name); 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 0ff4c416ba1..f73026124df 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 @@ -48,6 +48,13 @@ import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.action.search.SearchResponseSections; import org.elasticsearch.action.search.SearchScrollRequest; import org.elasticsearch.action.search.ShardSearchFailure; +import org.elasticsearch.client.indexlifecycle.AllocateAction; +import org.elasticsearch.client.indexlifecycle.DeleteAction; +import org.elasticsearch.client.indexlifecycle.ForceMergeAction; +import org.elasticsearch.client.indexlifecycle.LifecycleAction; +import org.elasticsearch.client.indexlifecycle.ReadOnlyAction; +import org.elasticsearch.client.indexlifecycle.RolloverAction; +import org.elasticsearch.client.indexlifecycle.ShrinkAction; import org.elasticsearch.cluster.ClusterName; import org.elasticsearch.common.CheckedFunction; import org.elasticsearch.common.bytes.BytesReference; @@ -617,7 +624,7 @@ public class RestHighLevelClientTests extends ESTestCase { public void testProvidedNamedXContents() { List namedXContents = RestHighLevelClient.getProvidedNamedXContents(); - assertEquals(10, namedXContents.size()); + assertEquals(16, namedXContents.size()); Map, Integer> categories = new HashMap<>(); List names = new ArrayList<>(); for (NamedXContentRegistry.Entry namedXContent : namedXContents) { @@ -627,7 +634,7 @@ public class RestHighLevelClientTests extends ESTestCase { categories.put(namedXContent.categoryClass, counter + 1); } } - assertEquals(3, categories.size()); + assertEquals(4, categories.size()); assertEquals(Integer.valueOf(2), categories.get(Aggregation.class)); assertTrue(names.contains(ChildrenAggregationBuilder.NAME)); assertTrue(names.contains(MatrixStatsAggregationBuilder.NAME)); @@ -641,6 +648,13 @@ public class RestHighLevelClientTests extends ESTestCase { assertTrue(names.contains(MeanReciprocalRank.NAME)); assertTrue(names.contains(DiscountedCumulativeGain.NAME)); assertTrue(names.contains(ExpectedReciprocalRank.NAME)); + assertEquals(Integer.valueOf(6), categories.get(LifecycleAction.class)); + 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(ShrinkAction.NAME)); } public void testApiNamingConventions() throws Exception { diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/indexlifecycle/GetLifecyclePolicyRequestTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/indexlifecycle/GetLifecyclePolicyRequestTests.java new file mode 100644 index 00000000000..06d28207ce9 --- /dev/null +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/indexlifecycle/GetLifecyclePolicyRequestTests.java @@ -0,0 +1,45 @@ +/* + * 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.test.ESTestCase; + +public class GetLifecyclePolicyRequestTests extends ESTestCase { + + private GetLifecyclePolicyRequest createTestInstance() { + int numPolicies = randomIntBetween(0, 10); + String[] policyNames = new String[numPolicies]; + for (int i = 0; i < numPolicies; i++) { + policyNames[i] = "policy-" + randomAlphaOfLengthBetween(2, 5); + } + return new GetLifecyclePolicyRequest(policyNames); + } + + public void testValidation() { + GetLifecyclePolicyRequest request = createTestInstance(); + assertFalse(request.validate().isPresent()); + } + + public void testNullPolicyNameShouldFail() { + expectThrows(IllegalArgumentException.class, + () -> new GetLifecyclePolicyRequest(randomAlphaOfLengthBetween(2,20), null, randomAlphaOfLengthBetween(2,20))); + } + +} 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 new file mode 100644 index 00000000000..89dfbb86353 --- /dev/null +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/indexlifecycle/GetLifecyclePolicyResponseTests.java @@ -0,0 +1,73 @@ +/* + * 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.cluster.ClusterModule; +import org.elasticsearch.common.ParseField; +import org.elasticsearch.common.collect.ImmutableOpenMap; +import org.elasticsearch.common.xcontent.NamedXContentRegistry; +import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.test.AbstractXContentTestCase; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static org.elasticsearch.client.indexlifecycle.LifecyclePolicyTests.createRandomPolicy; + +public class GetLifecyclePolicyResponseTests extends AbstractXContentTestCase { + + @Override + protected GetLifecyclePolicyResponse createTestInstance() { + int numPolicies = randomIntBetween(1, 10); + ImmutableOpenMap.Builder policies = ImmutableOpenMap.builder(); + for (int i = 0; i < numPolicies; i++) { + String policyName = "policy-" + randomAlphaOfLengthBetween(2, 5); + LifecyclePolicy policy = createRandomPolicy(policyName); + policies.put(policyName, new LifecyclePolicyMetadata(policy, randomLong(), randomLong())); + } + return new GetLifecyclePolicyResponse(policies.build()); + } + + @Override + protected GetLifecyclePolicyResponse doParseInstance(XContentParser parser) throws IOException { + return GetLifecyclePolicyResponse.fromXContent(parser); + } + + @Override + protected boolean supportsUnknownFields() { + return false; + } + + @Override + protected NamedXContentRegistry xContentRegistry() { + List entries = new ArrayList<>(ClusterModule.getNamedXWriteables()); + entries.addAll(Arrays.asList( + new NamedXContentRegistry.Entry(LifecycleAction.class, new ParseField(AllocateAction.NAME), AllocateAction::parse), + new NamedXContentRegistry.Entry(LifecycleAction.class, new ParseField(DeleteAction.NAME), DeleteAction::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(RolloverAction.NAME), RolloverAction::parse), + new NamedXContentRegistry.Entry(LifecycleAction.class, new ParseField(ShrinkAction.NAME), ShrinkAction::parse) + )); + return new NamedXContentRegistry(entries); + } +} diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/indexlifecycle/LifecyclePolicyMetadataTests.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/indexlifecycle/LifecyclePolicyMetadataTests.java new file mode 100644 index 00000000000..548ba366b64 --- /dev/null +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/indexlifecycle/LifecyclePolicyMetadataTests.java @@ -0,0 +1,69 @@ +/* + * 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.cluster.ClusterModule; +import org.elasticsearch.common.ParseField; +import org.elasticsearch.common.xcontent.NamedXContentRegistry; +import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.test.AbstractXContentTestCase; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static org.elasticsearch.client.indexlifecycle.LifecyclePolicyTests.createRandomPolicy; + +public class LifecyclePolicyMetadataTests extends AbstractXContentTestCase { + + private String policyName; + + @Override + protected LifecyclePolicyMetadata createTestInstance() { + policyName = randomAlphaOfLengthBetween(5,20); + LifecyclePolicy policy = createRandomPolicy(policyName); + return new LifecyclePolicyMetadata(policy, randomLong(), randomLong()); + } + + @Override + protected LifecyclePolicyMetadata doParseInstance(XContentParser parser) throws IOException { + return LifecyclePolicyMetadata.parse(parser, policyName); + } + + @Override + protected boolean supportsUnknownFields() { + return false; + } + + @Override + protected NamedXContentRegistry xContentRegistry() { + List entries = new ArrayList<>(ClusterModule.getNamedXWriteables()); + entries.addAll(Arrays.asList( + new NamedXContentRegistry.Entry(LifecycleAction.class, new ParseField(AllocateAction.NAME), AllocateAction::parse), + new NamedXContentRegistry.Entry(LifecycleAction.class, new ParseField(DeleteAction.NAME), DeleteAction::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(RolloverAction.NAME), RolloverAction::parse), + new NamedXContentRegistry.Entry(LifecycleAction.class, new ParseField(ShrinkAction.NAME), ShrinkAction::parse) + )); + return new NamedXContentRegistry(entries); + } +} 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 75ee5c83ba0..f1d45077c26 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 @@ -445,28 +445,6 @@ public class XPackClientPlugin extends Plugin implements ActionPlugin, NetworkPl RollupJobStatus::fromXContent), new NamedXContentRegistry.Entry(PersistentTaskState.class, new ParseField(RollupJobStatus.NAME), RollupJobStatus::fromXContent) - // ILM - // TODO NORELEASE: These lines may not be necessary, and they cause errors if present - // as they are duplicated in IndexLifecycle. - // Leaving this for now in case they are necessary as we move forward with the HLRC. -// new NamedXContentRegistry.Entry(LifecycleAction.class, -// new ParseField(org.elasticsearch.xpack.core.indexlifecycle.AllocateAction.NAME), -// org.elasticsearch.xpack.core.indexlifecycle.AllocateAction::parse), -// new NamedXContentRegistry.Entry(org.elasticsearch.xpack.core.indexlifecycle.LifecycleAction.class, -// new ParseField(org.elasticsearch.xpack.core.indexlifecycle.DeleteAction.NAME), -// org.elasticsearch.xpack.core.indexlifecycle.DeleteAction::parse), -// new NamedXContentRegistry.Entry(org.elasticsearch.xpack.core.indexlifecycle.LifecycleAction.class, -// new ParseField(org.elasticsearch.xpack.core.indexlifecycle.ForceMergeAction.NAME), -// org.elasticsearch.xpack.core.indexlifecycle.ForceMergeAction::parse), -// new NamedXContentRegistry.Entry(org.elasticsearch.xpack.core.indexlifecycle.LifecycleAction.class, -// new ParseField(org.elasticsearch.xpack.core.indexlifecycle.ReadOnlyAction.NAME), -// org.elasticsearch.xpack.core.indexlifecycle.ReadOnlyAction::parse), -// new NamedXContentRegistry.Entry(org.elasticsearch.xpack.core.indexlifecycle.LifecycleAction.class, -// new ParseField(org.elasticsearch.xpack.core.indexlifecycle.RolloverAction.NAME), -// org.elasticsearch.xpack.core.indexlifecycle.RolloverAction::parse), -// new NamedXContentRegistry.Entry(org.elasticsearch.xpack.core.indexlifecycle.LifecycleAction.class, -// new ParseField(org.elasticsearch.xpack.core.indexlifecycle.ShrinkAction.NAME), -// org.elasticsearch.xpack.core.indexlifecycle.ShrinkAction::parse) ); }