* Add REST APIs for IndexTemplateV2Metadata CRUD (#54039) * Add REST APIs for IndexTemplateV2Metadata CRUD This commit adds the get/put/delete APIs for interacting with the now v2 versions of index templates. These APIs are behind the existing `es.itv2_feature_flag_registered` system property feature flag. Relates to #53101 * Add exceptions for HLRC tests * Add skips for 7.x versions * Use index_template instead of template_v2 in action names * Add test for MetaDataIndexTemplateService.addIndexTemplateV2 * Move removal to static method and add test * Add unit tests for request classes (implement hashCode & equals) Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com> * Fix compilation Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
parent
1690e78646
commit
f2cc2b1127
|
@ -801,7 +801,9 @@ public class RestHighLevelClientTests extends ESTestCase {
|
||||||
"cluster.delete_component_template",
|
"cluster.delete_component_template",
|
||||||
"indices.create_data_stream",
|
"indices.create_data_stream",
|
||||||
"indices.get_data_streams",
|
"indices.get_data_streams",
|
||||||
"indices.delete_data_stream"
|
"indices.delete_data_stream",
|
||||||
|
"indices.put_index_template",
|
||||||
|
"indices.delete_index_template"
|
||||||
};
|
};
|
||||||
//These API are not required for high-level client feature completeness
|
//These API are not required for high-level client feature completeness
|
||||||
String[] notRequiredApi = new String[] {
|
String[] notRequiredApi = new String[] {
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
{
|
||||||
|
"indices.delete_index_template":{
|
||||||
|
"documentation":{
|
||||||
|
"url":"https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-templates.html",
|
||||||
|
"description":"Deletes an index template."
|
||||||
|
},
|
||||||
|
"stability":"stable",
|
||||||
|
"url":{
|
||||||
|
"paths":[
|
||||||
|
{
|
||||||
|
"path":"/_index_template/{name}",
|
||||||
|
"methods":[
|
||||||
|
"DELETE"
|
||||||
|
],
|
||||||
|
"parts":{
|
||||||
|
"name":{
|
||||||
|
"type":"string",
|
||||||
|
"description":"The name of the template"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"params":{
|
||||||
|
"timeout":{
|
||||||
|
"type":"time",
|
||||||
|
"description":"Explicit operation timeout"
|
||||||
|
},
|
||||||
|
"master_timeout":{
|
||||||
|
"type":"time",
|
||||||
|
"description":"Specify timeout for connection to master"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
{
|
||||||
|
"indices.get_index_template":{
|
||||||
|
"documentation":{
|
||||||
|
"url":"https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-templates.html",
|
||||||
|
"description":"Returns an index template."
|
||||||
|
},
|
||||||
|
"stability":"stable",
|
||||||
|
"url":{
|
||||||
|
"paths":[
|
||||||
|
{
|
||||||
|
"path":"/_index_template",
|
||||||
|
"methods":[
|
||||||
|
"GET"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path":"/_index_template/{name}",
|
||||||
|
"methods":[
|
||||||
|
"GET"
|
||||||
|
],
|
||||||
|
"parts":{
|
||||||
|
"name":{
|
||||||
|
"type":"list",
|
||||||
|
"description":"The comma separated names of the index templates"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"params":{
|
||||||
|
"flat_settings":{
|
||||||
|
"type":"boolean",
|
||||||
|
"description":"Return settings in flat format (default: false)"
|
||||||
|
},
|
||||||
|
"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)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
{
|
||||||
|
"indices.put_index_template":{
|
||||||
|
"documentation":{
|
||||||
|
"url":"https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-templates.html",
|
||||||
|
"description":"Creates or updates an index template."
|
||||||
|
},
|
||||||
|
"stability":"stable",
|
||||||
|
"url":{
|
||||||
|
"paths":[
|
||||||
|
{
|
||||||
|
"path":"/_index_template/{name}",
|
||||||
|
"methods":[
|
||||||
|
"PUT",
|
||||||
|
"POST"
|
||||||
|
],
|
||||||
|
"parts":{
|
||||||
|
"name":{
|
||||||
|
"type":"string",
|
||||||
|
"description":"The name of the template"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"params":{
|
||||||
|
"order":{
|
||||||
|
"type":"number",
|
||||||
|
"description":"The order for this template when merging multiple matching ones (higher numbers are merged later, overriding the lower numbers)"
|
||||||
|
},
|
||||||
|
"create":{
|
||||||
|
"type":"boolean",
|
||||||
|
"description":"Whether the index template should only be added if new or can also replace an existing one",
|
||||||
|
"default":false
|
||||||
|
},
|
||||||
|
"master_timeout":{
|
||||||
|
"type":"time",
|
||||||
|
"description":"Specify timeout for connection to master"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"body":{
|
||||||
|
"description":"The template definition",
|
||||||
|
"required":true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
setup:
|
||||||
|
- skip:
|
||||||
|
version: " - 7.7.99"
|
||||||
|
reason: "index template v2 API unavailable before 7.8"
|
||||||
|
|
||||||
|
- do:
|
||||||
|
indices.put_index_template:
|
||||||
|
name: test
|
||||||
|
body:
|
||||||
|
index_patterns: test-*
|
||||||
|
template:
|
||||||
|
settings:
|
||||||
|
number_of_shards: 1
|
||||||
|
number_of_replicas: 0
|
||||||
|
mappings:
|
||||||
|
properties:
|
||||||
|
field:
|
||||||
|
type: keyword
|
||||||
|
|
||||||
|
---
|
||||||
|
"Get index template":
|
||||||
|
- skip:
|
||||||
|
version: " - 7.7.99"
|
||||||
|
reason: "index template v2 API unavailable before 7.8"
|
||||||
|
|
||||||
|
- do:
|
||||||
|
indices.get_index_template:
|
||||||
|
name: test
|
||||||
|
|
||||||
|
- match: {index_templates.0.name: test}
|
||||||
|
- match: {index_templates.0.index_template.index_patterns: ["test-*"]}
|
||||||
|
- match: {index_templates.0.index_template.template.settings: {index: {number_of_shards: '1', number_of_replicas: '0'}}}
|
||||||
|
- match: {index_templates.0.index_template.template.mappings: {properties: {field: {type: keyword}}}}
|
||||||
|
|
||||||
|
---
|
||||||
|
"Get all tindex emplates":
|
||||||
|
- skip:
|
||||||
|
version: " - 7.7.99"
|
||||||
|
reason: "index template v2 API unavailable before 7.8"
|
||||||
|
|
||||||
|
- do:
|
||||||
|
indices.put_index_template:
|
||||||
|
name: test2
|
||||||
|
body:
|
||||||
|
index_patterns: test2-*
|
||||||
|
template:
|
||||||
|
settings:
|
||||||
|
number_of_shards: 1
|
||||||
|
|
||||||
|
- do:
|
||||||
|
indices.get_index_template: {}
|
||||||
|
|
||||||
|
- length: {index_templates: 2}
|
||||||
|
|
||||||
|
---
|
||||||
|
"Get index template with local flag":
|
||||||
|
- skip:
|
||||||
|
version: " - 7.7.99"
|
||||||
|
reason: "index template v2 API unavailable before 7.8"
|
||||||
|
|
||||||
|
- do:
|
||||||
|
indices.get_index_template:
|
||||||
|
name: test
|
||||||
|
local: true
|
||||||
|
|
||||||
|
- match: {index_templates.0.name: test}
|
|
@ -0,0 +1,20 @@
|
||||||
|
setup:
|
||||||
|
- skip:
|
||||||
|
version: " - 7.7.99"
|
||||||
|
reason: "index template v2 API unavailable before 7.8"
|
||||||
|
|
||||||
|
- do:
|
||||||
|
indices.delete_index_template:
|
||||||
|
name: '*'
|
||||||
|
ignore: 404
|
||||||
|
---
|
||||||
|
"Get missing template":
|
||||||
|
- skip:
|
||||||
|
version: " - 7.7.99"
|
||||||
|
reason: "index template v2 API unavailable before 7.8"
|
||||||
|
|
||||||
|
- do:
|
||||||
|
catch: missing
|
||||||
|
indices.get_index_template:
|
||||||
|
name: test
|
||||||
|
|
|
@ -0,0 +1,112 @@
|
||||||
|
---
|
||||||
|
"Put index template":
|
||||||
|
- skip:
|
||||||
|
version: " - 7.7.99"
|
||||||
|
reason: "index template v2 API unavailable before 7.8"
|
||||||
|
|
||||||
|
- do:
|
||||||
|
indices.put_index_template:
|
||||||
|
name: test
|
||||||
|
body:
|
||||||
|
index_patterns: test-*
|
||||||
|
template:
|
||||||
|
settings:
|
||||||
|
number_of_shards: 1
|
||||||
|
number_of_replicas: 0
|
||||||
|
mappings:
|
||||||
|
properties:
|
||||||
|
field:
|
||||||
|
type: keyword
|
||||||
|
|
||||||
|
- do:
|
||||||
|
indices.get_index_template:
|
||||||
|
name: test
|
||||||
|
|
||||||
|
- match: {index_templates.0.name: "test"}
|
||||||
|
- match: {index_templates.0.index_template.index_patterns: ["test-*"]}
|
||||||
|
- match: {index_templates.0.index_template.template.settings.index: {number_of_shards: '1', number_of_replicas: '0'}}
|
||||||
|
- match: {index_templates.0.index_template.template.mappings: {properties: {field: {type: keyword}}}}
|
||||||
|
|
||||||
|
---
|
||||||
|
"Put multiple index templates":
|
||||||
|
- skip:
|
||||||
|
version: " - 7.7.99"
|
||||||
|
reason: "index template v2 API unavailable before 7.8"
|
||||||
|
|
||||||
|
- do:
|
||||||
|
indices.put_index_template:
|
||||||
|
name: test
|
||||||
|
body:
|
||||||
|
index_patterns: [test-*, test2-*]
|
||||||
|
template:
|
||||||
|
settings:
|
||||||
|
number_of_shards: 1
|
||||||
|
number_of_replicas: 0
|
||||||
|
mappings:
|
||||||
|
properties:
|
||||||
|
field:
|
||||||
|
type: text
|
||||||
|
aliases:
|
||||||
|
test_alias: {}
|
||||||
|
test_blias: { routing: b }
|
||||||
|
test_clias: { filter: { term: { user: kimchy }}}
|
||||||
|
|
||||||
|
- do:
|
||||||
|
indices.get_index_template:
|
||||||
|
name: test
|
||||||
|
|
||||||
|
- match: {index_templates.0.index_template.index_patterns: ["test-*", "test2-*"]}
|
||||||
|
- match: {index_templates.0.index_template.template.settings.index: {number_of_shards: '1', number_of_replicas: '0'}}
|
||||||
|
- match: {index_templates.0.index_template.template.mappings: {properties: {field: {type: text}}}}
|
||||||
|
- length: {index_templates.0.index_template.template.aliases: 3}
|
||||||
|
- is_true: index_templates.0.index_template.template.aliases.test_alias
|
||||||
|
- match: {index_templates.0.index_template.template.aliases.test_blias.index_routing: "b" }
|
||||||
|
- match: {index_templates.0.index_template.template.aliases.test_blias.search_routing: "b" }
|
||||||
|
- match: {index_templates.0.index_template.template.aliases.test_clias.filter.term.user: "kimchy" }
|
||||||
|
|
||||||
|
---
|
||||||
|
"Put index template with 'create' flag":
|
||||||
|
- skip:
|
||||||
|
version: " - 7.7.99"
|
||||||
|
reason: "index template v2 API unavailable before 7.8"
|
||||||
|
|
||||||
|
- do:
|
||||||
|
indices.put_index_template:
|
||||||
|
name: test2
|
||||||
|
body:
|
||||||
|
index_patterns: test-*
|
||||||
|
template:
|
||||||
|
settings:
|
||||||
|
number_of_shards: 1
|
||||||
|
number_of_replicas: 0
|
||||||
|
|
||||||
|
- do:
|
||||||
|
indices.get_index_template:
|
||||||
|
name: test2
|
||||||
|
|
||||||
|
- match: {index_templates.0.index_template.index_patterns: ["test-*"]}
|
||||||
|
- match: {index_templates.0.index_template.template.settings.index: {number_of_shards: '1', number_of_replicas: '0'}}
|
||||||
|
|
||||||
|
- do:
|
||||||
|
catch: bad_request
|
||||||
|
indices.put_index_template:
|
||||||
|
name: test2
|
||||||
|
create: true
|
||||||
|
body:
|
||||||
|
index_patterns: test-*
|
||||||
|
template:
|
||||||
|
settings:
|
||||||
|
number_of_shards: 1
|
||||||
|
number_of_replicas: 0
|
||||||
|
|
||||||
|
---
|
||||||
|
"Put index template without index_patterns":
|
||||||
|
- skip:
|
||||||
|
version: " - 7.7.99"
|
||||||
|
reason: "index template v2 API unavailable before 7.8"
|
||||||
|
|
||||||
|
- do:
|
||||||
|
catch: bad_request
|
||||||
|
indices.put_index_template:
|
||||||
|
name: test
|
||||||
|
body: {}
|
|
@ -153,16 +153,22 @@ import org.elasticsearch.action.admin.indices.stats.IndicesStatsAction;
|
||||||
import org.elasticsearch.action.admin.indices.stats.TransportIndicesStatsAction;
|
import org.elasticsearch.action.admin.indices.stats.TransportIndicesStatsAction;
|
||||||
import org.elasticsearch.action.admin.indices.template.delete.DeleteComponentTemplateAction;
|
import org.elasticsearch.action.admin.indices.template.delete.DeleteComponentTemplateAction;
|
||||||
import org.elasticsearch.action.admin.indices.template.delete.DeleteIndexTemplateAction;
|
import org.elasticsearch.action.admin.indices.template.delete.DeleteIndexTemplateAction;
|
||||||
|
import org.elasticsearch.action.admin.indices.template.delete.DeleteIndexTemplateV2Action;
|
||||||
import org.elasticsearch.action.admin.indices.template.delete.TransportDeleteComponentTemplateAction;
|
import org.elasticsearch.action.admin.indices.template.delete.TransportDeleteComponentTemplateAction;
|
||||||
import org.elasticsearch.action.admin.indices.template.delete.TransportDeleteIndexTemplateAction;
|
import org.elasticsearch.action.admin.indices.template.delete.TransportDeleteIndexTemplateAction;
|
||||||
|
import org.elasticsearch.action.admin.indices.template.delete.TransportDeleteIndexTemplateV2Action;
|
||||||
import org.elasticsearch.action.admin.indices.template.get.GetComponentTemplateAction;
|
import org.elasticsearch.action.admin.indices.template.get.GetComponentTemplateAction;
|
||||||
|
import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplateV2Action;
|
||||||
import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesAction;
|
import org.elasticsearch.action.admin.indices.template.get.GetIndexTemplatesAction;
|
||||||
import org.elasticsearch.action.admin.indices.template.get.TransportGetComponentTemplateAction;
|
import org.elasticsearch.action.admin.indices.template.get.TransportGetComponentTemplateAction;
|
||||||
|
import org.elasticsearch.action.admin.indices.template.get.TransportGetIndexTemplateV2Action;
|
||||||
import org.elasticsearch.action.admin.indices.template.get.TransportGetIndexTemplatesAction;
|
import org.elasticsearch.action.admin.indices.template.get.TransportGetIndexTemplatesAction;
|
||||||
import org.elasticsearch.action.admin.indices.template.put.PutComponentTemplateAction;
|
import org.elasticsearch.action.admin.indices.template.put.PutComponentTemplateAction;
|
||||||
import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateAction;
|
import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateAction;
|
||||||
|
import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateV2Action;
|
||||||
import org.elasticsearch.action.admin.indices.template.put.TransportPutComponentTemplateAction;
|
import org.elasticsearch.action.admin.indices.template.put.TransportPutComponentTemplateAction;
|
||||||
import org.elasticsearch.action.admin.indices.template.put.TransportPutIndexTemplateAction;
|
import org.elasticsearch.action.admin.indices.template.put.TransportPutIndexTemplateAction;
|
||||||
|
import org.elasticsearch.action.admin.indices.template.put.TransportPutIndexTemplateV2Action;
|
||||||
import org.elasticsearch.action.admin.indices.upgrade.get.TransportUpgradeStatusAction;
|
import org.elasticsearch.action.admin.indices.upgrade.get.TransportUpgradeStatusAction;
|
||||||
import org.elasticsearch.action.admin.indices.upgrade.get.UpgradeStatusAction;
|
import org.elasticsearch.action.admin.indices.upgrade.get.UpgradeStatusAction;
|
||||||
import org.elasticsearch.action.admin.indices.upgrade.post.TransportUpgradeAction;
|
import org.elasticsearch.action.admin.indices.upgrade.post.TransportUpgradeAction;
|
||||||
|
@ -287,12 +293,14 @@ import org.elasticsearch.rest.action.admin.indices.RestCreateIndexAction;
|
||||||
import org.elasticsearch.rest.action.admin.indices.RestDeleteComponentTemplateAction;
|
import org.elasticsearch.rest.action.admin.indices.RestDeleteComponentTemplateAction;
|
||||||
import org.elasticsearch.rest.action.admin.indices.RestDeleteIndexAction;
|
import org.elasticsearch.rest.action.admin.indices.RestDeleteIndexAction;
|
||||||
import org.elasticsearch.rest.action.admin.indices.RestDeleteIndexTemplateAction;
|
import org.elasticsearch.rest.action.admin.indices.RestDeleteIndexTemplateAction;
|
||||||
|
import org.elasticsearch.rest.action.admin.indices.RestDeleteIndexTemplateV2Action;
|
||||||
import org.elasticsearch.rest.action.admin.indices.RestFlushAction;
|
import org.elasticsearch.rest.action.admin.indices.RestFlushAction;
|
||||||
import org.elasticsearch.rest.action.admin.indices.RestForceMergeAction;
|
import org.elasticsearch.rest.action.admin.indices.RestForceMergeAction;
|
||||||
import org.elasticsearch.rest.action.admin.indices.RestGetAliasesAction;
|
import org.elasticsearch.rest.action.admin.indices.RestGetAliasesAction;
|
||||||
import org.elasticsearch.rest.action.admin.indices.RestGetComponentTemplateAction;
|
import org.elasticsearch.rest.action.admin.indices.RestGetComponentTemplateAction;
|
||||||
import org.elasticsearch.rest.action.admin.indices.RestGetFieldMappingAction;
|
import org.elasticsearch.rest.action.admin.indices.RestGetFieldMappingAction;
|
||||||
import org.elasticsearch.rest.action.admin.indices.RestGetIndexTemplateAction;
|
import org.elasticsearch.rest.action.admin.indices.RestGetIndexTemplateAction;
|
||||||
|
import org.elasticsearch.rest.action.admin.indices.RestGetIndexTemplateV2Action;
|
||||||
import org.elasticsearch.rest.action.admin.indices.RestGetIndicesAction;
|
import org.elasticsearch.rest.action.admin.indices.RestGetIndicesAction;
|
||||||
import org.elasticsearch.rest.action.admin.indices.RestGetMappingAction;
|
import org.elasticsearch.rest.action.admin.indices.RestGetMappingAction;
|
||||||
import org.elasticsearch.rest.action.admin.indices.RestGetSettingsAction;
|
import org.elasticsearch.rest.action.admin.indices.RestGetSettingsAction;
|
||||||
|
@ -305,6 +313,7 @@ import org.elasticsearch.rest.action.admin.indices.RestIndicesStatsAction;
|
||||||
import org.elasticsearch.rest.action.admin.indices.RestOpenIndexAction;
|
import org.elasticsearch.rest.action.admin.indices.RestOpenIndexAction;
|
||||||
import org.elasticsearch.rest.action.admin.indices.RestPutComponentTemplateAction;
|
import org.elasticsearch.rest.action.admin.indices.RestPutComponentTemplateAction;
|
||||||
import org.elasticsearch.rest.action.admin.indices.RestPutIndexTemplateAction;
|
import org.elasticsearch.rest.action.admin.indices.RestPutIndexTemplateAction;
|
||||||
|
import org.elasticsearch.rest.action.admin.indices.RestPutIndexTemplateV2Action;
|
||||||
import org.elasticsearch.rest.action.admin.indices.RestPutMappingAction;
|
import org.elasticsearch.rest.action.admin.indices.RestPutMappingAction;
|
||||||
import org.elasticsearch.rest.action.admin.indices.RestRecoveryAction;
|
import org.elasticsearch.rest.action.admin.indices.RestRecoveryAction;
|
||||||
import org.elasticsearch.rest.action.admin.indices.RestRefreshAction;
|
import org.elasticsearch.rest.action.admin.indices.RestRefreshAction;
|
||||||
|
@ -549,6 +558,9 @@ public class ActionModule extends AbstractModule {
|
||||||
actions.register(PutComponentTemplateAction.INSTANCE, TransportPutComponentTemplateAction.class);
|
actions.register(PutComponentTemplateAction.INSTANCE, TransportPutComponentTemplateAction.class);
|
||||||
actions.register(GetComponentTemplateAction.INSTANCE, TransportGetComponentTemplateAction.class);
|
actions.register(GetComponentTemplateAction.INSTANCE, TransportGetComponentTemplateAction.class);
|
||||||
actions.register(DeleteComponentTemplateAction.INSTANCE, TransportDeleteComponentTemplateAction.class);
|
actions.register(DeleteComponentTemplateAction.INSTANCE, TransportDeleteComponentTemplateAction.class);
|
||||||
|
actions.register(PutIndexTemplateV2Action.INSTANCE, TransportPutIndexTemplateV2Action.class);
|
||||||
|
actions.register(GetIndexTemplateV2Action.INSTANCE, TransportGetIndexTemplateV2Action.class);
|
||||||
|
actions.register(DeleteIndexTemplateV2Action.INSTANCE, TransportDeleteIndexTemplateV2Action.class);
|
||||||
}
|
}
|
||||||
actions.register(ValidateQueryAction.INSTANCE, TransportValidateQueryAction.class);
|
actions.register(ValidateQueryAction.INSTANCE, TransportValidateQueryAction.class);
|
||||||
actions.register(RefreshAction.INSTANCE, TransportRefreshAction.class);
|
actions.register(RefreshAction.INSTANCE, TransportRefreshAction.class);
|
||||||
|
@ -688,6 +700,9 @@ public class ActionModule extends AbstractModule {
|
||||||
registerHandler.accept(new RestPutComponentTemplateAction());
|
registerHandler.accept(new RestPutComponentTemplateAction());
|
||||||
registerHandler.accept(new RestGetComponentTemplateAction());
|
registerHandler.accept(new RestGetComponentTemplateAction());
|
||||||
registerHandler.accept(new RestDeleteComponentTemplateAction());
|
registerHandler.accept(new RestDeleteComponentTemplateAction());
|
||||||
|
registerHandler.accept(new RestPutIndexTemplateV2Action());
|
||||||
|
registerHandler.accept(new RestGetIndexTemplateV2Action());
|
||||||
|
registerHandler.accept(new RestDeleteIndexTemplateV2Action());
|
||||||
}
|
}
|
||||||
|
|
||||||
registerHandler.accept(new RestPutMappingAction());
|
registerHandler.accept(new RestPutMappingAction());
|
||||||
|
|
|
@ -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.action.admin.indices.template.delete;
|
||||||
|
|
||||||
|
import org.elasticsearch.action.ActionRequestValidationException;
|
||||||
|
import org.elasticsearch.action.ActionType;
|
||||||
|
import org.elasticsearch.action.support.master.AcknowledgedResponse;
|
||||||
|
import org.elasticsearch.action.support.master.MasterNodeRequest;
|
||||||
|
import org.elasticsearch.common.io.stream.StreamInput;
|
||||||
|
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import static org.elasticsearch.action.ValidateActions.addValidationError;
|
||||||
|
|
||||||
|
public class DeleteIndexTemplateV2Action extends ActionType<AcknowledgedResponse> {
|
||||||
|
|
||||||
|
public static final DeleteIndexTemplateV2Action INSTANCE = new DeleteIndexTemplateV2Action();
|
||||||
|
public static final String NAME = "indices:admin/index_template/delete";
|
||||||
|
|
||||||
|
private DeleteIndexTemplateV2Action() {
|
||||||
|
super(NAME, AcknowledgedResponse::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Request extends MasterNodeRequest<Request> {
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public Request(StreamInput in) throws IOException {
|
||||||
|
super(in);
|
||||||
|
name = in.readString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Request() { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new delete template request for the specified name.
|
||||||
|
*/
|
||||||
|
public Request(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the index template name to delete.
|
||||||
|
*/
|
||||||
|
public Request name(String name) {
|
||||||
|
this.name = name;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ActionRequestValidationException validate() {
|
||||||
|
ActionRequestValidationException validationException = null;
|
||||||
|
if (name == null) {
|
||||||
|
validationException = addValidationError("name is missing", validationException);
|
||||||
|
}
|
||||||
|
return validationException;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The index template name to delete.
|
||||||
|
*/
|
||||||
|
public String name() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeTo(StreamOutput out) throws IOException {
|
||||||
|
super.writeTo(out);
|
||||||
|
out.writeString(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return name.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (obj == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (getClass() != obj.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Request other = (Request) obj;
|
||||||
|
return Objects.equals(other.name, this.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,78 @@
|
||||||
|
/*
|
||||||
|
* 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.action.admin.indices.template.delete;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.elasticsearch.action.ActionListener;
|
||||||
|
import org.elasticsearch.action.support.ActionFilters;
|
||||||
|
import org.elasticsearch.action.support.master.AcknowledgedResponse;
|
||||||
|
import org.elasticsearch.action.support.master.TransportMasterNodeAction;
|
||||||
|
import org.elasticsearch.cluster.ClusterState;
|
||||||
|
import org.elasticsearch.cluster.block.ClusterBlockException;
|
||||||
|
import org.elasticsearch.cluster.block.ClusterBlockLevel;
|
||||||
|
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
|
||||||
|
import org.elasticsearch.cluster.metadata.MetaDataIndexTemplateService;
|
||||||
|
import org.elasticsearch.cluster.service.ClusterService;
|
||||||
|
import org.elasticsearch.common.inject.Inject;
|
||||||
|
import org.elasticsearch.common.io.stream.StreamInput;
|
||||||
|
import org.elasticsearch.threadpool.ThreadPool;
|
||||||
|
import org.elasticsearch.transport.TransportService;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class TransportDeleteIndexTemplateV2Action
|
||||||
|
extends TransportMasterNodeAction<DeleteIndexTemplateV2Action.Request, AcknowledgedResponse> {
|
||||||
|
|
||||||
|
private static final Logger logger = LogManager.getLogger(TransportDeleteIndexTemplateV2Action.class);
|
||||||
|
|
||||||
|
private final MetaDataIndexTemplateService indexTemplateService;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public TransportDeleteIndexTemplateV2Action(TransportService transportService, ClusterService clusterService,
|
||||||
|
ThreadPool threadPool, MetaDataIndexTemplateService indexTemplateService,
|
||||||
|
ActionFilters actionFilters, IndexNameExpressionResolver indexNameExpressionResolver) {
|
||||||
|
super(DeleteIndexTemplateV2Action.NAME, transportService, clusterService, threadPool, actionFilters,
|
||||||
|
DeleteIndexTemplateV2Action.Request::new, indexNameExpressionResolver);
|
||||||
|
this.indexTemplateService = indexTemplateService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String executor() {
|
||||||
|
// we go async right away
|
||||||
|
return ThreadPool.Names.SAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected AcknowledgedResponse read(StreamInput in) throws IOException {
|
||||||
|
return new AcknowledgedResponse(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ClusterBlockException checkBlock(DeleteIndexTemplateV2Action.Request request, ClusterState state) {
|
||||||
|
return state.blocks().globalBlockedException(ClusterBlockLevel.METADATA_WRITE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void masterOperation(final DeleteIndexTemplateV2Action.Request request, final ClusterState state,
|
||||||
|
final ActionListener<AcknowledgedResponse> listener) {
|
||||||
|
indexTemplateService.removeIndexTemplateV2(request.name(), request.masterNodeTimeout(), listener);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,186 @@
|
||||||
|
/*
|
||||||
|
* 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.action.admin.indices.template.get;
|
||||||
|
|
||||||
|
import org.elasticsearch.action.ActionRequestValidationException;
|
||||||
|
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.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();
|
||||||
|
public static final String NAME = "indices:admin/index_template/get";
|
||||||
|
|
||||||
|
private GetIndexTemplateV2Action() {
|
||||||
|
super(NAME, GetIndexTemplateV2Action.Response::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request that to retrieve one or more index templates
|
||||||
|
*/
|
||||||
|
public static class Request extends MasterNodeReadRequest<Request> {
|
||||||
|
|
||||||
|
private String[] names;
|
||||||
|
|
||||||
|
public Request() { }
|
||||||
|
|
||||||
|
public Request(String... names) {
|
||||||
|
this.names = names;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Request(StreamInput in) throws IOException {
|
||||||
|
super(in);
|
||||||
|
names = in.readStringArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeTo(StreamOutput out) throws IOException {
|
||||||
|
super.writeTo(out);
|
||||||
|
out.writeStringArray(names);
|
||||||
|
}
|
||||||
|
|
||||||
|
@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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the names of the index templates.
|
||||||
|
*/
|
||||||
|
public Request names(String... names) {
|
||||||
|
this.names = names;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The names of the index templates.
|
||||||
|
*/
|
||||||
|
public String[] names() {
|
||||||
|
return this.names;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Arrays.hashCode(names);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (obj == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (getClass() != obj.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Request other = (Request) obj;
|
||||||
|
return Arrays.equals(other.names, this.names);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Response extends ActionResponse implements ToXContentObject {
|
||||||
|
public static final ParseField NAME = new ParseField("name");
|
||||||
|
public static final ParseField INDEX_TEMPLATES = new ParseField("index_templates");
|
||||||
|
public static final ParseField INDEX_TEMPLATE = new ParseField("index_template");
|
||||||
|
|
||||||
|
private final Map<String, IndexTemplateV2> indexTemplates;
|
||||||
|
|
||||||
|
public Response(StreamInput in) throws IOException {
|
||||||
|
super(in);
|
||||||
|
int size = in.readVInt();
|
||||||
|
indexTemplates = new HashMap<>();
|
||||||
|
for (int i = 0 ; i < size ; i++) {
|
||||||
|
indexTemplates.put(in.readString(), new IndexTemplateV2(in));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Response(Map<String, IndexTemplateV2> indexTemplates) {
|
||||||
|
this.indexTemplates = indexTemplates;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, IndexTemplateV2> indexTemplates() {
|
||||||
|
return indexTemplates;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeTo(StreamOutput out) throws IOException {
|
||||||
|
out.writeVInt(indexTemplates.size());
|
||||||
|
for (Map.Entry<String, IndexTemplateV2> indexTemplate : indexTemplates.entrySet()) {
|
||||||
|
out.writeString(indexTemplate.getKey());
|
||||||
|
indexTemplate.getValue().writeTo(out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
GetIndexTemplateV2Action.Response that = (GetIndexTemplateV2Action.Response) o;
|
||||||
|
return Objects.equals(indexTemplates, that.indexTemplates);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(indexTemplates);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||||
|
builder.startObject();
|
||||||
|
builder.startArray(INDEX_TEMPLATES.getPreferredName());
|
||||||
|
for (Map.Entry<String, IndexTemplateV2> indexTemplate : this.indexTemplates.entrySet()) {
|
||||||
|
builder.startObject();
|
||||||
|
builder.field(NAME.getPreferredName(), indexTemplate.getKey());
|
||||||
|
builder.field(INDEX_TEMPLATE.getPreferredName(), indexTemplate.getValue());
|
||||||
|
builder.endObject();
|
||||||
|
}
|
||||||
|
builder.endArray();
|
||||||
|
builder.endObject();
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,93 @@
|
||||||
|
/*
|
||||||
|
* 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.action.admin.indices.template.get;
|
||||||
|
|
||||||
|
import org.elasticsearch.action.ActionListener;
|
||||||
|
import org.elasticsearch.action.support.ActionFilters;
|
||||||
|
import org.elasticsearch.action.support.master.TransportMasterNodeReadAction;
|
||||||
|
import org.elasticsearch.cluster.ClusterState;
|
||||||
|
import org.elasticsearch.cluster.block.ClusterBlockException;
|
||||||
|
import org.elasticsearch.cluster.block.ClusterBlockLevel;
|
||||||
|
import org.elasticsearch.cluster.metadata.IndexTemplateV2;
|
||||||
|
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
|
||||||
|
import org.elasticsearch.cluster.service.ClusterService;
|
||||||
|
import org.elasticsearch.common.inject.Inject;
|
||||||
|
import org.elasticsearch.common.io.stream.StreamInput;
|
||||||
|
import org.elasticsearch.common.regex.Regex;
|
||||||
|
import org.elasticsearch.threadpool.ThreadPool;
|
||||||
|
import org.elasticsearch.transport.TransportService;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class TransportGetIndexTemplateV2Action
|
||||||
|
extends TransportMasterNodeReadAction<GetIndexTemplateV2Action.Request, GetIndexTemplateV2Action.Response> {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public TransportGetIndexTemplateV2Action(TransportService transportService, ClusterService clusterService,
|
||||||
|
ThreadPool threadPool, ActionFilters actionFilters,
|
||||||
|
IndexNameExpressionResolver indexNameExpressionResolver) {
|
||||||
|
super(GetIndexTemplateV2Action.NAME, transportService, clusterService, threadPool, actionFilters,
|
||||||
|
GetIndexTemplateV2Action.Request::new, indexNameExpressionResolver);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String executor() {
|
||||||
|
return ThreadPool.Names.SAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected GetIndexTemplateV2Action.Response read(StreamInput in) throws IOException {
|
||||||
|
return new GetIndexTemplateV2Action.Response(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ClusterBlockException checkBlock(GetIndexTemplateV2Action.Request request, ClusterState state) {
|
||||||
|
return state.blocks().globalBlockedException(ClusterBlockLevel.METADATA_READ);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void masterOperation(GetIndexTemplateV2Action.Request request, ClusterState state,
|
||||||
|
ActionListener<GetIndexTemplateV2Action.Response> listener) {
|
||||||
|
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) {
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (allTemplates.containsKey(name)) {
|
||||||
|
results.put(name, allTemplates.get(name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
listener.onResponse(new GetIndexTemplateV2Action.Response(results));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,181 @@
|
||||||
|
/*
|
||||||
|
* 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.action.admin.indices.template.put;
|
||||||
|
|
||||||
|
import org.elasticsearch.action.ActionRequestValidationException;
|
||||||
|
import org.elasticsearch.action.ActionType;
|
||||||
|
import org.elasticsearch.action.IndicesRequest;
|
||||||
|
import org.elasticsearch.action.support.IndicesOptions;
|
||||||
|
import org.elasticsearch.action.support.master.AcknowledgedResponse;
|
||||||
|
import org.elasticsearch.action.support.master.MasterNodeRequest;
|
||||||
|
import org.elasticsearch.cluster.metadata.IndexTemplateV2;
|
||||||
|
import org.elasticsearch.common.Nullable;
|
||||||
|
import org.elasticsearch.common.Strings;
|
||||||
|
import org.elasticsearch.common.io.stream.StreamInput;
|
||||||
|
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import static org.elasticsearch.action.ValidateActions.addValidationError;
|
||||||
|
|
||||||
|
public class PutIndexTemplateV2Action extends ActionType<AcknowledgedResponse> {
|
||||||
|
|
||||||
|
public static final PutIndexTemplateV2Action INSTANCE = new PutIndexTemplateV2Action();
|
||||||
|
public static final String NAME = "indices:admin/index_template/put";
|
||||||
|
|
||||||
|
private PutIndexTemplateV2Action() {
|
||||||
|
super(NAME, AcknowledgedResponse::new);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A request for putting a single index template into the cluster state
|
||||||
|
*/
|
||||||
|
public static class Request extends MasterNodeRequest<Request> implements IndicesRequest {
|
||||||
|
private final String name;
|
||||||
|
@Nullable
|
||||||
|
private String cause;
|
||||||
|
private boolean create;
|
||||||
|
private IndexTemplateV2 indexTemplate;
|
||||||
|
|
||||||
|
public Request(StreamInput in) throws IOException {
|
||||||
|
super(in);
|
||||||
|
this.name = in.readString();
|
||||||
|
this.cause = in.readOptionalString();
|
||||||
|
this.create = in.readBoolean();
|
||||||
|
this.indexTemplate = new IndexTemplateV2(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new put index template request with the provided name.
|
||||||
|
*/
|
||||||
|
public Request(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeTo(StreamOutput out) throws IOException {
|
||||||
|
super.writeTo(out);
|
||||||
|
out.writeString(name);
|
||||||
|
out.writeOptionalString(cause);
|
||||||
|
out.writeBoolean(create);
|
||||||
|
this.indexTemplate.writeTo(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ActionRequestValidationException validate() {
|
||||||
|
ActionRequestValidationException validationException = null;
|
||||||
|
if (name == null || Strings.hasText(name) == false) {
|
||||||
|
validationException = addValidationError("name is missing", validationException);
|
||||||
|
}
|
||||||
|
if (indexTemplate == null) {
|
||||||
|
validationException = addValidationError("an index template is required", validationException);
|
||||||
|
}
|
||||||
|
return validationException;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the index template.
|
||||||
|
*/
|
||||||
|
public String name() {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set to {@code true} to force only creation, not an update of an index template. If it already
|
||||||
|
* exists, it will fail with an {@link IllegalArgumentException}.
|
||||||
|
*/
|
||||||
|
public Request create(boolean create) {
|
||||||
|
this.create = create;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean create() {
|
||||||
|
return create;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The cause for this index template creation.
|
||||||
|
*/
|
||||||
|
public Request cause(@Nullable String cause) {
|
||||||
|
this.cause = cause;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public String cause() {
|
||||||
|
return this.cause;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The index template that will be inserted into the cluster state
|
||||||
|
*/
|
||||||
|
public Request indexTemplate(IndexTemplateV2 template) {
|
||||||
|
this.indexTemplate = template;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IndexTemplateV2 indexTemplate() {
|
||||||
|
return this.indexTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder sb = new StringBuilder("PutTemplateV2Request[");
|
||||||
|
sb.append("name=").append(name);
|
||||||
|
sb.append(", cause=").append(cause);
|
||||||
|
sb.append(", create=").append(create);
|
||||||
|
sb.append(", index_template=").append(indexTemplate);
|
||||||
|
sb.append("]");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] indices() {
|
||||||
|
return indexTemplate.indexPatterns().toArray(Strings.EMPTY_ARRAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IndicesOptions indicesOptions() {
|
||||||
|
return IndicesOptions.strictExpand();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(name, cause, create, indexTemplate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object obj) {
|
||||||
|
if (obj == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (getClass() != obj.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Request other = (Request) obj;
|
||||||
|
return Objects.equals(this.name, other.name) &&
|
||||||
|
Objects.equals(this.cause, other.cause) &&
|
||||||
|
Objects.equals(this.indexTemplate, other.indexTemplate) &&
|
||||||
|
this.create == other.create;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,88 @@
|
||||||
|
/*
|
||||||
|
* 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.action.admin.indices.template.put;
|
||||||
|
|
||||||
|
import org.elasticsearch.action.ActionListener;
|
||||||
|
import org.elasticsearch.action.support.ActionFilters;
|
||||||
|
import org.elasticsearch.action.support.master.AcknowledgedResponse;
|
||||||
|
import org.elasticsearch.action.support.master.TransportMasterNodeAction;
|
||||||
|
import org.elasticsearch.cluster.ClusterState;
|
||||||
|
import org.elasticsearch.cluster.block.ClusterBlockException;
|
||||||
|
import org.elasticsearch.cluster.block.ClusterBlockLevel;
|
||||||
|
import org.elasticsearch.cluster.metadata.IndexTemplateV2;
|
||||||
|
import org.elasticsearch.cluster.metadata.IndexMetaData;
|
||||||
|
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
|
||||||
|
import org.elasticsearch.cluster.metadata.MetaDataIndexTemplateService;
|
||||||
|
import org.elasticsearch.cluster.metadata.Template;
|
||||||
|
import org.elasticsearch.cluster.service.ClusterService;
|
||||||
|
import org.elasticsearch.common.inject.Inject;
|
||||||
|
import org.elasticsearch.common.io.stream.StreamInput;
|
||||||
|
import org.elasticsearch.common.settings.Settings;
|
||||||
|
import org.elasticsearch.threadpool.ThreadPool;
|
||||||
|
import org.elasticsearch.transport.TransportService;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class TransportPutIndexTemplateV2Action
|
||||||
|
extends TransportMasterNodeAction<PutIndexTemplateV2Action.Request, AcknowledgedResponse> {
|
||||||
|
|
||||||
|
private final MetaDataIndexTemplateService indexTemplateService;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public TransportPutIndexTemplateV2Action(TransportService transportService, ClusterService clusterService,
|
||||||
|
ThreadPool threadPool, MetaDataIndexTemplateService indexTemplateService,
|
||||||
|
ActionFilters actionFilters, IndexNameExpressionResolver indexNameExpressionResolver) {
|
||||||
|
super(PutIndexTemplateV2Action.NAME, transportService, clusterService, threadPool, actionFilters,
|
||||||
|
PutIndexTemplateV2Action.Request::new, indexNameExpressionResolver);
|
||||||
|
this.indexTemplateService = indexTemplateService;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String executor() {
|
||||||
|
// we go async right away
|
||||||
|
return ThreadPool.Names.SAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected AcknowledgedResponse read(StreamInput in) throws IOException {
|
||||||
|
return new AcknowledgedResponse(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ClusterBlockException checkBlock(PutIndexTemplateV2Action.Request request, ClusterState state) {
|
||||||
|
return state.blocks().globalBlockedException(ClusterBlockLevel.METADATA_WRITE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void masterOperation(final PutIndexTemplateV2Action.Request request, final ClusterState state,
|
||||||
|
final ActionListener<AcknowledgedResponse> listener) {
|
||||||
|
IndexTemplateV2 indexTemplate = request.indexTemplate();
|
||||||
|
Template template = indexTemplate.template();
|
||||||
|
// Normalize the index settings if necessary
|
||||||
|
if (template.settings() != null) {
|
||||||
|
Settings.Builder settings = Settings.builder().put(template.settings()).normalizePrefix(IndexMetaData.INDEX_SETTING_PREFIX);
|
||||||
|
template = new Template(settings.build(), template.mappings(), template.aliases());
|
||||||
|
indexTemplate = new IndexTemplateV2(indexTemplate.indexPatterns(), template, indexTemplate.composedOf(),
|
||||||
|
indexTemplate.priority(), indexTemplate.version(), indexTemplate.metadata());
|
||||||
|
}
|
||||||
|
indexTemplateService.putIndexTemplateV2(request.cause(), request.create(), request.name(), request.masterNodeTimeout(),
|
||||||
|
indexTemplate, listener);
|
||||||
|
}
|
||||||
|
}
|
|
@ -241,6 +241,108 @@ public class MetaDataIndexTemplateService {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the given component template to the cluster state. If {@code create} is true, an
|
||||||
|
* exception will be thrown if the component template already exists
|
||||||
|
*/
|
||||||
|
public void putIndexTemplateV2(final String cause, final boolean create, final String name, final TimeValue masterTimeout,
|
||||||
|
final IndexTemplateV2 template, final ActionListener<AcknowledgedResponse> listener) {
|
||||||
|
clusterService.submitStateUpdateTask("create-index-template-v2 [" + name + "], cause [" + cause + "]",
|
||||||
|
new ClusterStateUpdateTask(Priority.URGENT) {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TimeValue timeout() {
|
||||||
|
return masterTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(String source, Exception e) {
|
||||||
|
listener.onFailure(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ClusterState execute(ClusterState currentState) {
|
||||||
|
return addIndexTemplateV2(currentState, create, name, template);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clusterStateProcessed(String source, ClusterState oldState, ClusterState newState) {
|
||||||
|
listener.onResponse(new AcknowledgedResponse(true));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Package visible for testing
|
||||||
|
static ClusterState addIndexTemplateV2(final ClusterState currentState, final boolean create,
|
||||||
|
final String name, final IndexTemplateV2 template) {
|
||||||
|
if (create && currentState.metaData().templatesV2().containsKey(name)) {
|
||||||
|
throw new IllegalArgumentException("index template [" + name + "] already exists");
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: validation of index template
|
||||||
|
// validateAndAddTemplate(request, templateBuilder, indicesService, xContentRegistry);
|
||||||
|
|
||||||
|
logger.info("adding index template [{}]", name);
|
||||||
|
return ClusterState.builder(currentState)
|
||||||
|
.metaData(MetaData.builder(currentState.metaData()).put(name, template))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the given index template from the cluster state. The index template name
|
||||||
|
* supports simple regex wildcards for removing multiple index templates at a time.
|
||||||
|
*/
|
||||||
|
public void removeIndexTemplateV2(final String name, final TimeValue masterTimeout,
|
||||||
|
final ActionListener<AcknowledgedResponse> listener) {
|
||||||
|
clusterService.submitStateUpdateTask("remove-index-template-v2 [" + name + "]",
|
||||||
|
new ClusterStateUpdateTask(Priority.URGENT) {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TimeValue timeout() {
|
||||||
|
return masterTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(String source, Exception e) {
|
||||||
|
listener.onFailure(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ClusterState execute(ClusterState currentState) {
|
||||||
|
return innerRemoveIndexTemplateV2(currentState, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clusterStateProcessed(String source, ClusterState oldState, ClusterState newState) {
|
||||||
|
listener.onResponse(new AcknowledgedResponse(true));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Package visible for testing
|
||||||
|
static ClusterState innerRemoveIndexTemplateV2(ClusterState currentState, String name) {
|
||||||
|
Set<String> templateNames = new HashSet<>();
|
||||||
|
for (String templateName : currentState.metaData().templatesV2().keySet()) {
|
||||||
|
if (Regex.simpleMatch(name, templateName)) {
|
||||||
|
templateNames.add(templateName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (templateNames.isEmpty()) {
|
||||||
|
// if its a match all pattern, and no templates are found (we have none), don't
|
||||||
|
// fail with index missing...
|
||||||
|
if (Regex.isMatchAllPattern(name)) {
|
||||||
|
return currentState;
|
||||||
|
}
|
||||||
|
throw new IndexTemplateMissingException(name);
|
||||||
|
}
|
||||||
|
MetaData.Builder metaData = MetaData.builder(currentState.metaData());
|
||||||
|
for (String templateName : templateNames) {
|
||||||
|
logger.info("removing index template [{}]", templateName);
|
||||||
|
metaData.removeIndexTemplate(templateName);
|
||||||
|
}
|
||||||
|
return ClusterState.builder(currentState).metaData(metaData).build();
|
||||||
|
}
|
||||||
|
|
||||||
public void putTemplate(final PutRequest request, final PutListener listener) {
|
public void putTemplate(final PutRequest request, final PutListener listener) {
|
||||||
Settings.Builder updatedSettingsBuilder = Settings.builder();
|
Settings.Builder updatedSettingsBuilder = Settings.builder();
|
||||||
updatedSettingsBuilder.put(request.settings).normalizePrefix(IndexMetaData.INDEX_SETTING_PREFIX);
|
updatedSettingsBuilder.put(request.settings).normalizePrefix(IndexMetaData.INDEX_SETTING_PREFIX);
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* 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.admin.indices;
|
||||||
|
|
||||||
|
import org.elasticsearch.action.admin.indices.template.delete.DeleteIndexTemplateV2Action;
|
||||||
|
import org.elasticsearch.client.node.NodeClient;
|
||||||
|
import org.elasticsearch.rest.BaseRestHandler;
|
||||||
|
import org.elasticsearch.rest.RestRequest;
|
||||||
|
import org.elasticsearch.rest.action.RestToXContentListener;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.elasticsearch.rest.RestRequest.Method.DELETE;
|
||||||
|
|
||||||
|
public class RestDeleteIndexTemplateV2Action extends BaseRestHandler {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Route> routes() {
|
||||||
|
return Collections.singletonList(new Route(DELETE, "/_index_template/{name}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "delete_index_template_v2_action";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException {
|
||||||
|
|
||||||
|
DeleteIndexTemplateV2Action.Request deleteReq = new DeleteIndexTemplateV2Action.Request(request.param("name"));
|
||||||
|
deleteReq.masterNodeTimeout(request.paramAsTime("master_timeout", deleteReq.masterNodeTimeout()));
|
||||||
|
|
||||||
|
return channel -> client.execute(DeleteIndexTemplateV2Action.INSTANCE, deleteReq, new RestToXContentListener<>(channel));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
/*
|
||||||
|
* 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.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;
|
||||||
|
import org.elasticsearch.rest.RestStatus;
|
||||||
|
import org.elasticsearch.rest.action.RestToXContentListener;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import static org.elasticsearch.rest.RestRequest.Method.GET;
|
||||||
|
import static org.elasticsearch.rest.RestRequest.Method.HEAD;
|
||||||
|
import static org.elasticsearch.rest.RestStatus.NOT_FOUND;
|
||||||
|
import static org.elasticsearch.rest.RestStatus.OK;
|
||||||
|
|
||||||
|
public class RestGetIndexTemplateV2Action extends BaseRestHandler {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Route> routes() {
|
||||||
|
return Arrays.asList(
|
||||||
|
new Route(GET, "/_index_template"),
|
||||||
|
new Route(GET, "/_index_template/{name}"),
|
||||||
|
new Route(HEAD, "/_index_template/{name}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "get_index_template_v2_action";
|
||||||
|
}
|
||||||
|
|
||||||
|
@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);
|
||||||
|
|
||||||
|
getRequest.local(request.paramAsBoolean("local", getRequest.local()));
|
||||||
|
getRequest.masterNodeTimeout(request.paramAsTime("master_timeout", getRequest.masterNodeTimeout()));
|
||||||
|
|
||||||
|
final boolean implicitAll = getRequest.names().length == 0;
|
||||||
|
|
||||||
|
return channel ->
|
||||||
|
client.execute(GetIndexTemplateV2Action.INSTANCE, getRequest,
|
||||||
|
new RestToXContentListener<GetIndexTemplateV2Action.Response>(channel) {
|
||||||
|
@Override
|
||||||
|
protected RestStatus getStatus(final GetIndexTemplateV2Action.Response response) {
|
||||||
|
final boolean templateExists = response.indexTemplates().isEmpty() == false;
|
||||||
|
return (templateExists || implicitAll) ? OK : NOT_FOUND;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Set<String> responseParams() {
|
||||||
|
return Settings.FORMAT_PARAMS;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
* 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.admin.indices;
|
||||||
|
|
||||||
|
import org.elasticsearch.action.admin.indices.template.put.PutIndexTemplateV2Action;
|
||||||
|
import org.elasticsearch.client.node.NodeClient;
|
||||||
|
import org.elasticsearch.cluster.metadata.IndexTemplateV2;
|
||||||
|
import org.elasticsearch.rest.BaseRestHandler;
|
||||||
|
import org.elasticsearch.rest.RestRequest;
|
||||||
|
import org.elasticsearch.rest.action.RestToXContentListener;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.elasticsearch.rest.RestRequest.Method.POST;
|
||||||
|
import static org.elasticsearch.rest.RestRequest.Method.PUT;
|
||||||
|
|
||||||
|
public class RestPutIndexTemplateV2Action extends BaseRestHandler {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Route> routes() {
|
||||||
|
return Arrays.asList(
|
||||||
|
new Route(POST, "/_index_template/{name}"),
|
||||||
|
new Route(PUT, "/_index_template/{name}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "put_index_template_v2_action";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RestChannelConsumer prepareRequest(final RestRequest request, final NodeClient client) throws IOException {
|
||||||
|
|
||||||
|
PutIndexTemplateV2Action.Request putRequest = new PutIndexTemplateV2Action.Request(request.param("name"));
|
||||||
|
putRequest.masterNodeTimeout(request.paramAsTime("master_timeout", putRequest.masterNodeTimeout()));
|
||||||
|
putRequest.create(request.paramAsBoolean("create", false));
|
||||||
|
putRequest.cause(request.param("cause", "api"));
|
||||||
|
putRequest.indexTemplate(IndexTemplateV2.parse(request.contentParser()));
|
||||||
|
|
||||||
|
return channel -> client.execute(PutIndexTemplateV2Action.INSTANCE, putRequest, new RestToXContentListener<>(channel));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
* 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.action.admin.indices.template.delete;
|
||||||
|
|
||||||
|
import org.elasticsearch.common.io.stream.Writeable;
|
||||||
|
import org.elasticsearch.test.AbstractWireSerializingTestCase;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class DeleteIndexTemplateV2RequestTests extends AbstractWireSerializingTestCase<DeleteIndexTemplateV2Action.Request> {
|
||||||
|
@Override
|
||||||
|
protected Writeable.Reader<DeleteIndexTemplateV2Action.Request> instanceReader() {
|
||||||
|
return DeleteIndexTemplateV2Action.Request::new;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected DeleteIndexTemplateV2Action.Request createTestInstance() {
|
||||||
|
return new DeleteIndexTemplateV2Action.Request(randomAlphaOfLength(5));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected DeleteIndexTemplateV2Action.Request mutateInstance(DeleteIndexTemplateV2Action.Request instance) throws IOException {
|
||||||
|
return randomValueOtherThan(instance, this::createTestInstance);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
* 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.action.admin.indices.template.get;
|
||||||
|
|
||||||
|
import org.elasticsearch.common.io.stream.Writeable;
|
||||||
|
import org.elasticsearch.test.AbstractWireSerializingTestCase;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class GetIndexTemplateV2RequestTests extends AbstractWireSerializingTestCase<GetIndexTemplateV2Action.Request> {
|
||||||
|
@Override
|
||||||
|
protected Writeable.Reader<GetIndexTemplateV2Action.Request> instanceReader() {
|
||||||
|
return GetIndexTemplateV2Action.Request::new;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected GetIndexTemplateV2Action.Request createTestInstance() {
|
||||||
|
return new GetIndexTemplateV2Action.Request(generateRandomStringArray(5, 5, false, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected GetIndexTemplateV2Action.Request mutateInstance(GetIndexTemplateV2Action.Request instance) throws IOException {
|
||||||
|
return randomValueOtherThan(instance, this::createTestInstance);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* 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.action.admin.indices.template.get;
|
||||||
|
|
||||||
|
import org.elasticsearch.cluster.metadata.IndexTemplateV2;
|
||||||
|
import org.elasticsearch.cluster.metadata.IndexTemplateV2Tests;
|
||||||
|
import org.elasticsearch.common.io.stream.Writeable;
|
||||||
|
import org.elasticsearch.test.AbstractWireSerializingTestCase;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class GetIndexTemplateV2ResponseTests extends AbstractWireSerializingTestCase<GetIndexTemplateV2Action.Response> {
|
||||||
|
@Override
|
||||||
|
protected Writeable.Reader<GetIndexTemplateV2Action.Response> instanceReader() {
|
||||||
|
return GetIndexTemplateV2Action.Response::new;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected GetIndexTemplateV2Action.Response createTestInstance() {
|
||||||
|
if (randomBoolean()) {
|
||||||
|
return new GetIndexTemplateV2Action.Response(Collections.emptyMap());
|
||||||
|
}
|
||||||
|
Map<String, IndexTemplateV2> templates = new HashMap<>();
|
||||||
|
for (int i = 0; i < randomIntBetween(1, 4); i++) {
|
||||||
|
templates.put(randomAlphaOfLength(4), IndexTemplateV2Tests.randomInstance());
|
||||||
|
}
|
||||||
|
return new GetIndexTemplateV2Action.Response(templates);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected GetIndexTemplateV2Action.Response mutateInstance(GetIndexTemplateV2Action.Response instance) throws IOException {
|
||||||
|
return randomValueOtherThan(instance, this::createTestInstance);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
* 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.action.admin.indices.template.put;
|
||||||
|
|
||||||
|
import org.elasticsearch.cluster.metadata.IndexTemplateV2Tests;
|
||||||
|
import org.elasticsearch.common.io.stream.Writeable;
|
||||||
|
import org.elasticsearch.test.AbstractWireSerializingTestCase;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class PutIndexTemplateV2RequestTests extends AbstractWireSerializingTestCase<PutIndexTemplateV2Action.Request> {
|
||||||
|
@Override
|
||||||
|
protected Writeable.Reader<PutIndexTemplateV2Action.Request> instanceReader() {
|
||||||
|
return PutIndexTemplateV2Action.Request::new;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected PutIndexTemplateV2Action.Request createTestInstance() {
|
||||||
|
PutIndexTemplateV2Action.Request req = new PutIndexTemplateV2Action.Request(randomAlphaOfLength(4));
|
||||||
|
req.cause(randomAlphaOfLength(4));
|
||||||
|
req.create(randomBoolean());
|
||||||
|
req.indexTemplate(IndexTemplateV2Tests.randomInstance());
|
||||||
|
return req;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected PutIndexTemplateV2Action.Request mutateInstance(PutIndexTemplateV2Action.Request instance) throws IOException {
|
||||||
|
return randomValueOtherThan(instance, this::createTestInstance);
|
||||||
|
}
|
||||||
|
}
|
|
@ -32,6 +32,7 @@ import org.elasticsearch.common.xcontent.NamedXContentRegistry;
|
||||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||||
import org.elasticsearch.env.Environment;
|
import org.elasticsearch.env.Environment;
|
||||||
import org.elasticsearch.index.mapper.MapperParsingException;
|
import org.elasticsearch.index.mapper.MapperParsingException;
|
||||||
|
import org.elasticsearch.indices.IndexTemplateMissingException;
|
||||||
import org.elasticsearch.indices.IndicesService;
|
import org.elasticsearch.indices.IndicesService;
|
||||||
import org.elasticsearch.indices.InvalidIndexTemplateException;
|
import org.elasticsearch.indices.InvalidIndexTemplateException;
|
||||||
import org.elasticsearch.test.ESSingleNodeTestCase;
|
import org.elasticsearch.test.ESSingleNodeTestCase;
|
||||||
|
@ -237,6 +238,37 @@ public class MetaDataIndexTemplateServiceTests extends ESSingleNodeTestCase {
|
||||||
() -> metaDataIndexTemplateService.addComponentTemplate(throwState, true, "foo2", componentTemplate4));
|
() -> metaDataIndexTemplateService.addComponentTemplate(throwState, true, "foo2", componentTemplate4));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testAddIndexTemplateV2() {
|
||||||
|
ClusterState state = ClusterState.EMPTY_STATE;
|
||||||
|
IndexTemplateV2 template = IndexTemplateV2Tests.randomInstance();
|
||||||
|
state = MetaDataIndexTemplateService.addIndexTemplateV2(state, false, "foo", template);
|
||||||
|
|
||||||
|
assertNotNull(state.metaData().templatesV2().get("foo"));
|
||||||
|
assertThat(state.metaData().templatesV2().get("foo"), equalTo(template));
|
||||||
|
|
||||||
|
final ClusterState throwState = ClusterState.builder(state).build();
|
||||||
|
IllegalArgumentException e = expectThrows(IllegalArgumentException.class,
|
||||||
|
() -> MetaDataIndexTemplateService.addIndexTemplateV2(throwState, true, "foo", template));
|
||||||
|
assertThat(e.getMessage(), containsString("index template [foo] already exists"));
|
||||||
|
|
||||||
|
state = MetaDataIndexTemplateService.addIndexTemplateV2(state, randomBoolean(), "bar", template);
|
||||||
|
assertNotNull(state.metaData().templatesV2().get("bar"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testRemoveIndexTemplateV2() {
|
||||||
|
IndexTemplateV2 template = IndexTemplateV2Tests.randomInstance();
|
||||||
|
IndexTemplateMissingException e = expectThrows(IndexTemplateMissingException.class,
|
||||||
|
() -> MetaDataIndexTemplateService.innerRemoveIndexTemplateV2(ClusterState.EMPTY_STATE, "foo"));
|
||||||
|
assertThat(e.getMessage(), equalTo("index_template [foo] missing"));
|
||||||
|
|
||||||
|
final ClusterState state = MetaDataIndexTemplateService.addIndexTemplateV2(ClusterState.EMPTY_STATE, false, "foo", template);
|
||||||
|
assertNotNull(state.metaData().templatesV2().get("foo"));
|
||||||
|
assertThat(state.metaData().templatesV2().get("foo"), equalTo(template));
|
||||||
|
|
||||||
|
ClusterState updatedState = MetaDataIndexTemplateService.innerRemoveIndexTemplateV2(state, "foo");
|
||||||
|
assertNull(updatedState.metaData().templatesV2().get("foo"));
|
||||||
|
}
|
||||||
|
|
||||||
private static List<Throwable> putTemplate(NamedXContentRegistry xContentRegistry, PutRequest request) {
|
private static List<Throwable> putTemplate(NamedXContentRegistry xContentRegistry, PutRequest request) {
|
||||||
MetaDataCreateIndexService createIndexService = new MetaDataCreateIndexService(
|
MetaDataCreateIndexService createIndexService = new MetaDataCreateIndexService(
|
||||||
Settings.EMPTY,
|
Settings.EMPTY,
|
||||||
|
|
|
@ -58,7 +58,7 @@ public class ClusterPrivilegeResolver {
|
||||||
private static final Set<String> MONITOR_WATCHER_PATTERN = Collections.singleton("cluster:monitor/xpack/watcher/*");
|
private static final Set<String> MONITOR_WATCHER_PATTERN = Collections.singleton("cluster:monitor/xpack/watcher/*");
|
||||||
private static final Set<String> MONITOR_ROLLUP_PATTERN = Collections.singleton("cluster:monitor/xpack/rollup/*");
|
private static final Set<String> MONITOR_ROLLUP_PATTERN = Collections.singleton("cluster:monitor/xpack/rollup/*");
|
||||||
private static final Set<String> ALL_CLUSTER_PATTERN = Collections.unmodifiableSet(
|
private static final Set<String> ALL_CLUSTER_PATTERN = Collections.unmodifiableSet(
|
||||||
Sets.newHashSet("cluster:*", "indices:admin/template/*", "indices:admin/data_stream/*"));
|
Sets.newHashSet("cluster:*", "indices:admin/template/*", "indices:admin/index_template/*", "indices:admin/data_stream/*"));
|
||||||
private static final Set<String> MANAGE_ML_PATTERN = Collections.unmodifiableSet(
|
private static final Set<String> MANAGE_ML_PATTERN = Collections.unmodifiableSet(
|
||||||
Sets.newHashSet("cluster:admin/xpack/ml/*", "cluster:monitor/xpack/ml/*"));
|
Sets.newHashSet("cluster:admin/xpack/ml/*", "cluster:monitor/xpack/ml/*"));
|
||||||
private static final Set<String> MANAGE_TRANSFORM_PATTERN = Collections.unmodifiableSet(
|
private static final Set<String> MANAGE_TRANSFORM_PATTERN = Collections.unmodifiableSet(
|
||||||
|
@ -68,7 +68,8 @@ public class ClusterPrivilegeResolver {
|
||||||
Sets.newHashSet("cluster:admin/xpack/watcher/*", "cluster:monitor/xpack/watcher/*"));
|
Sets.newHashSet("cluster:admin/xpack/watcher/*", "cluster:monitor/xpack/watcher/*"));
|
||||||
private static final Set<String> TRANSPORT_CLIENT_PATTERN = Collections.unmodifiableSet(
|
private static final Set<String> TRANSPORT_CLIENT_PATTERN = Collections.unmodifiableSet(
|
||||||
Sets.newHashSet("cluster:monitor/nodes/liveness", "cluster:monitor/state"));
|
Sets.newHashSet("cluster:monitor/nodes/liveness", "cluster:monitor/state"));
|
||||||
private static final Set<String> MANAGE_IDX_TEMPLATE_PATTERN = Collections.singleton("indices:admin/template/*");
|
private static final Set<String> MANAGE_IDX_TEMPLATE_PATTERN = Collections.unmodifiableSet(Sets.newHashSet("indices:admin/template/*",
|
||||||
|
"indices:admin/index_template/*"));
|
||||||
private static final Set<String> MANAGE_INGEST_PIPELINE_PATTERN = Collections.singleton("cluster:admin/ingest/pipeline/*");
|
private static final Set<String> MANAGE_INGEST_PIPELINE_PATTERN = Collections.singleton("cluster:admin/ingest/pipeline/*");
|
||||||
private static final Set<String> MANAGE_ROLLUP_PATTERN = Collections.unmodifiableSet(
|
private static final Set<String> MANAGE_ROLLUP_PATTERN = Collections.unmodifiableSet(
|
||||||
Sets.newHashSet("cluster:admin/xpack/rollup/*", "cluster:monitor/xpack/rollup/*"));
|
Sets.newHashSet("cluster:admin/xpack/rollup/*", "cluster:monitor/xpack/rollup/*"));
|
||||||
|
@ -212,7 +213,8 @@ public class ClusterPrivilegeResolver {
|
||||||
return actionName.startsWith("cluster:") ||
|
return actionName.startsWith("cluster:") ||
|
||||||
actionName.startsWith("indices:admin/template/") ||
|
actionName.startsWith("indices:admin/template/") ||
|
||||||
// todo: hack until we implement security of data_streams
|
// todo: hack until we implement security of data_streams
|
||||||
actionName.startsWith("indices:admin/data_stream/");
|
actionName.startsWith("indices:admin/data_stream/") ||
|
||||||
|
actionName.startsWith("indices:admin/index_template/");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String actionToPattern(String text) {
|
private static String actionToPattern(String text) {
|
||||||
|
|
Loading…
Reference in New Issue