[7.x] Only allow retrieving a single index or component templa… (#54896)

* Only allow retrieving a single index or component template

This changes the Index Template v2 APIs to only allow retrieving a single "named" entity, where the
named entity can be nothing (return everything), a wildcard (return the ones that match), or the
name of a template.

Relates to #53101

* Throw exception when resource is not found

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
Lee Hinman 2020-04-07 08:55:44 -06:00 committed by GitHub
parent 3c56e0de42
commit 72f8457f52
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 57 additions and 81 deletions

View File

@ -24,8 +24,8 @@ import org.elasticsearch.action.ActionResponse;
import org.elasticsearch.action.ActionType;
import org.elasticsearch.action.support.master.MasterNodeReadRequest;
import org.elasticsearch.cluster.metadata.ComponentTemplate;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.ToXContentObject;
@ -36,8 +36,6 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import static org.elasticsearch.action.ValidateActions.addValidationError;
/**
* Action to retrieve one or more component templates
*/
@ -55,53 +53,44 @@ public class GetComponentTemplateAction extends ActionType<GetComponentTemplateA
*/
public static class Request extends MasterNodeReadRequest<Request> {
private String[] names;
@Nullable
private String name;
public Request() { }
public Request(String... names) {
this.names = names;
public Request(String name) {
this.name = name;
}
public Request(StreamInput in) throws IOException {
super(in);
names = in.readStringArray();
name = in.readOptionalString();
}
@Override
public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out);
out.writeStringArray(names);
out.writeOptionalString(name);
}
@Override
public ActionRequestValidationException validate() {
ActionRequestValidationException validationException = null;
if (names == null) {
validationException = addValidationError("names is null or empty", validationException);
} else {
for (String name : names) {
if (name == null || Strings.hasText(name) == false) {
validationException = addValidationError("name is missing", validationException);
}
}
}
return validationException;
return null;
}
/**
* Sets the names of the component templates.
* Sets the name of the component templates.
*/
public Request names(String... names) {
this.names = names;
public Request name(String name) {
this.name = name;
return this;
}
/**
* The names of the component templates.
* The name of the component templates.
*/
public String[] names() {
return this.names;
public String name() {
return this.name;
}
}

View File

@ -24,21 +24,18 @@ import org.elasticsearch.action.ActionResponse;
import org.elasticsearch.action.ActionType;
import org.elasticsearch.action.support.master.MasterNodeReadRequest;
import org.elasticsearch.cluster.metadata.IndexTemplateV2;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.ParseField;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.ToXContentObject;
import org.elasticsearch.common.xcontent.XContentBuilder;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import static org.elasticsearch.action.ValidateActions.addValidationError;
public class GetIndexTemplateV2Action extends ActionType<GetIndexTemplateV2Action.Response> {
public static final GetIndexTemplateV2Action INSTANCE = new GetIndexTemplateV2Action();
@ -53,58 +50,49 @@ public class GetIndexTemplateV2Action extends ActionType<GetIndexTemplateV2Actio
*/
public static class Request extends MasterNodeReadRequest<Request> {
private String[] names;
@Nullable
private String name;
public Request() { }
public Request(String... names) {
this.names = names;
public Request(@Nullable String name) {
this.name = name;
}
public Request(StreamInput in) throws IOException {
super(in);
names = in.readStringArray();
name = in.readOptionalString();
}
@Override
public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out);
out.writeStringArray(names);
out.writeOptionalString(name);
}
@Override
public ActionRequestValidationException validate() {
ActionRequestValidationException validationException = null;
if (names == null) {
validationException = addValidationError("names is null or empty", validationException);
} else {
for (String name : names) {
if (name == null || Strings.hasText(name) == false) {
validationException = addValidationError("name is missing", validationException);
}
}
}
return validationException;
return null;
}
/**
* Sets the names of the index templates.
* Sets the name of the index template.
*/
public Request names(String... names) {
this.names = names;
public Request name(String name) {
this.name = name;
return this;
}
/**
* The names of the index templates.
* The name of the index templates.
*/
public String[] names() {
return this.names;
public String name() {
return this.name;
}
@Override
public int hashCode() {
return Arrays.hashCode(names);
return Objects.hash(name);
}
@Override
@ -116,7 +104,7 @@ public class GetIndexTemplateV2Action extends ActionType<GetIndexTemplateV2Actio
return false;
}
Request other = (Request) obj;
return Arrays.equals(other.names, this.names);
return Objects.equals(name, other.name);
}
}

View File

@ -19,6 +19,7 @@
package org.elasticsearch.action.admin.indices.template.get;
import org.elasticsearch.ResourceNotFoundException;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.support.ActionFilters;
import org.elasticsearch.action.support.master.TransportMasterNodeReadAction;
@ -70,22 +71,23 @@ public class TransportGetComponentTemplateAction extends
Map<String, ComponentTemplate> allTemplates = state.metadata().componentTemplates();
// If we did not ask for a specific name, then we return all templates
if (request.names().length == 0) {
if (request.name() == null) {
listener.onResponse(new GetComponentTemplateAction.Response(allTemplates));
return;
}
final Map<String, ComponentTemplate> results = new HashMap<>();
for (String name : request.names()) {
if (Regex.isSimpleMatchPattern(name)) {
for (Map.Entry<String, ComponentTemplate> entry : allTemplates.entrySet()) {
if (Regex.simpleMatch(name, entry.getKey())) {
results.put(entry.getKey(), entry.getValue());
}
String name = request.name();
if (Regex.isSimpleMatchPattern(name)) {
for (Map.Entry<String, ComponentTemplate> entry : allTemplates.entrySet()) {
if (Regex.simpleMatch(name, entry.getKey())) {
results.put(entry.getKey(), entry.getValue());
}
} else if (allTemplates.containsKey(name)) {
results.put(name, allTemplates.get(name));
}
} else if (allTemplates.containsKey(name)) {
results.put(name, allTemplates.get(name));
} else {
throw new ResourceNotFoundException("component template matching [" + request.name() + "] not found");
}
listener.onResponse(new GetComponentTemplateAction.Response(results));

View File

@ -19,6 +19,7 @@
package org.elasticsearch.action.admin.indices.template.get;
import org.elasticsearch.ResourceNotFoundException;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.support.ActionFilters;
import org.elasticsearch.action.support.master.TransportMasterNodeReadAction;
@ -70,22 +71,23 @@ public class TransportGetIndexTemplateV2Action
Map<String, IndexTemplateV2> allTemplates = state.metadata().templatesV2();
// If we did not ask for a specific name, then we return all templates
if (request.names().length == 0) {
if (request.name() == null) {
listener.onResponse(new GetIndexTemplateV2Action.Response(allTemplates));
return;
}
final Map<String, IndexTemplateV2> results = new HashMap<>();
for (String name : request.names()) {
if (Regex.isSimpleMatchPattern(name)) {
for (Map.Entry<String, IndexTemplateV2> entry : allTemplates.entrySet()) {
if (Regex.simpleMatch(name, entry.getKey())) {
results.put(entry.getKey(), entry.getValue());
}
String name = request.name();
if (Regex.isSimpleMatchPattern(name)) {
for (Map.Entry<String, IndexTemplateV2> entry : allTemplates.entrySet()) {
if (Regex.simpleMatch(name, entry.getKey())) {
results.put(entry.getKey(), entry.getValue());
}
} else if (allTemplates.containsKey(name)) {
results.put(name, allTemplates.get(name));
}
} else if (allTemplates.containsKey(name)) {
results.put(name, allTemplates.get(name));
} else {
throw new ResourceNotFoundException("index template matching [" + request.name() + "] not found");
}
listener.onResponse(new GetIndexTemplateV2Action.Response(results));

View File

@ -21,7 +21,6 @@ package org.elasticsearch.rest.action.admin.indices;
import org.elasticsearch.action.admin.indices.template.get.GetComponentTemplateAction;
import org.elasticsearch.client.node.NodeClient;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.rest.BaseRestHandler;
import org.elasticsearch.rest.RestRequest;
@ -55,14 +54,13 @@ public class RestGetComponentTemplateAction extends BaseRestHandler {
@Override
public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException {
final String[] names = Strings.splitStringByCommaToArray(request.param("name"));
final GetComponentTemplateAction.Request getRequest = new GetComponentTemplateAction.Request(names);
final GetComponentTemplateAction.Request getRequest = new GetComponentTemplateAction.Request(request.param("name"));
getRequest.local(request.paramAsBoolean("local", getRequest.local()));
getRequest.masterNodeTimeout(request.paramAsTime("master_timeout", getRequest.masterNodeTimeout()));
final boolean implicitAll = getRequest.names().length == 0;
final boolean implicitAll = getRequest.name() == null;
return channel ->
client.execute(GetComponentTemplateAction.INSTANCE, getRequest,

View File

@ -21,7 +21,6 @@ package org.elasticsearch.rest.action.admin.indices;
import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplateV2Action;
import org.elasticsearch.client.node.NodeClient;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.rest.BaseRestHandler;
import org.elasticsearch.rest.RestRequest;
@ -55,14 +54,12 @@ public class RestGetIndexTemplateV2Action extends BaseRestHandler {
@Override
public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException {
final String[] names = Strings.splitStringByCommaToArray(request.param("name"));
final GetIndexTemplateV2Action.Request getRequest = new GetIndexTemplateV2Action.Request(names);
final GetIndexTemplateV2Action.Request getRequest = new GetIndexTemplateV2Action.Request(request.param("name"));
getRequest.local(request.paramAsBoolean("local", getRequest.local()));
getRequest.masterNodeTimeout(request.paramAsTime("master_timeout", getRequest.masterNodeTimeout()));
final boolean implicitAll = getRequest.names().length == 0;
final boolean implicitAll = getRequest.name() == null;
return channel ->
client.execute(GetIndexTemplateV2Action.INSTANCE, getRequest,

View File

@ -32,7 +32,7 @@ public class GetIndexTemplateV2RequestTests extends AbstractWireSerializingTestC
@Override
protected GetIndexTemplateV2Action.Request createTestInstance() {
return new GetIndexTemplateV2Action.Request(generateRandomStringArray(5, 5, false, false));
return new GetIndexTemplateV2Action.Request(randomBoolean() ? null : randomAlphaOfLength(4));
}
@Override