[7.x] HLRC support for Component Templates APIs (#54635) (#54828)

* HLRC support for Component Templates APIs (#54635)
This commit is contained in:
Przemko Robakowski 2020-04-06 20:24:23 +02:00 committed by GitHub
parent 1aa87cd4a9
commit 7b1bb9952a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 760 additions and 4 deletions

View File

@ -26,8 +26,14 @@ import org.elasticsearch.action.admin.cluster.settings.ClusterGetSettingsRequest
import org.elasticsearch.action.admin.cluster.settings.ClusterGetSettingsResponse;
import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest;
import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.client.cluster.RemoteInfoRequest;
import org.elasticsearch.client.cluster.RemoteInfoResponse;
import org.elasticsearch.client.indices.ComponentTemplatesExistRequest;
import org.elasticsearch.client.indices.DeleteComponentTemplateRequest;
import org.elasticsearch.client.indices.GetComponentTemplatesRequest;
import org.elasticsearch.client.indices.GetComponentTemplatesResponse;
import org.elasticsearch.client.indices.PutComponentTemplateRequest;
import org.elasticsearch.rest.RestStatus;
import java.io.IOException;
@ -169,4 +175,113 @@ public final class ClusterClient {
return restHighLevelClient.performRequestAsyncAndParseEntity(request, ClusterRequestConverters::remoteInfo, options,
RemoteInfoResponse::fromXContent, listener, singleton(RestStatus.REQUEST_TIMEOUT.getStatus()));
}
/**
* Delete a component template using the Component Templates API
*
* @param req the request
* @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
* @throws IOException in case there is a problem sending the request or parsing back the response
*/
public AcknowledgedResponse deleteComponentTemplate(DeleteComponentTemplateRequest req, RequestOptions options) throws IOException {
return restHighLevelClient.performRequestAndParseEntity(req, ClusterRequestConverters::deleteComponentTemplate,
options, AcknowledgedResponse::fromXContent, emptySet());
}
/**
* Asynchronously delete a component template using the Component Templates API
*
* @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
* @return cancellable that may be used to cancel the request
*/
public Cancellable deleteComponentTemplateAsync(DeleteComponentTemplateRequest request, RequestOptions options,
ActionListener<AcknowledgedResponse> listener) {
return restHighLevelClient.performRequestAsyncAndParseEntity(request, ClusterRequestConverters::deleteComponentTemplate,
options, AcknowledgedResponse::fromXContent, listener, emptySet());
}
/**
* Puts a component template using the Component Templates API.
*
* @param putComponentTemplateRequest 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 AcknowledgedResponse putComponentTemplate(PutComponentTemplateRequest putComponentTemplateRequest,
RequestOptions options) throws IOException {
return restHighLevelClient.performRequestAndParseEntity(putComponentTemplateRequest, ClusterRequestConverters::putComponentTemplate,
options, AcknowledgedResponse::fromXContent, emptySet());
}
/**
* Asynchronously puts a component template using the Component Templates API.
*
* @param putComponentTemplateRequest 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
* @return cancellable that may be used to cancel the request
*/
public Cancellable putComponentTemplateAsync(PutComponentTemplateRequest putComponentTemplateRequest,
RequestOptions options, ActionListener<AcknowledgedResponse> listener) {
return restHighLevelClient.performRequestAsyncAndParseEntity(putComponentTemplateRequest,
ClusterRequestConverters::putComponentTemplate, options, AcknowledgedResponse::fromXContent, listener, emptySet());
}
/**
* Gets component templates using the Components Templates API
* @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
* @param getComponentTemplatesRequest the request
* @return the response
* @throws IOException in case there is a problem sending the request or parsing back the response
*/
public GetComponentTemplatesResponse getComponentTemplate(GetComponentTemplatesRequest getComponentTemplatesRequest,
RequestOptions options) throws IOException {
return restHighLevelClient.performRequestAndParseEntity(getComponentTemplatesRequest,
ClusterRequestConverters::getComponentTemplates, options, GetComponentTemplatesResponse::fromXContent, emptySet());
}
/**
* Asynchronously gets component templates using the Components Templates API
* @param getComponentTemplatesRequest 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
* @return cancellable that may be used to cancel the request
*/
public Cancellable getComponentTemplateAsync(GetComponentTemplatesRequest getComponentTemplatesRequest, RequestOptions options,
ActionListener<GetComponentTemplatesResponse> listener) {
return restHighLevelClient.performRequestAsyncAndParseEntity(getComponentTemplatesRequest,
ClusterRequestConverters::getComponentTemplates, options, GetComponentTemplatesResponse::fromXContent, listener, emptySet());
}
/**
* Uses the Component Templates API to determine if component templates exist
*
* @param componentTemplatesRequest the request
* @param options the request options (e.g. headers), use {@link RequestOptions#DEFAULT} if nothing needs to be customized
* @return true if any index templates in the request exist, false otherwise
* @throws IOException in case there is a problem sending the request or parsing back the response
*/
public boolean existsComponentTemplate(ComponentTemplatesExistRequest componentTemplatesRequest,
RequestOptions options) throws IOException {
return restHighLevelClient.performRequest(componentTemplatesRequest,
ClusterRequestConverters::componentTemplatesExist, options, RestHighLevelClient::convertExistsResponse, emptySet());
}
/**
* Uses the Index Templates API to determine if index templates exist
* @param componentTemplatesRequest 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. The listener will be called with the value {@code true}
* @return cancellable that may be used to cancel the request
*/
public Cancellable existsComponentTemplateAsync(ComponentTemplatesExistRequest componentTemplatesRequest,
RequestOptions options,
ActionListener<Boolean> listener) {
return restHighLevelClient.performRequestAsync(componentTemplatesRequest,
ClusterRequestConverters::componentTemplatesExist, options, RestHighLevelClient::convertExistsResponse, listener, emptySet());
}
}

View File

@ -19,13 +19,19 @@
package org.elasticsearch.client;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpHead;
import org.apache.http.client.methods.HttpPut;
import org.elasticsearch.action.admin.cluster.health.ClusterHealthRequest;
import org.elasticsearch.action.admin.cluster.settings.ClusterGetSettingsRequest;
import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest;
import org.elasticsearch.action.support.ActiveShardCount;
import org.elasticsearch.client.cluster.RemoteInfoRequest;
import org.elasticsearch.client.indices.ComponentTemplatesExistRequest;
import org.elasticsearch.client.indices.DeleteComponentTemplateRequest;
import org.elasticsearch.client.indices.GetComponentTemplatesRequest;
import org.elasticsearch.client.indices.PutComponentTemplateRequest;
import org.elasticsearch.common.Strings;
import java.io.IOException;
@ -81,4 +87,57 @@ final class ClusterRequestConverters {
static Request remoteInfo(RemoteInfoRequest remoteInfoRequest) {
return new Request(HttpGet.METHOD_NAME, "/_remote/info");
}
static Request putComponentTemplate(PutComponentTemplateRequest putComponentTemplateRequest) throws IOException {
String endpoint = new RequestConverters.EndpointBuilder().addPathPartAsIs("_component_template")
.addPathPart(putComponentTemplateRequest.name()).build();
Request request = new Request(HttpPut.METHOD_NAME, endpoint);
RequestConverters.Params params = new RequestConverters.Params();
params.withMasterTimeout(putComponentTemplateRequest.masterNodeTimeout());
if (putComponentTemplateRequest.create()) {
params.putParam("create", Boolean.TRUE.toString());
}
if (Strings.hasText(putComponentTemplateRequest.cause())) {
params.putParam("cause", putComponentTemplateRequest.cause());
}
request.addParameters(params.asMap());
request.setEntity(RequestConverters.createEntity(putComponentTemplateRequest, RequestConverters.REQUEST_BODY_CONTENT_TYPE));
return request;
}
static Request getComponentTemplates(GetComponentTemplatesRequest getComponentTemplatesRequest){
final String endpoint = new RequestConverters.EndpointBuilder()
.addPathPartAsIs("_component_template")
.addPathPart(getComponentTemplatesRequest.name())
.build();
final Request request = new Request(HttpGet.METHOD_NAME, endpoint);
final RequestConverters.Params params = new RequestConverters.Params();
params.withLocal(getComponentTemplatesRequest.isLocal());
params.withMasterTimeout(getComponentTemplatesRequest.getMasterNodeTimeout());
request.addParameters(params.asMap());
return request;
}
static Request componentTemplatesExist(ComponentTemplatesExistRequest componentTemplatesRequest) {
final String endpoint = new RequestConverters.EndpointBuilder()
.addPathPartAsIs("_component_template")
.addPathPart(componentTemplatesRequest.name())
.build();
final Request request = new Request(HttpHead.METHOD_NAME, endpoint);
final RequestConverters.Params params = new RequestConverters.Params();
params.withLocal(componentTemplatesRequest.isLocal());
params.withMasterTimeout(componentTemplatesRequest.getMasterNodeTimeout());
request.addParameters(params.asMap());
return request;
}
static Request deleteComponentTemplate(DeleteComponentTemplateRequest deleteComponentTemplateRequest) {
String name = deleteComponentTemplateRequest.getName();
String endpoint = new RequestConverters.EndpointBuilder().addPathPartAsIs("_component_template").addPathPart(name).build();
Request request = new Request(HttpDelete.METHOD_NAME, endpoint);
RequestConverters.Params params = new RequestConverters.Params();
params.withMasterTimeout(deleteComponentTemplateRequest.masterNodeTimeout());
request.addParameters(params.asMap());
return request;
}
}

View File

@ -0,0 +1,40 @@
/*
* 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.indices;
import org.elasticsearch.common.Strings;
/**
* A request to check for the existence of component templates
*/
public class ComponentTemplatesExistRequest extends GetComponentTemplatesRequest {
/**
* Create a request to check for the existence of component template. Name must be provided
*
* @param name the name of template to check for the existence of
*/
public ComponentTemplatesExistRequest(String name) {
super(name);
if (Strings.isNullOrEmpty(name)) {
throw new IllegalArgumentException("must provide component template name");
}
}
}

View File

@ -0,0 +1,35 @@
/*
* 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.indices;
import org.elasticsearch.client.TimedRequest;
public class DeleteComponentTemplateRequest extends TimedRequest {
private final String name;
public DeleteComponentTemplateRequest(String name) {
this.name = name;
}
public String getName() {
return name;
}
}

View File

@ -0,0 +1,80 @@
/*
* 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.indices;
import org.elasticsearch.client.TimedRequest;
import org.elasticsearch.client.Validatable;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.unit.TimeValue;
/**
* A request to read the content of component templates
*/
public class GetComponentTemplatesRequest implements Validatable {
private final String name;
private TimeValue masterNodeTimeout = TimedRequest.DEFAULT_MASTER_NODE_TIMEOUT;
private boolean local = false;
/**
* Create a request to read the content of component template. If no template name is provided, all templates will
* be read
*
* @param name the name of template to read
*/
public GetComponentTemplatesRequest(String name) {
this.name = name;
}
/**
* @return the name of component template this request is requesting
*/
public String name() {
return name;
}
/**
* @return the timeout for waiting for the master node to respond
*/
public TimeValue getMasterNodeTimeout() {
return masterNodeTimeout;
}
public void setMasterNodeTimeout(@Nullable TimeValue masterNodeTimeout) {
this.masterNodeTimeout = masterNodeTimeout;
}
public void setMasterNodeTimeout(String masterNodeTimeout) {
final TimeValue timeValue = TimeValue.parseTimeValue(masterNodeTimeout, getClass().getSimpleName() + ".masterNodeTimeout");
setMasterNodeTimeout(timeValue);
}
/**
* @return true if this request is to read from the local cluster state, rather than the master node - false otherwise
*/
public boolean isLocal() {
return local;
}
public void setLocal(boolean local) {
this.local = local;
}
}

View File

@ -0,0 +1,108 @@
/*
* 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.indices;
import org.elasticsearch.cluster.metadata.ComponentTemplate;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
import org.elasticsearch.common.xcontent.XContentParser;
import java.io.IOException;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
public class GetComponentTemplatesResponse {
public static final ParseField NAME = new ParseField("name");
public static final ParseField COMPONENT_TEMPLATES = new ParseField("component_templates");
public static final ParseField COMPONENT_TEMPLATE = new ParseField("component_template");
@SuppressWarnings("unchecked")
private static final ConstructingObjectParser<Map<String, ComponentTemplate>, Void> PARSER =
new ConstructingObjectParser<>("component_templates", false,
a -> ((List<NamedComponentTemplate>) a[0]).stream().collect(Collectors.toMap(n -> n.name, n -> n.componentTemplate,
(n1, n2) -> n1, LinkedHashMap::new)));
private static final ConstructingObjectParser<NamedComponentTemplate, Void> INNER_PARSER =
new ConstructingObjectParser<>("named_component_template", false,
a -> new NamedComponentTemplate((String) a[0], (ComponentTemplate) a[1]));
static {
INNER_PARSER.declareString(ConstructingObjectParser.constructorArg(), NAME);
INNER_PARSER.declareObject(ConstructingObjectParser.constructorArg(), ComponentTemplate.PARSER, COMPONENT_TEMPLATE);
PARSER.declareObjectArray(ConstructingObjectParser.constructorArg(), INNER_PARSER, COMPONENT_TEMPLATES);
}
private static class NamedComponentTemplate {
String name;
ComponentTemplate componentTemplate;
private NamedComponentTemplate(String name, ComponentTemplate componentTemplate) {
this.name = name;
this.componentTemplate = componentTemplate;
}
}
@Override
public String toString() {
return "GetIndexTemplatesResponse [indexTemplates=" + componentTemplates + "]";
}
private final Map<String, ComponentTemplate> componentTemplates;
GetComponentTemplatesResponse(Map<String, ComponentTemplate> componentTemplates) {
this.componentTemplates = Collections.unmodifiableMap(new LinkedHashMap<>(componentTemplates));
}
public Map<String, ComponentTemplate> getComponentTemplates() {
return componentTemplates;
}
public static GetComponentTemplatesResponse fromXContent(XContentParser parser) throws IOException {
return new GetComponentTemplatesResponse(PARSER.apply(parser, null));
}
@Override
public int hashCode() {
return Objects.hash(componentTemplates);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
GetComponentTemplatesResponse other = (GetComponentTemplatesResponse) obj;
return Objects.equals(componentTemplates, other.componentTemplates);
}
}

View File

@ -0,0 +1,100 @@
/*
* 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.indices;
import org.elasticsearch.client.TimedRequest;
import org.elasticsearch.cluster.metadata.ComponentTemplate;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.xcontent.ToXContentObject;
import org.elasticsearch.common.xcontent.XContentBuilder;
import java.io.IOException;
/**
* A request to create an component template.
*/
public class PutComponentTemplateRequest extends TimedRequest implements ToXContentObject {
private String name;
private String cause = "";
private boolean create;
private ComponentTemplate componentTemplate;
/**
* Sets the name of the component template.
*/
public PutComponentTemplateRequest name(String name) {
if (Strings.isNullOrEmpty(name)) {
throw new IllegalArgumentException("name cannot be null or empty");
}
this.name = name;
return this;
}
/**
* The name of the component template.
*/
public String name() {
return this.name;
}
/**
* Set to {@code true} to force only creation, not an update of an component template. If it already
* exists, it will fail with an {@link IllegalArgumentException}.
*/
public PutComponentTemplateRequest create(boolean create) {
this.create = create;
return this;
}
public boolean create() {
return create;
}
/**
* The component template to create.
*/
public PutComponentTemplateRequest componentTemplate(ComponentTemplate componentTemplate) {
this.componentTemplate = componentTemplate;
return this;
}
/**
* The cause for this component template creation.
*/
public PutComponentTemplateRequest cause(String cause) {
this.cause = cause;
return this;
}
public String cause() {
return this.cause;
}
@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
if (componentTemplate != null) {
componentTemplate.toXContent(builder, params);
}
return builder;
}
}

View File

@ -21,20 +21,31 @@ package org.elasticsearch.client;
import org.apache.http.util.EntityUtils;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.ElasticsearchStatusException;
import org.elasticsearch.action.admin.cluster.health.ClusterHealthRequest;
import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
import org.elasticsearch.action.admin.cluster.settings.ClusterGetSettingsRequest;
import org.elasticsearch.action.admin.cluster.settings.ClusterGetSettingsResponse;
import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsRequest;
import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.client.cluster.RemoteConnectionInfo;
import org.elasticsearch.client.cluster.RemoteInfoRequest;
import org.elasticsearch.client.cluster.RemoteInfoResponse;
import org.elasticsearch.client.cluster.SniffModeInfo;
import org.elasticsearch.client.indices.ComponentTemplatesExistRequest;
import org.elasticsearch.client.indices.DeleteComponentTemplateRequest;
import org.elasticsearch.client.indices.GetComponentTemplatesRequest;
import org.elasticsearch.client.indices.GetComponentTemplatesResponse;
import org.elasticsearch.client.indices.PutComponentTemplateRequest;
import org.elasticsearch.cluster.health.ClusterHealthStatus;
import org.elasticsearch.cluster.health.ClusterIndexHealth;
import org.elasticsearch.cluster.health.ClusterShardHealth;
import org.elasticsearch.cluster.metadata.AliasMetadata;
import org.elasticsearch.cluster.metadata.ComponentTemplate;
import org.elasticsearch.cluster.metadata.Template;
import org.elasticsearch.cluster.routing.allocation.decider.EnableAllocationDecider;
import org.elasticsearch.common.compress.CompressedXContent;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.ByteSizeUnit;
import org.elasticsearch.common.unit.TimeValue;
@ -46,6 +57,7 @@ import org.elasticsearch.transport.RemoteClusterService;
import org.elasticsearch.transport.SniffConnectionStrategy;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -342,4 +354,48 @@ public class ClusterClientIT extends ESRestHighLevelClientTestCase {
assertThat(sniffModeInfo.getSeedNodes(), equalTo(seeds));
}
public void testComponentTemplates() throws Exception {
String templateName = "my-template";
Settings settings = Settings.builder().put("index.number_of_shards", 1).build();
CompressedXContent mappings = new CompressedXContent("{\"properties\":{\"host_name\":{\"type\":\"keyword\"}}}");
AliasMetadata alias = AliasMetadata.builder("alias").writeIndex(true).build();
Template template = new Template(settings, mappings, Collections.singletonMap("alias", alias));
ComponentTemplate componentTemplate = new ComponentTemplate(template, 1L, new HashMap<>());
PutComponentTemplateRequest putComponentTemplateRequest =
new PutComponentTemplateRequest().name(templateName).create(true).componentTemplate(componentTemplate);
AcknowledgedResponse response = execute(putComponentTemplateRequest,
highLevelClient().cluster()::putComponentTemplate, highLevelClient().cluster()::putComponentTemplateAsync);
assertThat(response.isAcknowledged(), equalTo(true));
ComponentTemplatesExistRequest componentTemplatesExistRequest = new ComponentTemplatesExistRequest(templateName);
boolean exist = execute(componentTemplatesExistRequest,
highLevelClient().cluster()::existsComponentTemplate, highLevelClient().cluster()::existsComponentTemplateAsync);
assertTrue(exist);
GetComponentTemplatesRequest getComponentTemplatesRequest = new GetComponentTemplatesRequest(templateName);
GetComponentTemplatesResponse getResponse = execute(getComponentTemplatesRequest,
highLevelClient().cluster()::getComponentTemplate, highLevelClient().cluster()::getComponentTemplateAsync);
assertThat(getResponse.getComponentTemplates().size(), equalTo(1));
assertThat(getResponse.getComponentTemplates().containsKey(templateName), equalTo(true));
assertThat(getResponse.getComponentTemplates().get(templateName), equalTo(componentTemplate));
DeleteComponentTemplateRequest deleteComponentTemplateRequest = new DeleteComponentTemplateRequest(templateName);
response = execute(deleteComponentTemplateRequest, highLevelClient().cluster()::deleteComponentTemplate,
highLevelClient().cluster()::deleteComponentTemplateAsync);
assertThat(response.isAcknowledged(), equalTo(true));
ElasticsearchStatusException statusException = expectThrows(ElasticsearchStatusException.class,
() -> execute(getComponentTemplatesRequest,
highLevelClient().cluster()::getComponentTemplate, highLevelClient().cluster()::getComponentTemplateAsync));
assertThat(statusException.status(), equalTo(RestStatus.NOT_FOUND));
exist = execute(componentTemplatesExistRequest,
highLevelClient().cluster()::existsComponentTemplate, highLevelClient().cluster()::existsComponentTemplateAsync);
assertFalse(exist);
}
}

View File

@ -858,9 +858,6 @@ public class RestHighLevelClientTests extends ESTestCase {
"indices.put_alias",
"render_search_template",
"scripts_painless_execute",
"cluster.put_component_template",
"cluster.get_component_template",
"cluster.delete_component_template",
"indices.create_data_stream",
"indices.get_data_streams",
"indices.delete_data_stream",

View File

@ -0,0 +1,131 @@
/*
* 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.indices;
import org.elasticsearch.cluster.metadata.AliasMetadata;
import org.elasticsearch.cluster.metadata.ComponentTemplate;
import org.elasticsearch.cluster.metadata.Template;
import org.elasticsearch.common.compress.CompressedXContent;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.test.ESTestCase;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import static org.elasticsearch.test.AbstractXContentTestCase.xContentTester;
public class GetComponentTemplatesResponseTests extends ESTestCase {
public void testFromXContent() throws Exception {
xContentTester(
this::createParser,
GetComponentTemplatesResponseTests::createTestInstance,
GetComponentTemplatesResponseTests::toXContent,
GetComponentTemplatesResponse::fromXContent)
.supportsUnknownFields(true)
.randomFieldsExcludeFilter(a -> true)
.test();
}
private static GetComponentTemplatesResponse createTestInstance() {
Map<String, ComponentTemplate> templates = new HashMap<>();
if (randomBoolean()) {
int count = randomInt(10);
for (int i = 0; i < count; i++) {
templates.put(randomAlphaOfLength(10), randomTemplate());
}
}
return new GetComponentTemplatesResponse(templates);
}
private static void toXContent(GetComponentTemplatesResponse response, XContentBuilder builder) throws IOException {
builder.startObject();
builder.startArray("component_templates");
for (Map.Entry<String, ComponentTemplate> e : response.getComponentTemplates().entrySet()) {
builder.startObject();
builder.field("name", e.getKey());
builder.field("component_template");
e.getValue().toXContent(builder, null);
builder.endObject();
}
builder.endArray();
builder.endObject();
}
private static ComponentTemplate randomTemplate() {
Settings settings = null;
CompressedXContent mappings = null;
Map<String, AliasMetadata> aliases = null;
if (randomBoolean()) {
settings = randomSettings();
}
if (randomBoolean()) {
mappings = randomMappings();
}
if (randomBoolean()) {
aliases = randomAliases();
}
Template template = new Template(settings, mappings, aliases);
Map<String, Object> meta = null;
if (randomBoolean()) {
meta = randomMeta();
}
return new ComponentTemplate(template, randomBoolean() ? null : randomNonNegativeLong(), meta);
}
private static Map<String, AliasMetadata> randomAliases() {
String aliasName = randomAlphaOfLength(5);
AliasMetadata aliasMeta = AliasMetadata.builder(aliasName)
.filter(Collections.singletonMap(randomAlphaOfLength(2), randomAlphaOfLength(2)))
.routing(randomBoolean() ? null : randomAlphaOfLength(3))
.isHidden(randomBoolean() ? null : randomBoolean())
.writeIndex(randomBoolean() ? null : randomBoolean())
.build();
return Collections.singletonMap(aliasName, aliasMeta);
}
private static CompressedXContent randomMappings() {
try {
return new CompressedXContent("{\"" + randomAlphaOfLength(3) + "\":\"" + randomAlphaOfLength(7) + "\"}");
} catch (IOException e) {
fail("got an IO exception creating fake mappings: " + e);
return null;
}
}
private static Settings randomSettings() {
return Settings.builder()
.put(randomAlphaOfLength(4), randomAlphaOfLength(10))
.build();
}
private static Map<String, Object> randomMeta() {
if (randomBoolean()) {
return Collections.singletonMap(randomAlphaOfLength(4), randomAlphaOfLength(4));
} else {
return Collections.singletonMap(randomAlphaOfLength(5),
Collections.singletonMap(randomAlphaOfLength(4), randomAlphaOfLength(4)));
}
}
}

View File

@ -0,0 +1,35 @@
{
"cluster.exists_component_template":{
"documentation":{
"url":"https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-component-templates.html",
"description":"Returns information about whether a particular component template exist"
},
"stability":"stable",
"url":{
"paths":[
{
"path":"/_component_template/{name}",
"methods":[
"HEAD"
],
"parts":{
"name":{
"type":"string",
"description":"The name of the template"
}
}
}
]
},
"params":{
"master_timeout":{
"type":"time",
"description":"Explicit operation timeout for connection to master node"
},
"local":{
"type":"boolean",
"description":"Return local information, do not retrieve the state from master node (default: false)"
}
}
}
}

View File

@ -47,7 +47,7 @@ public class ComponentTemplate extends AbstractDiffable<ComponentTemplate> imple
private static final ParseField METADATA = new ParseField("_meta");
@SuppressWarnings("unchecked")
private static final ConstructingObjectParser<ComponentTemplate, Void> PARSER =
public static final ConstructingObjectParser<ComponentTemplate, Void> PARSER =
new ConstructingObjectParser<>("component_template", false,
a -> new ComponentTemplate((Template) a[0], (Long) a[1], (Map<String, Object>) a[2]));