diff --git a/client/rest-high-level/src/main/java/org/elasticsearch/client/IndicesClient.java b/client/rest-high-level/src/main/java/org/elasticsearch/client/IndicesClient.java index fa7eb9ab9ec8a..59d2cf1392d30 100644 --- a/client/rest-high-level/src/main/java/org/elasticsearch/client/IndicesClient.java +++ b/client/rest-high-level/src/main/java/org/elasticsearch/client/IndicesClient.java @@ -54,6 +54,8 @@ import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsResponse; import org.elasticsearch.action.admin.indices.shrink.ResizeRequest; import org.elasticsearch.action.admin.indices.shrink.ResizeResponse; +import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesRequest; +import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesResponse; import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest; import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateResponse; @@ -1059,4 +1061,33 @@ public void putTemplateAsync(PutIndexTemplateRequest putIndexTemplateRequest, Re restHighLevelClient.performRequestAsyncAndParseEntity(putIndexTemplateRequest, RequestConverters::putTemplate, options, PutIndexTemplateResponse::fromXContent, listener, emptySet()); } + + /** + * Gets index templates using the Index Templates API + * See Index Templates API + * on elastic.co + * @param getIndexTemplatesRequest 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 GetIndexTemplatesResponse getTemplate(GetIndexTemplatesRequest getIndexTemplatesRequest, + RequestOptions options) throws IOException { + return restHighLevelClient.performRequestAndParseEntity(getIndexTemplatesRequest, RequestConverters::getTemplates, + options, GetIndexTemplatesResponse::fromXContent, emptySet()); + } + + /** + * Asynchronously gets index templates using the Index Templates API + * See Index Templates API + * on elastic.co + * @param getIndexTemplatesRequest 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 getTemplateAsync(GetIndexTemplatesRequest getIndexTemplatesRequest, RequestOptions options, + ActionListener listener) { + restHighLevelClient.performRequestAsyncAndParseEntity(getIndexTemplatesRequest, RequestConverters::getTemplates, + options, GetIndexTemplatesResponse::fromXContent, listener, emptySet()); + } } 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 96fb7e59de32a..02b91f5298011 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 @@ -55,6 +55,7 @@ import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsRequest; import org.elasticsearch.action.admin.indices.shrink.ResizeRequest; import org.elasticsearch.action.admin.indices.shrink.ResizeType; +import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesRequest; import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest; import org.elasticsearch.action.bulk.BulkRequest; import org.elasticsearch.action.delete.DeleteRequest; @@ -830,6 +831,16 @@ static Request putTemplate(PutIndexTemplateRequest putIndexTemplateRequest) thro return request; } + static Request getTemplates(GetIndexTemplatesRequest getIndexTemplatesRequest) throws IOException { + String[] names = getIndexTemplatesRequest.names(); + String endpoint = new EndpointBuilder().addPathPartAsIs("_template").addCommaSeparatedPathParts(names).build(); + Request request = new Request(HttpGet.METHOD_NAME, endpoint); + Params params = new Params(request); + params.withLocal(getIndexTemplatesRequest.local()); + params.withMasterTimeout(getIndexTemplatesRequest.masterNodeTimeout()); + return request; + } + private static HttpEntity createEntity(ToXContent toXContent, XContentType xContentType) throws IOException { BytesRef source = XContentHelper.toXContent(toXContent, xContentType, false).toBytesRef(); return new ByteArrayEntity(source.bytes, source.offset, source.length, createContentType(xContentType)); diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/IndicesClientIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/IndicesClientIT.java index 986c3380ff3c8..3945a39e8c77e 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/IndicesClientIT.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/IndicesClientIT.java @@ -59,6 +59,8 @@ import org.elasticsearch.action.admin.indices.shrink.ResizeRequest; import org.elasticsearch.action.admin.indices.shrink.ResizeResponse; import org.elasticsearch.action.admin.indices.shrink.ResizeType; +import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesRequest; +import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesResponse; import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest; import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateResponse; import org.elasticsearch.action.index.IndexRequest; @@ -66,6 +68,7 @@ import org.elasticsearch.action.support.WriteRequest; import org.elasticsearch.action.support.broadcast.BroadcastResponse; import org.elasticsearch.cluster.metadata.IndexMetaData; +import org.elasticsearch.cluster.metadata.IndexTemplateMetaData; import org.elasticsearch.common.ValidationException; import org.elasticsearch.common.settings.Setting; import org.elasticsearch.common.settings.Settings; @@ -88,6 +91,7 @@ import static org.elasticsearch.common.xcontent.support.XContentMapValues.extractRawValues; import static org.elasticsearch.common.xcontent.support.XContentMapValues.extractValue; import static org.hamcrest.CoreMatchers.hasItem; +import static org.hamcrest.Matchers.arrayContainingInAnyOrder; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; @@ -1002,4 +1006,51 @@ public void testPutTemplateBadRequests() throws Exception { () -> execute(unknownSettingTemplate, client.indices()::putTemplate, client.indices()::putTemplateAsync)); assertThat(unknownSettingError.getDetailedMessage(), containsString("unknown setting [index.this-setting-does-not-exist]")); } + + public void testGetIndexTemplate() throws Exception { + RestHighLevelClient client = highLevelClient(); + + PutIndexTemplateRequest putTemplate1 = new PutIndexTemplateRequest().name("template-1") + .patterns(Arrays.asList("pattern-1", "name-1")).alias(new Alias("alias-1")); + assertThat(execute(putTemplate1, client.indices()::putTemplate, client.indices()::putTemplateAsync).isAcknowledged(), + equalTo(true)); + PutIndexTemplateRequest putTemplate2 = new PutIndexTemplateRequest().name("template-2") + .patterns(Arrays.asList("pattern-2", "name-2")) + .settings(Settings.builder().put("number_of_shards", "2").put("number_of_replicas", "0")); + assertThat(execute(putTemplate2, client.indices()::putTemplate, client.indices()::putTemplateAsync).isAcknowledged(), + equalTo(true)); + + GetIndexTemplatesResponse getTemplate1 = execute(new GetIndexTemplatesRequest().names("template-1"), + client.indices()::getTemplate, client.indices()::getTemplateAsync); + assertThat(getTemplate1.getIndexTemplates(), hasSize(1)); + IndexTemplateMetaData template1 = getTemplate1.getIndexTemplates().get(0); + assertThat(template1.name(), equalTo("template-1")); + assertThat(template1.patterns(), contains("pattern-1", "name-1")); + assertTrue(template1.aliases().containsKey("alias-1")); + + GetIndexTemplatesResponse getTemplate2 = execute(new GetIndexTemplatesRequest().names("template-2"), + client.indices()::getTemplate, client.indices()::getTemplateAsync); + assertThat(getTemplate2.getIndexTemplates(), hasSize(1)); + IndexTemplateMetaData template2 = getTemplate2.getIndexTemplates().get(0); + assertThat(template2.name(), equalTo("template-2")); + assertThat(template2.patterns(), contains("pattern-2", "name-2")); + assertTrue(template2.aliases().isEmpty()); + assertThat(template2.settings().get("index.number_of_shards"), equalTo("2")); + assertThat(template2.settings().get("index.number_of_replicas"), equalTo("0")); + + GetIndexTemplatesRequest getBothRequest = new GetIndexTemplatesRequest(); + if (randomBoolean()) { + getBothRequest.names("*-1", "template-2"); + } else { + getBothRequest.names("template-*"); + } + GetIndexTemplatesResponse getBoth = execute(getBothRequest, client.indices()::getTemplate, client.indices()::getTemplateAsync); + assertThat(getBoth.getIndexTemplates(), hasSize(2)); + assertThat(getBoth.getIndexTemplates().stream().map(IndexTemplateMetaData::getName).toArray(), + arrayContainingInAnyOrder("template-1", "template-2")); + + ElasticsearchException notFound = expectThrows(ElasticsearchException.class, () -> execute( + new GetIndexTemplatesRequest().names("the-template-*"), client.indices()::getTemplate, client.indices()::getTemplateAsync)); + assertThat(notFound.status(), equalTo(RestStatus.NOT_FOUND)); + } } 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 a0312118a8b3f..02000a1b59cbf 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 @@ -58,6 +58,7 @@ import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsRequest; import org.elasticsearch.action.admin.indices.shrink.ResizeRequest; import org.elasticsearch.action.admin.indices.shrink.ResizeType; +import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesRequest; import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest; import org.elasticsearch.action.bulk.BulkRequest; import org.elasticsearch.action.bulk.BulkShardRequest; @@ -142,6 +143,7 @@ import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Supplier; +import java.util.stream.Collectors; import static java.util.Collections.singletonMap; import static org.elasticsearch.client.RequestConverters.REQUEST_BODY_CONTENT_TYPE; @@ -1781,6 +1783,24 @@ public void testPutTemplateRequest() throws Exception { assertToXContentBody(putTemplateRequest, request.getEntity()); } + public void testGetTemplateRequest() throws Exception { + Map encodes = new HashMap<>(); + encodes.put("log", "log"); + encodes.put("1", "1"); + encodes.put("template#1", "template%231"); + encodes.put("template-*", "template-*"); + encodes.put("foo^bar", "foo%5Ebar"); + List names = randomSubsetOf(1, encodes.keySet()); + GetIndexTemplatesRequest getTemplatesRequest = new GetIndexTemplatesRequest().names(names.toArray(new String[0])); + Map expectedParams = new HashMap<>(); + setRandomMasterTimeout(getTemplatesRequest, expectedParams); + setRandomLocal(getTemplatesRequest, expectedParams); + Request request = RequestConverters.getTemplates(getTemplatesRequest); + assertThat(request.getEndpoint(), equalTo("/_template/" + names.stream().map(encodes::get).collect(Collectors.joining(",")))); + assertThat(request.getParameters(), equalTo(expectedParams)); + assertThat(request.getEntity(), nullValue()); + } + private static void assertToXContentBody(ToXContent expectedBody, HttpEntity actualEntity) throws IOException { BytesReference expectedBytes = XContentHelper.toXContent(expectedBody, REQUEST_BODY_CONTENT_TYPE, false); assertEquals(XContentType.JSON.mediaTypeWithoutParameters(), actualEntity.getContentType().getValue()); diff --git a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/IndicesClientDocumentationIT.java b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/IndicesClientDocumentationIT.java index 2b81e4a4adce9..bdaac91b374c6 100644 --- a/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/IndicesClientDocumentationIT.java +++ b/client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/IndicesClientDocumentationIT.java @@ -58,6 +58,8 @@ import org.elasticsearch.action.admin.indices.shrink.ResizeRequest; import org.elasticsearch.action.admin.indices.shrink.ResizeResponse; import org.elasticsearch.action.admin.indices.shrink.ResizeType; +import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesRequest; +import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesResponse; import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest; import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateResponse; import org.elasticsearch.action.support.ActiveShardCount; @@ -67,6 +69,7 @@ import org.elasticsearch.client.RequestOptions; import org.elasticsearch.client.RestHighLevelClient; import org.elasticsearch.client.SyncedFlushResponse; +import org.elasticsearch.cluster.metadata.IndexTemplateMetaData; import org.elasticsearch.cluster.metadata.MappingMetaData; import org.elasticsearch.common.collect.ImmutableOpenMap; import org.elasticsearch.common.settings.Settings; @@ -82,11 +85,13 @@ import java.io.IOException; import java.util.Arrays; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasSize; /** * This class is used to generate the Java Indices API documentation. @@ -1983,4 +1988,71 @@ public void onFailure(Exception e) { assertTrue(latch.await(30L, TimeUnit.SECONDS)); } + + public void testGetTemplates() throws Exception { + RestHighLevelClient client = highLevelClient(); + { + PutIndexTemplateRequest putRequest = new PutIndexTemplateRequest("my-template"); + putRequest.patterns(Arrays.asList("pattern-1", "log-*")); + putRequest.settings(Settings.builder().put("index.number_of_shards", 3).put("index.number_of_replicas", 1)); + putRequest.mapping("tweet", + "{\n" + + " \"tweet\": {\n" + + " \"properties\": {\n" + + " \"message\": {\n" + + " \"type\": \"text\"\n" + + " }\n" + + " }\n" + + " }\n" + + "}", XContentType.JSON); + assertTrue(client.indices().putTemplate(putRequest, RequestOptions.DEFAULT).isAcknowledged()); + } + + // tag::get-templates-request + GetIndexTemplatesRequest request = new GetIndexTemplatesRequest("my-template"); // <1> + request.names("template-1", "template-2"); // <2> + request.names("my-*"); // <3> + // end::get-templates-request + + // tag::get-templates-request-masterTimeout + request.masterNodeTimeout(TimeValue.timeValueMinutes(1)); // <1> + request.masterNodeTimeout("1m"); // <2> + // end::get-templates-request-masterTimeout + + // tag::get-templates-execute + GetIndexTemplatesResponse getTemplatesResponse = client.indices().getTemplate(request, RequestOptions.DEFAULT); + // end::get-templates-execute + + // tag::get-templates-response + List templates = getTemplatesResponse.getIndexTemplates(); // <1> + // end::get-templates-response + + assertThat(templates, hasSize(1)); + assertThat(templates.get(0).name(), equalTo("my-template")); + + // tag::get-templates-execute-listener + ActionListener listener = + new ActionListener() { + @Override + public void onResponse(GetIndexTemplatesResponse response) { + // <1> + } + + @Override + public void onFailure(Exception e) { + // <2> + } + }; + // end::get-templates-execute-listener + + // Replace the empty listener by a blocking listener in test + final CountDownLatch latch = new CountDownLatch(1); + listener = new LatchedActionListener<>(listener, latch); + + // tag::get-templates-execute-async + client.indices().getTemplateAsync(request, RequestOptions.DEFAULT, listener); // <1> + // end::get-templates-execute-async + + assertTrue(latch.await(30L, TimeUnit.SECONDS)); + } } diff --git a/docs/java-rest/high-level/indices/get_templates.asciidoc b/docs/java-rest/high-level/indices/get_templates.asciidoc new file mode 100644 index 0000000000000..4a882bb53aa7d --- /dev/null +++ b/docs/java-rest/high-level/indices/get_templates.asciidoc @@ -0,0 +1,73 @@ +[[java-rest-high-get-templates]] +=== Get Templates API + +The Get Templates API allows to retrieve a list of index templates by name. + +[[java-rest-high-get-templates-request]] +==== Get Index Templates Request + +A `GetIndexTemplatesRequest` specifies one or several names of the index templates to get. + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[get-templates-request] +-------------------------------------------------- +<1> A single index template name +<2> Multiple index template names +<3> An index template name using wildcard + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[get-templates-request-masterTimeout] +-------------------------------------------------- +<1> Timeout to connect to the master node as a `TimeValue` +<2> Timeout to connect to the master node as a `String` + +[[java-rest-high-get-templates-sync]] +==== Synchronous Execution + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[get-templates-execute] +-------------------------------------------------- + +[[java-rest-high-get-templates-async]] +==== Asynchronous Execution + +The asynchronous execution of a get index templates request requires a `GetTemplatesRequest` +instance and an `ActionListener` instance to be passed to the asynchronous +method: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[get-templates-execute-async] +-------------------------------------------------- +<1> The `GetTemplatesRequest` to execute and the `ActionListener` to use when +the execution completes + +The asynchronous method does not block and returns immediately. Once it is +completed the `ActionListener` is called back using the `onResponse` method +if the execution successfully completed or using the `onFailure` method if +it failed. + +A typical listener for `GetTemplatesResponse` looks like: + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[get-templates-execute-listener] +-------------------------------------------------- +<1> Called when the execution is successfully completed. The response is +provided as an argument +<2> Called in case of failure. The raised exception is provided as an argument + +[[java-rest-high-get-templates-response]] +==== Get Templates Response + +The returned `GetTemplatesResponse` consists a list of matching index templates. + +["source","java",subs="attributes,callouts,macros"] +-------------------------------------------------- +include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[get-templates-response] +-------------------------------------------------- +<1> A list of matching index templates + diff --git a/docs/java-rest/high-level/supported-apis.asciidoc b/docs/java-rest/high-level/supported-apis.asciidoc index 783cc773e961d..24f8fefff3430 100644 --- a/docs/java-rest/high-level/supported-apis.asciidoc +++ b/docs/java-rest/high-level/supported-apis.asciidoc @@ -101,6 +101,7 @@ include::indices/exists_alias.asciidoc[] include::indices/put_settings.asciidoc[] include::indices/get_settings.asciidoc[] include::indices/put_template.asciidoc[] +include::indices/get_templates.asciidoc[] == Cluster APIs diff --git a/server/src/main/java/org/elasticsearch/action/admin/indices/template/get/GetIndexTemplatesResponse.java b/server/src/main/java/org/elasticsearch/action/admin/indices/template/get/GetIndexTemplatesResponse.java index 3c5fb36d6c6aa..2bdc966c74e59 100644 --- a/server/src/main/java/org/elasticsearch/action/admin/indices/template/get/GetIndexTemplatesResponse.java +++ b/server/src/main/java/org/elasticsearch/action/admin/indices/template/get/GetIndexTemplatesResponse.java @@ -25,6 +25,7 @@ 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.ArrayList; @@ -34,9 +35,10 @@ public class GetIndexTemplatesResponse extends ActionResponse implements ToXContentObject { - private List indexTemplates; + private final List indexTemplates; GetIndexTemplatesResponse() { + indexTemplates = new ArrayList<>(); } GetIndexTemplatesResponse(List indexTemplates) { @@ -51,7 +53,7 @@ public List getIndexTemplates() { public void readFrom(StreamInput in) throws IOException { super.readFrom(in); int size = in.readVInt(); - indexTemplates = new ArrayList<>(size); + indexTemplates.clear(); for (int i = 0 ; i < size ; i++) { indexTemplates.add(0, IndexTemplateMetaData.readFrom(in)); } @@ -76,4 +78,15 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws builder.endObject(); return builder; } + + public static GetIndexTemplatesResponse fromXContent(XContentParser parser) throws IOException { + final List templates = new ArrayList<>(); + for (XContentParser.Token token = parser.nextToken(); token != XContentParser.Token.END_OBJECT; token = parser.nextToken()) { + if (token == XContentParser.Token.FIELD_NAME) { + final IndexTemplateMetaData templateMetaData = IndexTemplateMetaData.Builder.fromXContent(parser, parser.currentName()); + templates.add(templateMetaData); + } + } + return new GetIndexTemplatesResponse(templates); + } } diff --git a/server/src/test/java/org/elasticsearch/action/admin/indices/template/get/GetIndexTemplatesResponseTests.java b/server/src/test/java/org/elasticsearch/action/admin/indices/template/get/GetIndexTemplatesResponseTests.java new file mode 100644 index 0000000000000..6cb26967d07fa --- /dev/null +++ b/server/src/test/java/org/elasticsearch/action/admin/indices/template/get/GetIndexTemplatesResponseTests.java @@ -0,0 +1,89 @@ +/* + * 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.action.admin.indices.template.get; + +import org.elasticsearch.cluster.metadata.AliasMetaData; +import org.elasticsearch.cluster.metadata.IndexTemplateMetaData; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.xcontent.XContentParser; +import org.elasticsearch.test.AbstractXContentTestCase; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import static org.hamcrest.Matchers.equalTo; + +public class GetIndexTemplatesResponseTests extends AbstractXContentTestCase { + @Override + protected GetIndexTemplatesResponse doParseInstance(XContentParser parser) throws IOException { + return GetIndexTemplatesResponse.fromXContent(parser); + } + + @Override + protected GetIndexTemplatesResponse createTestInstance() { + List templates = new ArrayList<>(); + int numTemplates = between(0, 10); + for (int t = 0; t < numTemplates; t++) { + IndexTemplateMetaData.Builder templateBuilder = IndexTemplateMetaData.builder("template-" + t); + templateBuilder.patterns(IntStream.range(0, between(1, 5)).mapToObj(i -> "pattern-" + i).collect(Collectors.toList())); + int numAlias = between(0, 5); + for (int i = 0; i < numAlias; i++) { + templateBuilder.putAlias(AliasMetaData.builder(randomAlphaOfLengthBetween(1, 10))); + } + if (randomBoolean()) { + templateBuilder.settings(Settings.builder().put("index.setting-1", randomLong())); + } + if (randomBoolean()) { + templateBuilder.order(randomInt()); + } + if (randomBoolean()) { + templateBuilder.version(between(0, 100)); + } + if (randomBoolean()) { + try { + templateBuilder.putMapping("doc", "{\"doc\":{\"properties\":{\"type\":\"text\"}}}"); + } catch (IOException ex) { + throw new UncheckedIOException(ex); + } + } + templates.add(templateBuilder.build()); + } + return new GetIndexTemplatesResponse(templates); + } + + @Override + protected boolean supportsUnknownFields() { + // We can not inject anything at the top level because a GetIndexTemplatesResponse is serialized as a map + // from template name to template content. IndexTemplateMetaDataTests already covers situations where we + // inject arbitrary things inside the IndexTemplateMetaData. + return false; + } + + @Override + protected void assertEqualInstances(GetIndexTemplatesResponse expectedInstance, GetIndexTemplatesResponse newInstance) { + assertNotSame(newInstance, expectedInstance); + assertThat(new HashSet<>(newInstance.getIndexTemplates()), equalTo(new HashSet<>(expectedInstance.getIndexTemplates()))); + } +}