3636import org .elasticsearch .common .settings .IndexScopedSettings ;
3737import org .elasticsearch .common .settings .Setting ;
3838import org .elasticsearch .common .settings .Settings ;
39+ import org .elasticsearch .core .Nullable ;
3940import org .elasticsearch .core .TimeValue ;
4041import org .elasticsearch .index .Index ;
4142import org .elasticsearch .index .IndexSettings ;
5152import java .util .Objects ;
5253import java .util .Set ;
5354import java .util .function .BiFunction ;
55+ import java .util .function .Function ;
5456
57+ import static org .elasticsearch .cluster .metadata .MetadataIndexStateService .VERIFIED_READ_ONLY_SETTING ;
5558import static org .elasticsearch .index .IndexSettings .same ;
5659
5760/**
@@ -181,11 +184,14 @@ ClusterState execute(ClusterState currentState) {
181184
182185 RoutingTable .Builder routingTableBuilder = null ;
183186 Metadata .Builder metadataBuilder = Metadata .builder (currentState .metadata ());
187+ final var minSupportedIndexVersion = currentState .nodes ().getMinSupportedIndexVersion ();
184188
185189 // allow to change any settings to a closed index, and only allow dynamic settings to be changed
186190 // on an open index
187191 Set <Index > openIndices = new HashSet <>();
188192 Set <Index > closedIndices = new HashSet <>();
193+ Set <Index > readOnlyIndices = null ;
194+
189195 final String [] actualIndices = new String [request .indices ().length ];
190196 for (int i = 0 ; i < request .indices ().length ; i ++) {
191197 Index index = request .indices ()[i ];
@@ -197,6 +203,12 @@ ClusterState execute(ClusterState currentState) {
197203 } else {
198204 closedIndices .add (index );
199205 }
206+ if (metadata .getCompatibilityVersion ().before (minSupportedIndexVersion )) {
207+ if (readOnlyIndices == null ) {
208+ readOnlyIndices = new HashSet <>();
209+ }
210+ readOnlyIndices .add (index );
211+ }
200212 }
201213
202214 if (skippedSettings .isEmpty () == false && openIndices .isEmpty () == false ) {
@@ -327,10 +339,23 @@ ClusterState execute(ClusterState currentState) {
327339 }
328340 }
329341
342+ // provides the value of VERIFIED_READ_ONLY_SETTING before block changes
343+ final Function <String , Boolean > verifiedReadOnly = indexName -> VERIFIED_READ_ONLY_SETTING .get (
344+ currentState .metadata ().index (indexName ).getSettings ()
345+ );
346+
330347 final ClusterBlocks .Builder blocks = ClusterBlocks .builder ().blocks (currentState .blocks ());
331348 boolean changedBlocks = false ;
332349 for (IndexMetadata .APIBlock block : IndexMetadata .APIBlock .values ()) {
333- changedBlocks |= maybeUpdateClusterBlock (actualIndices , blocks , block .block , block .setting , openSettings , metadataBuilder );
350+ changedBlocks |= maybeUpdateClusterBlock (
351+ actualIndices ,
352+ blocks ,
353+ block .block ,
354+ block .setting ,
355+ openSettings ,
356+ metadataBuilder ,
357+ verifiedReadOnly
358+ );
334359 }
335360 changed |= changedBlocks ;
336361
@@ -359,6 +384,7 @@ ClusterState execute(ClusterState currentState) {
359384 // This step is mandatory since we allow to update non-dynamic settings on closed indices.
360385 indicesService .verifyIndexMetadata (updatedMetadata , updatedMetadata );
361386 }
387+ verifyReadOnlyIndices (readOnlyIndices , updatedState .blocks ());
362388 } catch (IOException ex ) {
363389 throw ExceptionsHelper .convertToElastic (ex );
364390 }
@@ -417,6 +443,18 @@ public static void updateIndexSettings(
417443 }
418444 }
419445
446+ private static void verifyReadOnlyIndices (@ Nullable Set <Index > readOnlyIndices , ClusterBlocks blocks ) {
447+ if (readOnlyIndices != null ) {
448+ for (Index readOnlyIndex : readOnlyIndices ) {
449+ if (blocks .hasIndexBlockLevel (readOnlyIndex .getName (), ClusterBlockLevel .WRITE ) == false ) {
450+ throw new IllegalArgumentException (
451+ String .format (Locale .ROOT , "Can't remove the write block on read-only compatible index %s" , readOnlyIndex )
452+ );
453+ }
454+ }
455+ }
456+ }
457+
420458 /**
421459 * Updates the cluster block only iff the setting exists in the given settings
422460 */
@@ -426,7 +464,8 @@ private static boolean maybeUpdateClusterBlock(
426464 ClusterBlock block ,
427465 Setting <Boolean > setting ,
428466 Settings openSettings ,
429- Metadata .Builder metadataBuilder
467+ Metadata .Builder metadataBuilder ,
468+ Function <String , Boolean > verifiedReadOnlyBeforeBlockChanges
430469 ) {
431470 boolean changed = false ;
432471 if (setting .exists (openSettings )) {
@@ -436,16 +475,32 @@ private static boolean maybeUpdateClusterBlock(
436475 if (blocks .hasIndexBlock (index , block ) == false ) {
437476 blocks .addIndexBlock (index , block );
438477 changed = true ;
478+ if (block .contains (ClusterBlockLevel .WRITE )) {
479+ var isVerifiedReadOnly = verifiedReadOnlyBeforeBlockChanges .apply (index );
480+ if (isVerifiedReadOnly ) {
481+ var indexMetadata = metadataBuilder .get (index );
482+ metadataBuilder .put (
483+ IndexMetadata .builder (indexMetadata )
484+ .settings (
485+ Settings .builder ()
486+ .put (indexMetadata .getSettings ())
487+ .put (VERIFIED_READ_ONLY_SETTING .getKey (), true )
488+ )
489+ );
490+ }
491+ }
439492 }
440493 } else {
441494 if (blocks .hasIndexBlock (index , block )) {
442495 blocks .removeIndexBlock (index , block );
443496 changed = true ;
444497 if (block .contains (ClusterBlockLevel .WRITE )) {
445- IndexMetadata indexMetadata = metadataBuilder .get (index );
446- Settings .Builder indexSettings = Settings .builder ().put (indexMetadata .getSettings ());
447- indexSettings .remove (MetadataIndexStateService .VERIFIED_READ_ONLY_SETTING .getKey ());
448- metadataBuilder .put (IndexMetadata .builder (indexMetadata ).settings (indexSettings ));
498+ if (blocks .hasIndexBlockLevel (index , ClusterBlockLevel .WRITE ) == false ) {
499+ var indexMetadata = metadataBuilder .get (index );
500+ var indexSettings = Settings .builder ().put (indexMetadata .getSettings ());
501+ indexSettings .remove (VERIFIED_READ_ONLY_SETTING .getKey ());
502+ metadataBuilder .put (IndexMetadata .builder (indexMetadata ).settings (indexSettings ));
503+ }
449504 }
450505 }
451506 }
0 commit comments