Added support for multiple indices in open/close index apis

Open/Close index api supports now multiple indices the same way as the delete index api works. The only exception is when dealing with all indices: it's required to explicitly use _all or a pattern that identifies all the indices, not just an empty array of indices. Supports the ignore_missing param too.
Added also a new flag action.disable_close_all_indices (default false) to disable closing all indices

Closes #3217
This commit is contained in:
Luca Cavanna 2013-07-03 18:48:10 +02:00 committed by Luca Cavanna
parent 6e9ad03b27
commit 933fd50466
17 changed files with 883 additions and 106 deletions

View File

@ -20,6 +20,7 @@
package org.elasticsearch.action.admin.indices.close; package org.elasticsearch.action.admin.indices.close;
import org.elasticsearch.action.ActionRequestValidationException; import org.elasticsearch.action.ActionRequestValidationException;
import org.elasticsearch.action.support.IgnoreIndices;
import org.elasticsearch.action.support.master.MasterNodeOperationRequest; import org.elasticsearch.action.support.master.MasterNodeOperationRequest;
import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.io.stream.StreamOutput;
@ -36,9 +37,9 @@ import static org.elasticsearch.common.unit.TimeValue.timeValueSeconds;
*/ */
public class CloseIndexRequest extends MasterNodeOperationRequest<CloseIndexRequest> { public class CloseIndexRequest extends MasterNodeOperationRequest<CloseIndexRequest> {
private String index; private String[] indices;
private TimeValue timeout = timeValueSeconds(10); private TimeValue timeout = timeValueSeconds(10);
private IgnoreIndices ignoreIndices = IgnoreIndices.DEFAULT;
CloseIndexRequest() { CloseIndexRequest() {
} }
@ -46,28 +47,34 @@ public class CloseIndexRequest extends MasterNodeOperationRequest<CloseIndexRequ
/** /**
* Constructs a new delete index request for the specified index. * Constructs a new delete index request for the specified index.
*/ */
public CloseIndexRequest(String index) { public CloseIndexRequest(String... indices) {
this.index = index; this.indices = indices;
} }
@Override @Override
public ActionRequestValidationException validate() { public ActionRequestValidationException validate() {
ActionRequestValidationException validationException = null; ActionRequestValidationException validationException = null;
if (index == null) { if (indices == null || indices.length == 0) {
validationException = addValidationError("index is missing", validationException); validationException = addValidationError("index is missing", validationException);
} }
return validationException; return validationException;
} }
/** /**
* The index to delete. * The indices to be closed
* @return the indices to be closed
*/ */
String index() { String[] indices() {
return index; return indices;
} }
public CloseIndexRequest index(String index) { /**
this.index = index; * Sets the indices to be closed
* @param indices the indices to be closed
* @return the request itself
*/
public CloseIndexRequest indices(String... indices) {
this.indices = indices;
return this; return this;
} }
@ -96,17 +103,38 @@ public class CloseIndexRequest extends MasterNodeOperationRequest<CloseIndexRequ
return timeout(TimeValue.parseTimeValue(timeout, null)); return timeout(TimeValue.parseTimeValue(timeout, null));
} }
/**
* Specifies what type of requested indices to ignore. For example indices that don't exist.
* @return the desired behaviour regarding indices to ignore
*/
public IgnoreIndices ignoreIndices() {
return ignoreIndices;
}
/**
* Specifies what type of requested indices to ignore. For example indices that don't exist.
* @param ignoreIndices the desired behaviour regarding indices to ignore
* @return the request itself
*/
public CloseIndexRequest ignoreIndices(IgnoreIndices ignoreIndices) {
this.ignoreIndices = ignoreIndices;
return this;
}
@Override @Override
public void readFrom(StreamInput in) throws IOException { public void readFrom(StreamInput in) throws IOException {
super.readFrom(in); super.readFrom(in);
index = in.readString(); indices = in.readStringArray();
timeout = readTimeValue(in); timeout = readTimeValue(in);
ignoreIndices = IgnoreIndices.fromId(in.readByte());
} }
@Override @Override
public void writeTo(StreamOutput out) throws IOException { public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out); super.writeTo(out);
out.writeString(index); out.writeStringArray(indices);
timeout.writeTo(out); timeout.writeTo(out);
out.writeByte(ignoreIndices.id());
} }
} }

View File

@ -20,6 +20,7 @@
package org.elasticsearch.action.admin.indices.close; package org.elasticsearch.action.admin.indices.close;
import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.support.IgnoreIndices;
import org.elasticsearch.action.support.master.MasterNodeOperationRequestBuilder; import org.elasticsearch.action.support.master.MasterNodeOperationRequestBuilder;
import org.elasticsearch.client.IndicesAdminClient; import org.elasticsearch.client.IndicesAdminClient;
import org.elasticsearch.client.internal.InternalIndicesAdminClient; import org.elasticsearch.client.internal.InternalIndicesAdminClient;
@ -34,12 +35,17 @@ public class CloseIndexRequestBuilder extends MasterNodeOperationRequestBuilder<
super((InternalIndicesAdminClient) indicesClient, new CloseIndexRequest()); super((InternalIndicesAdminClient) indicesClient, new CloseIndexRequest());
} }
public CloseIndexRequestBuilder(IndicesAdminClient indicesClient, String index) { public CloseIndexRequestBuilder(IndicesAdminClient indicesClient, String... indices) {
super((InternalIndicesAdminClient) indicesClient, new CloseIndexRequest(index)); super((InternalIndicesAdminClient) indicesClient, new CloseIndexRequest(indices));
} }
public CloseIndexRequestBuilder setIndex(String index) { /**
request.index(index); * Sets the indices to be closed
* @param indices the indices to be closed
* @return the request itself
*/
public CloseIndexRequestBuilder setIndices(String... indices) {
request.indices(indices);
return this; return this;
} }
@ -61,6 +67,16 @@ public class CloseIndexRequestBuilder extends MasterNodeOperationRequestBuilder<
return this; return this;
} }
/**
* Specifies what type of requested indices to ignore. For example indices that don't exist.
* @param ignoreIndices the desired behaviour regarding indices to ignore
* @return the request itself
*/
public CloseIndexRequestBuilder setIgnoreIndices(IgnoreIndices ignoreIndices) {
request.ignoreIndices(ignoreIndices);
return this;
}
@Override @Override
protected void doExecute(ActionListener<CloseIndexResponse> listener) { protected void doExecute(ActionListener<CloseIndexResponse> listener) {
((IndicesAdminClient) client).close(request, listener); ((IndicesAdminClient) client).close(request, listener);

View File

@ -20,6 +20,8 @@
package org.elasticsearch.action.admin.indices.close; package org.elasticsearch.action.admin.indices.close;
import org.elasticsearch.ElasticSearchException; import org.elasticsearch.ElasticSearchException;
import org.elasticsearch.ElasticSearchIllegalArgumentException;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.support.master.TransportMasterNodeOperationAction; import org.elasticsearch.action.support.master.TransportMasterNodeOperationAction;
import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterService;
import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterState;
@ -40,12 +42,15 @@ import java.util.concurrent.atomic.AtomicReference;
public class TransportCloseIndexAction extends TransportMasterNodeOperationAction<CloseIndexRequest, CloseIndexResponse> { public class TransportCloseIndexAction extends TransportMasterNodeOperationAction<CloseIndexRequest, CloseIndexResponse> {
private final MetaDataStateIndexService stateIndexService; private final MetaDataStateIndexService stateIndexService;
private final boolean disableCloseAllIndices;
@Inject @Inject
public TransportCloseIndexAction(Settings settings, TransportService transportService, ClusterService clusterService, public TransportCloseIndexAction(Settings settings, TransportService transportService, ClusterService clusterService,
ThreadPool threadPool, MetaDataStateIndexService stateIndexService) { ThreadPool threadPool, MetaDataStateIndexService stateIndexService) {
super(settings, transportService, clusterService, threadPool); super(settings, transportService, clusterService, threadPool);
this.stateIndexService = stateIndexService; this.stateIndexService = stateIndexService;
this.disableCloseAllIndices = settings.getAsBoolean("action.disable_close_all_indices", false);
} }
@Override @Override
@ -68,10 +73,25 @@ public class TransportCloseIndexAction extends TransportMasterNodeOperationActio
return new CloseIndexResponse(); return new CloseIndexResponse();
} }
@Override
protected void doExecute(CloseIndexRequest request, ActionListener<CloseIndexResponse> listener) {
ClusterState state = clusterService.state();
String[] indicesOrAliases = request.indices();
request.indices(state.metaData().concreteIndices(indicesOrAliases, request.ignoreIndices(), false));
if (disableCloseAllIndices) {
if (state.metaData().isExplicitAllIndices(indicesOrAliases) ||
state.metaData().isPatternMatchingAllIndices(indicesOrAliases, request.indices())) {
throw new ElasticSearchIllegalArgumentException("closing all indices is disabled");
}
}
super.doExecute(request, listener);
}
@Override @Override
protected ClusterBlockException checkBlock(CloseIndexRequest request, ClusterState state) { protected ClusterBlockException checkBlock(CloseIndexRequest request, ClusterState state) {
request.index(clusterService.state().metaData().concreteIndex(request.index())); return state.blocks().indicesBlockedException(ClusterBlockLevel.METADATA, request.indices());
return state.blocks().indexBlockedException(ClusterBlockLevel.METADATA, request.index());
} }
@Override @Override
@ -79,7 +99,7 @@ public class TransportCloseIndexAction extends TransportMasterNodeOperationActio
final AtomicReference<CloseIndexResponse> responseRef = new AtomicReference<CloseIndexResponse>(); final AtomicReference<CloseIndexResponse> responseRef = new AtomicReference<CloseIndexResponse>();
final AtomicReference<Throwable> failureRef = new AtomicReference<Throwable>(); final AtomicReference<Throwable> failureRef = new AtomicReference<Throwable>();
final CountDownLatch latch = new CountDownLatch(1); final CountDownLatch latch = new CountDownLatch(1);
stateIndexService.closeIndex(new MetaDataStateIndexService.Request(request.index()).timeout(request.timeout()), new MetaDataStateIndexService.Listener() { stateIndexService.closeIndex(new MetaDataStateIndexService.Request(request.indices()).timeout(request.timeout()), new MetaDataStateIndexService.Listener() {
@Override @Override
public void onResponse(MetaDataStateIndexService.Response response) { public void onResponse(MetaDataStateIndexService.Response response) {
responseRef.set(new CloseIndexResponse(response.acknowledged())); responseRef.set(new CloseIndexResponse(response.acknowledged()));

View File

@ -33,7 +33,6 @@ import org.elasticsearch.cluster.block.ClusterBlockLevel;
import org.elasticsearch.cluster.metadata.IndexMetaData; import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.cluster.metadata.MetaDataDeleteIndexService; import org.elasticsearch.cluster.metadata.MetaDataDeleteIndexService;
import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.regex.Regex;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.percolator.PercolatorService; import org.elasticsearch.index.percolator.PercolatorService;
import org.elasticsearch.threadpool.ThreadPool; import org.elasticsearch.threadpool.ThreadPool;
@ -87,24 +86,14 @@ public class TransportDeleteIndexAction extends TransportMasterNodeOperationActi
protected void doExecute(DeleteIndexRequest request, ActionListener<DeleteIndexResponse> listener) { protected void doExecute(DeleteIndexRequest request, ActionListener<DeleteIndexResponse> listener) {
ClusterState state = clusterService.state(); ClusterState state = clusterService.state();
String[] indicesOrAliases = request.indices(); String[] indicesOrAliases = request.indices();
request.indices(state.metaData().concreteIndices(request.indices())); request.indices(state.metaData().concreteIndices(request.indices()));
if (disableDeleteAllIndices) { if (disableDeleteAllIndices) {
// simple check on the original indices with "all" default parameter if (state.metaData().isAllIndices(indicesOrAliases) ||
if (indicesOrAliases == null || indicesOrAliases.length == 0 || (indicesOrAliases.length == 1 && indicesOrAliases[0].equals("_all"))) { state.metaData().isPatternMatchingAllIndices(indicesOrAliases, request.indices())) {
throw new ElasticSearchIllegalArgumentException("deleting all indices is disabled"); throw new ElasticSearchIllegalArgumentException("deleting all indices is disabled");
} }
// if we end up matching on all indices, check, if its a wildcard parameter, or a "-something" structure
if (request.indices().length == state.metaData().concreteAllIndices().length && indicesOrAliases.length > 0) {
boolean hasRegex = false;
for (String indexOrAlias : indicesOrAliases) {
if (Regex.isSimpleMatchPattern(indexOrAlias)) {
hasRegex = true;
}
}
if (indicesOrAliases.length > 0 && (hasRegex || indicesOrAliases[0].charAt(0) == '-')) {
throw new ElasticSearchIllegalArgumentException("deleting all indices is disabled");
}
}
} }
super.doExecute(request, listener); super.doExecute(request, listener);
} }

View File

@ -20,6 +20,7 @@
package org.elasticsearch.action.admin.indices.open; package org.elasticsearch.action.admin.indices.open;
import org.elasticsearch.action.ActionRequestValidationException; import org.elasticsearch.action.ActionRequestValidationException;
import org.elasticsearch.action.support.IgnoreIndices;
import org.elasticsearch.action.support.master.MasterNodeOperationRequest; import org.elasticsearch.action.support.master.MasterNodeOperationRequest;
import org.elasticsearch.common.io.stream.StreamInput; import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput; import org.elasticsearch.common.io.stream.StreamOutput;
@ -36,9 +37,9 @@ import static org.elasticsearch.common.unit.TimeValue.timeValueSeconds;
*/ */
public class OpenIndexRequest extends MasterNodeOperationRequest<OpenIndexRequest> { public class OpenIndexRequest extends MasterNodeOperationRequest<OpenIndexRequest> {
private String index; private String[] indices;
private TimeValue timeout = timeValueSeconds(10); private TimeValue timeout = timeValueSeconds(10);
private IgnoreIndices ignoreIndices = IgnoreIndices.DEFAULT;
OpenIndexRequest() { OpenIndexRequest() {
} }
@ -46,28 +47,34 @@ public class OpenIndexRequest extends MasterNodeOperationRequest<OpenIndexReques
/** /**
* Constructs a new delete index request for the specified index. * Constructs a new delete index request for the specified index.
*/ */
public OpenIndexRequest(String index) { public OpenIndexRequest(String... indices) {
this.index = index; this.indices = indices;
} }
@Override @Override
public ActionRequestValidationException validate() { public ActionRequestValidationException validate() {
ActionRequestValidationException validationException = null; ActionRequestValidationException validationException = null;
if (index == null) { if (indices == null || indices.length == 0) {
validationException = addValidationError("index is missing", validationException); validationException = addValidationError("index is missing", validationException);
} }
return validationException; return validationException;
} }
/** /**
* The index to delete. * The indices to be opened
* @return the indices to be opened
*/ */
String index() { String[] indices() {
return index; return indices;
} }
public OpenIndexRequest index(String index) { /**
this.index = index; * Sets the indices to be opened
* @param indices the indices to be opened
* @return the request itself
*/
public OpenIndexRequest indices(String... indices) {
this.indices = indices;
return this; return this;
} }
@ -96,17 +103,37 @@ public class OpenIndexRequest extends MasterNodeOperationRequest<OpenIndexReques
return timeout(TimeValue.parseTimeValue(timeout, null)); return timeout(TimeValue.parseTimeValue(timeout, null));
} }
/**
* Specifies what type of requested indices to ignore. For example indices that don't exist.
* @return the current behaviour when it comes to index names
*/
public IgnoreIndices ignoreIndices() {
return ignoreIndices;
}
/**
* Specifies what type of requested indices to ignore. For example indices that don't exist.
* @param ignoreIndices the desired behaviour regarding indices to ignore
* @return the request itself
*/
public OpenIndexRequest ignoreIndices(IgnoreIndices ignoreIndices) {
this.ignoreIndices = ignoreIndices;
return this;
}
@Override @Override
public void readFrom(StreamInput in) throws IOException { public void readFrom(StreamInput in) throws IOException {
super.readFrom(in); super.readFrom(in);
index = in.readString(); indices = in.readStringArray();
timeout = readTimeValue(in); timeout = readTimeValue(in);
ignoreIndices = IgnoreIndices.fromId(in.readByte());
} }
@Override @Override
public void writeTo(StreamOutput out) throws IOException { public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out); super.writeTo(out);
out.writeString(index); out.writeStringArray(indices);
timeout.writeTo(out); timeout.writeTo(out);
out.writeByte(ignoreIndices.id());
} }
} }

View File

@ -20,6 +20,7 @@
package org.elasticsearch.action.admin.indices.open; package org.elasticsearch.action.admin.indices.open;
import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.support.IgnoreIndices;
import org.elasticsearch.action.support.master.MasterNodeOperationRequestBuilder; import org.elasticsearch.action.support.master.MasterNodeOperationRequestBuilder;
import org.elasticsearch.client.IndicesAdminClient; import org.elasticsearch.client.IndicesAdminClient;
import org.elasticsearch.client.internal.InternalIndicesAdminClient; import org.elasticsearch.client.internal.InternalIndicesAdminClient;
@ -34,12 +35,17 @@ public class OpenIndexRequestBuilder extends MasterNodeOperationRequestBuilder<O
super((InternalIndicesAdminClient) indicesClient, new OpenIndexRequest()); super((InternalIndicesAdminClient) indicesClient, new OpenIndexRequest());
} }
public OpenIndexRequestBuilder(IndicesAdminClient indicesClient, String index) { public OpenIndexRequestBuilder(IndicesAdminClient indicesClient, String... indices) {
super((InternalIndicesAdminClient) indicesClient, new OpenIndexRequest(index)); super((InternalIndicesAdminClient) indicesClient, new OpenIndexRequest(indices));
} }
public OpenIndexRequestBuilder setIndex(String index) { /**
request.index(index); * Sets the indices to be opened
* @param indices the indices to be opened
* @return the request itself
*/
public OpenIndexRequestBuilder setIndices(String... indices) {
request.indices(indices);
return this; return this;
} }
@ -61,6 +67,16 @@ public class OpenIndexRequestBuilder extends MasterNodeOperationRequestBuilder<O
return this; return this;
} }
/**
* Specifies what type of requested indices to ignore. For example indices that don't exist.
* @param ignoreIndices the desired behaviour regarding indices to ignore
* @return the request itself
*/
public OpenIndexRequestBuilder setIgnoreIndices(IgnoreIndices ignoreIndices) {
request.ignoreIndices(ignoreIndices);
return this;
}
@Override @Override
protected void doExecute(ActionListener<OpenIndexResponse> listener) { protected void doExecute(ActionListener<OpenIndexResponse> listener) {
((IndicesAdminClient) client).open(request, listener); ((IndicesAdminClient) client).open(request, listener);

View File

@ -20,6 +20,7 @@
package org.elasticsearch.action.admin.indices.open; package org.elasticsearch.action.admin.indices.open;
import org.elasticsearch.ElasticSearchException; import org.elasticsearch.ElasticSearchException;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.support.master.TransportMasterNodeOperationAction; import org.elasticsearch.action.support.master.TransportMasterNodeOperationAction;
import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterService;
import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterState;
@ -68,10 +69,15 @@ public class TransportOpenIndexAction extends TransportMasterNodeOperationAction
return new OpenIndexResponse(); return new OpenIndexResponse();
} }
@Override
protected void doExecute(OpenIndexRequest request, ActionListener<OpenIndexResponse> listener) {
request.indices(clusterService.state().metaData().concreteIndices(request.indices(), request.ignoreIndices(), false));
super.doExecute(request, listener);
}
@Override @Override
protected ClusterBlockException checkBlock(OpenIndexRequest request, ClusterState state) { protected ClusterBlockException checkBlock(OpenIndexRequest request, ClusterState state) {
request.index(clusterService.state().metaData().concreteIndex(request.index())); return state.blocks().indicesBlockedException(ClusterBlockLevel.METADATA, request.indices());
return state.blocks().indexBlockedException(ClusterBlockLevel.METADATA, request.index());
} }
@Override @Override
@ -79,7 +85,7 @@ public class TransportOpenIndexAction extends TransportMasterNodeOperationAction
final AtomicReference<OpenIndexResponse> responseRef = new AtomicReference<OpenIndexResponse>(); final AtomicReference<OpenIndexResponse> responseRef = new AtomicReference<OpenIndexResponse>();
final AtomicReference<Throwable> failureRef = new AtomicReference<Throwable>(); final AtomicReference<Throwable> failureRef = new AtomicReference<Throwable>();
final CountDownLatch latch = new CountDownLatch(1); final CountDownLatch latch = new CountDownLatch(1);
stateIndexService.openIndex(new MetaDataStateIndexService.Request(request.index()).timeout(request.timeout()), new MetaDataStateIndexService.Listener() { stateIndexService.openIndex(new MetaDataStateIndexService.Request(request.indices()).timeout(request.timeout()), new MetaDataStateIndexService.Listener() {
@Override @Override
public void onResponse(MetaDataStateIndexService.Response response) { public void onResponse(MetaDataStateIndexService.Response response) {
responseRef.set(new OpenIndexResponse(response.acknowledged())); responseRef.set(new OpenIndexResponse(response.acknowledged()));

View File

@ -295,14 +295,14 @@ public interface IndicesAdminClient {
void close(CloseIndexRequest request, ActionListener<CloseIndexResponse> listener); void close(CloseIndexRequest request, ActionListener<CloseIndexResponse> listener);
/** /**
* Closes an index based on the index name. * Closes one or more indices based on their index name.
* *
* @param index The index name to close * @param indices The name of the indices to close
*/ */
CloseIndexRequestBuilder prepareClose(String index); CloseIndexRequestBuilder prepareClose(String... indices);
/** /**
* OPen an index based on the index name. * Open an index based on the index name.
* *
* @param request The close index request * @param request The close index request
* @return The result future * @return The result future
@ -320,11 +320,11 @@ public interface IndicesAdminClient {
void open(OpenIndexRequest request, ActionListener<OpenIndexResponse> listener); void open(OpenIndexRequest request, ActionListener<OpenIndexResponse> listener);
/** /**
* Opens an index based on the index name. * Opens one or more indices based on their index name.
* *
* @param index The index name to close * @param indices The name of the indices to close
*/ */
OpenIndexRequestBuilder prepareOpen(String index); OpenIndexRequestBuilder prepareOpen(String... indices);
/** /**
* Explicitly refresh one or more indices (making the content indexed since the last refresh searchable). * Explicitly refresh one or more indices (making the content indexed since the last refresh searchable).

View File

@ -276,8 +276,8 @@ public abstract class AbstractIndicesAdminClient implements InternalIndicesAdmin
} }
@Override @Override
public CloseIndexRequestBuilder prepareClose(String index) { public CloseIndexRequestBuilder prepareClose(String... indices) {
return new CloseIndexRequestBuilder(this, index); return new CloseIndexRequestBuilder(this, indices);
} }
@Override @Override
@ -291,8 +291,8 @@ public abstract class AbstractIndicesAdminClient implements InternalIndicesAdmin
} }
@Override @Override
public OpenIndexRequestBuilder prepareOpen(String index) { public OpenIndexRequestBuilder prepareOpen(String... indices) {
return new OpenIndexRequestBuilder(this, index); return new OpenIndexRequestBuilder(this, indices);
} }
@Override @Override

View File

@ -875,10 +875,54 @@ public class MetaData implements Iterable<IndexMetaData> {
return filteringAliases.toArray(new String[filteringAliases.size()]); return filteringAliases.toArray(new String[filteringAliases.size()]);
} }
private boolean isAllIndices(String[] aliasesOrIndices) { /**
return (aliasesOrIndices == null || aliasesOrIndices.length == 0 || (aliasesOrIndices.length == 1 && "_all".equals(aliasesOrIndices[0]))); * Identifies whether the array containing index names given as argument refers to all indices
* The empty or null array identifies all indices
*
* @param aliasesOrIndices the array containing index names
* @return true if the provided array maps to all indices, false otherwise
*/
public boolean isAllIndices(String[] aliasesOrIndices) {
return aliasesOrIndices == null || aliasesOrIndices.length == 0 || isExplicitAllIndices(aliasesOrIndices);
} }
/**
* Identifies whether the array containing index names given as argument explicitly refers to all indices
* The empty or null array doesn't explicitly map to all indices
*
* @param aliasesOrIndices the array containing index names
* @return true if the provided array explicitly maps to all indices, false otherwise
*/
public boolean isExplicitAllIndices(String[] aliasesOrIndices) {
return aliasesOrIndices != null && aliasesOrIndices.length == 1 && "_all".equals(aliasesOrIndices[0]);
}
/**
* Identifies whether the first argument (an array containing index names) is a pattern that matches all indices
*
* @param indicesOrAliases the array containing index names
* @param concreteIndices array containing the concrete indices that the first argument refers to
* @return true if the first argument is a pattern that maps to all available indices, false otherwise
*/
public boolean isPatternMatchingAllIndices(String[] indicesOrAliases, String[] concreteIndices) {
// if we end up matching on all indices, check, if its a wildcard parameter, or a "-something" structure
if (concreteIndices.length == concreteAllIndices().length && indicesOrAliases.length > 0) {
//we might have something like /-test1,+test1 that would identify all indices
//or something like /-test1 with test1 index missing and IgnoreIndices.MISSING
if (indicesOrAliases[0].charAt(0) == '-') {
return true;
}
//otherwise we check if there's any simple regex
for (String indexOrAlias : indicesOrAliases) {
if (Regex.isSimpleMatchPattern(indexOrAlias)) {
return true;
}
}
}
return false;
}
@Override @Override
public UnmodifiableIterator<IndexMetaData> iterator() { public UnmodifiableIterator<IndexMetaData> iterator() {

View File

@ -19,6 +19,7 @@
package org.elasticsearch.cluster.metadata; package org.elasticsearch.cluster.metadata;
import org.elasticsearch.ElasticSearchIllegalArgumentException;
import org.elasticsearch.cluster.ClusterService; import org.elasticsearch.cluster.ClusterService;
import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.ProcessedClusterStateUpdateTask; import org.elasticsearch.cluster.ProcessedClusterStateUpdateTask;
@ -37,7 +38,9 @@ import org.elasticsearch.index.Index;
import org.elasticsearch.indices.IndexMissingException; import org.elasticsearch.indices.IndexMissingException;
import org.elasticsearch.rest.RestStatus; import org.elasticsearch.rest.RestStatus;
import static org.elasticsearch.cluster.ClusterState.newClusterStateBuilder; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/** /**
* *
@ -58,37 +61,51 @@ public class MetaDataStateIndexService extends AbstractComponent {
} }
public void closeIndex(final Request request, final Listener listener) { public void closeIndex(final Request request, final Listener listener) {
clusterService.submitStateUpdateTask("close-index [" + request.index + "]", Priority.URGENT, new ProcessedClusterStateUpdateTask() { if (request.indices == null || request.indices.length == 0) {
@Override throw new ElasticSearchIllegalArgumentException("Index name is required");
public ClusterState execute(ClusterState currentState) {
IndexMetaData indexMetaData = currentState.metaData().index(request.index);
if (indexMetaData == null) {
listener.onFailure(new IndexMissingException(new Index(request.index)));
return currentState;
} }
if (indexMetaData.state() == IndexMetaData.State.CLOSE) { final String indicesAsString = Arrays.toString(request.indices);
clusterService.submitStateUpdateTask("close-indices " + indicesAsString, Priority.URGENT, new ProcessedClusterStateUpdateTask() {
@Override
public ClusterState execute(ClusterState currentState) {
List<String> indicesToClose = new ArrayList<String>();
for (String index : request.indices) {
IndexMetaData indexMetaData = currentState.metaData().index(index);
if (indexMetaData == null) {
listener.onFailure(new IndexMissingException(new Index(index)));
return currentState;
}
if (indexMetaData.state() != IndexMetaData.State.CLOSE) {
indicesToClose.add(index);
}
}
if (indicesToClose.isEmpty()) {
listener.onResponse(new Response(true)); listener.onResponse(new Response(true));
return currentState; return currentState;
} }
logger.info("[{}] closing index", request.index); logger.info("closing indices [{}]", indicesAsString);
MetaData.Builder mdBuilder = MetaData.builder() MetaData.Builder mdBuilder = MetaData.builder()
.metaData(currentState.metaData()) .metaData(currentState.metaData());
.put(IndexMetaData.newIndexMetaDataBuilder(currentState.metaData().index(request.index)).state(IndexMetaData.State.CLOSE)); ClusterBlocks.Builder blocksBuilder = ClusterBlocks.builder()
.blocks(currentState.blocks());
for (String index : indicesToClose) {
mdBuilder.put(IndexMetaData.newIndexMetaDataBuilder(currentState.metaData().index(index)).state(IndexMetaData.State.CLOSE));
blocksBuilder.addIndexBlock(index, INDEX_CLOSED_BLOCK);
}
ClusterBlocks.Builder blocks = ClusterBlocks.builder().blocks(currentState.blocks()) ClusterState updatedState = ClusterState.builder().state(currentState).metaData(mdBuilder).blocks(blocksBuilder).build();
.addIndexBlock(request.index, INDEX_CLOSED_BLOCK);
ClusterState updatedState = ClusterState.builder().state(currentState).metaData(mdBuilder).blocks(blocks).build();
RoutingTable.Builder rtBuilder = RoutingTable.builder() RoutingTable.Builder rtBuilder = RoutingTable.builder()
.routingTable(currentState.routingTable()) .routingTable(currentState.routingTable());
.remove(request.index); for (String index : indicesToClose) {
rtBuilder.remove(index);
}
RoutingAllocation.Result routingResult = allocationService.reroute(newClusterStateBuilder().state(updatedState).routingTable(rtBuilder).build()); RoutingAllocation.Result routingResult = allocationService.reroute(ClusterState.builder().state(updatedState).routingTable(rtBuilder).build());
return ClusterState.builder().state(updatedState).routingResult(routingResult).build(); return ClusterState.builder().state(updatedState).routingResult(routingResult).build();
} }
@ -101,36 +118,51 @@ public class MetaDataStateIndexService extends AbstractComponent {
} }
public void openIndex(final Request request, final Listener listener) { public void openIndex(final Request request, final Listener listener) {
clusterService.submitStateUpdateTask("open-index [" + request.index + "]", Priority.URGENT, new ProcessedClusterStateUpdateTask() { if (request.indices == null || request.indices.length == 0) {
@Override throw new ElasticSearchIllegalArgumentException("Index name is required");
public ClusterState execute(ClusterState currentState) {
IndexMetaData indexMetaData = currentState.metaData().index(request.index);
if (indexMetaData == null) {
listener.onFailure(new IndexMissingException(new Index(request.index)));
return currentState;
} }
if (indexMetaData.state() == IndexMetaData.State.OPEN) { final String indicesAsString = Arrays.toString(request.indices);
clusterService.submitStateUpdateTask("open-indices " + indicesAsString, Priority.URGENT, new ProcessedClusterStateUpdateTask() {
@Override
public ClusterState execute(ClusterState currentState) {
List<String> indicesToOpen = new ArrayList<String>();
for (String index : request.indices) {
IndexMetaData indexMetaData = currentState.metaData().index(index);
if (indexMetaData == null) {
listener.onFailure(new IndexMissingException(new Index(index)));
return currentState;
}
if (indexMetaData.state() != IndexMetaData.State.OPEN) {
indicesToOpen.add(index);
}
}
if (indicesToOpen.isEmpty()) {
listener.onResponse(new Response(true)); listener.onResponse(new Response(true));
return currentState; return currentState;
} }
logger.info("[{}] opening index", request.index); logger.info("opening indices [{}]", indicesAsString);
MetaData.Builder mdBuilder = MetaData.builder() MetaData.Builder mdBuilder = MetaData.builder()
.metaData(currentState.metaData()) .metaData(currentState.metaData());
.put(IndexMetaData.newIndexMetaDataBuilder(currentState.metaData().index(request.index)).state(IndexMetaData.State.OPEN)); ClusterBlocks.Builder blocksBuilder = ClusterBlocks.builder()
.blocks(currentState.blocks());
for (String index : indicesToOpen) {
mdBuilder.put(IndexMetaData.newIndexMetaDataBuilder(currentState.metaData().index(index)).state(IndexMetaData.State.OPEN));
blocksBuilder.removeIndexBlock(index, INDEX_CLOSED_BLOCK);
}
ClusterBlocks.Builder blocks = ClusterBlocks.builder().blocks(currentState.blocks()) ClusterState updatedState = ClusterState.builder().state(currentState).metaData(mdBuilder).blocks(blocksBuilder).build();
.removeIndexBlock(request.index, INDEX_CLOSED_BLOCK);
ClusterState updatedState = ClusterState.builder().state(currentState).metaData(mdBuilder).blocks(blocks).build(); RoutingTable.Builder rtBuilder = RoutingTable.builder()
.routingTable(updatedState.routingTable());
for (String index : indicesToOpen) {
rtBuilder.addAsRecovery(updatedState.metaData().index(index));
}
RoutingTable.Builder rtBuilder = RoutingTable.builder().routingTable(updatedState.routingTable()) RoutingAllocation.Result routingResult = allocationService.reroute(ClusterState.builder().state(updatedState).routingTable(rtBuilder).build());
.addAsRecovery(updatedState.metaData().index(request.index));
RoutingAllocation.Result routingResult = allocationService.reroute(newClusterStateBuilder().state(updatedState).routingTable(rtBuilder).build());
return ClusterState.builder().state(updatedState).routingResult(routingResult).build(); return ClusterState.builder().state(updatedState).routingResult(routingResult).build();
} }
@ -151,12 +183,12 @@ public class MetaDataStateIndexService extends AbstractComponent {
public static class Request { public static class Request {
final String index; final String[] indices;
TimeValue timeout = TimeValue.timeValueSeconds(10); TimeValue timeout = TimeValue.timeValueSeconds(10);
public Request(String index) { public Request(String[] indices) {
this.index = index; this.indices = indices;
} }
public Request timeout(TimeValue timeout) { public Request timeout(TimeValue timeout) {

View File

@ -22,6 +22,7 @@ package org.elasticsearch.rest.action.admin.indices.close;
import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.admin.indices.close.CloseIndexRequest; import org.elasticsearch.action.admin.indices.close.CloseIndexRequest;
import org.elasticsearch.action.admin.indices.close.CloseIndexResponse; import org.elasticsearch.action.admin.indices.close.CloseIndexResponse;
import org.elasticsearch.action.support.IgnoreIndices;
import org.elasticsearch.client.Client; import org.elasticsearch.client.Client;
import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
@ -34,6 +35,7 @@ import java.io.IOException;
import static org.elasticsearch.common.unit.TimeValue.timeValueSeconds; import static org.elasticsearch.common.unit.TimeValue.timeValueSeconds;
import static org.elasticsearch.rest.RestStatus.OK; import static org.elasticsearch.rest.RestStatus.OK;
import static org.elasticsearch.rest.action.support.RestActions.splitIndices;
/** /**
* *
@ -43,14 +45,18 @@ public class RestCloseIndexAction extends BaseRestHandler {
@Inject @Inject
public RestCloseIndexAction(Settings settings, Client client, RestController controller) { public RestCloseIndexAction(Settings settings, Client client, RestController controller) {
super(settings, client); super(settings, client);
controller.registerHandler(RestRequest.Method.POST, "/_close", this);
controller.registerHandler(RestRequest.Method.POST, "/{index}/_close", this); controller.registerHandler(RestRequest.Method.POST, "/{index}/_close", this);
} }
@Override @Override
public void handleRequest(final RestRequest request, final RestChannel channel) { public void handleRequest(final RestRequest request, final RestChannel channel) {
CloseIndexRequest closeIndexRequest = new CloseIndexRequest(request.param("index")); CloseIndexRequest closeIndexRequest = new CloseIndexRequest(splitIndices(request.param("index")));
closeIndexRequest.listenerThreaded(false); closeIndexRequest.listenerThreaded(false);
closeIndexRequest.timeout(request.paramAsTime("timeout", timeValueSeconds(10))); closeIndexRequest.timeout(request.paramAsTime("timeout", timeValueSeconds(10)));
if (request.hasParam("ignore_indices")) {
closeIndexRequest.ignoreIndices(IgnoreIndices.fromString(request.param("ignore_indices")));
}
client.admin().indices().close(closeIndexRequest, new ActionListener<CloseIndexResponse>() { client.admin().indices().close(closeIndexRequest, new ActionListener<CloseIndexResponse>() {
@Override @Override
public void onResponse(CloseIndexResponse response) { public void onResponse(CloseIndexResponse response) {

View File

@ -22,6 +22,7 @@ package org.elasticsearch.rest.action.admin.indices.open;
import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.admin.indices.open.OpenIndexRequest; import org.elasticsearch.action.admin.indices.open.OpenIndexRequest;
import org.elasticsearch.action.admin.indices.open.OpenIndexResponse; import org.elasticsearch.action.admin.indices.open.OpenIndexResponse;
import org.elasticsearch.action.support.IgnoreIndices;
import org.elasticsearch.client.Client; import org.elasticsearch.client.Client;
import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
@ -34,6 +35,7 @@ import java.io.IOException;
import static org.elasticsearch.common.unit.TimeValue.timeValueSeconds; import static org.elasticsearch.common.unit.TimeValue.timeValueSeconds;
import static org.elasticsearch.rest.RestStatus.OK; import static org.elasticsearch.rest.RestStatus.OK;
import static org.elasticsearch.rest.action.support.RestActions.splitIndices;
/** /**
* *
@ -43,14 +45,18 @@ public class RestOpenIndexAction extends BaseRestHandler {
@Inject @Inject
public RestOpenIndexAction(Settings settings, Client client, RestController controller) { public RestOpenIndexAction(Settings settings, Client client, RestController controller) {
super(settings, client); super(settings, client);
controller.registerHandler(RestRequest.Method.POST, "/_open", this);
controller.registerHandler(RestRequest.Method.POST, "/{index}/_open", this); controller.registerHandler(RestRequest.Method.POST, "/{index}/_open", this);
} }
@Override @Override
public void handleRequest(final RestRequest request, final RestChannel channel) { public void handleRequest(final RestRequest request, final RestChannel channel) {
OpenIndexRequest openIndexRequest = new OpenIndexRequest(request.param("index")); OpenIndexRequest openIndexRequest = new OpenIndexRequest(splitIndices(request.param("index")));
openIndexRequest.listenerThreaded(false); openIndexRequest.listenerThreaded(false);
openIndexRequest.timeout(request.paramAsTime("timeout", timeValueSeconds(10))); openIndexRequest.timeout(request.paramAsTime("timeout", timeValueSeconds(10)));
if (request.hasParam("ignore_indices")) {
openIndexRequest.ignoreIndices(IgnoreIndices.fromString(request.param("ignore_indices")));
}
client.admin().indices().open(openIndexRequest, new ActionListener<OpenIndexResponse>() { client.admin().indices().open(openIndexRequest, new ActionListener<OpenIndexResponse>() {
@Override @Override
public void onResponse(OpenIndexResponse response) { public void onResponse(OpenIndexResponse response) {

View File

@ -27,6 +27,7 @@ import org.elasticsearch.common.network.NetworkUtils;
import org.elasticsearch.common.settings.ImmutableSettings; import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.unit.TimeValue; import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.indices.IndexMissingException;
import org.elasticsearch.node.Node; import org.elasticsearch.node.Node;
import java.util.Map; import java.util.Map;
@ -141,4 +142,18 @@ public abstract class AbstractNodesTests extends ElasticsearchTestCase {
while (!blocks.isEmpty() && (System.currentTimeMillis() - start) < timeout.millis()); while (!blocks.isEmpty() && (System.currentTimeMillis() - start) < timeout.millis());
return blocks; return blocks;
} }
public void createIndices(Client client, String... indices) {
for (String index : indices) {
client.admin().indices().prepareCreate(index).execute().actionGet();
}
}
public void wipeIndices(Client client, String... names) {
try {
client.admin().indices().prepareDelete(names).execute().actionGet();
} catch (IndexMissingException e) {
// ignore
}
}
} }

View File

@ -0,0 +1,127 @@
/*
* 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.test.integration.indices.state;
import org.elasticsearch.ElasticSearchIllegalArgumentException;
import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
import org.elasticsearch.action.admin.cluster.state.ClusterStateResponse;
import org.elasticsearch.action.admin.indices.close.CloseIndexResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.common.settings.ImmutableSettings;
import org.elasticsearch.test.integration.AbstractNodesTests;
import org.testng.annotations.AfterClass;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.notNullValue;
public class CloseIndexDisableCloseAllTests extends AbstractNodesTests {
@BeforeClass
public void createNodes() {
ImmutableSettings.Builder settings = ImmutableSettings.builder().put("action.disable_close_all_indices", true);
startNode("server1", settings);
startNode("server2", settings);
}
@AfterClass
public void closeNodes() {
closeAllNodes();
}
@AfterMethod
public void wipeAllIndices() {
wipeIndices(client("server1"), "_all");
}
@Test(expectedExceptions = ElasticSearchIllegalArgumentException.class)
public void testCloseAllExplicitly() {
Client client = client("server1");
createIndices(client, "test1", "test2", "test3");
ClusterHealthResponse healthResponse = client.admin().cluster().prepareHealth().setWaitForGreenStatus().execute().actionGet();
assertThat(healthResponse.isTimedOut(), equalTo(false));
client.admin().indices().prepareClose("_all").execute().actionGet();
}
@Test(expectedExceptions = ElasticSearchIllegalArgumentException.class)
public void testCloseAllWildcard() {
Client client = client("server2");
createIndices(client, "test1", "test2", "test3");
ClusterHealthResponse healthResponse = client.admin().cluster().prepareHealth().setWaitForGreenStatus().execute().actionGet();
assertThat(healthResponse.isTimedOut(), equalTo(false));
client.admin().indices().prepareClose("*").execute().actionGet();
}
@Test(expectedExceptions = ElasticSearchIllegalArgumentException.class)
public void testCloseAllWildcard2() {
Client client = client("server2");
createIndices(client, "test1", "test2", "test3");
ClusterHealthResponse healthResponse = client.admin().cluster().prepareHealth().setWaitForGreenStatus().execute().actionGet();
assertThat(healthResponse.isTimedOut(), equalTo(false));
client.admin().indices().prepareClose("test*").execute().actionGet();
}
@Test
public void testCloseWildcardNonMatchingAll() {
Client client = client("server1");
createIndices(client, "test1", "test2", "test3");
ClusterHealthResponse healthResponse = client.admin().cluster().prepareHealth().setWaitForGreenStatus().execute().actionGet();
assertThat(healthResponse.isTimedOut(), equalTo(false));
CloseIndexResponse closeIndexResponse = client.admin().indices().prepareClose("*", "-test1").execute().actionGet();
assertThat(closeIndexResponse.isAcknowledged(), equalTo(true));
assertIndexIsClosed("test2", "test3");
}
@Test(expectedExceptions = ElasticSearchIllegalArgumentException.class)
public void testCloseWildcardMatchingAll() {
Client client = client("server2");
createIndices(client, "test1", "test2", "test3");
ClusterHealthResponse healthResponse = client.admin().cluster().prepareHealth().setWaitForGreenStatus().execute().actionGet();
assertThat(healthResponse.isTimedOut(), equalTo(false));
client.admin().indices().prepareClose("*", "-test1", "+test1").execute().actionGet();
}
@Test
public void testCloseWildcardNonMatchingAll2() {
Client client = client("server1");
createIndices(client, "test1", "test2", "test3", "a");
ClusterHealthResponse healthResponse = client.admin().cluster().prepareHealth().setWaitForGreenStatus().execute().actionGet();
assertThat(healthResponse.isTimedOut(), equalTo(false));
CloseIndexResponse closeIndexResponse = client.admin().indices().prepareClose("test*").execute().actionGet();
assertThat(closeIndexResponse.isAcknowledged(), equalTo(true));
assertIndexIsClosed("test1", "test2", "test3");
}
private void assertIndexIsClosed(String... indices) {
checkIndexState(IndexMetaData.State.CLOSE, indices);
}
private void checkIndexState(IndexMetaData.State state, String... indices) {
ClusterStateResponse clusterStateResponse = client("server1").admin().cluster().prepareState().execute().actionGet();
for (String index : indices) {
IndexMetaData indexMetaData = clusterStateResponse.getState().metaData().indices().get(index);
assertThat(indexMetaData, notNullValue());
assertThat(indexMetaData.getState(), equalTo(state));
}
}
}

View File

@ -0,0 +1,292 @@
/*
* 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.test.integration.indices.state;
import org.elasticsearch.action.ActionRequestValidationException;
import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
import org.elasticsearch.action.admin.cluster.state.ClusterStateResponse;
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesResponse;
import org.elasticsearch.action.admin.indices.close.CloseIndexResponse;
import org.elasticsearch.action.admin.indices.open.OpenIndexResponse;
import org.elasticsearch.action.support.IgnoreIndices;
import org.elasticsearch.client.Client;
import org.elasticsearch.cluster.metadata.IndexMetaData;
import org.elasticsearch.indices.IndexMissingException;
import org.elasticsearch.test.integration.AbstractSharedClusterTest;
import org.testng.annotations.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.notNullValue;
public class OpenCloseIndexTests extends AbstractSharedClusterTest {
@Test
public void testSimpleCloseOpen() {
Client client = client();
createIndex("test1");
ClusterHealthResponse healthResponse = client.admin().cluster().prepareHealth().setWaitForGreenStatus().execute().actionGet();
assertThat(healthResponse.isTimedOut(), equalTo(false));
CloseIndexResponse closeIndexResponse = client.admin().indices().prepareClose("test1").execute().actionGet();
assertThat(closeIndexResponse.isAcknowledged(), equalTo(true));
assertIndexIsClosed("test1");
OpenIndexResponse openIndexResponse = client.admin().indices().prepareOpen("test1").execute().actionGet();
assertThat(openIndexResponse.isAcknowledged(), equalTo(true));
assertIndexIsOpened("test1");
}
@Test(expectedExceptions = IndexMissingException.class)
public void testSimpleCloseMissingIndex() {
Client client = client();
client.admin().indices().prepareClose("test1").execute().actionGet();
}
@Test(expectedExceptions = IndexMissingException.class)
public void testSimpleOpenMissingIndex() {
Client client = client();
client.admin().indices().prepareOpen("test1").execute().actionGet();
}
@Test(expectedExceptions = IndexMissingException.class)
public void testCloseOneMissingIndex() {
Client client = client();
createIndex("test1");
ClusterHealthResponse healthResponse = client.admin().cluster().prepareHealth().setWaitForGreenStatus().execute().actionGet();
assertThat(healthResponse.isTimedOut(), equalTo(false));
client.admin().indices().prepareClose("test1", "test2").execute().actionGet();
}
@Test
public void testCloseOneMissingIndexIgnoreMissing() {
Client client = client();
createIndex("test1");
ClusterHealthResponse healthResponse = client.admin().cluster().prepareHealth().setWaitForGreenStatus().execute().actionGet();
assertThat(healthResponse.isTimedOut(), equalTo(false));
CloseIndexResponse closeIndexResponse = client.admin().indices().prepareClose("test1", "test2")
.setIgnoreIndices(IgnoreIndices.MISSING).execute().actionGet();
assertThat(closeIndexResponse.isAcknowledged(), equalTo(true));
assertIndexIsClosed("test1");
}
@Test(expectedExceptions = IndexMissingException.class)
public void testOpenOneMissingIndex() {
Client client = client();
createIndex("test1");
ClusterHealthResponse healthResponse = client.admin().cluster().prepareHealth().setWaitForGreenStatus().execute().actionGet();
assertThat(healthResponse.isTimedOut(), equalTo(false));
client.admin().indices().prepareOpen("test1", "test2").execute().actionGet();
}
@Test
public void testOpenOneMissingIndexIgnoreMissing() {
Client client = client();
createIndex("test1");
ClusterHealthResponse healthResponse = client.admin().cluster().prepareHealth().setWaitForGreenStatus().execute().actionGet();
assertThat(healthResponse.isTimedOut(), equalTo(false));
OpenIndexResponse openIndexResponse = client.admin().indices().prepareOpen("test1", "test2")
.setIgnoreIndices(IgnoreIndices.MISSING).execute().actionGet();
assertThat(openIndexResponse.isAcknowledged(), equalTo(true));
assertIndexIsOpened("test1");
}
@Test
public void testCloseOpenMultipleIndices() {
Client client = client();
createIndex("test1", "test2", "test3");
ClusterHealthResponse healthResponse = client.admin().cluster().prepareHealth().setWaitForGreenStatus().execute().actionGet();
assertThat(healthResponse.isTimedOut(), equalTo(false));
CloseIndexResponse closeIndexResponse1 = client.admin().indices().prepareClose("test1").execute().actionGet();
assertThat(closeIndexResponse1.isAcknowledged(), equalTo(true));
CloseIndexResponse closeIndexResponse2 = client.admin().indices().prepareClose("test2").execute().actionGet();
assertThat(closeIndexResponse2.isAcknowledged(), equalTo(true));
assertIndexIsClosed("test1", "test2");
assertIndexIsOpened("test3");
OpenIndexResponse openIndexResponse1 = client.admin().indices().prepareOpen("test1").execute().actionGet();
assertThat(openIndexResponse1.isAcknowledged(), equalTo(true));
OpenIndexResponse openIndexResponse2 = client.admin().indices().prepareOpen("test2").execute().actionGet();
assertThat(openIndexResponse2.isAcknowledged(), equalTo(true));
assertIndexIsOpened("test1", "test2", "test3");
}
@Test
public void testCloseOpenWildcard() {
Client client = client();
createIndex("test1", "test2", "a");
ClusterHealthResponse healthResponse = client.admin().cluster().prepareHealth().setWaitForGreenStatus().execute().actionGet();
assertThat(healthResponse.isTimedOut(), equalTo(false));
CloseIndexResponse closeIndexResponse = client.admin().indices().prepareClose("test*").execute().actionGet();
assertThat(closeIndexResponse.isAcknowledged(), equalTo(true));
assertIndexIsClosed("test1", "test2");
assertIndexIsOpened("a");
OpenIndexResponse openIndexResponse = client.admin().indices().prepareOpen("test*").execute().actionGet();
assertThat(openIndexResponse.isAcknowledged(), equalTo(true));
assertIndexIsOpened("test1", "test2", "a");
}
@Test
public void testCloseOpenAll() {
Client client = client();
createIndex("test1", "test2", "test3");
ClusterHealthResponse healthResponse = client.admin().cluster().prepareHealth().setWaitForGreenStatus().execute().actionGet();
assertThat(healthResponse.isTimedOut(), equalTo(false));
CloseIndexResponse closeIndexResponse = client.admin().indices().prepareClose("_all").execute().actionGet();
assertThat(closeIndexResponse.isAcknowledged(), equalTo(true));
assertIndexIsClosed("test1", "test2", "test3");
OpenIndexResponse openIndexResponse = client.admin().indices().prepareOpen("_all").execute().actionGet();
assertThat(openIndexResponse.isAcknowledged(), equalTo(true));
assertIndexIsOpened("test1", "test2", "test3");
}
@Test
public void testCloseOpenAllWildcard() {
Client client = client();
createIndex("test1", "test2", "test3");
ClusterHealthResponse healthResponse = client.admin().cluster().prepareHealth().setWaitForGreenStatus().execute().actionGet();
assertThat(healthResponse.isTimedOut(), equalTo(false));
CloseIndexResponse closeIndexResponse = client.admin().indices().prepareClose("*").execute().actionGet();
assertThat(closeIndexResponse.isAcknowledged(), equalTo(true));
assertIndexIsClosed("test1", "test2", "test3");
OpenIndexResponse openIndexResponse = client.admin().indices().prepareOpen("*").execute().actionGet();
assertThat(openIndexResponse.isAcknowledged(), equalTo(true));
assertIndexIsOpened("test1", "test2", "test3");
}
@Test(expectedExceptions = ActionRequestValidationException.class)
public void testCloseNoIndex() {
Client client = client();
client.admin().indices().prepareClose().execute().actionGet();
}
@Test(expectedExceptions = ActionRequestValidationException.class)
public void testCloseNullIndex() {
Client client = client();
client.admin().indices().prepareClose(null).execute().actionGet();
}
@Test(expectedExceptions = ActionRequestValidationException.class)
public void testOpenNoIndex() {
Client client = client();
client.admin().indices().prepareOpen().execute().actionGet();
}
@Test(expectedExceptions = ActionRequestValidationException.class)
public void testOpenNullIndex() {
Client client = client();
client.admin().indices().prepareOpen(null).execute().actionGet();
}
@Test
public void testOpenAlreadyOpenedIndex() {
Client client = client();
createIndex("test1");
ClusterHealthResponse healthResponse = client.admin().cluster().prepareHealth().setWaitForGreenStatus().execute().actionGet();
assertThat(healthResponse.isTimedOut(), equalTo(false));
//no problem if we try to open an index that's already in open state
OpenIndexResponse openIndexResponse1 = client.admin().indices().prepareOpen("test1").execute().actionGet();
assertThat(openIndexResponse1.isAcknowledged(), equalTo(true));
assertIndexIsOpened("test1");
}
@Test
public void testCloseAlreadyClosedIndex() {
Client client = client();
createIndex("test1");
ClusterHealthResponse healthResponse = client.admin().cluster().prepareHealth().setWaitForGreenStatus().execute().actionGet();
assertThat(healthResponse.isTimedOut(), equalTo(false));
//closing the index
CloseIndexResponse closeIndexResponse = client.admin().indices().prepareClose("test1").execute().actionGet();
assertThat(closeIndexResponse.isAcknowledged(), equalTo(true));
assertIndexIsClosed("test1");
//no problem if we try to close an index that's already in close state
OpenIndexResponse openIndexResponse1 = client.admin().indices().prepareOpen("test1").execute().actionGet();
assertThat(openIndexResponse1.isAcknowledged(), equalTo(true));
assertIndexIsOpened("test1");
}
@Test
public void testSimpleCloseOpenAlias() {
Client client = client();
createIndex("test1");
ClusterHealthResponse healthResponse = client.admin().cluster().prepareHealth().setWaitForGreenStatus().execute().actionGet();
assertThat(healthResponse.isTimedOut(), equalTo(false));
IndicesAliasesResponse aliasesResponse = client.admin().indices().prepareAliases().addAlias("test1", "test1-alias").execute().actionGet();
assertThat(aliasesResponse.isAcknowledged(), equalTo(true));
CloseIndexResponse closeIndexResponse = client.admin().indices().prepareClose("test1-alias").execute().actionGet();
assertThat(closeIndexResponse.isAcknowledged(), equalTo(true));
assertIndexIsClosed("test1");
OpenIndexResponse openIndexResponse = client.admin().indices().prepareOpen("test1-alias").execute().actionGet();
assertThat(openIndexResponse.isAcknowledged(), equalTo(true));
assertIndexIsOpened("test1");
}
@Test
public void testCloseOpenAliasMultipleIndices() {
Client client = client();
createIndex("test1", "test2");
ClusterHealthResponse healthResponse = client.admin().cluster().prepareHealth().setWaitForGreenStatus().execute().actionGet();
assertThat(healthResponse.isTimedOut(), equalTo(false));
IndicesAliasesResponse aliasesResponse1 = client.admin().indices().prepareAliases().addAlias("test1", "test-alias").execute().actionGet();
assertThat(aliasesResponse1.isAcknowledged(), equalTo(true));
IndicesAliasesResponse aliasesResponse2 = client.admin().indices().prepareAliases().addAlias("test2", "test-alias").execute().actionGet();
assertThat(aliasesResponse2.isAcknowledged(), equalTo(true));
CloseIndexResponse closeIndexResponse = client.admin().indices().prepareClose("test-alias").execute().actionGet();
assertThat(closeIndexResponse.isAcknowledged(), equalTo(true));
assertIndexIsClosed("test1", "test2");
OpenIndexResponse openIndexResponse = client.admin().indices().prepareOpen("test-alias").execute().actionGet();
assertThat(openIndexResponse.isAcknowledged(), equalTo(true));
assertIndexIsOpened("test1", "test2");
}
private void assertIndexIsOpened(String... indices) {
checkIndexState(IndexMetaData.State.OPEN, indices);
}
private void assertIndexIsClosed(String... indices) {
checkIndexState(IndexMetaData.State.CLOSE, indices);
}
private void checkIndexState(IndexMetaData.State state, String... indices) {
ClusterStateResponse clusterStateResponse = client().admin().cluster().prepareState().execute().actionGet();
for (String index : indices) {
IndexMetaData indexMetaData = clusterStateResponse.getState().metaData().indices().get(index);
assertThat(indexMetaData, notNullValue());
assertThat(indexMetaData.getState(), equalTo(state));
}
}
}

View File

@ -104,4 +104,157 @@ public class MetaDataTests {
MetaData md = mdBuilder.build(); MetaData md = mdBuilder.build();
assertThat(newHashSet(md.concreteIndices(new String[]{}, IgnoreIndices.MISSING, true)), equalTo(Sets.<String>newHashSet("kuku","testXXX"))); assertThat(newHashSet(md.concreteIndices(new String[]{}, IgnoreIndices.MISSING, true)), equalTo(Sets.<String>newHashSet("kuku","testXXX")));
} }
@Test
public void testIsAllIndices_null() throws Exception {
MetaData metaData = MetaData.builder().build();
assertThat(metaData.isAllIndices(null), equalTo(true));
}
@Test
public void testIsAllIndices_empty() throws Exception {
MetaData metaData = MetaData.builder().build();
assertThat(metaData.isAllIndices(new String[0]), equalTo(true));
}
@Test
public void testIsAllIndices_explicitAll() throws Exception {
MetaData metaData = MetaData.builder().build();
assertThat(metaData.isAllIndices(new String[]{"_all"}), equalTo(true));
}
@Test
public void testIsAllIndices_explicitAllPlusOther() throws Exception {
MetaData metaData = MetaData.builder().build();
assertThat(metaData.isAllIndices(new String[]{"_all", "other"}), equalTo(false));
}
@Test
public void testIsAllIndices_normalIndexes() throws Exception {
MetaData metaData = MetaData.builder().build();
assertThat(metaData.isAllIndices(new String[]{"index1", "index2", "index3"}), equalTo(false));
}
@Test
public void testIsAllIndices_wildcard() throws Exception {
MetaData metaData = MetaData.builder().build();
assertThat(metaData.isAllIndices(new String[]{"*"}), equalTo(false));
}
@Test
public void testIsExplicitAllIndices_null() throws Exception {
MetaData metaData = MetaData.builder().build();
assertThat(metaData.isExplicitAllIndices(null), equalTo(false));
}
@Test
public void testIsExplicitAllIndices_empty() throws Exception {
MetaData metaData = MetaData.builder().build();
assertThat(metaData.isExplicitAllIndices(new String[0]), equalTo(false));
}
@Test
public void testIsExplicitAllIndices_explicitAll() throws Exception {
MetaData metaData = MetaData.builder().build();
assertThat(metaData.isExplicitAllIndices(new String[]{"_all"}), equalTo(true));
}
@Test
public void testIsExplicitAllIndices_explicitAllPlusOther() throws Exception {
MetaData metaData = MetaData.builder().build();
assertThat(metaData.isExplicitAllIndices(new String[]{"_all", "other"}), equalTo(false));
}
@Test
public void testIsExplicitAllIndices_normalIndexes() throws Exception {
MetaData metaData = MetaData.builder().build();
assertThat(metaData.isExplicitAllIndices(new String[]{"index1", "index2", "index3"}), equalTo(false));
}
@Test
public void testIsExplicitAllIndices_wildcard() throws Exception {
MetaData metaData = MetaData.builder().build();
assertThat(metaData.isExplicitAllIndices(new String[]{"*"}), equalTo(false));
}
@Test
public void testIsPatternMatchingAllIndices_explicitList() throws Exception {
//even though it does identify all indices, it's not a pattern but just an explicit list of them
String[] concreteIndices = new String[]{"index1", "index2", "index3"};
String[] indicesOrAliases = concreteIndices;
String[] allConcreteIndices = concreteIndices;
MetaData metaData = metaDataBuilder(allConcreteIndices);
assertThat(metaData.isPatternMatchingAllIndices(indicesOrAliases, concreteIndices), equalTo(false));
}
@Test
public void testIsPatternMatchingAllIndices_onlyWildcard() throws Exception {
String[] indicesOrAliases = new String[]{"*"};
String[] concreteIndices = new String[]{"index1", "index2", "index3"};
String[] allConcreteIndices = concreteIndices;
MetaData metaData = metaDataBuilder(allConcreteIndices);
assertThat(metaData.isPatternMatchingAllIndices(indicesOrAliases, concreteIndices), equalTo(true));
}
@Test
public void testIsPatternMatchingAllIndices_matchingTrailingWildcard() throws Exception {
String[] indicesOrAliases = new String[]{"index*"};
String[] concreteIndices = new String[]{"index1", "index2", "index3"};
String[] allConcreteIndices = concreteIndices;
MetaData metaData = metaDataBuilder(allConcreteIndices);
assertThat(metaData.isPatternMatchingAllIndices(indicesOrAliases, concreteIndices), equalTo(true));
}
@Test
public void testIsPatternMatchingAllIndices_nonMatchingTrailingWildcard() throws Exception {
String[] indicesOrAliases = new String[]{"index*"};
String[] concreteIndices = new String[]{"index1", "index2", "index3"};
String[] allConcreteIndices = new String[]{"index1", "index2", "index3", "a", "b"};
MetaData metaData = metaDataBuilder(allConcreteIndices);
assertThat(metaData.isPatternMatchingAllIndices(indicesOrAliases, concreteIndices), equalTo(false));
}
@Test
public void testIsPatternMatchingAllIndices_matchingSingleExclusion() throws Exception {
String[] indicesOrAliases = new String[]{"-index1", "+index1"};
String[] concreteIndices = new String[]{"index1", "index2", "index3"};
String[] allConcreteIndices = concreteIndices;
MetaData metaData = metaDataBuilder(allConcreteIndices);
assertThat(metaData.isPatternMatchingAllIndices(indicesOrAliases, concreteIndices), equalTo(true));
}
@Test
public void testIsPatternMatchingAllIndices_nonMatchingSingleExclusion() throws Exception {
String[] indicesOrAliases = new String[]{"-index1"};
String[] concreteIndices = new String[]{"index2", "index3"};
String[] allConcreteIndices = new String[]{"index1", "index2", "index3"};
MetaData metaData = metaDataBuilder(allConcreteIndices);
assertThat(metaData.isPatternMatchingAllIndices(indicesOrAliases, concreteIndices), equalTo(false));
}
@Test
public void testIsPatternMatchingAllIndices_matchingTrailingWildcardAndExclusion() throws Exception {
String[] indicesOrAliases = new String[]{"index*", "-index1", "+index1"};
String[] concreteIndices = new String[]{"index1", "index2", "index3"};
String[] allConcreteIndices = concreteIndices;
MetaData metaData = metaDataBuilder(allConcreteIndices);
assertThat(metaData.isPatternMatchingAllIndices(indicesOrAliases, concreteIndices), equalTo(true));
}
@Test
public void testIsPatternMatchingAllIndices_nonMatchingTrailingWildcardAndExclusion() throws Exception {
String[] indicesOrAliases = new String[]{"index*", "-index1"};
String[] concreteIndices = new String[]{"index2", "index3"};
String[] allConcreteIndices = new String[]{"index1", "index2", "index3"};
MetaData metaData = metaDataBuilder(allConcreteIndices);
assertThat(metaData.isPatternMatchingAllIndices(indicesOrAliases, concreteIndices), equalTo(false));
}
private MetaData metaDataBuilder(String... indices) {
MetaData.Builder mdBuilder = MetaData.builder();
for (String concreteIndex : indices) {
mdBuilder.put(indexBuilder(concreteIndex));
}
return mdBuilder.build();
}
} }