Browse Source

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
Alexander Lin 9 years ago
parent
commit
d31a8e6558

+ 2 - 0
core/src/main/java/org/elasticsearch/action/ActionModule.java

@@ -288,6 +288,7 @@ import org.elasticsearch.rest.action.cat.RestSegmentsAction;
 import org.elasticsearch.rest.action.cat.RestShardsAction;
 import org.elasticsearch.rest.action.cat.RestSnapshotAction;
 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.document.RestBulkAction;
 import org.elasticsearch.rest.action.document.RestDeleteAction;
@@ -603,6 +604,7 @@ public class ActionModule extends AbstractModule {
         registerRestHandler(handlers, RestNodeAttrsAction.class);
         registerRestHandler(handlers, RestRepositoriesAction.class);
         registerRestHandler(handlers, RestSnapshotAction.class);
+        registerRestHandler(handlers, RestTemplatesAction.class);
         for (ActionPlugin plugin : actionPlugins) {
             for (Class<? extends RestHandler> handler : plugin.getRestHandlers()) {
                 registerRestHandler(handlers, handler);

+ 97 - 0
core/src/main/java/org/elasticsearch/rest/action/cat/RestTemplatesAction.java

@@ -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;
+    }
+}

+ 2 - 0
docs/reference/cat.asciidoc

@@ -186,3 +186,5 @@ include::cat/shards.asciidoc[]
 include::cat/segments.asciidoc[]
 
 include::cat/snapshots.asciidoc[]
+
+include::cat/templates.asciidoc[]

+ 20 - 0
docs/reference/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`.

+ 45 - 0
rest-api-spec/src/main/resources/rest-api-spec/api/cat.templates.json

@@ -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
+  }
+}

+ 174 - 0
rest-api-spec/src/main/resources/rest-api-spec/test/cat.templates/10_basic.yaml

@@ -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
+                $/
+