Auto create index to support white/black lists of index patterns

closes #2344
This commit is contained in:
Shay Banon 2012-10-21 02:27:30 +02:00
parent 6a936a9efc
commit a3e7daf415
5 changed files with 124 additions and 10 deletions

View File

@ -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) {

View File

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

View File

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

View File

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

View File

@ -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"));
}
} }