1
0
Эх сурвалжийг харах

Core: don't replace indices within the ActionRequest with the concrete ones, and make sure check blocks is executed on concrete indices

Concrete indices is now called multiple times when needed instead of changing what's inside the incoming request with the concrete indices. Ideally we want to keep the original aliases or indices or wildcard expressions in the request.

Also made sure that the check blocks is done against the concrete indices, which wasn't the case for delete index, delete mapping, open index, close index, types exists and indices exists.

Closes #6694
Closes #6777
javanna 11 жил өмнө
parent
commit
8dedbd01df
20 өөрчлөгдсөн 204 нэмэгдсэн , 155 устгасан
  1. 6 2
      rest-api-spec/test/cluster.state/20_filtering.yaml
  2. 1 3
      src/main/java/org/elasticsearch/action/admin/indices/alias/exists/TransportAliasesExistAction.java
  3. 1 3
      src/main/java/org/elasticsearch/action/admin/indices/alias/get/TransportGetAliasesAction.java
  4. 4 4
      src/main/java/org/elasticsearch/action/admin/indices/close/TransportCloseIndexAction.java
  5. 5 5
      src/main/java/org/elasticsearch/action/admin/indices/delete/TransportDeleteIndexAction.java
  6. 4 8
      src/main/java/org/elasticsearch/action/admin/indices/exists/indices/TransportIndicesExistsAction.java
  7. 1 1
      src/main/java/org/elasticsearch/action/admin/indices/exists/types/TransportTypesExistsAction.java
  8. 7 7
      src/main/java/org/elasticsearch/action/admin/indices/mapping/delete/TransportDeleteMappingAction.java
  9. 1 1
      src/main/java/org/elasticsearch/action/admin/indices/mapping/get/TransportGetFieldMappingsAction.java
  10. 2 2
      src/main/java/org/elasticsearch/action/admin/indices/mapping/get/TransportGetMappingsAction.java
  11. 4 9
      src/main/java/org/elasticsearch/action/admin/indices/mapping/put/TransportPutMappingAction.java
  12. 4 4
      src/main/java/org/elasticsearch/action/admin/indices/open/TransportOpenIndexAction.java
  13. 2 2
      src/main/java/org/elasticsearch/action/admin/indices/settings/get/TransportGetSettingsAction.java
  14. 3 8
      src/main/java/org/elasticsearch/action/admin/indices/settings/put/TransportUpdateSettingsAction.java
  15. 5 11
      src/main/java/org/elasticsearch/action/admin/indices/warmer/delete/TransportDeleteWarmerAction.java
  16. 2 2
      src/main/java/org/elasticsearch/action/admin/indices/warmer/get/TransportGetWarmersAction.java
  17. 2 3
      src/main/java/org/elasticsearch/action/support/master/info/TransportClusterInfoAction.java
  18. 1 1
      src/main/java/org/elasticsearch/action/support/replication/TransportIndicesReplicationOperationAction.java
  19. 62 57
      src/test/java/org/elasticsearch/action/bulk/BulkProcessorTests.java
  20. 87 22
      src/test/java/org/elasticsearch/cluster/BlockClusterStatsTests.java

+ 6 - 2
rest-api-spec/test/cluster.state/20_filtering.yaml

@@ -24,8 +24,6 @@ setup:
 
 ---
 "Filtering the cluster state by blocks should return the blocks":
-# read only index
-# TODO: can this cause issues leaving it read only when deleting it in teardown
   - do:
       indices.put_settings:
         index: testidx
@@ -42,6 +40,12 @@ setup:
   - is_false: routing_nodes
   - length:   { blocks: 1 }
 
+  - do:
+      indices.put_settings:
+        index: testidx
+        body:
+          index.blocks.read_only: false
+
 ---
 "Filtering the cluster state by nodes only should work":
   - do:

+ 1 - 3
src/main/java/org/elasticsearch/action/admin/indices/alias/exists/TransportAliasesExistAction.java

@@ -62,9 +62,7 @@ public class TransportAliasesExistAction extends TransportMasterNodeReadOperatio
     @Override
     protected void masterOperation(GetAliasesRequest request, ClusterState state, ActionListener<AliasesExistResponse> listener) throws ElasticsearchException {
         String[] concreteIndices = state.metaData().concreteIndices(request.indicesOptions(), request.indices());
-        request.indices(concreteIndices);
-
-        boolean result = state.metaData().hasAliases(request.aliases(), request.indices());
+        boolean result = state.metaData().hasAliases(request.aliases(), concreteIndices);
         listener.onResponse(new AliasesExistResponse(result));
     }
 

+ 1 - 3
src/main/java/org/elasticsearch/action/admin/indices/alias/get/TransportGetAliasesAction.java

@@ -65,10 +65,8 @@ public class TransportGetAliasesAction extends TransportMasterNodeReadOperationA
     @Override
     protected void masterOperation(GetAliasesRequest request, ClusterState state, ActionListener<GetAliasesResponse> listener) throws ElasticsearchException {
         String[] concreteIndices = state.metaData().concreteIndices(request.indicesOptions(), request.indices());
-        request.indices(concreteIndices);
-
         @SuppressWarnings("unchecked") // ImmutableList to List results incompatible type
-        ImmutableOpenMap<String, List<AliasMetaData>> result = (ImmutableOpenMap) state.metaData().findAliases(request.aliases(), request.indices());
+        ImmutableOpenMap<String, List<AliasMetaData>> result = (ImmutableOpenMap) state.metaData().findAliases(request.aliases(), concreteIndices);
         listener.onResponse(new GetAliasesResponse(result));
     }
 

+ 4 - 4
src/main/java/org/elasticsearch/action/admin/indices/close/TransportCloseIndexAction.java

@@ -80,15 +80,15 @@ public class TransportCloseIndexAction extends TransportMasterNodeOperationActio
 
     @Override
     protected ClusterBlockException checkBlock(CloseIndexRequest request, ClusterState state) {
-        return state.blocks().indicesBlockedException(ClusterBlockLevel.METADATA, request.indices());
+        return state.blocks().indicesBlockedException(ClusterBlockLevel.METADATA, state.metaData().concreteIndices(request.indicesOptions(), request.indices()));
     }
 
     @Override
     protected void masterOperation(final CloseIndexRequest request, final ClusterState state, final ActionListener<CloseIndexResponse> listener) throws ElasticsearchException {
-        request.indices(state.metaData().concreteIndices(request.indicesOptions(), request.indices()));
+        final String[] concreteIndices = state.metaData().concreteIndices(request.indicesOptions(), request.indices());
         CloseIndexClusterStateUpdateRequest updateRequest = new CloseIndexClusterStateUpdateRequest()
                 .ackTimeout(request.timeout()).masterNodeTimeout(request.masterNodeTimeout())
-                .indices(request.indices());
+                .indices(concreteIndices);
 
         indexStateService.closeIndex(updateRequest, new ActionListener<ClusterStateUpdateResponse>() {
 
@@ -99,7 +99,7 @@ public class TransportCloseIndexAction extends TransportMasterNodeOperationActio
 
             @Override
             public void onFailure(Throwable t) {
-                logger.debug("failed to close indices [{}]", t, request.indices());
+                logger.debug("failed to close indices [{}]", t, concreteIndices);
                 listener.onFailure(t);
             }
         });

+ 5 - 5
src/main/java/org/elasticsearch/action/admin/indices/delete/TransportDeleteIndexAction.java

@@ -80,19 +80,19 @@ public class TransportDeleteIndexAction extends TransportMasterNodeOperationActi
 
     @Override
     protected ClusterBlockException checkBlock(DeleteIndexRequest request, ClusterState state) {
-        return state.blocks().indicesBlockedException(ClusterBlockLevel.METADATA, request.indices());
+        return state.blocks().indicesBlockedException(ClusterBlockLevel.METADATA, state.metaData().concreteIndices(request.indicesOptions(), request.indices()));
     }
 
     @Override
     protected void masterOperation(final DeleteIndexRequest request, final ClusterState state, final ActionListener<DeleteIndexResponse> listener) throws ElasticsearchException {
-        request.indices(state.metaData().concreteIndices(request.indicesOptions(), request.indices()));
-        if (request.indices().length == 0) {
+        String[] concreteIndices = state.metaData().concreteIndices(request.indicesOptions(), request.indices());
+        if (concreteIndices.length == 0) {
             listener.onResponse(new DeleteIndexResponse(true));
             return;
         }
         // TODO: this API should be improved, currently, if one delete index failed, we send a failure, we should send a response array that includes all the indices that were deleted
-        final CountDown count = new CountDown(request.indices().length);
-        for (final String index : request.indices()) {
+        final CountDown count = new CountDown(concreteIndices.length);
+        for (final String index : concreteIndices) {
             deleteIndexService.deleteIndex(new MetaDataDeleteIndexService.Request(index).timeout(request.timeout()).masterTimeout(request.masterNodeTimeout()), new MetaDataDeleteIndexService.Listener() {
 
                 private volatile Throwable lastFailure;

+ 4 - 8
src/main/java/org/elasticsearch/action/admin/indices/exists/indices/TransportIndicesExistsAction.java

@@ -21,6 +21,7 @@ package org.elasticsearch.action.admin.indices.exists.indices;
 
 import org.elasticsearch.ElasticsearchException;
 import org.elasticsearch.action.ActionListener;
+import org.elasticsearch.action.support.IndicesOptions;
 import org.elasticsearch.action.support.master.TransportMasterNodeReadOperationAction;
 import org.elasticsearch.cluster.ClusterService;
 import org.elasticsearch.cluster.ClusterState;
@@ -64,16 +65,11 @@ public class TransportIndicesExistsAction extends TransportMasterNodeReadOperati
         return new IndicesExistsResponse();
     }
 
-    @Override
-    protected void doExecute(IndicesExistsRequest request, ActionListener<IndicesExistsResponse> listener) {
-        // don't call this since it will throw IndexMissingException
-        //request.indices(clusterService.state().metaData().concreteIndices(request.indices()));
-        super.doExecute(request, listener);
-    }
-
     @Override
     protected ClusterBlockException checkBlock(IndicesExistsRequest request, ClusterState state) {
-        return state.blocks().indicesBlockedException(ClusterBlockLevel.METADATA, request.indices());
+        //make sure through indices options that the concrete indices call never throws IndexMissingException
+        IndicesOptions indicesOptions = IndicesOptions.fromOptions(true, true, request.indicesOptions().expandWildcardsOpen(), request.indicesOptions().expandWildcardsClosed());
+        return state.blocks().indicesBlockedException(ClusterBlockLevel.METADATA, clusterService.state().metaData().concreteIndices(indicesOptions, request.indices()));
     }
 
     @Override

+ 1 - 1
src/main/java/org/elasticsearch/action/admin/indices/exists/types/TransportTypesExistsAction.java

@@ -66,7 +66,7 @@ public class TransportTypesExistsAction extends TransportMasterNodeReadOperation
 
     @Override
     protected ClusterBlockException checkBlock(TypesExistsRequest request, ClusterState state) {
-        return state.blocks().indicesBlockedException(ClusterBlockLevel.METADATA, request.indices());
+        return state.blocks().indicesBlockedException(ClusterBlockLevel.METADATA, state.metaData().concreteIndices(request.indicesOptions(), request.indices()));
     }
 
     @Override

+ 7 - 7
src/main/java/org/elasticsearch/action/admin/indices/mapping/delete/TransportDeleteMappingAction.java

@@ -110,13 +110,13 @@ public class TransportDeleteMappingAction extends TransportMasterNodeOperationAc
 
     @Override
     protected ClusterBlockException checkBlock(DeleteMappingRequest request, ClusterState state) {
-        return state.blocks().indicesBlockedException(ClusterBlockLevel.METADATA, request.indices());
+        return state.blocks().indicesBlockedException(ClusterBlockLevel.METADATA, state.metaData().concreteIndices(request.indicesOptions(), request.indices()));
     }
 
     @Override
     protected void masterOperation(final DeleteMappingRequest request, final ClusterState state, final ActionListener<DeleteMappingResponse> listener) throws ElasticsearchException {
-        request.indices(state.metaData().concreteIndices(request.indicesOptions(), request.indices()));
-        flushAction.execute(Requests.flushRequest(request.indices()), new ActionListener<FlushResponse>() {
+        final String[] concreteIndices = state.metaData().concreteIndices(request.indicesOptions(), request.indices());
+        flushAction.execute(Requests.flushRequest(concreteIndices), new ActionListener<FlushResponse>() {
             @Override
             public void onResponse(FlushResponse flushResponse) {
                 if (logger.isTraceEnabled()) {
@@ -125,7 +125,7 @@ public class TransportDeleteMappingAction extends TransportMasterNodeOperationAc
   
                 // get all types that need to be deleted.
                 ImmutableOpenMap<String, ImmutableOpenMap<String, MappingMetaData>> result = clusterService.state().metaData().findMappings(
-                        request.indices(), request.types()
+                        concreteIndices, request.types()
                 );
                 // create OrFilter with type filters within to account for different types
                 BoolFilterBuilder filterBuilder = new BoolFilterBuilder();
@@ -142,7 +142,7 @@ public class TransportDeleteMappingAction extends TransportMasterNodeOperationAc
                 request.types(types.toArray(new String[types.size()]));
                 QuerySourceBuilder querySourceBuilder = new QuerySourceBuilder()
                         .setQuery(QueryBuilders.filteredQuery(QueryBuilders.matchAllQuery(), filterBuilder));
-                deleteByQueryAction.execute(Requests.deleteByQueryRequest(request.indices()).source(querySourceBuilder), new ActionListener<DeleteByQueryResponse>() {
+                deleteByQueryAction.execute(Requests.deleteByQueryRequest(concreteIndices).source(querySourceBuilder), new ActionListener<DeleteByQueryResponse>() {
                     @Override
                     public void onResponse(DeleteByQueryResponse deleteByQueryResponse) {
                         if (logger.isTraceEnabled()) {
@@ -155,7 +155,7 @@ public class TransportDeleteMappingAction extends TransportMasterNodeOperationAc
                                 }
                             }
                         }
-                        refreshAction.execute(Requests.refreshRequest(request.indices()), new ActionListener<RefreshResponse>() {
+                        refreshAction.execute(Requests.refreshRequest(concreteIndices), new ActionListener<RefreshResponse>() {
                             @Override
                             public void onResponse(RefreshResponse refreshResponse) {
                                 if (logger.isTraceEnabled()) {
@@ -174,7 +174,7 @@ public class TransportDeleteMappingAction extends TransportMasterNodeOperationAc
 
                             protected void removeMapping() {
                                 DeleteMappingClusterStateUpdateRequest clusterStateUpdateRequest = new DeleteMappingClusterStateUpdateRequest()
-                                        .indices(request.indices()).types(request.types())
+                                        .indices(concreteIndices).types(request.types())
                                         .ackTimeout(request.timeout())
                                         .masterNodeTimeout(request.masterNodeTimeout());
 

+ 1 - 1
src/main/java/org/elasticsearch/action/admin/indices/mapping/get/TransportGetFieldMappingsAction.java

@@ -60,7 +60,7 @@ public class TransportGetFieldMappingsAction extends TransportAction<GetFieldMap
         final AtomicInteger completionCounter = new AtomicInteger(concreteIndices.length);
         final AtomicReferenceArray<Object> indexResponses = new AtomicReferenceArray<>(concreteIndices.length);
 
-        if (concreteIndices == null || concreteIndices.length == 0) {
+        if (concreteIndices.length == 0) {
             listener.onResponse(new GetFieldMappingsResponse());
         } else {
             boolean probablySingleFieldRequest = concreteIndices.length == 1 && request.types().length == 1 && request.fields().length == 1;

+ 2 - 2
src/main/java/org/elasticsearch/action/admin/indices/mapping/get/TransportGetMappingsAction.java

@@ -56,10 +56,10 @@ public class TransportGetMappingsAction extends TransportClusterInfoAction<GetMa
     }
 
     @Override
-    protected void doMasterOperation(final GetMappingsRequest request, final ClusterState state, final ActionListener<GetMappingsResponse> listener) throws ElasticsearchException {
+    protected void doMasterOperation(final GetMappingsRequest request, String[] concreteIndices, final ClusterState state, final ActionListener<GetMappingsResponse> listener) throws ElasticsearchException {
         logger.trace("serving getMapping request based on version {}", state.version());
         ImmutableOpenMap<String, ImmutableOpenMap<String, MappingMetaData>> result = state.metaData().findMappings(
-                request.indices(), request.types()
+                concreteIndices, request.types()
         );
         listener.onResponse(new GetMappingsResponse(result));
     }

+ 4 - 9
src/main/java/org/elasticsearch/action/admin/indices/mapping/put/TransportPutMappingAction.java

@@ -68,22 +68,17 @@ public class TransportPutMappingAction extends TransportMasterNodeOperationActio
         return new PutMappingResponse();
     }
 
-    @Override
-    protected void doExecute(PutMappingRequest request, ActionListener<PutMappingResponse> listener) {
-        request.indices(clusterService.state().metaData().concreteIndices(request.indicesOptions(), request.indices()));
-        super.doExecute(request, listener);
-    }
-
     @Override
     protected ClusterBlockException checkBlock(PutMappingRequest request, ClusterState state) {
-        return state.blocks().indicesBlockedException(ClusterBlockLevel.METADATA, request.indices());
+        return state.blocks().indicesBlockedException(ClusterBlockLevel.METADATA, clusterService.state().metaData().concreteIndices(request.indicesOptions(), request.indices()));
     }
 
     @Override
     protected void masterOperation(final PutMappingRequest request, final ClusterState state, final ActionListener<PutMappingResponse> listener) throws ElasticsearchException {
+        final String[] concreteIndices = clusterService.state().metaData().concreteIndices(request.indicesOptions(), request.indices());
         PutMappingClusterStateUpdateRequest updateRequest = new PutMappingClusterStateUpdateRequest()
                 .ackTimeout(request.timeout()).masterNodeTimeout(request.masterNodeTimeout())
-                .indices(request.indices()).type(request.type())
+                .indices(concreteIndices).type(request.type())
                 .source(request.source()).ignoreConflicts(request.ignoreConflicts());
 
         metaDataMappingService.putMapping(updateRequest, new ActionListener<ClusterStateUpdateResponse>() {
@@ -95,7 +90,7 @@ public class TransportPutMappingAction extends TransportMasterNodeOperationActio
 
             @Override
             public void onFailure(Throwable t) {
-                logger.debug("failed to put mappings on indices [{}], type [{}]", t, request.indices(), request.type());
+                logger.debug("failed to put mappings on indices [{}], type [{}]", t, concreteIndices, request.type());
                 listener.onFailure(t);
             }
         });

+ 4 - 4
src/main/java/org/elasticsearch/action/admin/indices/open/TransportOpenIndexAction.java

@@ -80,15 +80,15 @@ public class TransportOpenIndexAction extends TransportMasterNodeOperationAction
 
     @Override
     protected ClusterBlockException checkBlock(OpenIndexRequest request, ClusterState state) {
-        return state.blocks().indicesBlockedException(ClusterBlockLevel.METADATA, request.indices());
+        return state.blocks().indicesBlockedException(ClusterBlockLevel.METADATA, state.metaData().concreteIndices(request.indicesOptions(), request.indices()));
     }
 
     @Override
     protected void masterOperation(final OpenIndexRequest request, final ClusterState state, final ActionListener<OpenIndexResponse> listener) throws ElasticsearchException {
-        request.indices(state.metaData().concreteIndices(request.indicesOptions(), request.indices()));
+        final String[] concreteIndices = state.metaData().concreteIndices(request.indicesOptions(), request.indices());
         OpenIndexClusterStateUpdateRequest updateRequest = new OpenIndexClusterStateUpdateRequest()
                 .ackTimeout(request.timeout()).masterNodeTimeout(request.masterNodeTimeout())
-                .indices(request.indices());
+                .indices(concreteIndices);
 
         indexStateService.openIndex(updateRequest, new ActionListener<ClusterStateUpdateResponse>() {
 
@@ -99,7 +99,7 @@ public class TransportOpenIndexAction extends TransportMasterNodeOperationAction
 
             @Override
             public void onFailure(Throwable t) {
-                logger.debug("failed to open indices [{}]", t, request.indices());
+                logger.debug("failed to open indices [{}]", t, concreteIndices);
                 listener.onFailure(t);
             }
         });

+ 2 - 2
src/main/java/org/elasticsearch/action/admin/indices/settings/get/TransportGetSettingsAction.java

@@ -73,9 +73,9 @@ public class TransportGetSettingsAction extends TransportMasterNodeReadOperation
 
     @Override
     protected void masterOperation(GetSettingsRequest request, ClusterState state, ActionListener<GetSettingsResponse> listener) throws ElasticsearchException {
-        request.indices(state.metaData().concreteIndices(request.indicesOptions(), request.indices()));
+        String[] concreteIndices = state.metaData().concreteIndices(request.indicesOptions(), request.indices());
         ImmutableOpenMap.Builder<String, Settings> indexToSettingsBuilder = ImmutableOpenMap.builder();
-        for (String concreteIndex : request.indices()) {
+        for (String concreteIndex : concreteIndices) {
             IndexMetaData indexMetaData = state.getMetaData().index(concreteIndex);
             if (indexMetaData == null) {
                 continue;

+ 3 - 8
src/main/java/org/elasticsearch/action/admin/indices/settings/put/TransportUpdateSettingsAction.java

@@ -66,16 +66,11 @@ public class TransportUpdateSettingsAction extends TransportMasterNodeOperationA
         return new UpdateSettingsResponse();
     }
 
-    @Override
-    protected void doExecute(UpdateSettingsRequest request, ActionListener<UpdateSettingsResponse> listener) {
-        request.indices(clusterService.state().metaData().concreteIndices(request.indicesOptions(), request.indices()));
-        super.doExecute(request, listener);
-    }
-
     @Override
     protected void masterOperation(final UpdateSettingsRequest request, final ClusterState state, final ActionListener<UpdateSettingsResponse> listener) throws ElasticsearchException {
+        final String[] concreteIndices = clusterService.state().metaData().concreteIndices(request.indicesOptions(), request.indices());
         UpdateSettingsClusterStateUpdateRequest clusterStateUpdateRequest = new UpdateSettingsClusterStateUpdateRequest()
-                .indices(request.indices())
+                .indices(concreteIndices)
                 .settings(request.settings())
                 .ackTimeout(request.timeout())
                 .masterNodeTimeout(request.masterNodeTimeout());
@@ -88,7 +83,7 @@ public class TransportUpdateSettingsAction extends TransportMasterNodeOperationA
 
             @Override
             public void onFailure(Throwable t) {
-                logger.debug("failed to update settings on indices [{}]", t, request.indices());
+                logger.debug("failed to update settings on indices [{}]", t, concreteIndices);
                 listener.onFailure(t);
             }
         });

+ 5 - 11
src/main/java/org/elasticsearch/action/admin/indices/warmer/delete/TransportDeleteWarmerAction.java

@@ -73,20 +73,14 @@ public class TransportDeleteWarmerAction extends TransportMasterNodeOperationAct
         return new DeleteWarmerResponse();
     }
 
-    @Override
-    protected void doExecute(DeleteWarmerRequest request, ActionListener<DeleteWarmerResponse> listener) {
-        // update to concrete indices
-        request.indices(clusterService.state().metaData().concreteIndices(request.indicesOptions(), request.indices()));
-        super.doExecute(request, listener);
-    }
-
     @Override
     protected ClusterBlockException checkBlock(DeleteWarmerRequest request, ClusterState state) {
-        return state.blocks().indicesBlockedException(ClusterBlockLevel.METADATA, request.indices());
+        return state.blocks().indicesBlockedException(ClusterBlockLevel.METADATA, clusterService.state().metaData().concreteIndices(request.indicesOptions(), request.indices()));
     }
 
     @Override
     protected void masterOperation(final DeleteWarmerRequest request, final ClusterState state, final ActionListener<DeleteWarmerResponse> listener) throws ElasticsearchException {
+        final String[] concreteIndices = clusterService.state().metaData().concreteIndices(request.indicesOptions(), request.indices());
         clusterService.submitStateUpdateTask("delete_warmer [" + Arrays.toString(request.names()) + "]", new AckedClusterStateUpdateTask<DeleteWarmerResponse>(request, listener) {
 
             @Override
@@ -96,7 +90,7 @@ public class TransportDeleteWarmerAction extends TransportMasterNodeOperationAct
 
             @Override
             public void onFailure(String source, Throwable t) {
-                logger.debug("failed to delete warmer [{}] on indices [{}]", t, Arrays.toString(request.names()), request.indices());
+                logger.debug("failed to delete warmer [{}] on indices [{}]", t, Arrays.toString(request.names()), concreteIndices);
                 super.onFailure(source, t);
             }
 
@@ -105,7 +99,7 @@ public class TransportDeleteWarmerAction extends TransportMasterNodeOperationAct
                 MetaData.Builder mdBuilder = MetaData.builder(currentState.metaData());
 
                 boolean globalFoundAtLeastOne = false;
-                for (String index : request.indices()) {
+                for (String index : concreteIndices) {
                     IndexMetaData indexMetaData = currentState.metaData().index(index);
                     if (indexMetaData == null) {
                         throw new IndexMissingException(new Index(index));
@@ -141,7 +135,7 @@ public class TransportDeleteWarmerAction extends TransportMasterNodeOperationAct
                 }
 
                 if (logger.isInfoEnabled()) {
-                    for (String index : request.indices()) {
+                    for (String index : concreteIndices) {
                         IndexMetaData indexMetaData = currentState.metaData().index(index);
                         if (indexMetaData == null) {
                             throw new IndexMissingException(new Index(index));

+ 2 - 2
src/main/java/org/elasticsearch/action/admin/indices/warmer/get/TransportGetWarmersAction.java

@@ -57,9 +57,9 @@ public class TransportGetWarmersAction extends TransportClusterInfoAction<GetWar
     }
 
     @Override
-    protected void doMasterOperation(final GetWarmersRequest request, final ClusterState state, final ActionListener<GetWarmersResponse> listener) throws ElasticsearchException {
+    protected void doMasterOperation(final GetWarmersRequest request, String[] concreteIndices, final ClusterState state, final ActionListener<GetWarmersResponse> listener) throws ElasticsearchException {
         ImmutableOpenMap<String, ImmutableList<IndexWarmersMetaData.Entry>> result = state.metaData().findWarmers(
-                request.indices(), request.types(), request.warmers()
+                concreteIndices, request.types(), request.warmers()
         );
         listener.onResponse(new GetWarmersResponse(result));
     }

+ 2 - 3
src/main/java/org/elasticsearch/action/support/master/info/TransportClusterInfoAction.java

@@ -45,9 +45,8 @@ public abstract class TransportClusterInfoAction<Request extends ClusterInfoRequ
     @Override
     protected final void masterOperation(final Request request, final ClusterState state, final ActionListener<Response> listener) throws ElasticsearchException {
         String[] concreteIndices = state.metaData().concreteIndices(request.indicesOptions(), request.indices());
-        request.indices(concreteIndices);
-        doMasterOperation(request, state, listener);
+        doMasterOperation(request, concreteIndices, state, listener);
     }
 
-    protected abstract void doMasterOperation(Request request, ClusterState state, final ActionListener<Response> listener) throws ElasticsearchException;
+    protected abstract void doMasterOperation(Request request, String[] concreteIndices, ClusterState state, final ActionListener<Response> listener) throws ElasticsearchException;
 }

+ 1 - 1
src/main/java/org/elasticsearch/action/support/replication/TransportIndicesReplicationOperationAction.java

@@ -86,7 +86,7 @@ public abstract class TransportIndicesReplicationOperationAction<Request extends
         final long startTimeInMillis = System.currentTimeMillis();
 
         Map<String, Set<String>> routingMap = resolveRouting(clusterState, request);
-        if (concreteIndices == null || concreteIndices.length == 0) {
+        if (concreteIndices.length == 0) {
             listener.onResponse(newResponseInstance(request, indexResponses));
         } else {
             for (final String index : concreteIndices) {

+ 62 - 57
src/test/java/org/elasticsearch/action/bulk/BulkProcessorTests.java

@@ -192,70 +192,75 @@ public class BulkProcessorTests extends ElasticsearchIntegrationTest {
     @Test
     public void testBulkProcessorConcurrentRequestsReadOnlyIndex() throws Exception {
         createIndex("test-ro");
-        assertAcked(client().admin().indices().prepareUpdateSettings("test-ro")
-                .setSettings(ImmutableSettings.builder().put("index.blocks.read_only", true)));
-        ensureGreen();
-
-        int bulkActions = randomIntBetween(10, 100);
-        int numDocs = randomIntBetween(bulkActions, bulkActions + 100);
-        int concurrentRequests = randomIntBetween(0, 10);
-
-        int expectedBulkActions = numDocs / bulkActions;
-
-        final CountDownLatch latch = new CountDownLatch(expectedBulkActions);
-        int totalExpectedBulkActions = numDocs % bulkActions == 0 ? expectedBulkActions : expectedBulkActions + 1;
-        final CountDownLatch closeLatch = new CountDownLatch(totalExpectedBulkActions);
-
-        int testDocs = 0;
-        int testReadOnlyDocs = 0;
-        MultiGetRequestBuilder multiGetRequestBuilder = client().prepareMultiGet();
-        BulkProcessorTestListener listener = new BulkProcessorTestListener(latch, closeLatch);
+        try {
+            assertAcked(client().admin().indices().prepareUpdateSettings("test-ro")
+                    .setSettings(ImmutableSettings.builder().put("index.blocks.read_only", true)));
+            ensureGreen();
+
+            int bulkActions = randomIntBetween(10, 100);
+            int numDocs = randomIntBetween(bulkActions, bulkActions + 100);
+            int concurrentRequests = randomIntBetween(0, 10);
+
+            int expectedBulkActions = numDocs / bulkActions;
+
+            final CountDownLatch latch = new CountDownLatch(expectedBulkActions);
+            int totalExpectedBulkActions = numDocs % bulkActions == 0 ? expectedBulkActions : expectedBulkActions + 1;
+            final CountDownLatch closeLatch = new CountDownLatch(totalExpectedBulkActions);
+
+            int testDocs = 0;
+            int testReadOnlyDocs = 0;
+            MultiGetRequestBuilder multiGetRequestBuilder = client().prepareMultiGet();
+            BulkProcessorTestListener listener = new BulkProcessorTestListener(latch, closeLatch);
+
+            try (BulkProcessor processor = BulkProcessor.builder(client(), listener)
+                    .setConcurrentRequests(concurrentRequests).setBulkActions(bulkActions)
+                            //set interval and size to high values
+                    .setFlushInterval(TimeValue.timeValueHours(24)).setBulkSize(new ByteSizeValue(1, ByteSizeUnit.GB)).build()) {
+
+                for (int i = 1; i <= numDocs; i++) {
+                    if (randomBoolean()) {
+                        testDocs++;
+                        processor.add(new IndexRequest("test", "test", Integer.toString(testDocs)).source("field", "value"));
+                        multiGetRequestBuilder.add("test", "test", Integer.toString(testDocs));
+                    } else {
+                        testReadOnlyDocs++;
+                        processor.add(new IndexRequest("test-ro", "test", Integer.toString(testReadOnlyDocs)).source("field", "value"));
+                    }
+                }
+            }
 
-        try (BulkProcessor processor = BulkProcessor.builder(client(), listener)
-                .setConcurrentRequests(concurrentRequests).setBulkActions(bulkActions)
-                 //set interval and size to high values
-                .setFlushInterval(TimeValue.timeValueHours(24)).setBulkSize(new ByteSizeValue(1, ByteSizeUnit.GB)).build()) {
+            closeLatch.await();
 
-            for (int i = 1; i <= numDocs; i++) {
-                if (randomBoolean()) {
-                    testDocs++;
-                    processor.add(new IndexRequest("test", "test", Integer.toString(testDocs)).source("field", "value"));
-                    multiGetRequestBuilder.add("test", "test", Integer.toString(testDocs));
+            assertThat(listener.beforeCounts.get(), equalTo(totalExpectedBulkActions));
+            assertThat(listener.afterCounts.get(), equalTo(totalExpectedBulkActions));
+            assertThat(listener.bulkFailures.size(), equalTo(0));
+            assertThat(listener.bulkItems.size(), equalTo(testDocs + testReadOnlyDocs));
+
+            Set<String> ids = new HashSet<>();
+            Set<String> readOnlyIds = new HashSet<>();
+            for (BulkItemResponse bulkItemResponse : listener.bulkItems) {
+                assertThat(bulkItemResponse.getIndex(), either(equalTo("test")).or(equalTo("test-ro")));
+                assertThat(bulkItemResponse.getType(), equalTo("test"));
+                if (bulkItemResponse.getIndex().equals("test")) {
+                    assertThat(bulkItemResponse.isFailed(), equalTo(false));
+                    //with concurrent requests > 1 we can't rely on the order of the bulk requests
+                    assertThat(Integer.valueOf(bulkItemResponse.getId()), both(greaterThan(0)).and(lessThanOrEqualTo(testDocs)));
+                    //we do want to check that we don't get duplicate ids back
+                    assertThat(ids.add(bulkItemResponse.getId()), equalTo(true));
                 } else {
-                    testReadOnlyDocs++;
-                    processor.add(new IndexRequest("test-ro", "test", Integer.toString(testReadOnlyDocs)).source("field", "value"));
+                    assertThat(bulkItemResponse.isFailed(), equalTo(true));
+                    //with concurrent requests > 1 we can't rely on the order of the bulk requests
+                    assertThat(Integer.valueOf(bulkItemResponse.getId()), both(greaterThan(0)).and(lessThanOrEqualTo(testReadOnlyDocs)));
+                    //we do want to check that we don't get duplicate ids back
+                    assertThat(readOnlyIds.add(bulkItemResponse.getId()), equalTo(true));
                 }
             }
-        }
 
-        closeLatch.await();
-
-        assertThat(listener.beforeCounts.get(), equalTo(totalExpectedBulkActions));
-        assertThat(listener.afterCounts.get(), equalTo(totalExpectedBulkActions));
-        assertThat(listener.bulkFailures.size(), equalTo(0));
-        assertThat(listener.bulkItems.size(), equalTo(testDocs + testReadOnlyDocs));
-
-        Set<String> ids = new HashSet<>();
-        Set<String> readOnlyIds = new HashSet<>();
-        for (BulkItemResponse bulkItemResponse : listener.bulkItems) {
-            assertThat(bulkItemResponse.getIndex(), either(equalTo("test")).or(equalTo("test-ro")));
-            assertThat(bulkItemResponse.getType(), equalTo("test"));
-            if (bulkItemResponse.getIndex().equals("test")) {
-                assertThat(bulkItemResponse.isFailed(), equalTo(false));
-                //with concurrent requests > 1 we can't rely on the order of the bulk requests
-                assertThat(Integer.valueOf(bulkItemResponse.getId()), both(greaterThan(0)).and(lessThanOrEqualTo(testDocs)));
-                //we do want to check that we don't get duplicate ids back
-                assertThat(ids.add(bulkItemResponse.getId()), equalTo(true));
-            } else {
-                assertThat(bulkItemResponse.isFailed(), equalTo(true));
-                //with concurrent requests > 1 we can't rely on the order of the bulk requests
-                assertThat(Integer.valueOf(bulkItemResponse.getId()), both(greaterThan(0)).and(lessThanOrEqualTo(testReadOnlyDocs)));
-                //we do want to check that we don't get duplicate ids back
-                assertThat(readOnlyIds.add(bulkItemResponse.getId()), equalTo(true));
-            }
+            assertMultiGetResponse(multiGetRequestBuilder.get(), testDocs);
+        } finally {
+            assertAcked(client().admin().indices().prepareUpdateSettings("test-ro")
+                    .setSettings(ImmutableSettings.builder().put("index.blocks.read_only", false)));
         }
-
-        assertMultiGetResponse(multiGetRequestBuilder.get(), testDocs);
     }
 
     private static MultiGetRequestBuilder indexDocs(Client client, BulkProcessor processor, int numDocs) {

+ 87 - 22
src/test/java/org/elasticsearch/cluster/BlockClusterStatsTests.java

@@ -20,40 +20,105 @@ package org.elasticsearch.cluster;
 
 import org.elasticsearch.action.admin.cluster.settings.ClusterUpdateSettingsResponse;
 import org.elasticsearch.action.admin.cluster.state.ClusterStateResponse;
-import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsResponse;
+import org.elasticsearch.action.admin.indices.alias.Alias;
+import org.elasticsearch.client.Requests;
+import org.elasticsearch.cluster.block.ClusterBlock;
+import org.elasticsearch.cluster.block.ClusterBlockException;
 import org.elasticsearch.common.settings.ImmutableSettings;
+import org.elasticsearch.rest.RestStatus;
 import org.elasticsearch.test.ElasticsearchIntegrationTest;
-import org.elasticsearch.test.ElasticsearchIntegrationTest.ClusterScope;
 import org.junit.Test;
 
+import static org.elasticsearch.test.ElasticsearchIntegrationTest.*;
 import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
-import static org.hamcrest.Matchers.hasSize;
-import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.*;
 
 /**
  * Scoped as test, because the if the test with cluster read only block fails, all other tests fail as well, as this is not cleaned up properly
  */
-@ClusterScope(scope= ElasticsearchIntegrationTest.Scope.TEST)
+@ClusterScope(scope= Scope.TEST)
 public class BlockClusterStatsTests extends ElasticsearchIntegrationTest {
 
     @Test
     public void testBlocks() throws Exception {
-        createIndex("foo");
-        ClusterUpdateSettingsResponse updateSettingsResponse = client().admin().cluster().prepareUpdateSettings().setTransientSettings(
-                ImmutableSettings.settingsBuilder().put("cluster.blocks.read_only", true).build()).get();
-        assertThat(updateSettingsResponse.isAcknowledged(), is(true));
-        UpdateSettingsResponse indexSettingsResponse = client().admin().indices().prepareUpdateSettings("foo").setSettings(
-                ImmutableSettings.settingsBuilder().put("index.blocks.read_only", true)).get();
-        assertThat(indexSettingsResponse.isAcknowledged(), is(true));
-
-        ClusterStateResponse clusterStateResponseUnfiltered = client().admin().cluster().prepareState().clear().setBlocks(true).get();
-        assertThat(clusterStateResponseUnfiltered.getState().blocks().global(), hasSize(1));
-        assertThat(clusterStateResponseUnfiltered.getState().blocks().indices().size(), is(1));
-
-        ClusterStateResponse clusterStateResponse = client().admin().cluster().prepareState().clear().get();
-        assertThat(clusterStateResponse.getState().blocks().global(), hasSize(0));
-        assertThat(clusterStateResponse.getState().blocks().indices().size(), is(0));
-        assertAcked(client().admin().cluster().prepareUpdateSettings().setTransientSettings(
-                ImmutableSettings.settingsBuilder().put("cluster.blocks.read_only", false).build()).get());
+        assertAcked(prepareCreate("foo").addAlias(new Alias("foo-alias")));
+        try {
+            ClusterUpdateSettingsResponse updateSettingsResponse = client().admin().cluster().prepareUpdateSettings().setTransientSettings(
+                    ImmutableSettings.settingsBuilder().put("cluster.blocks.read_only", true).build()).get();
+            assertThat(updateSettingsResponse.isAcknowledged(), is(true));
+            assertAcked(client().admin().indices().prepareUpdateSettings("foo").setSettings(
+                    ImmutableSettings.settingsBuilder().put("index.blocks.read_only", true)));
+
+            ClusterStateResponse clusterStateResponseUnfiltered = client().admin().cluster().prepareState().clear().setBlocks(true).get();
+            assertThat(clusterStateResponseUnfiltered.getState().blocks().global(), hasSize(1));
+            assertThat(clusterStateResponseUnfiltered.getState().blocks().indices().size(), is(1));
+            ClusterStateResponse clusterStateResponse = client().admin().cluster().prepareState().clear().get();
+            assertThat(clusterStateResponse.getState().blocks().global(), hasSize(0));
+            assertThat(clusterStateResponse.getState().blocks().indices().size(), is(0));
+
+            try {
+                client().admin().indices().prepareClose("foo-alias").get();
+                fail("close index should have failed");
+            } catch(ClusterBlockException e) {
+                assertClusterAndIndexBlocks(e);
+            }
+
+            try {
+                client().admin().indices().prepareDeleteMapping("foo-alias").setType("test").get();
+                fail("delete mapping should have failed");
+            } catch(ClusterBlockException e) {
+                assertClusterAndIndexBlocks(e);
+            }
+
+            try {
+                client().admin().indices().preparePutMapping("foo-alias").setType("type1").setSource("field1", "type=string").get();
+                fail("put mapping should have failed");
+            } catch(ClusterBlockException e) {
+                assertClusterAndIndexBlocks(e);
+            }
+
+            try {
+                client().admin().indices().preparePutWarmer("foo-alias").setSearchRequest(Requests.searchRequest("foo-alias")).get();
+                fail("put warmer should have failed");
+            } catch(ClusterBlockException e) {
+                assertClusterAndIndexBlocks(e);
+            }
+
+            try {
+                client().admin().indices().prepareDeleteWarmer().setIndices("foo-alias").setNames("warmer1").get();
+                fail("delete warmer should have failed");
+            } catch(ClusterBlockException e) {
+                assertClusterAndIndexBlocks(e);
+            }
+
+            try {
+                client().admin().indices().prepareTypesExists("foo-alias").setTypes("test").get();
+                fail("types exists should have failed");
+            } catch(ClusterBlockException e) {
+                assertClusterAndIndexBlocks(e);
+            }
+
+            try {
+                client().admin().indices().prepareExists("foo-alias").get();
+                fail("indices exists should have failed");
+            } catch(ClusterBlockException e) {
+                assertClusterAndIndexBlocks(e);
+            }
+
+        } finally {
+            assertAcked(client().admin().cluster().prepareUpdateSettings().setTransientSettings(
+                    ImmutableSettings.settingsBuilder().put("cluster.blocks.read_only", false).build()).get());
+            assertAcked(client().admin().indices().prepareUpdateSettings("foo").setSettings(
+                    ImmutableSettings.settingsBuilder().put("index.blocks.read_only", false)));
+        }
+    }
+
+    private void assertClusterAndIndexBlocks(ClusterBlockException e) {
+        assertThat(e.blocks().size(), equalTo(2));
+        for (ClusterBlock clusterBlock : e.blocks()) {
+            assertThat(clusterBlock.status(), equalTo(RestStatus.FORBIDDEN));
+            assertThat(clusterBlock.id(), either(equalTo(5)).or(equalTo(6)));
+            assertThat(clusterBlock.description(), either(containsString("cluster read-only (api)")).or(containsString("index read-only (api)")));
+        }
     }
 }