Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Run TransportGetComposableIndexTemplate on local node #119830

Merged
merged 2 commits into from
Jan 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions docs/changelog/119830.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pr: 119830
summary: Run `TransportGetComposableIndexTemplate` on local node
area: Indices APIs
type: enhancement
issues: []
2 changes: 1 addition & 1 deletion docs/reference/indices/get-index-template.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ expressions. If omitted, all templates are returned.

include::{docdir}/rest-api/common-parms.asciidoc[tag=flat-settings]

include::{docdir}/rest-api/common-parms.asciidoc[tag=local]
include::{docdir}/rest-api/common-parms.asciidoc[tag=local-deprecated-9.0.0]

include::{docdir}/rest-api/common-parms.asciidoc[tag=master-timeout]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -718,7 +718,7 @@ public void testCannotDeleteComposableTemplateUsedByDataStream() throws Exceptio
TransportDeleteComposableIndexTemplateAction.Request deleteRequest = new TransportDeleteComposableIndexTemplateAction.Request("id");
client().execute(TransportDeleteComposableIndexTemplateAction.TYPE, deleteRequest).get();

GetComposableIndexTemplateAction.Request getReq = new GetComposableIndexTemplateAction.Request("id");
GetComposableIndexTemplateAction.Request getReq = new GetComposableIndexTemplateAction.Request(TEST_REQUEST_TIMEOUT, "id");
Exception e3 = expectThrows(Exception.class, client().execute(GetComposableIndexTemplateAction.INSTANCE, getReq));
maybeE = ExceptionsHelper.unwrapCausesAndSuppressed(e3, err -> err.getMessage().contains("index template matching [id] not found"));
assertTrue(maybeE.isPresent());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import org.elasticsearch.action.admin.indices.alias.get.GetAliasesAction;
import org.elasticsearch.action.admin.indices.recovery.RecoveryAction;
import org.elasticsearch.action.admin.indices.template.get.GetComponentTemplateAction;
import org.elasticsearch.action.admin.indices.template.get.GetComposableIndexTemplateAction;
import org.elasticsearch.action.support.CancellableActionTestPlugin;
import org.elasticsearch.action.support.PlainActionFuture;
import org.elasticsearch.action.support.RefCountingListener;
Expand Down Expand Up @@ -71,6 +72,10 @@ public void testGetComponentTemplateCancellation() {
runRestActionCancellationTest(new Request(HttpGet.METHOD_NAME, "/_component_template"), GetComponentTemplateAction.NAME);
}

public void testGetComposableTemplateCancellation() {
runRestActionCancellationTest(new Request(HttpGet.METHOD_NAME, "/_index_template"), GetComposableIndexTemplateAction.NAME);
}

private void runRestActionCancellationTest(Request request, String actionName) {
final var node = usually() ? internalCluster().getRandomNodeName() : internalCluster().startCoordinatingOnlyNode(Settings.EMPTY);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,10 @@
},
"master_timeout":{
"type":"time",
"description":"Explicit operation timeout for connection to master node"
"description":"Timeout for waiting for new cluster state in case it is blocked"
},
"local":{
"deprecated":true,
"type":"boolean",
"description":"Return local information, do not retrieve the state from master node (default: false)"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,10 @@
},
"master_timeout":{
"type":"time",
"description":"Explicit operation timeout for connection to master node"
"description":"Timeout for waiting for new cluster state in case it is blocked"
},
"local":{
"deprecated":true,
"type":"boolean",
"description":"Return local information, do not retrieve the state from master node (default: false)"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,14 +82,48 @@ setup:

---
"Get index template with local flag":
- requires:
test_runner_features: ["allowed_warnings"]

- do:
indices.get_index_template:
name: test
local: true
allowed_warnings:
- "the [?local] query parameter to this API has no effect, is now deprecated, and will be removed in a future version"

- match: {index_templates.0.name: test}

---
"Deprecated local parameter":
- requires:
capabilities:
- method: GET
path: /_get_index_template
capabilities: ["local_param_deprecated"]
test_runner_features: ["capabilities", "warnings"]
reason: Deprecation was implemented with capability

- do:
indices.get_index_template:
local: true
warnings:
- "the [?local] query parameter to this API has no effect, is now deprecated, and will be removed in a future version"

---
"Deprecated local parameter works in v8 compat mode":
- requires:
test_runner_features: ["headers"]

- do:
headers:
Content-Type: "application/vnd.elasticsearch+json;compatible-with=8"
Accept: "application/vnd.elasticsearch+json;compatible-with=8"
indices.get_index_template:
local: true

- exists: index_templates

---
"Add data stream lifecycle":
- requires:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,7 @@ private void assertComponentAndIndexTemplateDelete(CountDownLatch savedClusterSt

final var response = client().execute(
GetComposableIndexTemplateAction.INSTANCE,
new GetComposableIndexTemplateAction.Request("template*")
new GetComposableIndexTemplateAction.Request(TEST_REQUEST_TIMEOUT, "template*")
).get();

assertThat(response.indexTemplates().keySet().stream().collect(Collectors.toSet()), containsInAnyOrder("template_1", "template_2"));
Expand Down Expand Up @@ -594,7 +594,7 @@ private void assertClusterStateNotSaved(CountDownLatch savedClusterState, Atomic

final var response = client().execute(
GetComposableIndexTemplateAction.INSTANCE,
new GetComposableIndexTemplateAction.Request("err*")
new GetComposableIndexTemplateAction.Request(TEST_REQUEST_TIMEOUT, "err*")
).get();

assertTrue(response.indexTemplates().isEmpty());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,17 @@
import org.elasticsearch.action.ActionResponse;
import org.elasticsearch.action.ActionType;
import org.elasticsearch.action.admin.indices.rollover.RolloverConfiguration;
import org.elasticsearch.action.support.master.MasterNodeReadRequest;
import org.elasticsearch.action.support.local.LocalClusterStateRequest;
import org.elasticsearch.cluster.metadata.ComposableIndexTemplate;
import org.elasticsearch.cluster.metadata.DataStreamGlobalRetention;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.core.Nullable;
import org.elasticsearch.core.TimeValue;
import org.elasticsearch.core.UpdateForV10;
import org.elasticsearch.tasks.CancellableTask;
import org.elasticsearch.tasks.Task;
import org.elasticsearch.tasks.TaskId;
import org.elasticsearch.xcontent.ParseField;
import org.elasticsearch.xcontent.ToXContentObject;
import org.elasticsearch.xcontent.XContentBuilder;
Expand All @@ -40,24 +45,30 @@ private GetComposableIndexTemplateAction() {
/**
* Request that to retrieve one or more index templates
*/
public static class Request extends MasterNodeReadRequest<Request> {
public static class Request extends LocalClusterStateRequest {

@Nullable
private final String name;
private boolean includeDefaults;

/**
* @param masterTimeout Timeout for waiting for new cluster state in case it is blocked.
* @param name A template name or pattern, or {@code null} to retrieve all templates.
*/
public Request(@Nullable String name) {
super(TRAPPY_IMPLICIT_DEFAULT_MASTER_NODE_TIMEOUT);
public Request(TimeValue masterTimeout, @Nullable String name) {
super(masterTimeout);
if (name != null && name.contains(",")) {
throw new IllegalArgumentException("template name may not contain ','");
}
this.name = name;
this.includeDefaults = false;
}

/**
* NB prior to 9.0 this was a TransportMasterNodeReadAction so for BwC we must remain able to read these requests until
* we no longer need to support calling this action remotely.
*/
@UpdateForV10(owner = UpdateForV10.Owner.DATA_MANAGEMENT)
public Request(StreamInput in) throws IOException {
super(in);
name = in.readOptionalString();
Expand All @@ -68,15 +79,6 @@ public Request(StreamInput in) throws IOException {
}
}

@Override
public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out);
out.writeOptionalString(name);
if (out.getTransportVersion().onOrAfter(TransportVersions.V_8_9_X)) {
out.writeBoolean(includeDefaults);
}
}

public void includeDefaults(boolean includeDefaults) {
this.includeDefaults = includeDefaults;
}
Expand All @@ -90,6 +92,11 @@ public ActionRequestValidationException validate() {
return null;
}

@Override
public Task createTask(long id, String type, String action, TaskId parentTaskId, Map<String, String> headers) {
return new CancellableTask(id, type, action, "", parentTaskId, headers);
}

/**
* The name of the index templates.
*/
Expand Down Expand Up @@ -124,19 +131,6 @@ public static class Response extends ActionResponse implements ToXContentObject
@Nullable
private final RolloverConfiguration rolloverConfiguration;

public Response(StreamInput in) throws IOException {
super(in);
indexTemplates = in.readMap(ComposableIndexTemplate::new);
if (in.getTransportVersion().onOrAfter(TransportVersions.V_8_9_X)) {
rolloverConfiguration = in.readOptionalWriteable(RolloverConfiguration::new);
} else {
rolloverConfiguration = null;
}
if (in.getTransportVersion().between(TransportVersions.V_8_14_0, TransportVersions.V_8_16_0)) {
in.readOptionalWriteable(DataStreamGlobalRetention::read);
}
}

/**
* Please use {@link GetComposableIndexTemplateAction.Response#Response(Map)}
*/
Expand Down Expand Up @@ -184,6 +178,11 @@ public RolloverConfiguration getRolloverConfiguration() {
return rolloverConfiguration;
}

/**
* NB prior to 9.0 this was a TransportMasterNodeReadAction so for BwC we must remain able to write these responses until
* we no longer need to support calling this action remotely.
*/
@UpdateForV10(owner = UpdateForV10.Owner.DATA_MANAGEMENT)
@Override
public void writeTo(StreamOutput out) throws IOException {
out.writeMap(indexTemplates, StreamOutput::writeWriteable);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,51 +12,61 @@
import org.elasticsearch.ResourceNotFoundException;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.support.ActionFilters;
import org.elasticsearch.action.support.master.TransportMasterNodeReadAction;
import org.elasticsearch.action.support.ChannelActionListener;
import org.elasticsearch.action.support.local.TransportLocalClusterStateAction;
import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.block.ClusterBlockException;
import org.elasticsearch.cluster.block.ClusterBlockLevel;
import org.elasticsearch.cluster.metadata.ComposableIndexTemplate;
import org.elasticsearch.cluster.metadata.DataStreamLifecycle;
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.regex.Regex;
import org.elasticsearch.common.settings.ClusterSettings;
import org.elasticsearch.common.util.concurrent.EsExecutors;
import org.elasticsearch.core.UpdateForV10;
import org.elasticsearch.injection.guice.Inject;
import org.elasticsearch.tasks.CancellableTask;
import org.elasticsearch.tasks.Task;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportService;

import java.util.HashMap;
import java.util.Map;

public class TransportGetComposableIndexTemplateAction extends TransportMasterNodeReadAction<
public class TransportGetComposableIndexTemplateAction extends TransportLocalClusterStateAction<
GetComposableIndexTemplateAction.Request,
GetComposableIndexTemplateAction.Response> {

private final ClusterSettings clusterSettings;

/**
* NB prior to 9.0 this was a TransportMasterNodeReadAction so for BwC it must be registered with the TransportService until
* we no longer need to support calling this action remotely.
*/
@UpdateForV10(owner = UpdateForV10.Owner.DATA_MANAGEMENT)
@SuppressWarnings("this-escape")
@Inject
public TransportGetComposableIndexTemplateAction(
TransportService transportService,
ClusterService clusterService,
ThreadPool threadPool,
ActionFilters actionFilters,
IndexNameExpressionResolver indexNameExpressionResolver
ActionFilters actionFilters
) {
super(
GetComposableIndexTemplateAction.NAME,
transportService,
clusterService,
threadPool,
actionFilters,
GetComposableIndexTemplateAction.Request::new,
indexNameExpressionResolver,
GetComposableIndexTemplateAction.Response::new,
transportService.getTaskManager(),
clusterService,
EsExecutors.DIRECT_EXECUTOR_SERVICE
);
clusterSettings = clusterService.getClusterSettings();

transportService.registerRequestHandler(
actionName,
executor,
false,
true,
GetComposableIndexTemplateAction.Request::new,
(request, channel, task) -> executeDirect(task, request, new ChannelActionListener<>(channel))
);
}

@Override
Expand All @@ -65,12 +75,13 @@ protected ClusterBlockException checkBlock(GetComposableIndexTemplateAction.Requ
}

@Override
protected void masterOperation(
protected void localClusterStateOperation(
Task task,
GetComposableIndexTemplateAction.Request request,
ClusterState state,
ActionListener<GetComposableIndexTemplateAction.Response> listener
) {
final var cancellableTask = (CancellableTask) task;
Map<String, ComposableIndexTemplate> allTemplates = state.metadata().templatesV2();
Map<String, ComposableIndexTemplate> results;
// If we did not ask for a specific name, then we return all templates
Expand All @@ -91,6 +102,7 @@ protected void masterOperation(
throw new ResourceNotFoundException("index template matching [" + request.name() + "] not found");
}
}
cancellableTask.ensureNotCancelled();
if (request.includeDefaults()) {
listener.onResponse(
new GetComposableIndexTemplateAction.Response(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,10 @@
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.rest.BaseRestHandler;
import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.rest.RestUtils;
import org.elasticsearch.rest.Scope;
import org.elasticsearch.rest.ServerlessScope;
import org.elasticsearch.rest.action.RestCancellableNodeClient;
import org.elasticsearch.rest.action.RestToXContentListener;

import java.io.IOException;
Expand All @@ -26,7 +28,6 @@
import static org.elasticsearch.rest.RestRequest.Method.HEAD;
import static org.elasticsearch.rest.RestStatus.NOT_FOUND;
import static org.elasticsearch.rest.RestStatus.OK;
import static org.elasticsearch.rest.RestUtils.getMasterNodeTimeout;

@ServerlessScope(Scope.PUBLIC)
public class RestGetComposableIndexTemplateAction extends BaseRestHandler {
Expand All @@ -47,17 +48,23 @@ public String getName() {

@Override
public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException {
final GetComposableIndexTemplateAction.Request getRequest = new GetComposableIndexTemplateAction.Request(request.param("name"));

getRequest.local(request.paramAsBoolean("local", getRequest.local()));
getRequest.masterNodeTimeout(getMasterNodeTimeout(request));
final GetComposableIndexTemplateAction.Request getRequest = new GetComposableIndexTemplateAction.Request(
RestUtils.getMasterNodeTimeout(request),
request.param("name")
);
getRequest.includeDefaults(request.paramAsBoolean("include_defaults", false));
RestUtils.consumeDeprecatedLocalParameter(request);

final boolean implicitAll = getRequest.name() == null;

return channel -> client.execute(GetComposableIndexTemplateAction.INSTANCE, getRequest, new RestToXContentListener<>(channel, r -> {
final boolean templateExists = r.indexTemplates().isEmpty() == false;
return (templateExists || implicitAll) ? OK : NOT_FOUND;
}));
return channel -> new RestCancellableNodeClient(client, request.getHttpChannel()).execute(
GetComposableIndexTemplateAction.INSTANCE,
getRequest,
new RestToXContentListener<>(channel, r -> {
final boolean templateExists = r.indexTemplates().isEmpty() == false;
return (templateExists || implicitAll) ? OK : NOT_FOUND;
})
);
}

@Override
Expand Down
Loading