Provides a cat api endpoint for templates. (#20545)
Adds a cat api endpoint: /_cat/templates and its more specific version, /_cat/templates/{name}. It looks something like: $ curl "localhost:9200/_cat/templates?v" name template order version sushi_california_roll *avocado* 1 1 pizza_hawaiian *pineapples* 1 pizza_pepperoni *pepperoni* 1 The specified version (only allows * globs) looks like: $ curl "localhost:9200/_cat/templates/pizza*" name template order version pizza_hawaiian *pineapples* 1 pizza_pepperoni *pepperoni* 1 Partially specified columns: $ curl "localhost:9200/_cat/templates/pizza*?v=true&h=name,template" name template pizza_hawaiian *pineapples* pizza_pepperoni *pepperoni* The help text: $ curl "localhost:9200/_cat/templates/pizza*?help" name | n | template name template | t | template pattern string order | o | template application order number version | v | version Closes #20467
This commit is contained in:
parent
6921b4a66b
commit
d31a8e6558
|
@ -288,6 +288,7 @@ import org.elasticsearch.rest.action.cat.RestSegmentsAction;
|
||||||
import org.elasticsearch.rest.action.cat.RestShardsAction;
|
import org.elasticsearch.rest.action.cat.RestShardsAction;
|
||||||
import org.elasticsearch.rest.action.cat.RestSnapshotAction;
|
import org.elasticsearch.rest.action.cat.RestSnapshotAction;
|
||||||
import org.elasticsearch.rest.action.cat.RestTasksAction;
|
import org.elasticsearch.rest.action.cat.RestTasksAction;
|
||||||
|
import org.elasticsearch.rest.action.cat.RestTemplatesAction;
|
||||||
import org.elasticsearch.rest.action.cat.RestThreadPoolAction;
|
import org.elasticsearch.rest.action.cat.RestThreadPoolAction;
|
||||||
import org.elasticsearch.rest.action.document.RestBulkAction;
|
import org.elasticsearch.rest.action.document.RestBulkAction;
|
||||||
import org.elasticsearch.rest.action.document.RestDeleteAction;
|
import org.elasticsearch.rest.action.document.RestDeleteAction;
|
||||||
|
@ -603,6 +604,7 @@ public class ActionModule extends AbstractModule {
|
||||||
registerRestHandler(handlers, RestNodeAttrsAction.class);
|
registerRestHandler(handlers, RestNodeAttrsAction.class);
|
||||||
registerRestHandler(handlers, RestRepositoriesAction.class);
|
registerRestHandler(handlers, RestRepositoriesAction.class);
|
||||||
registerRestHandler(handlers, RestSnapshotAction.class);
|
registerRestHandler(handlers, RestSnapshotAction.class);
|
||||||
|
registerRestHandler(handlers, RestTemplatesAction.class);
|
||||||
for (ActionPlugin plugin : actionPlugins) {
|
for (ActionPlugin plugin : actionPlugins) {
|
||||||
for (Class<? extends RestHandler> handler : plugin.getRestHandlers()) {
|
for (Class<? extends RestHandler> handler : plugin.getRestHandlers()) {
|
||||||
registerRestHandler(handlers, handler);
|
registerRestHandler(handlers, handler);
|
||||||
|
|
|
@ -0,0 +1,97 @@
|
||||||
|
/*
|
||||||
|
* 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.rest.action.cat;
|
||||||
|
|
||||||
|
import com.carrotsearch.hppc.cursors.ObjectObjectCursor;
|
||||||
|
import org.elasticsearch.action.admin.cluster.state.ClusterStateRequest;
|
||||||
|
import org.elasticsearch.action.admin.cluster.state.ClusterStateResponse;
|
||||||
|
import org.elasticsearch.client.node.NodeClient;
|
||||||
|
import org.elasticsearch.cluster.metadata.IndexTemplateMetaData;
|
||||||
|
import org.elasticsearch.cluster.metadata.MetaData;
|
||||||
|
import org.elasticsearch.common.Table;
|
||||||
|
import org.elasticsearch.common.inject.Inject;
|
||||||
|
import org.elasticsearch.common.regex.Regex;
|
||||||
|
import org.elasticsearch.common.settings.Settings;
|
||||||
|
import org.elasticsearch.rest.RestChannel;
|
||||||
|
import org.elasticsearch.rest.RestController;
|
||||||
|
import org.elasticsearch.rest.RestRequest;
|
||||||
|
import org.elasticsearch.rest.RestResponse;
|
||||||
|
import org.elasticsearch.rest.action.RestResponseListener;
|
||||||
|
|
||||||
|
import static org.elasticsearch.rest.RestRequest.Method.GET;
|
||||||
|
|
||||||
|
public class RestTemplatesAction extends AbstractCatAction {
|
||||||
|
@Inject
|
||||||
|
public RestTemplatesAction(Settings settings, RestController controller) {
|
||||||
|
super(settings);
|
||||||
|
controller.registerHandler(GET, "/_cat/templates", this);
|
||||||
|
controller.registerHandler(GET, "/_cat/templates/{name}", this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void documentation(StringBuilder sb) {
|
||||||
|
sb.append("/_cat/templates\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doRequest(final RestRequest request, RestChannel channel, NodeClient client) {
|
||||||
|
final String matchPattern = request.hasParam("name") ? request.param("name") : null;
|
||||||
|
final ClusterStateRequest clusterStateRequest = new ClusterStateRequest();
|
||||||
|
clusterStateRequest.clear().metaData(true);
|
||||||
|
clusterStateRequest.local(request.paramAsBoolean("local", clusterStateRequest.local()));
|
||||||
|
clusterStateRequest.masterNodeTimeout(request.paramAsTime("master_timeout", clusterStateRequest.masterNodeTimeout()));
|
||||||
|
|
||||||
|
client.admin().cluster().state(clusterStateRequest, new RestResponseListener<ClusterStateResponse>(channel) {
|
||||||
|
@Override
|
||||||
|
public RestResponse buildResponse(ClusterStateResponse clusterStateResponse) throws Exception {
|
||||||
|
return RestTable.buildResponse(buildTable(request, clusterStateResponse, matchPattern), channel);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Table getTableWithHeader(RestRequest request) {
|
||||||
|
Table table = new Table();
|
||||||
|
table.startHeaders();
|
||||||
|
table.addCell("name", "alias:n;desc:template name");
|
||||||
|
table.addCell("template", "alias:t;desc:template pattern string");
|
||||||
|
table.addCell("order", "alias:o;desc:template application order number");
|
||||||
|
table.addCell("version", "alias:v;desc:version");
|
||||||
|
table.endHeaders();
|
||||||
|
return table;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Table buildTable(RestRequest request, ClusterStateResponse clusterStateResponse, String patternString) {
|
||||||
|
Table table = getTableWithHeader(request);
|
||||||
|
MetaData metadata = clusterStateResponse.getState().metaData();
|
||||||
|
for (ObjectObjectCursor<String, IndexTemplateMetaData> entry : metadata.templates()) {
|
||||||
|
IndexTemplateMetaData indexData = entry.value;
|
||||||
|
if (patternString == null || Regex.simpleMatch(patternString, indexData.name())) {
|
||||||
|
table.startRow();
|
||||||
|
table.addCell(indexData.name());
|
||||||
|
table.addCell(indexData.getTemplate());
|
||||||
|
table.addCell(indexData.getOrder());
|
||||||
|
table.addCell(indexData.getVersion());
|
||||||
|
table.endRow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return table;
|
||||||
|
}
|
||||||
|
}
|
|
@ -186,3 +186,5 @@ include::cat/shards.asciidoc[]
|
||||||
include::cat/segments.asciidoc[]
|
include::cat/segments.asciidoc[]
|
||||||
|
|
||||||
include::cat/snapshots.asciidoc[]
|
include::cat/snapshots.asciidoc[]
|
||||||
|
|
||||||
|
include::cat/templates.asciidoc[]
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
[[cat-templates]]
|
||||||
|
== cat templates
|
||||||
|
|
||||||
|
The `templates` command provides information about existing templates.
|
||||||
|
|
||||||
|
[source, sh]
|
||||||
|
--------------------------------------------------
|
||||||
|
% curl 'localhost:9200/_cat/templates?v=true'
|
||||||
|
name template order version
|
||||||
|
template0 te* 0
|
||||||
|
template1 tea* 1
|
||||||
|
template2 teak* 2 7
|
||||||
|
--------------------------------------------------
|
||||||
|
|
||||||
|
The output shows that there are three existing templates,
|
||||||
|
with template_2 having a version value.
|
||||||
|
|
||||||
|
The endpoint also supports giving a template name or pattern in the url
|
||||||
|
to filter the results, for example `/_cat/templates/template*` or
|
||||||
|
`/_cat/templates/template0`.
|
|
@ -0,0 +1,45 @@
|
||||||
|
{
|
||||||
|
"cat.templates": {
|
||||||
|
"documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/master/cat-templates.html",
|
||||||
|
"methods": ["GET"],
|
||||||
|
"url": {
|
||||||
|
"path": "/_cat/templates",
|
||||||
|
"paths": ["/_cat/templates", "/_cat/templates/{name}"],
|
||||||
|
"parts": {
|
||||||
|
"name": {
|
||||||
|
"type" : "string",
|
||||||
|
"description" : "A pattern that returned template names must match"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"params": {
|
||||||
|
"format": {
|
||||||
|
"type" : "string",
|
||||||
|
"description" : "a short version of the Accept header, e.g. json, yaml"
|
||||||
|
},
|
||||||
|
"local": {
|
||||||
|
"type" : "boolean",
|
||||||
|
"description" : "Return local information, do not retrieve the state from master node (default: false)"
|
||||||
|
},
|
||||||
|
"master_timeout": {
|
||||||
|
"type" : "time",
|
||||||
|
"description" : "Explicit operation timeout for connection to master node"
|
||||||
|
},
|
||||||
|
"h": {
|
||||||
|
"type": "list",
|
||||||
|
"description" : "Comma-separated list of column names to display"
|
||||||
|
},
|
||||||
|
"help": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Return help information",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"v": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Verbose mode. Display column headers",
|
||||||
|
"default": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"body": null
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,174 @@
|
||||||
|
---
|
||||||
|
"Help":
|
||||||
|
|
||||||
|
- do:
|
||||||
|
cat.templates:
|
||||||
|
help: true
|
||||||
|
|
||||||
|
- match:
|
||||||
|
$body: |
|
||||||
|
/^ name .+ \n
|
||||||
|
template .+ \n
|
||||||
|
order .+ \n
|
||||||
|
version .+ \n
|
||||||
|
$/
|
||||||
|
|
||||||
|
---
|
||||||
|
"No templates":
|
||||||
|
|
||||||
|
- do:
|
||||||
|
cat.templates: {}
|
||||||
|
|
||||||
|
- match:
|
||||||
|
$body: |
|
||||||
|
/^
|
||||||
|
$/
|
||||||
|
|
||||||
|
---
|
||||||
|
"Normal templates":
|
||||||
|
|
||||||
|
- do:
|
||||||
|
indices.put_template:
|
||||||
|
name: test
|
||||||
|
body:
|
||||||
|
order: 0
|
||||||
|
version: 1
|
||||||
|
template: test-*
|
||||||
|
settings:
|
||||||
|
number_of_shards: 1
|
||||||
|
number_of_replicas: 0
|
||||||
|
|
||||||
|
- do:
|
||||||
|
indices.put_template:
|
||||||
|
name: test_2
|
||||||
|
body:
|
||||||
|
order: 1
|
||||||
|
version: 2
|
||||||
|
template: test-2*
|
||||||
|
settings:
|
||||||
|
number_of_shards: 1
|
||||||
|
number_of_replicas: 0
|
||||||
|
|
||||||
|
- do:
|
||||||
|
cat.templates: {}
|
||||||
|
|
||||||
|
- match:
|
||||||
|
$body: /
|
||||||
|
(^|\n)test \s+
|
||||||
|
test-\* \s+
|
||||||
|
0 \s+
|
||||||
|
1
|
||||||
|
(\n|$)
|
||||||
|
/
|
||||||
|
|
||||||
|
- match:
|
||||||
|
$body: /
|
||||||
|
(^|\n)test_2 \s+
|
||||||
|
test-2\* \s+
|
||||||
|
1 \s+
|
||||||
|
2
|
||||||
|
(\n|$)
|
||||||
|
/
|
||||||
|
|
||||||
|
---
|
||||||
|
"Filtered templates":
|
||||||
|
|
||||||
|
- do:
|
||||||
|
indices.put_template:
|
||||||
|
name: test
|
||||||
|
body:
|
||||||
|
order: 0
|
||||||
|
version: 1
|
||||||
|
template: t*
|
||||||
|
settings:
|
||||||
|
number_of_shards: 1
|
||||||
|
number_of_replicas: 0
|
||||||
|
|
||||||
|
- do:
|
||||||
|
indices.put_template:
|
||||||
|
name: nomatch
|
||||||
|
body:
|
||||||
|
order: 2
|
||||||
|
version: 1
|
||||||
|
template: tea*
|
||||||
|
settings:
|
||||||
|
number_of_shards: 1
|
||||||
|
number_of_replicas: 0
|
||||||
|
|
||||||
|
- do:
|
||||||
|
cat.templates:
|
||||||
|
name: test*
|
||||||
|
|
||||||
|
- match:
|
||||||
|
$body: |
|
||||||
|
/^
|
||||||
|
test \s+
|
||||||
|
t\* \s+
|
||||||
|
0 \s+
|
||||||
|
1
|
||||||
|
\n
|
||||||
|
$/
|
||||||
|
|
||||||
|
---
|
||||||
|
"Column headers":
|
||||||
|
|
||||||
|
- do:
|
||||||
|
indices.put_template:
|
||||||
|
name: test
|
||||||
|
body:
|
||||||
|
order: 0
|
||||||
|
version: 1
|
||||||
|
template: t*
|
||||||
|
settings:
|
||||||
|
number_of_shards: 1
|
||||||
|
number_of_replicas: 0
|
||||||
|
|
||||||
|
- do:
|
||||||
|
cat.templates:
|
||||||
|
v: true
|
||||||
|
|
||||||
|
- match:
|
||||||
|
$body: |
|
||||||
|
/^
|
||||||
|
name \s+
|
||||||
|
template \s+
|
||||||
|
order \s+
|
||||||
|
version
|
||||||
|
\n
|
||||||
|
test \s+
|
||||||
|
t\* \s+
|
||||||
|
0 \s+
|
||||||
|
1
|
||||||
|
\n
|
||||||
|
$/
|
||||||
|
|
||||||
|
---
|
||||||
|
"Select columns":
|
||||||
|
|
||||||
|
- do:
|
||||||
|
indices.put_template:
|
||||||
|
name: test
|
||||||
|
body:
|
||||||
|
order: 0
|
||||||
|
version: 1
|
||||||
|
template: t*
|
||||||
|
settings:
|
||||||
|
number_of_shards: 1
|
||||||
|
number_of_replicas: 0
|
||||||
|
|
||||||
|
- do:
|
||||||
|
cat.templates:
|
||||||
|
h: [name, template]
|
||||||
|
v: true
|
||||||
|
|
||||||
|
- match:
|
||||||
|
$body: |
|
||||||
|
/^
|
||||||
|
name \s+
|
||||||
|
template
|
||||||
|
\n
|
||||||
|
test \s+
|
||||||
|
t\*
|
||||||
|
\n
|
||||||
|
$/
|
||||||
|
|
Loading…
Reference in New Issue