Auto create index to support white/black lists of index patterns
closes #2344
This commit is contained in:
parent
6a936a9efc
commit
a3e7daf415
|
@ -30,6 +30,7 @@ import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
|
||||||
import org.elasticsearch.action.admin.indices.create.TransportCreateIndexAction;
|
import org.elasticsearch.action.admin.indices.create.TransportCreateIndexAction;
|
||||||
import org.elasticsearch.action.delete.DeleteRequest;
|
import org.elasticsearch.action.delete.DeleteRequest;
|
||||||
import org.elasticsearch.action.index.IndexRequest;
|
import org.elasticsearch.action.index.IndexRequest;
|
||||||
|
import org.elasticsearch.action.support.AutoCreateIndex;
|
||||||
import org.elasticsearch.action.support.TransportAction;
|
import org.elasticsearch.action.support.TransportAction;
|
||||||
import org.elasticsearch.cluster.ClusterService;
|
import org.elasticsearch.cluster.ClusterService;
|
||||||
import org.elasticsearch.cluster.ClusterState;
|
import org.elasticsearch.cluster.ClusterState;
|
||||||
|
@ -59,7 +60,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||||
*/
|
*/
|
||||||
public class TransportBulkAction extends TransportAction<BulkRequest, BulkResponse> {
|
public class TransportBulkAction extends TransportAction<BulkRequest, BulkResponse> {
|
||||||
|
|
||||||
private final boolean autoCreateIndex;
|
private final AutoCreateIndex autoCreateIndex;
|
||||||
|
|
||||||
private final boolean allowIdGeneration;
|
private final boolean allowIdGeneration;
|
||||||
|
|
||||||
|
@ -77,7 +78,7 @@ public class TransportBulkAction extends TransportAction<BulkRequest, BulkRespon
|
||||||
this.shardBulkAction = shardBulkAction;
|
this.shardBulkAction = shardBulkAction;
|
||||||
this.createIndexAction = createIndexAction;
|
this.createIndexAction = createIndexAction;
|
||||||
|
|
||||||
this.autoCreateIndex = settings.getAsBoolean("action.auto_create_index", true);
|
this.autoCreateIndex = new AutoCreateIndex(settings);
|
||||||
this.allowIdGeneration = componentSettings.getAsBoolean("action.allow_id_generation", true);
|
this.allowIdGeneration = componentSettings.getAsBoolean("action.allow_id_generation", true);
|
||||||
|
|
||||||
transportService.registerHandler(BulkAction.NAME, new TransportHandler());
|
transportService.registerHandler(BulkAction.NAME, new TransportHandler());
|
||||||
|
@ -101,11 +102,12 @@ public class TransportBulkAction extends TransportAction<BulkRequest, BulkRespon
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (autoCreateIndex) {
|
if (autoCreateIndex.needToCheck()) {
|
||||||
final AtomicInteger counter = new AtomicInteger(indices.size());
|
final AtomicInteger counter = new AtomicInteger(indices.size());
|
||||||
final AtomicBoolean failed = new AtomicBoolean();
|
final AtomicBoolean failed = new AtomicBoolean();
|
||||||
|
ClusterState state = clusterService.state();
|
||||||
for (String index : indices) {
|
for (String index : indices) {
|
||||||
if (!clusterService.state().metaData().hasConcreteIndex(index)) {
|
if (autoCreateIndex.shouldAutoCreate(index, state)) {
|
||||||
createIndexAction.execute(new CreateIndexRequest(index).cause("auto(bulk api)"), new ActionListener<CreateIndexResponse>() {
|
createIndexAction.execute(new CreateIndexRequest(index).cause("auto(bulk api)"), new ActionListener<CreateIndexResponse>() {
|
||||||
@Override
|
@Override
|
||||||
public void onResponse(CreateIndexResponse result) {
|
public void onResponse(CreateIndexResponse result) {
|
||||||
|
|
|
@ -28,6 +28,7 @@ import org.elasticsearch.action.delete.index.IndexDeleteRequest;
|
||||||
import org.elasticsearch.action.delete.index.IndexDeleteResponse;
|
import org.elasticsearch.action.delete.index.IndexDeleteResponse;
|
||||||
import org.elasticsearch.action.delete.index.ShardDeleteResponse;
|
import org.elasticsearch.action.delete.index.ShardDeleteResponse;
|
||||||
import org.elasticsearch.action.delete.index.TransportIndexDeleteAction;
|
import org.elasticsearch.action.delete.index.TransportIndexDeleteAction;
|
||||||
|
import org.elasticsearch.action.support.AutoCreateIndex;
|
||||||
import org.elasticsearch.action.support.replication.TransportShardReplicationOperationAction;
|
import org.elasticsearch.action.support.replication.TransportShardReplicationOperationAction;
|
||||||
import org.elasticsearch.cluster.ClusterService;
|
import org.elasticsearch.cluster.ClusterService;
|
||||||
import org.elasticsearch.cluster.ClusterState;
|
import org.elasticsearch.cluster.ClusterState;
|
||||||
|
@ -50,7 +51,7 @@ import org.elasticsearch.transport.TransportService;
|
||||||
*/
|
*/
|
||||||
public class TransportDeleteAction extends TransportShardReplicationOperationAction<DeleteRequest, DeleteRequest, DeleteResponse> {
|
public class TransportDeleteAction extends TransportShardReplicationOperationAction<DeleteRequest, DeleteRequest, DeleteResponse> {
|
||||||
|
|
||||||
private final boolean autoCreateIndex;
|
private final AutoCreateIndex autoCreateIndex;
|
||||||
|
|
||||||
private final TransportCreateIndexAction createIndexAction;
|
private final TransportCreateIndexAction createIndexAction;
|
||||||
|
|
||||||
|
@ -63,7 +64,7 @@ public class TransportDeleteAction extends TransportShardReplicationOperationAct
|
||||||
super(settings, transportService, clusterService, indicesService, threadPool, shardStateAction);
|
super(settings, transportService, clusterService, indicesService, threadPool, shardStateAction);
|
||||||
this.createIndexAction = createIndexAction;
|
this.createIndexAction = createIndexAction;
|
||||||
this.indexDeleteAction = indexDeleteAction;
|
this.indexDeleteAction = indexDeleteAction;
|
||||||
this.autoCreateIndex = settings.getAsBoolean("action.auto_create_index", true);
|
this.autoCreateIndex = new AutoCreateIndex(settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -73,7 +74,7 @@ public class TransportDeleteAction extends TransportShardReplicationOperationAct
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doExecute(final DeleteRequest request, final ActionListener<DeleteResponse> listener) {
|
protected void doExecute(final DeleteRequest request, final ActionListener<DeleteResponse> listener) {
|
||||||
if (autoCreateIndex && !clusterService.state().metaData().hasConcreteIndex(request.index())) {
|
if (autoCreateIndex.shouldAutoCreate(request.index(), clusterService.state())) {
|
||||||
request.beforeLocalFork();
|
request.beforeLocalFork();
|
||||||
createIndexAction.execute(new CreateIndexRequest(request.index()).cause("auto(delete api)").masterNodeTimeout(request.timeout()), new ActionListener<CreateIndexResponse>() {
|
createIndexAction.execute(new CreateIndexRequest(request.index()).cause("auto(delete api)").masterNodeTimeout(request.timeout()), new ActionListener<CreateIndexResponse>() {
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -25,6 +25,7 @@ import org.elasticsearch.action.RoutingMissingException;
|
||||||
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
|
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
|
||||||
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
|
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
|
||||||
import org.elasticsearch.action.admin.indices.create.TransportCreateIndexAction;
|
import org.elasticsearch.action.admin.indices.create.TransportCreateIndexAction;
|
||||||
|
import org.elasticsearch.action.support.AutoCreateIndex;
|
||||||
import org.elasticsearch.action.support.replication.TransportShardReplicationOperationAction;
|
import org.elasticsearch.action.support.replication.TransportShardReplicationOperationAction;
|
||||||
import org.elasticsearch.cluster.ClusterService;
|
import org.elasticsearch.cluster.ClusterService;
|
||||||
import org.elasticsearch.cluster.ClusterState;
|
import org.elasticsearch.cluster.ClusterState;
|
||||||
|
@ -66,7 +67,7 @@ import java.util.concurrent.TimeUnit;
|
||||||
*/
|
*/
|
||||||
public class TransportIndexAction extends TransportShardReplicationOperationAction<IndexRequest, IndexRequest, IndexResponse> {
|
public class TransportIndexAction extends TransportShardReplicationOperationAction<IndexRequest, IndexRequest, IndexResponse> {
|
||||||
|
|
||||||
private final boolean autoCreateIndex;
|
private final AutoCreateIndex autoCreateIndex;
|
||||||
|
|
||||||
private final boolean allowIdGeneration;
|
private final boolean allowIdGeneration;
|
||||||
|
|
||||||
|
@ -83,7 +84,7 @@ public class TransportIndexAction extends TransportShardReplicationOperationActi
|
||||||
super(settings, transportService, clusterService, indicesService, threadPool, shardStateAction);
|
super(settings, transportService, clusterService, indicesService, threadPool, shardStateAction);
|
||||||
this.createIndexAction = createIndexAction;
|
this.createIndexAction = createIndexAction;
|
||||||
this.mappingUpdatedAction = mappingUpdatedAction;
|
this.mappingUpdatedAction = mappingUpdatedAction;
|
||||||
this.autoCreateIndex = settings.getAsBoolean("action.auto_create_index", true);
|
this.autoCreateIndex = new AutoCreateIndex(settings);
|
||||||
this.allowIdGeneration = settings.getAsBoolean("action.allow_id_generation", true);
|
this.allowIdGeneration = settings.getAsBoolean("action.allow_id_generation", true);
|
||||||
this.waitForMappingChange = settings.getAsBoolean("action.wait_on_mapping_change", false);
|
this.waitForMappingChange = settings.getAsBoolean("action.wait_on_mapping_change", false);
|
||||||
}
|
}
|
||||||
|
@ -91,7 +92,7 @@ public class TransportIndexAction extends TransportShardReplicationOperationActi
|
||||||
@Override
|
@Override
|
||||||
protected void doExecute(final IndexRequest request, final ActionListener<IndexResponse> listener) {
|
protected void doExecute(final IndexRequest request, final ActionListener<IndexResponse> listener) {
|
||||||
// if we don't have a master, we don't have metadata, that's fine, let it find a master using create index API
|
// if we don't have a master, we don't have metadata, that's fine, let it find a master using create index API
|
||||||
if (autoCreateIndex && !clusterService.state().metaData().hasConcreteIndex(request.index())) {
|
if (autoCreateIndex.shouldAutoCreate(request.index(), clusterService.state())) {
|
||||||
request.beforeLocalFork(); // we fork on another thread...
|
request.beforeLocalFork(); // we fork on another thread...
|
||||||
createIndexAction.execute(new CreateIndexRequest(request.index()).cause("auto(index api)").masterNodeTimeout(request.timeout()), new ActionListener<CreateIndexResponse>() {
|
createIndexAction.execute(new CreateIndexRequest(request.index()).cause("auto(index api)").masterNodeTimeout(request.timeout()), new ActionListener<CreateIndexResponse>() {
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -0,0 +1,102 @@
|
||||||
|
/*
|
||||||
|
* Licensed to ElasticSearch and Shay Banon 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.support;
|
||||||
|
|
||||||
|
import org.elasticsearch.cluster.ClusterState;
|
||||||
|
import org.elasticsearch.common.Booleans;
|
||||||
|
import org.elasticsearch.common.Strings;
|
||||||
|
import org.elasticsearch.common.regex.Regex;
|
||||||
|
import org.elasticsearch.common.settings.Settings;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*/
|
||||||
|
public class AutoCreateIndex {
|
||||||
|
|
||||||
|
private final boolean needToCheck;
|
||||||
|
private final boolean globallyDisabled;
|
||||||
|
private final String[] matches;
|
||||||
|
private final String[] matches2;
|
||||||
|
|
||||||
|
public AutoCreateIndex(Settings settings) {
|
||||||
|
String value = settings.get("action.auto_create_index");
|
||||||
|
if (value == null || Booleans.isExplicitTrue(value)) {
|
||||||
|
needToCheck = true;
|
||||||
|
globallyDisabled = false;
|
||||||
|
matches = null;
|
||||||
|
matches2 = null;
|
||||||
|
} else if (Booleans.isExplicitFalse(value)) {
|
||||||
|
needToCheck = false;
|
||||||
|
globallyDisabled = true;
|
||||||
|
matches = null;
|
||||||
|
matches2 = null;
|
||||||
|
} else {
|
||||||
|
needToCheck = true;
|
||||||
|
globallyDisabled = false;
|
||||||
|
matches = Strings.commaDelimitedListToStringArray(value);
|
||||||
|
matches2 = new String[matches.length];
|
||||||
|
for (int i = 0; i < matches.length; i++) {
|
||||||
|
matches2[i] = matches[i].substring(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Do we really need to check if an index should be auto created?
|
||||||
|
*/
|
||||||
|
public boolean needToCheck() {
|
||||||
|
return this.needToCheck;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should the index be auto created?
|
||||||
|
*/
|
||||||
|
public boolean shouldAutoCreate(String index, ClusterState state) {
|
||||||
|
if (!needToCheck) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (state.metaData().hasConcreteIndex(index)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (globallyDisabled) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// matches not set, default value of "true"
|
||||||
|
if (matches == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < matches.length; i++) {
|
||||||
|
char c = matches[i].charAt(0);
|
||||||
|
if (c == '-') {
|
||||||
|
if (Regex.simpleMatch(matches2[i], index)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (c == '+') {
|
||||||
|
if (Regex.simpleMatch(matches2[i], index)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (Regex.simpleMatch(matches[i], index)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -56,4 +56,12 @@ public class Booleans {
|
||||||
}
|
}
|
||||||
return !(value.equals("false") || value.equals("0") || value.equals("off") || value.equals("no"));
|
return !(value.equals("false") || value.equals("0") || value.equals("off") || value.equals("no"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isExplicitFalse(String value) {
|
||||||
|
return (value.equals("false") || value.equals("0") || value.equals("off") || value.equals("no"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isExplicitTrue(String value) {
|
||||||
|
return (value.equals("true") || value.equals("1") || value.equals("on") || value.equals("yes"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue