Add put index template api to high level rest client (#30400)
Relates #27205
This commit is contained in:
parent
b46d01d409
commit
eed8a3b585
|
@ -51,6 +51,8 @@ import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsRequest
|
|||
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.put.PutIndexTemplateRequest;
|
||||
import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateResponse;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
|
@ -456,4 +458,26 @@ public final class IndicesClient {
|
|||
UpdateSettingsResponse::fromXContent, listener, emptySet(), headers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Puts an index template using the Index Templates API
|
||||
* <p>
|
||||
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-templates.html"> Index Templates API
|
||||
* on elastic.co</a>
|
||||
*/
|
||||
public PutIndexTemplateResponse putTemplate(PutIndexTemplateRequest putIndexTemplateRequest, Header... headers) throws IOException {
|
||||
return restHighLevelClient.performRequestAndParseEntity(putIndexTemplateRequest, RequestConverters::putTemplate,
|
||||
PutIndexTemplateResponse::fromXContent, emptySet(), headers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asynchronously puts an index template using the Index Templates API
|
||||
* <p>
|
||||
* See <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-templates.html"> Index Templates API
|
||||
* on elastic.co</a>
|
||||
*/
|
||||
public void putTemplateAsync(PutIndexTemplateRequest putIndexTemplateRequest,
|
||||
ActionListener<PutIndexTemplateResponse> listener, Header... headers) {
|
||||
restHighLevelClient.performRequestAsyncAndParseEntity(putIndexTemplateRequest, RequestConverters::putTemplate,
|
||||
PutIndexTemplateResponse::fromXContent, listener, emptySet(), headers);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,6 +47,7 @@ import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsRequest
|
|||
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsRequest;
|
||||
import org.elasticsearch.action.admin.indices.shrink.ResizeRequest;
|
||||
import org.elasticsearch.action.admin.indices.shrink.ResizeType;
|
||||
import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest;
|
||||
import org.elasticsearch.action.bulk.BulkRequest;
|
||||
import org.elasticsearch.action.delete.DeleteRequest;
|
||||
import org.elasticsearch.action.fieldcaps.FieldCapabilitiesRequest;
|
||||
|
@ -77,7 +78,6 @@ import org.elasticsearch.common.xcontent.XContentParser;
|
|||
import org.elasticsearch.common.xcontent.XContentType;
|
||||
import org.elasticsearch.index.VersionType;
|
||||
import org.elasticsearch.index.rankeval.RankEvalRequest;
|
||||
import org.elasticsearch.rest.action.RestFieldCapabilitiesAction;
|
||||
import org.elasticsearch.rest.action.search.RestSearchAction;
|
||||
import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
|
||||
|
||||
|
@ -86,10 +86,7 @@ import java.io.IOException;
|
|||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
final class RequestConverters {
|
||||
|
@ -647,6 +644,21 @@ final class RequestConverters {
|
|||
return request;
|
||||
}
|
||||
|
||||
static Request putTemplate(PutIndexTemplateRequest putIndexTemplateRequest) throws IOException {
|
||||
String endpoint = new EndpointBuilder().addPathPartAsIs("_template").addPathPart(putIndexTemplateRequest.name()).build();
|
||||
Request request = new Request(HttpPut.METHOD_NAME, endpoint);
|
||||
Params params = new Params(request);
|
||||
params.withMasterTimeout(putIndexTemplateRequest.masterNodeTimeout());
|
||||
if (putIndexTemplateRequest.create()) {
|
||||
params.putParam("create", Boolean.TRUE.toString());
|
||||
}
|
||||
if (Strings.hasText(putIndexTemplateRequest.cause())) {
|
||||
params.putParam("cause", putIndexTemplateRequest.cause());
|
||||
}
|
||||
request.setEntity(createEntity(putIndexTemplateRequest, REQUEST_BODY_CONTENT_TYPE));
|
||||
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));
|
||||
|
|
|
@ -56,11 +56,14 @@ import org.elasticsearch.action.admin.indices.settings.get.GetSettingsResponse;
|
|||
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.put.PutIndexTemplateRequest;
|
||||
import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateResponse;
|
||||
import org.elasticsearch.action.index.IndexRequest;
|
||||
import org.elasticsearch.action.support.IndicesOptions;
|
||||
import org.elasticsearch.action.support.WriteRequest;
|
||||
import org.elasticsearch.action.support.broadcast.BroadcastResponse;
|
||||
import org.elasticsearch.cluster.metadata.IndexMetaData;
|
||||
import org.elasticsearch.common.ValidationException;
|
||||
import org.elasticsearch.common.settings.Setting;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.unit.ByteSizeUnit;
|
||||
|
@ -73,11 +76,19 @@ import org.elasticsearch.index.IndexSettings;
|
|||
import org.elasticsearch.rest.RestStatus;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.elasticsearch.cluster.metadata.IndexMetaData.SETTING_NUMBER_OF_REPLICAS;
|
||||
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.contains;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.hasEntry;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.hamcrest.Matchers.startsWith;
|
||||
|
||||
|
@ -812,4 +823,59 @@ public class IndicesClientIT extends ESRestHighLevelClientTestCase {
|
|||
+ "or check the breaking changes documentation for removed settings]"));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testPutTemplate() throws Exception {
|
||||
PutIndexTemplateRequest putTemplateRequest = new PutIndexTemplateRequest()
|
||||
.name("my-template")
|
||||
.patterns(Arrays.asList("pattern-1", "name-*"))
|
||||
.order(10)
|
||||
.create(randomBoolean())
|
||||
.settings(Settings.builder().put("number_of_shards", "3").put("number_of_replicas", "0"))
|
||||
.mapping("doc", "host_name", "type=keyword", "description", "type=text")
|
||||
.alias(new Alias("alias-1").indexRouting("abc")).alias(new Alias("{index}-write").searchRouting("xyz"));
|
||||
|
||||
PutIndexTemplateResponse putTemplateResponse = execute(putTemplateRequest,
|
||||
highLevelClient().indices()::putTemplate, highLevelClient().indices()::putTemplateAsync);
|
||||
assertThat(putTemplateResponse.isAcknowledged(), equalTo(true));
|
||||
|
||||
Map<String, Object> templates = getAsMap("/_template/my-template");
|
||||
assertThat(templates.keySet(), hasSize(1));
|
||||
assertThat(extractValue("my-template.order", templates), equalTo(10));
|
||||
assertThat(extractRawValues("my-template.index_patterns", templates), contains("pattern-1", "name-*"));
|
||||
assertThat(extractValue("my-template.settings.index.number_of_shards", templates), equalTo("3"));
|
||||
assertThat(extractValue("my-template.settings.index.number_of_replicas", templates), equalTo("0"));
|
||||
assertThat(extractValue("my-template.mappings.doc.properties.host_name.type", templates), equalTo("keyword"));
|
||||
assertThat(extractValue("my-template.mappings.doc.properties.description.type", templates), equalTo("text"));
|
||||
assertThat((Map<String, String>) extractValue("my-template.aliases.alias-1", templates), hasEntry("index_routing", "abc"));
|
||||
assertThat((Map<String, String>) extractValue("my-template.aliases.{index}-write", templates), hasEntry("search_routing", "xyz"));
|
||||
}
|
||||
|
||||
public void testPutTemplateBadRequests() throws Exception {
|
||||
RestHighLevelClient client = highLevelClient();
|
||||
|
||||
// Failed to validate because index patterns are missing
|
||||
PutIndexTemplateRequest withoutPattern = new PutIndexTemplateRequest("t1");
|
||||
ValidationException withoutPatternError = expectThrows(ValidationException.class,
|
||||
() -> execute(withoutPattern, client.indices()::putTemplate, client.indices()::putTemplateAsync));
|
||||
assertThat(withoutPatternError.validationErrors(), contains("index patterns are missing"));
|
||||
|
||||
// Create-only specified but an template exists already
|
||||
PutIndexTemplateRequest goodTemplate = new PutIndexTemplateRequest("t2").patterns(Arrays.asList("qa-*", "prod-*"));
|
||||
assertTrue(execute(goodTemplate, client.indices()::putTemplate, client.indices()::putTemplateAsync).isAcknowledged());
|
||||
goodTemplate.create(true);
|
||||
ElasticsearchException alreadyExistsError = expectThrows(ElasticsearchException.class,
|
||||
() -> execute(goodTemplate, client.indices()::putTemplate, client.indices()::putTemplateAsync));
|
||||
assertThat(alreadyExistsError.getDetailedMessage(),
|
||||
containsString("[type=illegal_argument_exception, reason=index_template [t2] already exists]"));
|
||||
goodTemplate.create(false);
|
||||
assertTrue(execute(goodTemplate, client.indices()::putTemplate, client.indices()::putTemplateAsync).isAcknowledged());
|
||||
|
||||
// Rejected due to unknown settings
|
||||
PutIndexTemplateRequest unknownSettingTemplate = new PutIndexTemplateRequest("t3")
|
||||
.patterns(Collections.singletonList("any"))
|
||||
.settings(Settings.builder().put("this-setting-does-not-exist", 100));
|
||||
ElasticsearchStatusException unknownSettingError = expectThrows(ElasticsearchStatusException.class,
|
||||
() -> execute(unknownSettingTemplate, client.indices()::putTemplate, client.indices()::putTemplateAsync));
|
||||
assertThat(unknownSettingError.getDetailedMessage(), containsString("unknown setting [index.this-setting-does-not-exist]"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,12 +26,11 @@ import org.apache.http.client.methods.HttpHead;
|
|||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.client.methods.HttpPut;
|
||||
import org.apache.http.entity.ByteArrayEntity;
|
||||
import org.apache.http.entity.ContentType;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
import org.elasticsearch.action.ActionRequestValidationException;
|
||||
import org.elasticsearch.action.DocWriteRequest;
|
||||
import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest;
|
||||
import org.elasticsearch.action.admin.indices.alias.Alias;
|
||||
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
|
||||
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest.AliasActions;
|
||||
import org.elasticsearch.action.admin.indices.alias.get.GetAliasesRequest;
|
||||
|
@ -46,10 +45,11 @@ import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
|
|||
import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
|
||||
import org.elasticsearch.action.admin.indices.refresh.RefreshRequest;
|
||||
import org.elasticsearch.action.admin.indices.rollover.RolloverRequest;
|
||||
import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsRequest;
|
||||
import org.elasticsearch.action.admin.indices.settings.get.GetSettingsRequest;
|
||||
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.put.PutIndexTemplateRequest;
|
||||
import org.elasticsearch.action.bulk.BulkRequest;
|
||||
import org.elasticsearch.action.bulk.BulkShardRequest;
|
||||
import org.elasticsearch.action.delete.DeleteRequest;
|
||||
|
@ -70,6 +70,7 @@ import org.elasticsearch.action.support.master.MasterNodeReadRequest;
|
|||
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.common.CheckedBiConsumer;
|
||||
import org.elasticsearch.common.CheckedFunction;
|
||||
import org.elasticsearch.common.Strings;
|
||||
|
@ -77,15 +78,13 @@ import org.elasticsearch.common.bytes.BytesArray;
|
|||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
import org.elasticsearch.common.io.Streams;
|
||||
import org.elasticsearch.common.lucene.uid.Versions;
|
||||
import org.elasticsearch.common.settings.IndexScopedSettings;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentHelper;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.common.xcontent.XContentType;
|
||||
import org.elasticsearch.client.RequestConverters.EndpointBuilder;
|
||||
import org.elasticsearch.client.RequestConverters.Params;
|
||||
import org.elasticsearch.index.RandomCreateIndexGenerator;
|
||||
import org.elasticsearch.index.VersionType;
|
||||
import org.elasticsearch.index.query.TermQueryBuilder;
|
||||
|
@ -94,7 +93,6 @@ import org.elasticsearch.index.rankeval.RankEvalRequest;
|
|||
import org.elasticsearch.index.rankeval.RankEvalSpec;
|
||||
import org.elasticsearch.index.rankeval.RatedRequest;
|
||||
import org.elasticsearch.index.rankeval.RestRankEvalAction;
|
||||
import org.elasticsearch.rest.action.RestFieldCapabilitiesAction;
|
||||
import org.elasticsearch.rest.action.search.RestSearchAction;
|
||||
import org.elasticsearch.search.Scroll;
|
||||
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
|
||||
|
@ -111,8 +109,6 @@ import org.elasticsearch.test.RandomObjects;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
@ -121,7 +117,6 @@ import java.util.HashSet;
|
|||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.StringJoiner;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
@ -1432,6 +1427,48 @@ public class RequestConvertersTests extends ESTestCase {
|
|||
assertEquals(expectedParams, request.getParameters());
|
||||
}
|
||||
|
||||
public void testPutTemplateRequest() throws Exception {
|
||||
Map<String, String> names = new HashMap<>();
|
||||
names.put("log", "log");
|
||||
names.put("template#1", "template%231");
|
||||
names.put("-#template", "-%23template");
|
||||
names.put("foo^bar", "foo%5Ebar");
|
||||
|
||||
PutIndexTemplateRequest putTemplateRequest = new PutIndexTemplateRequest()
|
||||
.name(randomFrom(names.keySet()))
|
||||
.patterns(Arrays.asList(generateRandomStringArray(20, 100, false, false)));
|
||||
if (randomBoolean()) {
|
||||
putTemplateRequest.order(randomInt());
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
putTemplateRequest.version(randomInt());
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
putTemplateRequest.settings(Settings.builder().put("setting-" + randomInt(), randomTimeValue()));
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
putTemplateRequest.mapping("doc-" + randomInt(), "field-" + randomInt(), "type=" + randomFrom("text", "keyword"));
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
putTemplateRequest.alias(new Alias("alias-" + randomInt()));
|
||||
}
|
||||
Map<String, String> expectedParams = new HashMap<>();
|
||||
if (randomBoolean()) {
|
||||
expectedParams.put("create", Boolean.TRUE.toString());
|
||||
putTemplateRequest.create(true);
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
String cause = randomUnicodeOfCodepointLengthBetween(1, 50);
|
||||
putTemplateRequest.cause(cause);
|
||||
expectedParams.put("cause", cause);
|
||||
}
|
||||
setRandomMasterTimeout(putTemplateRequest, expectedParams);
|
||||
Request request = RequestConverters.putTemplate(putTemplateRequest);
|
||||
assertThat(request.getEndpoint(), equalTo("/_template/" + names.get(putTemplateRequest.name())));
|
||||
assertThat(request.getParameters(), equalTo(expectedParams));
|
||||
assertToXContentBody(putTemplateRequest, request.getEntity());
|
||||
}
|
||||
|
||||
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());
|
||||
|
|
|
@ -55,6 +55,10 @@ import org.elasticsearch.action.admin.indices.settings.get.GetSettingsResponse;
|
|||
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.delete.DeleteIndexTemplateRequest;
|
||||
import org.elasticsearch.action.admin.indices.template.delete.DeleteIndexTemplateResponse;
|
||||
import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateRequest;
|
||||
import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateResponse;
|
||||
import org.elasticsearch.action.support.ActiveShardCount;
|
||||
import org.elasticsearch.action.support.DefaultShardOperationFailedException;
|
||||
import org.elasticsearch.action.support.IndicesOptions;
|
||||
|
@ -71,11 +75,14 @@ import org.elasticsearch.index.query.QueryBuilders;
|
|||
import org.elasticsearch.rest.RestStatus;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
|
||||
/**
|
||||
* This class is used to generate the Java Indices API documentation.
|
||||
* You need to wrap your code between two tags like:
|
||||
|
@ -1598,4 +1605,164 @@ public class IndicesClientDocumentationIT extends ESRestHighLevelClientTestCase
|
|||
assertTrue(latch.await(30L, TimeUnit.SECONDS));
|
||||
}
|
||||
|
||||
public void testPutTemplate() throws Exception {
|
||||
RestHighLevelClient client = highLevelClient();
|
||||
|
||||
// tag::put-template-request
|
||||
PutIndexTemplateRequest request = new PutIndexTemplateRequest("my-template"); // <1>
|
||||
request.patterns(Arrays.asList("pattern-1", "log-*")); // <2>
|
||||
// end::put-template-request
|
||||
|
||||
// tag::put-template-request-settings
|
||||
request.settings(Settings.builder() // <1>
|
||||
.put("index.number_of_shards", 3)
|
||||
.put("index.number_of_replicas", 1)
|
||||
);
|
||||
// end::put-template-request-settings
|
||||
|
||||
{
|
||||
// tag::create-put-template-request-mappings
|
||||
request.mapping("tweet", // <1>
|
||||
"{\n" +
|
||||
" \"tweet\": {\n" +
|
||||
" \"properties\": {\n" +
|
||||
" \"message\": {\n" +
|
||||
" \"type\": \"text\"\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
"}", // <2>
|
||||
XContentType.JSON);
|
||||
// end::create-put-template-mappings
|
||||
assertTrue(client.indices().putTemplate(request).isAcknowledged());
|
||||
}
|
||||
{
|
||||
//tag::put-template-mappings-map
|
||||
Map<String, Object> jsonMap = new HashMap<>();
|
||||
Map<String, Object> message = new HashMap<>();
|
||||
message.put("type", "text");
|
||||
Map<String, Object> properties = new HashMap<>();
|
||||
properties.put("message", message);
|
||||
Map<String, Object> tweet = new HashMap<>();
|
||||
tweet.put("properties", properties);
|
||||
jsonMap.put("tweet", tweet);
|
||||
request.mapping("tweet", jsonMap); // <1>
|
||||
//end::put-template-mappings-map
|
||||
assertTrue(client.indices().putTemplate(request).isAcknowledged());
|
||||
}
|
||||
{
|
||||
//tag::put-template-mappings-xcontent
|
||||
XContentBuilder builder = XContentFactory.jsonBuilder();
|
||||
builder.startObject();
|
||||
{
|
||||
builder.startObject("tweet");
|
||||
{
|
||||
builder.startObject("properties");
|
||||
{
|
||||
builder.startObject("message");
|
||||
{
|
||||
builder.field("type", "text");
|
||||
}
|
||||
builder.endObject();
|
||||
}
|
||||
builder.endObject();
|
||||
}
|
||||
builder.endObject();
|
||||
}
|
||||
builder.endObject();
|
||||
request.mapping("tweet", builder); // <1>
|
||||
//end::put-template-mappings-xcontent
|
||||
assertTrue(client.indices().putTemplate(request).isAcknowledged());
|
||||
}
|
||||
{
|
||||
//tag::put-template-mappings-shortcut
|
||||
request.mapping("tweet", "message", "type=text"); // <1>
|
||||
//end::put-template-mappings-shortcut
|
||||
assertTrue(client.indices().putTemplate(request).isAcknowledged());
|
||||
}
|
||||
|
||||
// tag::put-template-request-aliases
|
||||
request.alias(new Alias("twitter_alias").filter(QueryBuilders.termQuery("user", "kimchy"))); // <1>
|
||||
request.alias(new Alias("{index}_alias").searchRouting("xyz")); // <2>
|
||||
// end::put-template-request-aliases
|
||||
|
||||
// tag::put-template-request-order
|
||||
request.order(20); // <1>
|
||||
// end::put-template-request-order
|
||||
|
||||
// tag::put-template-request-order
|
||||
request.version(4); // <1>
|
||||
// end::put-template-request-order
|
||||
|
||||
// tag::put-template-whole-source
|
||||
request.source("{\n" +
|
||||
" \"index_patterns\": [\n" +
|
||||
" \"log-*\",\n" +
|
||||
" \"pattern-1\"\n" +
|
||||
" ],\n" +
|
||||
" \"order\": 1,\n" +
|
||||
" \"settings\": {\n" +
|
||||
" \"number_of_shards\": 1\n" +
|
||||
" },\n" +
|
||||
" \"mappings\": {\n" +
|
||||
" \"tweet\": {\n" +
|
||||
" \"properties\": {\n" +
|
||||
" \"message\": {\n" +
|
||||
" \"type\": \"text\"\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
" },\n" +
|
||||
" \"aliases\": {\n" +
|
||||
" \"alias-1\": {},\n" +
|
||||
" \"{index}-alias\": {}\n" +
|
||||
" }\n" +
|
||||
"}", XContentType.JSON); // <1>
|
||||
// end::put-template-whole-source
|
||||
|
||||
// tag::put-template-request-create
|
||||
request.create(true); // <1>
|
||||
// end::put-template-request-create
|
||||
|
||||
// tag::put-template-request-masterTimeout
|
||||
request.masterNodeTimeout(TimeValue.timeValueMinutes(1)); // <1>
|
||||
request.masterNodeTimeout("1m"); // <2>
|
||||
// end::put-template-request-masterTimeout
|
||||
|
||||
request.create(false); // make test happy
|
||||
|
||||
// tag::put-template-execute
|
||||
PutIndexTemplateResponse putTemplateResponse = client.indices().putTemplate(request);
|
||||
// end::put-template-execute
|
||||
|
||||
// tag::put-template-response
|
||||
boolean acknowledged = putTemplateResponse.isAcknowledged(); // <1>
|
||||
// end::put-template-response
|
||||
assertTrue(acknowledged);
|
||||
|
||||
// tag::put-template-execute-listener
|
||||
ActionListener<PutIndexTemplateResponse> listener =
|
||||
new ActionListener<PutIndexTemplateResponse>() {
|
||||
@Override
|
||||
public void onResponse(PutIndexTemplateResponse putTemplateResponse) {
|
||||
// <1>
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
// <2>
|
||||
}
|
||||
};
|
||||
// end::put-template-execute-listener
|
||||
|
||||
// Replace the empty listener by a blocking listener in test
|
||||
final CountDownLatch latch = new CountDownLatch(1);
|
||||
listener = new LatchedActionListener<>(listener, latch);
|
||||
|
||||
// tag::put-template-execute-async
|
||||
client.indices().putTemplateAsync(request, listener); // <1>
|
||||
// end::put-template-execute-async
|
||||
|
||||
assertTrue(latch.await(30L, TimeUnit.SECONDS));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -163,6 +163,8 @@ synchronous and predictable. Also the trigger engine thread is only started on
|
|||
data nodes. And the Execute Watch API can be triggered regardless is watcher is
|
||||
started or stopped. ({pull}30118[#30118])
|
||||
|
||||
Added put index template API to the high level rest client ({pull}30400[#30400])
|
||||
|
||||
[float]
|
||||
=== Bug Fixes
|
||||
|
||||
|
|
|
@ -0,0 +1,168 @@
|
|||
[[java-rest-high-put-template]]
|
||||
=== Put Template API
|
||||
|
||||
[[java-rest-high-put-template-request]]
|
||||
==== Put Index Template Request
|
||||
|
||||
A `PutIndexTemplateRequest` specifies the `name` of a template and `patterns`
|
||||
which controls whether the template should be applied to the new index.
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[put-template-request]
|
||||
--------------------------------------------------
|
||||
<1> The name of the template
|
||||
<2> The patterns of the template
|
||||
|
||||
==== Settings
|
||||
The settings of the template will be applied to the new index whose name matches the
|
||||
template's patterns.
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[put-template-request-settings]
|
||||
--------------------------------------------------
|
||||
<1> Settings for this template
|
||||
|
||||
[[java-rest-high-put-template-request-mappings]]
|
||||
==== Mappings
|
||||
The mapping of the template will be applied to the new index whose name matches the
|
||||
template's patterns.
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[put-template-request-mappings]
|
||||
--------------------------------------------------
|
||||
<1> The type to define
|
||||
<2> The mapping for this type, provided as a JSON string
|
||||
|
||||
The mapping source can be provided in different ways in addition to the
|
||||
`String` example shown above:
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[put-template-mappings-map]
|
||||
--------------------------------------------------
|
||||
<1> Mapping source provided as a `Map` which gets automatically converted
|
||||
to JSON format
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[put-template-mappings-xcontent]
|
||||
--------------------------------------------------
|
||||
<1> Mapping source provided as an `XContentBuilder` object, the Elasticsearch
|
||||
built-in helpers to generate JSON content
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[put-template-mappings-shortcut]
|
||||
--------------------------------------------------
|
||||
<1> Mapping source provided as `Object` key-pairs, which gets converted to
|
||||
JSON format
|
||||
|
||||
==== Aliases
|
||||
The aliases of the template will define aliasing to the index whose name matches the
|
||||
template's patterns. A placeholder `{index}` can be used in an alias of a template.
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[put-template-request-aliases]
|
||||
--------------------------------------------------
|
||||
<1> The alias to define
|
||||
<2> The alias to define with placeholder
|
||||
|
||||
==== Order
|
||||
In case multiple templates match an index, the orders of matching templates determine
|
||||
the sequence that settings, mappings, and alias of each matching template is applied.
|
||||
Templates with lower orders are applied first, and higher orders override them.
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[put-template-request-order]
|
||||
--------------------------------------------------
|
||||
<1> The order of the template
|
||||
|
||||
==== Version
|
||||
A template can optionally specify a version number which can be used to simplify template
|
||||
management by external systems.
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[put-template-request-version]
|
||||
--------------------------------------------------
|
||||
<1> The version number of the template
|
||||
|
||||
==== Providing the whole source
|
||||
The whole source including all of its sections (mappings, settings and aliases)
|
||||
can also be provided:
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[put-template-whole-source]
|
||||
--------------------------------------------------
|
||||
<1> The source provided as a JSON string. It can also be provided as a `Map`
|
||||
or an `XContentBuilder`.
|
||||
|
||||
==== Optional arguments
|
||||
The following arguments can optionally be provided:
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[put-template-request-create]
|
||||
--------------------------------------------------
|
||||
<1> To force to only create a new template; do not overwrite the existing template
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[put-template-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-put-template-sync]]
|
||||
==== Synchronous Execution
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[put-template-execute]
|
||||
--------------------------------------------------
|
||||
|
||||
[[java-rest-high-put-template-async]]
|
||||
==== Asynchronous Execution
|
||||
|
||||
The asynchronous execution of a put template request requires both the `PutIndexTemplateRequest`
|
||||
instance and an `ActionListener` instance to be passed to the asynchronous method:
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[put-template-execute-async]
|
||||
--------------------------------------------------
|
||||
<1> The `PutIndexTemplateRequest` 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 `PutIndexTemplateResponse` looks like:
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[put-template-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-put-template-response]]
|
||||
==== Put Index Template Response
|
||||
|
||||
The returned `PutIndexTemplateResponse` allows to retrieve information about the
|
||||
executed operation as follows:
|
||||
|
||||
["source","java",subs="attributes,callouts,macros"]
|
||||
--------------------------------------------------
|
||||
include-tagged::{doc-tests}/IndicesClientDocumentationIT.java[put-template-response]
|
||||
--------------------------------------------------
|
||||
<1> Indicates whether all of the nodes have acknowledged the request
|
|
@ -95,6 +95,7 @@ include::indices/update_aliases.asciidoc[]
|
|||
include::indices/exists_alias.asciidoc[]
|
||||
include::indices/put_settings.asciidoc[]
|
||||
include::indices/get_settings.asciidoc[]
|
||||
include::indices/put_template.asciidoc[]
|
||||
|
||||
== Cluster APIs
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ import org.elasticsearch.common.logging.Loggers;
|
|||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.LoggingDeprecationHandler;
|
||||
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||
import org.elasticsearch.common.xcontent.XContentHelper;
|
||||
|
@ -58,14 +59,14 @@ import java.util.Set;
|
|||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.elasticsearch.action.ValidateActions.addValidationError;
|
||||
import static org.elasticsearch.common.settings.Settings.Builder.EMPTY_SETTINGS;
|
||||
import static org.elasticsearch.common.settings.Settings.readSettingsFromStream;
|
||||
import static org.elasticsearch.common.settings.Settings.writeSettingsToStream;
|
||||
import static org.elasticsearch.common.settings.Settings.Builder.EMPTY_SETTINGS;
|
||||
|
||||
/**
|
||||
* A request to create an index template.
|
||||
*/
|
||||
public class PutIndexTemplateRequest extends MasterNodeRequest<PutIndexTemplateRequest> implements IndicesRequest {
|
||||
public class PutIndexTemplateRequest extends MasterNodeRequest<PutIndexTemplateRequest> implements IndicesRequest, ToXContent {
|
||||
|
||||
private static final DeprecationLogger DEPRECATION_LOGGER = new DeprecationLogger(Loggers.getLogger(PutIndexTemplateRequest.class));
|
||||
|
||||
|
@ -539,4 +540,34 @@ public class PutIndexTemplateRequest extends MasterNodeRequest<PutIndexTemplateR
|
|||
}
|
||||
out.writeOptionalVInt(version);
|
||||
}
|
||||
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
if (customs.isEmpty() == false) {
|
||||
throw new IllegalArgumentException("Custom data type is no longer supported in index template [" + customs + "]");
|
||||
}
|
||||
builder.field("index_patterns", indexPatterns);
|
||||
builder.field("order", order);
|
||||
if (version != null) {
|
||||
builder.field("version", version);
|
||||
}
|
||||
|
||||
builder.startObject("settings");
|
||||
settings.toXContent(builder, params);
|
||||
builder.endObject();
|
||||
|
||||
builder.startObject("mappings");
|
||||
for (Map.Entry<String, String> entry : mappings.entrySet()) {
|
||||
Map<String, Object> mapping = XContentHelper.convertToMap(new BytesArray(entry.getValue()), false).v2();
|
||||
builder.field(entry.getKey(), mapping);
|
||||
}
|
||||
builder.endObject();
|
||||
|
||||
builder.startObject("aliases");
|
||||
for (Alias alias : aliases) {
|
||||
alias.toXContent(builder, params);
|
||||
}
|
||||
builder.endObject();
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,8 @@ package org.elasticsearch.action.admin.indices.template.put;
|
|||
import org.elasticsearch.action.support.master.AcknowledgedResponse;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
|
@ -47,4 +49,14 @@ public class PutIndexTemplateResponse extends AcknowledgedResponse {
|
|||
super.writeTo(out);
|
||||
writeAcknowledged(out);
|
||||
}
|
||||
|
||||
private static final ConstructingObjectParser<PutIndexTemplateResponse, Void> PARSER;
|
||||
static {
|
||||
PARSER = new ConstructingObjectParser<>("put_index_template", true, args -> new PutIndexTemplateResponse((boolean) args[0]));
|
||||
declareAcknowledgedField(PARSER);
|
||||
}
|
||||
|
||||
public static PutIndexTemplateResponse fromXContent(XContentParser parser) {
|
||||
return PARSER.apply(parser, null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,10 +20,15 @@ package org.elasticsearch.action.admin.indices.template.put;
|
|||
|
||||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.action.ActionRequestValidationException;
|
||||
import org.elasticsearch.action.admin.indices.alias.Alias;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.bytes.BytesArray;
|
||||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
import org.elasticsearch.common.io.stream.BytesStreamOutput;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.ToXContent;
|
||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||
import org.elasticsearch.common.xcontent.XContentHelper;
|
||||
import org.elasticsearch.common.xcontent.XContentType;
|
||||
import org.elasticsearch.common.xcontent.yaml.YamlXContent;
|
||||
|
@ -35,6 +40,7 @@ import java.util.Base64;
|
|||
import java.util.Collections;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.hamcrest.core.Is.is;
|
||||
|
@ -131,4 +137,52 @@ public class PutIndexTemplateRequestTests extends ESTestCase {
|
|||
assertThat(noError, is(nullValue()));
|
||||
}
|
||||
|
||||
private PutIndexTemplateRequest randomPutIndexTemplateRequest() throws IOException {
|
||||
PutIndexTemplateRequest request = new PutIndexTemplateRequest();
|
||||
request.name("test");
|
||||
if (randomBoolean()){
|
||||
request.version(randomInt());
|
||||
}
|
||||
if (randomBoolean()){
|
||||
request.order(randomInt());
|
||||
}
|
||||
request.patterns(Arrays.asList(generateRandomStringArray(20, 100, false, false)));
|
||||
int numAlias = between(0, 5);
|
||||
for (int i = 0; i < numAlias; i++) {
|
||||
Alias alias = new Alias(randomRealisticUnicodeOfLengthBetween(1, 10));
|
||||
if (randomBoolean()) {
|
||||
alias.indexRouting(randomRealisticUnicodeOfLengthBetween(1, 10));
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
alias.searchRouting(randomRealisticUnicodeOfLengthBetween(1, 10));
|
||||
}
|
||||
request.alias(alias);
|
||||
}
|
||||
if (randomBoolean()) {
|
||||
request.mapping("doc", XContentFactory.jsonBuilder().startObject()
|
||||
.startObject("doc").startObject("properties")
|
||||
.startObject("field-" + randomInt()).field("type", randomFrom("keyword", "text")).endObject()
|
||||
.endObject().endObject().endObject());
|
||||
}
|
||||
if (randomBoolean()){
|
||||
request.settings(Settings.builder().put("setting1", randomLong()).put("setting2", randomTimeValue()).build());
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
public void testFromToXContentPutTemplateRequest() throws Exception {
|
||||
for (int i = 0; i < 10; i++) {
|
||||
PutIndexTemplateRequest expected = randomPutIndexTemplateRequest();
|
||||
XContentType xContentType = randomFrom(XContentType.values());
|
||||
BytesReference shuffled = toShuffledXContent(expected, xContentType, ToXContent.EMPTY_PARAMS, randomBoolean());
|
||||
PutIndexTemplateRequest parsed = new PutIndexTemplateRequest().source(shuffled, xContentType);
|
||||
assertNotSame(expected, parsed);
|
||||
assertThat(parsed.version(), equalTo(expected.version()));
|
||||
assertThat(parsed.order(), equalTo(expected.order()));
|
||||
assertThat(parsed.patterns(), equalTo(expected.patterns()));
|
||||
assertThat(parsed.aliases(), equalTo(expected.aliases()));
|
||||
assertThat(parsed.mappings(), equalTo(expected.mappings()));
|
||||
assertThat(parsed.settings(), equalTo(expected.settings()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue