Skip to content

Commit 99e0458

Browse files
authored
HLRest: Add get index templates API (#31161)
Relates #27205
1 parent bf58660 commit 99e0458

File tree

9 files changed

+363
-2
lines changed

9 files changed

+363
-2
lines changed

client/rest-high-level/src/main/java/org/elasticsearch/client/IndicesClient.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@
5454
import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsResponse;
5555
import org.elasticsearch.action.admin.indices.shrink.ResizeRequest;
5656
import org.elasticsearch.action.admin.indices.shrink.ResizeResponse;
57+
import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesRequest;
58+
import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesResponse;
5759
import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest;
5860
import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateResponse;
5961

@@ -1059,4 +1061,33 @@ public void putTemplateAsync(PutIndexTemplateRequest putIndexTemplateRequest, Re
10591061
restHighLevelClient.performRequestAsyncAndParseEntity(putIndexTemplateRequest, RequestConverters::putTemplate, options,
10601062
PutIndexTemplateResponse::fromXContent, listener, emptySet());
10611063
}
1064+
1065+
/**
1066+
* Gets index templates using the Index Templates API
1067+
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-templates.html"> Index Templates API
1068+
* on elastic.co</a>
1069+
* @param getIndexTemplatesRequest the request
1070+
* @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
1071+
* @return the response
1072+
* @throws IOException in case there is a problem sending the request or parsing back the response
1073+
*/
1074+
public GetIndexTemplatesResponse getTemplate(GetIndexTemplatesRequest getIndexTemplatesRequest,
1075+
RequestOptions options) throws IOException {
1076+
return restHighLevelClient.performRequestAndParseEntity(getIndexTemplatesRequest, RequestConverters::getTemplates,
1077+
options, GetIndexTemplatesResponse::fromXContent, emptySet());
1078+
}
1079+
1080+
/**
1081+
* Asynchronously gets index templates using the Index Templates API
1082+
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-templates.html"> Index Templates API
1083+
* on elastic.co</a>
1084+
* @param getIndexTemplatesRequest the request
1085+
* @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
1086+
* @param listener the listener to be notified upon request completion
1087+
*/
1088+
public void getTemplateAsync(GetIndexTemplatesRequest getIndexTemplatesRequest, RequestOptions options,
1089+
ActionListener<GetIndexTemplatesResponse> listener) {
1090+
restHighLevelClient.performRequestAsyncAndParseEntity(getIndexTemplatesRequest, RequestConverters::getTemplates,
1091+
options, GetIndexTemplatesResponse::fromXContent, listener, emptySet());
1092+
}
10621093
}

client/rest-high-level/src/main/java/org/elasticsearch/client/RequestConverters.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsRequest;
5656
import org.elasticsearch.action.admin.indices.shrink.ResizeRequest;
5757
import org.elasticsearch.action.admin.indices.shrink.ResizeType;
58+
import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesRequest;
5859
import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest;
5960
import org.elasticsearch.action.bulk.BulkRequest;
6061
import org.elasticsearch.action.delete.DeleteRequest;
@@ -830,6 +831,16 @@ static Request putTemplate(PutIndexTemplateRequest putIndexTemplateRequest) thro
830831
return request;
831832
}
832833

834+
static Request getTemplates(GetIndexTemplatesRequest getIndexTemplatesRequest) throws IOException {
835+
String[] names = getIndexTemplatesRequest.names();
836+
String endpoint = new EndpointBuilder().addPathPartAsIs("_template").addCommaSeparatedPathParts(names).build();
837+
Request request = new Request(HttpGet.METHOD_NAME, endpoint);
838+
Params params = new Params(request);
839+
params.withLocal(getIndexTemplatesRequest.local());
840+
params.withMasterTimeout(getIndexTemplatesRequest.masterNodeTimeout());
841+
return request;
842+
}
843+
833844
private static HttpEntity createEntity(ToXContent toXContent, XContentType xContentType) throws IOException {
834845
BytesRef source = XContentHelper.toXContent(toXContent, xContentType, false).toBytesRef();
835846
return new ByteArrayEntity(source.bytes, source.offset, source.length, createContentType(xContentType));

client/rest-high-level/src/test/java/org/elasticsearch/client/IndicesClientIT.java

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,16 @@
5959
import org.elasticsearch.action.admin.indices.shrink.ResizeRequest;
6060
import org.elasticsearch.action.admin.indices.shrink.ResizeResponse;
6161
import org.elasticsearch.action.admin.indices.shrink.ResizeType;
62+
import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesRequest;
63+
import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesResponse;
6264
import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest;
6365
import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateResponse;
6466
import org.elasticsearch.action.index.IndexRequest;
6567
import org.elasticsearch.action.support.IndicesOptions;
6668
import org.elasticsearch.action.support.WriteRequest;
6769
import org.elasticsearch.action.support.broadcast.BroadcastResponse;
6870
import org.elasticsearch.cluster.metadata.IndexMetaData;
71+
import org.elasticsearch.cluster.metadata.IndexTemplateMetaData;
6972
import org.elasticsearch.common.ValidationException;
7073
import org.elasticsearch.common.settings.Setting;
7174
import org.elasticsearch.common.settings.Settings;
@@ -88,6 +91,7 @@
8891
import static org.elasticsearch.common.xcontent.support.XContentMapValues.extractRawValues;
8992
import static org.elasticsearch.common.xcontent.support.XContentMapValues.extractValue;
9093
import static org.hamcrest.CoreMatchers.hasItem;
94+
import static org.hamcrest.Matchers.arrayContainingInAnyOrder;
9195
import static org.hamcrest.Matchers.contains;
9296
import static org.hamcrest.Matchers.containsString;
9397
import static org.hamcrest.Matchers.equalTo;
@@ -1002,4 +1006,51 @@ public void testPutTemplateBadRequests() throws Exception {
10021006
() -> execute(unknownSettingTemplate, client.indices()::putTemplate, client.indices()::putTemplateAsync));
10031007
assertThat(unknownSettingError.getDetailedMessage(), containsString("unknown setting [index.this-setting-does-not-exist]"));
10041008
}
1009+
1010+
public void testGetIndexTemplate() throws Exception {
1011+
RestHighLevelClient client = highLevelClient();
1012+
1013+
PutIndexTemplateRequest putTemplate1 = new PutIndexTemplateRequest().name("template-1")
1014+
.patterns(Arrays.asList("pattern-1", "name-1")).alias(new Alias("alias-1"));
1015+
assertThat(execute(putTemplate1, client.indices()::putTemplate, client.indices()::putTemplateAsync).isAcknowledged(),
1016+
equalTo(true));
1017+
PutIndexTemplateRequest putTemplate2 = new PutIndexTemplateRequest().name("template-2")
1018+
.patterns(Arrays.asList("pattern-2", "name-2"))
1019+
.settings(Settings.builder().put("number_of_shards", "2").put("number_of_replicas", "0"));
1020+
assertThat(execute(putTemplate2, client.indices()::putTemplate, client.indices()::putTemplateAsync).isAcknowledged(),
1021+
equalTo(true));
1022+
1023+
GetIndexTemplatesResponse getTemplate1 = execute(new GetIndexTemplatesRequest().names("template-1"),
1024+
client.indices()::getTemplate, client.indices()::getTemplateAsync);
1025+
assertThat(getTemplate1.getIndexTemplates(), hasSize(1));
1026+
IndexTemplateMetaData template1 = getTemplate1.getIndexTemplates().get(0);
1027+
assertThat(template1.name(), equalTo("template-1"));
1028+
assertThat(template1.patterns(), contains("pattern-1", "name-1"));
1029+
assertTrue(template1.aliases().containsKey("alias-1"));
1030+
1031+
GetIndexTemplatesResponse getTemplate2 = execute(new GetIndexTemplatesRequest().names("template-2"),
1032+
client.indices()::getTemplate, client.indices()::getTemplateAsync);
1033+
assertThat(getTemplate2.getIndexTemplates(), hasSize(1));
1034+
IndexTemplateMetaData template2 = getTemplate2.getIndexTemplates().get(0);
1035+
assertThat(template2.name(), equalTo("template-2"));
1036+
assertThat(template2.patterns(), contains("pattern-2", "name-2"));
1037+
assertTrue(template2.aliases().isEmpty());
1038+
assertThat(template2.settings().get("index.number_of_shards"), equalTo("2"));
1039+
assertThat(template2.settings().get("index.number_of_replicas"), equalTo("0"));
1040+
1041+
GetIndexTemplatesRequest getBothRequest = new GetIndexTemplatesRequest();
1042+
if (randomBoolean()) {
1043+
getBothRequest.names("*-1", "template-2");
1044+
} else {
1045+
getBothRequest.names("template-*");
1046+
}
1047+
GetIndexTemplatesResponse getBoth = execute(getBothRequest, client.indices()::getTemplate, client.indices()::getTemplateAsync);
1048+
assertThat(getBoth.getIndexTemplates(), hasSize(2));
1049+
assertThat(getBoth.getIndexTemplates().stream().map(IndexTemplateMetaData::getName).toArray(),
1050+
arrayContainingInAnyOrder("template-1", "template-2"));
1051+
1052+
ElasticsearchException notFound = expectThrows(ElasticsearchException.class, () -> execute(
1053+
new GetIndexTemplatesRequest().names("the-template-*"), client.indices()::getTemplate, client.indices()::getTemplateAsync));
1054+
assertThat(notFound.status(), equalTo(RestStatus.NOT_FOUND));
1055+
}
10051056
}

client/rest-high-level/src/test/java/org/elasticsearch/client/RequestConvertersTests.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsRequest;
5858
import org.elasticsearch.action.admin.indices.shrink.ResizeRequest;
5959
import org.elasticsearch.action.admin.indices.shrink.ResizeType;
60+
import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesRequest;
6061
import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest;
6162
import org.elasticsearch.action.bulk.BulkRequest;
6263
import org.elasticsearch.action.bulk.BulkShardRequest;
@@ -140,6 +141,7 @@
140141
import java.util.function.Consumer;
141142
import java.util.function.Function;
142143
import java.util.function.Supplier;
144+
import java.util.stream.Collectors;
143145

144146
import static java.util.Collections.singletonMap;
145147
import static org.elasticsearch.client.RequestConverters.REQUEST_BODY_CONTENT_TYPE;
@@ -1779,6 +1781,24 @@ public void testPutTemplateRequest() throws Exception {
17791781
assertToXContentBody(putTemplateRequest, request.getEntity());
17801782
}
17811783

1784+
public void testGetTemplateRequest() throws Exception {
1785+
Map<String, String> encodes = new HashMap<>();
1786+
encodes.put("log", "log");
1787+
encodes.put("1", "1");
1788+
encodes.put("template#1", "template%231");
1789+
encodes.put("template-*", "template-*");
1790+
encodes.put("foo^bar", "foo%5Ebar");
1791+
List<String> names = randomSubsetOf(1, encodes.keySet());
1792+
GetIndexTemplatesRequest getTemplatesRequest = new GetIndexTemplatesRequest().names(names.toArray(new String[0]));
1793+
Map<String, String> expectedParams = new HashMap<>();
1794+
setRandomMasterTimeout(getTemplatesRequest, expectedParams);
1795+
setRandomLocal(getTemplatesRequest, expectedParams);
1796+
Request request = RequestConverters.getTemplates(getTemplatesRequest);
1797+
assertThat(request.getEndpoint(), equalTo("/_template/" + names.stream().map(encodes::get).collect(Collectors.joining(","))));
1798+
assertThat(request.getParameters(), equalTo(expectedParams));
1799+
assertThat(request.getEntity(), nullValue());
1800+
}
1801+
17821802
private static void assertToXContentBody(ToXContent expectedBody, HttpEntity actualEntity) throws IOException {
17831803
BytesReference expectedBytes = XContentHelper.toXContent(expectedBody, REQUEST_BODY_CONTENT_TYPE, false);
17841804
assertEquals(XContentType.JSON.mediaTypeWithoutParameters(), actualEntity.getContentType().getValue());

client/rest-high-level/src/test/java/org/elasticsearch/client/documentation/IndicesClientDocumentationIT.java

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@
5858
import org.elasticsearch.action.admin.indices.shrink.ResizeRequest;
5959
import org.elasticsearch.action.admin.indices.shrink.ResizeResponse;
6060
import org.elasticsearch.action.admin.indices.shrink.ResizeType;
61+
import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesRequest;
62+
import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesResponse;
6163
import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest;
6264
import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateResponse;
6365
import org.elasticsearch.action.support.ActiveShardCount;
@@ -67,6 +69,7 @@
6769
import org.elasticsearch.client.RequestOptions;
6870
import org.elasticsearch.client.RestHighLevelClient;
6971
import org.elasticsearch.client.SyncedFlushResponse;
72+
import org.elasticsearch.cluster.metadata.IndexTemplateMetaData;
7073
import org.elasticsearch.cluster.metadata.MappingMetaData;
7174
import org.elasticsearch.common.collect.ImmutableOpenMap;
7275
import org.elasticsearch.common.settings.Settings;
@@ -82,11 +85,13 @@
8285
import java.io.IOException;
8386
import java.util.Arrays;
8487
import java.util.HashMap;
88+
import java.util.List;
8589
import java.util.Map;
8690
import java.util.concurrent.CountDownLatch;
8791
import java.util.concurrent.TimeUnit;
8892

8993
import static org.hamcrest.Matchers.equalTo;
94+
import static org.hamcrest.Matchers.hasSize;
9095

9196
/**
9297
* This class is used to generate the Java Indices API documentation.
@@ -1983,4 +1988,71 @@ public void onFailure(Exception e) {
19831988

19841989
assertTrue(latch.await(30L, TimeUnit.SECONDS));
19851990
}
1991+
1992+
public void testGetTemplates() throws Exception {
1993+
RestHighLevelClient client = highLevelClient();
1994+
{
1995+
PutIndexTemplateRequest putRequest = new PutIndexTemplateRequest("my-template");
1996+
putRequest.patterns(Arrays.asList("pattern-1", "log-*"));
1997+
putRequest.settings(Settings.builder().put("index.number_of_shards", 3).put("index.number_of_replicas", 1));
1998+
putRequest.mapping("tweet",
1999+
"{\n" +
2000+
" \"tweet\": {\n" +
2001+
" \"properties\": {\n" +
2002+
" \"message\": {\n" +
2003+
" \"type\": \"text\"\n" +
2004+
" }\n" +
2005+
" }\n" +
2006+
" }\n" +
2007+
"}", XContentType.JSON);
2008+
assertTrue(client.indices().putTemplate(putRequest, RequestOptions.DEFAULT).isAcknowledged());
2009+
}
2010+
2011+
// tag::get-templates-request
2012+
GetIndexTemplatesRequest request = new GetIndexTemplatesRequest("my-template"); // <1>
2013+
request.names("template-1", "template-2"); // <2>
2014+
request.names("my-*"); // <3>
2015+
// end::get-templates-request
2016+
2017+
// tag::get-templates-request-masterTimeout
2018+
request.masterNodeTimeout(TimeValue.timeValueMinutes(1)); // <1>
2019+
request.masterNodeTimeout("1m"); // <2>
2020+
// end::get-templates-request-masterTimeout
2021+
2022+
// tag::get-templates-execute
2023+
GetIndexTemplatesResponse getTemplatesResponse = client.indices().getTemplate(request, RequestOptions.DEFAULT);
2024+
// end::get-templates-execute
2025+
2026+
// tag::get-templates-response
2027+
List<IndexTemplateMetaData> templates = getTemplatesResponse.getIndexTemplates(); // <1>
2028+
// end::get-templates-response
2029+
2030+
assertThat(templates, hasSize(1));
2031+
assertThat(templates.get(0).name(), equalTo("my-template"));
2032+
2033+
// tag::get-templates-execute-listener
2034+
ActionListener<GetIndexTemplatesResponse> listener =
2035+
new ActionListener<GetIndexTemplatesResponse>() {
2036+
@Override
2037+
public void onResponse(GetIndexTemplatesResponse response) {
2038+
// <1>
2039+
}
2040+
2041+
@Override
2042+
public void onFailure(Exception e) {
2043+
// <2>
2044+
}
2045+
};
2046+
// end::get-templates-execute-listener
2047+
2048+
// Replace the empty listener by a blocking listener in test
2049+
final CountDownLatch latch = new CountDownLatch(1);
2050+
listener = new LatchedActionListener<>(listener, latch);
2051+
2052+
// tag::get-templates-execute-async
2053+
client.indices().getTemplateAsync(request, RequestOptions.DEFAULT, listener); // <1>
2054+
// end::get-templates-execute-async
2055+
2056+
assertTrue(latch.await(30L, TimeUnit.SECONDS));
2057+
}
19862058
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
[[java-rest-high-get-templates]]
2+
=== Get Templates API
3+
4+
The Get Templates API allows to retrieve a list of index templates by name.
5+
6+
[[java-rest-high-get-templates-request]]
7+
==== Get Index Templates Request
8+
9+
A `GetIndexTemplatesRequest` specifies one or several names of the index templates to get.
10+
11+
["source","java",subs="attributes,callouts,macros"]
12+
--------------------------------------------------
13+
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[get-templates-request]
14+
--------------------------------------------------
15+
<1> A single index template name
16+
<2> Multiple index template names
17+
<3> An index template name using wildcard
18+
19+
["source","java",subs="attributes,callouts,macros"]
20+
--------------------------------------------------
21+
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[get-templates-request-masterTimeout]
22+
--------------------------------------------------
23+
<1> Timeout to connect to the master node as a `TimeValue`
24+
<2> Timeout to connect to the master node as a `String`
25+
26+
[[java-rest-high-get-templates-sync]]
27+
==== Synchronous Execution
28+
29+
["source","java",subs="attributes,callouts,macros"]
30+
--------------------------------------------------
31+
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[get-templates-execute]
32+
--------------------------------------------------
33+
34+
[[java-rest-high-get-templates-async]]
35+
==== Asynchronous Execution
36+
37+
The asynchronous execution of a get index templates request requires a `GetTemplatesRequest`
38+
instance and an `ActionListener` instance to be passed to the asynchronous
39+
method:
40+
41+
["source","java",subs="attributes,callouts,macros"]
42+
--------------------------------------------------
43+
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[get-templates-execute-async]
44+
--------------------------------------------------
45+
<1> The `GetTemplatesRequest` to execute and the `ActionListener` to use when
46+
the execution completes
47+
48+
The asynchronous method does not block and returns immediately. Once it is
49+
completed the `ActionListener` is called back using the `onResponse` method
50+
if the execution successfully completed or using the `onFailure` method if
51+
it failed.
52+
53+
A typical listener for `GetTemplatesResponse` looks like:
54+
55+
["source","java",subs="attributes,callouts,macros"]
56+
--------------------------------------------------
57+
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[get-templates-execute-listener]
58+
--------------------------------------------------
59+
<1> Called when the execution is successfully completed. The response is
60+
provided as an argument
61+
<2> Called in case of failure. The raised exception is provided as an argument
62+
63+
[[java-rest-high-get-templates-response]]
64+
==== Get Templates Response
65+
66+
The returned `GetTemplatesResponse` consists a list of matching index templates.
67+
68+
["source","java",subs="attributes,callouts,macros"]
69+
--------------------------------------------------
70+
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[get-templates-response]
71+
--------------------------------------------------
72+
<1> A list of matching index templates
73+

docs/java-rest/high-level/supported-apis.asciidoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ include::indices/exists_alias.asciidoc[]
101101
include::indices/put_settings.asciidoc[]
102102
include::indices/get_settings.asciidoc[]
103103
include::indices/put_template.asciidoc[]
104+
include::indices/get_templates.asciidoc[]
104105

105106
== Cluster APIs
106107

0 commit comments

Comments
 (0)