From 96893cd7bc8db312b249f4e5cddae21accbb32f4 Mon Sep 17 00:00:00 2001 From: Jason Tedor Date: Sat, 20 Apr 2019 12:58:50 -0400 Subject: [PATCH 1/3] Introduce aliases version This commit introduces aliases versions to index metadata. This will be useful in CCR when we replicate aliases. --- .../elasticsearch/cluster/ClusterState.java | 1 + .../cluster/metadata/IndexMetaData.java | 121 +++++- .../metadata/MetaDataIndexAliasesService.java | 16 +- .../snapshots/RestoreService.java | 17 +- .../elasticsearch/aliases/IndexAliasesIT.java | 349 +++++++++++++----- .../MetaDataIndexAliasesServiceTests.java | 132 ++++++- 6 files changed, 506 insertions(+), 130 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/cluster/ClusterState.java b/server/src/main/java/org/elasticsearch/cluster/ClusterState.java index 93ee8af779472..a5996cc5da9c6 100644 --- a/server/src/main/java/org/elasticsearch/cluster/ClusterState.java +++ b/server/src/main/java/org/elasticsearch/cluster/ClusterState.java @@ -313,6 +313,7 @@ public String toString() { sb.append(": v[").append(indexMetaData.getVersion()) .append("], mv[").append(indexMetaData.getMappingVersion()) .append("], sv[").append(indexMetaData.getSettingsVersion()) + .append("], av[").append(indexMetaData.getAliasesVersion()) .append("]\n"); for (int shard = 0; shard < indexMetaData.getNumberOfShards(); shard++) { sb.append(TAB).append(TAB).append(shard).append(": "); diff --git a/server/src/main/java/org/elasticsearch/cluster/metadata/IndexMetaData.java b/server/src/main/java/org/elasticsearch/cluster/metadata/IndexMetaData.java index 6fc73ef5f7fa8..6b465648d972a 100644 --- a/server/src/main/java/org/elasticsearch/cluster/metadata/IndexMetaData.java +++ b/server/src/main/java/org/elasticsearch/cluster/metadata/IndexMetaData.java @@ -260,6 +260,7 @@ public Iterator> settings() { static final String KEY_VERSION = "version"; static final String KEY_MAPPING_VERSION = "mapping_version"; static final String KEY_SETTINGS_VERSION = "settings_version"; + static final String KEY_ALIASES_VERSION = "aliases_version"; static final String KEY_ROUTING_NUM_SHARDS = "routing_num_shards"; static final String KEY_SETTINGS = "settings"; static final String KEY_STATE = "state"; @@ -282,6 +283,8 @@ public Iterator> settings() { private final long mappingVersion; private final long settingsVersion; + + private final long aliasesVersion; private final long[] primaryTerms; @@ -310,15 +313,31 @@ public Iterator> settings() { private final ActiveShardCount waitForActiveShards; private final ImmutableOpenMap rolloverInfos; - private IndexMetaData(Index index, long version, long mappingVersion, long settingsVersion, long[] primaryTerms, State state, - int numberOfShards, int numberOfReplicas, Settings settings, - ImmutableOpenMap mappings, ImmutableOpenMap aliases, - ImmutableOpenMap customData, ImmutableOpenIntMap> inSyncAllocationIds, - DiscoveryNodeFilters requireFilters, DiscoveryNodeFilters initialRecoveryFilters, - DiscoveryNodeFilters includeFilters, DiscoveryNodeFilters excludeFilters, - Version indexCreatedVersion, Version indexUpgradedVersion, - int routingNumShards, int routingPartitionSize, ActiveShardCount waitForActiveShards, - ImmutableOpenMap rolloverInfos) { + private IndexMetaData( + final Index index, + final long version, + final long mappingVersion, + final long settingsVersion, + final long aliasesVersion, + final long[] primaryTerms, + final State state, + final int numberOfShards, + final int numberOfReplicas, + final Settings settings, + final ImmutableOpenMap mappings, + final ImmutableOpenMap aliases, + final ImmutableOpenMap customData, + final ImmutableOpenIntMap> inSyncAllocationIds, + final DiscoveryNodeFilters requireFilters, + final DiscoveryNodeFilters initialRecoveryFilters, + final DiscoveryNodeFilters includeFilters, + final DiscoveryNodeFilters excludeFilters, + final Version indexCreatedVersion, + final Version indexUpgradedVersion, + final int routingNumShards, + final int routingPartitionSize, + final ActiveShardCount waitForActiveShards, + final ImmutableOpenMap rolloverInfos) { this.index = index; this.version = version; @@ -326,6 +345,8 @@ private IndexMetaData(Index index, long version, long mappingVersion, long setti this.mappingVersion = mappingVersion; assert settingsVersion >= 0 : settingsVersion; this.settingsVersion = settingsVersion; + assert aliasesVersion >= 0 : aliasesVersion; + this.aliasesVersion = aliasesVersion; this.primaryTerms = primaryTerms; assert primaryTerms.length == numberOfShards; this.state = state; @@ -383,6 +404,10 @@ public long getSettingsVersion() { return settingsVersion; } + public long getAliasesVersion() { + return aliasesVersion; + } + /** * The term of the current selected primary. This is a non-negative number incremented when * a primary shard is assigned after a full cluster restart or a replica shard is promoted to a primary. @@ -652,6 +677,7 @@ private static class IndexMetaDataDiff implements Diff { private final long version; private final long mappingVersion; private final long settingsVersion; + private final long aliasesVersion; private final long[] primaryTerms; private final State state; private final Settings settings; @@ -666,6 +692,7 @@ private static class IndexMetaDataDiff implements Diff { version = after.version; mappingVersion = after.mappingVersion; settingsVersion = after.settingsVersion; + aliasesVersion = after.aliasesVersion; routingNumShards = after.routingNumShards; state = after.state; settings = after.settings; @@ -684,6 +711,11 @@ private static class IndexMetaDataDiff implements Diff { version = in.readLong(); mappingVersion = in.readVLong(); settingsVersion = in.readVLong(); + if (in.getVersion().onOrAfter(Version.V_8_0_0)) { + aliasesVersion = in.readVLong(); + } else { + aliasesVersion = 1; + } state = State.fromId(in.readByte()); settings = Settings.readSettingsFromStream(in); primaryTerms = in.readVLongArray(); @@ -706,6 +738,9 @@ public void writeTo(StreamOutput out) throws IOException { out.writeLong(version); out.writeVLong(mappingVersion); out.writeVLong(settingsVersion); + if (out.getVersion().onOrAfter(Version.V_8_0_0)) { + out.writeVLong(aliasesVersion); + } out.writeByte(state.id); Settings.writeSettingsToStream(settings, out); out.writeVLongArray(primaryTerms); @@ -722,6 +757,7 @@ public IndexMetaData apply(IndexMetaData part) { builder.version(version); builder.mappingVersion(mappingVersion); builder.settingsVersion(settingsVersion); + builder.aliasesVersion(aliasesVersion); builder.setRoutingNumShards(routingNumShards); builder.state(state); builder.settings(settings); @@ -740,6 +776,9 @@ public static IndexMetaData readFrom(StreamInput in) throws IOException { builder.version(in.readLong()); builder.mappingVersion(in.readVLong()); builder.settingsVersion(in.readVLong()); + if (in.getVersion().onOrAfter(Version.V_8_0_0)) { + builder.aliasesVersion(in.readVLong()); + } builder.setRoutingNumShards(in.readInt()); builder.state(State.fromId(in.readByte())); builder.settings(readSettingsFromStream(in)); @@ -779,6 +818,9 @@ public void writeTo(StreamOutput out) throws IOException { out.writeLong(version); out.writeVLong(mappingVersion); out.writeVLong(settingsVersion); + if (out.getVersion().onOrAfter(Version.V_8_0_0)) { + out.writeVLong(aliasesVersion); + } out.writeInt(routingNumShards); out.writeByte(state.id()); writeSettingsToStream(settings, out); @@ -822,6 +864,7 @@ public static class Builder { private long version = 1; private long mappingVersion = 1; private long settingsVersion = 1; + private long aliasesVersion = 1; private long[] primaryTerms = null; private Settings settings = Settings.Builder.EMPTY_SETTINGS; private final ImmutableOpenMap.Builder mappings; @@ -846,6 +889,7 @@ public Builder(IndexMetaData indexMetaData) { this.version = indexMetaData.version; this.mappingVersion = indexMetaData.mappingVersion; this.settingsVersion = indexMetaData.settingsVersion; + this.aliasesVersion = indexMetaData.aliasesVersion; this.settings = indexMetaData.getSettings(); this.primaryTerms = indexMetaData.primaryTerms.clone(); this.mappings = ImmutableOpenMap.builder(indexMetaData.mappings); @@ -994,20 +1038,29 @@ public long mappingVersion() { return mappingVersion; } - public long settingsVersion() { - return settingsVersion; - } - public Builder mappingVersion(final long mappingVersion) { this.mappingVersion = mappingVersion; return this; } - + + public long settingsVersion() { + return settingsVersion; + } + public Builder settingsVersion(final long settingsVersion) { this.settingsVersion = settingsVersion; return this; } - + + public long aliasesVersion() { + return aliasesVersion; + } + + public Builder aliasesVersion(final long aliasesVersion) { + this.aliasesVersion = aliasesVersion; + return this; + } + /** * returns the primary term for the given shard. * See {@link IndexMetaData#primaryTerm(int)} for more information. @@ -1136,11 +1189,31 @@ public IndexMetaData build() { final String uuid = settings.get(SETTING_INDEX_UUID, INDEX_UUID_NA_VALUE); - return new IndexMetaData(new Index(index, uuid), version, mappingVersion, settingsVersion, primaryTerms, state, - numberOfShards, numberOfReplicas, tmpSettings, mappings.build(), tmpAliases.build(), customMetaData.build(), - filledInSyncAllocationIds.build(), requireFilters, initialRecoveryFilters, includeFilters, excludeFilters, - indexCreatedVersion, indexUpgradedVersion, getRoutingNumShards(), routingPartitionSize, waitForActiveShards, - rolloverInfos.build()); + return new IndexMetaData( + new Index(index, uuid), + version, + mappingVersion, + settingsVersion, + aliasesVersion, + primaryTerms, + state, + numberOfShards, + numberOfReplicas, + tmpSettings, + mappings.build(), + tmpAliases.build(), + customMetaData.build(), + filledInSyncAllocationIds.build(), + requireFilters, + initialRecoveryFilters, + includeFilters, + excludeFilters, + indexCreatedVersion, + indexUpgradedVersion, + getRoutingNumShards(), + routingPartitionSize, + waitForActiveShards, + rolloverInfos.build()); } public static void toXContent(IndexMetaData indexMetaData, XContentBuilder builder, ToXContent.Params params) throws IOException { @@ -1149,6 +1222,7 @@ public static void toXContent(IndexMetaData indexMetaData, XContentBuilder build builder.field(KEY_VERSION, indexMetaData.getVersion()); builder.field(KEY_MAPPING_VERSION, indexMetaData.getMappingVersion()); builder.field(KEY_SETTINGS_VERSION, indexMetaData.getSettingsVersion()); + builder.field(KEY_ALIASES_VERSION, indexMetaData.getAliasesVersion()); builder.field(KEY_ROUTING_NUM_SHARDS, indexMetaData.getRoutingNumShards()); builder.field(KEY_STATE, indexMetaData.getState().toString().toLowerCase(Locale.ENGLISH)); @@ -1223,6 +1297,7 @@ public static IndexMetaData fromXContent(XContentParser parser) throws IOExcepti } boolean mappingVersion = false; boolean settingsVersion = false; + boolean aliasesVersion = false; while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { if (token == XContentParser.Token.FIELD_NAME) { currentFieldName = parser.currentName(); @@ -1321,6 +1396,9 @@ public static IndexMetaData fromXContent(XContentParser parser) throws IOExcepti } else if (KEY_SETTINGS_VERSION.equals(currentFieldName)) { settingsVersion = true; builder.settingsVersion(parser.longValue()); + } else if (KEY_ALIASES_VERSION.equals(currentFieldName)) { + aliasesVersion = true; + builder.aliasesVersion(parser.longValue()); } else if (KEY_ROUTING_NUM_SHARDS.equals(currentFieldName)) { builder.setRoutingNumShards(parser.intValue()); } else { @@ -1336,6 +1414,9 @@ public static IndexMetaData fromXContent(XContentParser parser) throws IOExcepti if (Assertions.ENABLED && Version.indexCreated(builder.settings).onOrAfter(Version.V_6_5_0)) { assert settingsVersion : "settings version should be present for indices created on or after 6.5.0"; } + if (Assertions.ENABLED && Version.indexCreated(builder.settings).onOrAfter(Version.V_8_0_0)) { + assert aliasesVersion : "aliases version should be present for indices created on or after 8.0.0"; + } return builder.build(); } } diff --git a/server/src/main/java/org/elasticsearch/cluster/metadata/MetaDataIndexAliasesService.java b/server/src/main/java/org/elasticsearch/cluster/metadata/MetaDataIndexAliasesService.java index e6d0fc0832445..84e2f512e569f 100644 --- a/server/src/main/java/org/elasticsearch/cluster/metadata/MetaDataIndexAliasesService.java +++ b/server/src/main/java/org/elasticsearch/cluster/metadata/MetaDataIndexAliasesService.java @@ -115,6 +115,7 @@ ClusterState innerExecute(ClusterState currentState, Iterable actio } MetaData.Builder metadata = MetaData.builder(currentState.metaData()); // Run the remaining alias actions + final Set maybeModifiedIndices = new HashSet<>(); for (AliasAction action : actions) { if (action.removeIndex()) { // Handled above @@ -151,7 +152,20 @@ ClusterState innerExecute(ClusterState currentState, Iterable actio xContentRegistry); } }; - changed |= action.apply(newAliasValidator, metadata, index); + if (action.apply(newAliasValidator, metadata, index)) { + changed = true; + maybeModifiedIndices.add(index.getIndex().getName()); + } + } + + for (final String maybeModifiedIndex : maybeModifiedIndices) { + final IndexMetaData currentIndexMetaData = currentState.metaData().index(maybeModifiedIndex); + final IndexMetaData newIndexMetaData = metadata.get(maybeModifiedIndex); + // only increment the aliases version if the aliases actually changed for this index + if (currentIndexMetaData.getAliases().equals(newIndexMetaData.getAliases()) == false) { + assert currentIndexMetaData.getAliasesVersion() == newIndexMetaData.getAliasesVersion(); + metadata.put(new IndexMetaData.Builder(newIndexMetaData).aliasesVersion(1 + currentIndexMetaData.getAliasesVersion())); + } } if (changed) { diff --git a/server/src/main/java/org/elasticsearch/snapshots/RestoreService.java b/server/src/main/java/org/elasticsearch/snapshots/RestoreService.java index 3a81a9956870a..5e77dcc18628e 100644 --- a/server/src/main/java/org/elasticsearch/snapshots/RestoreService.java +++ b/server/src/main/java/org/elasticsearch/snapshots/RestoreService.java @@ -301,13 +301,16 @@ public ClusterState execute(ClusterState currentState) { } else { validateExistingIndex(currentIndexMetaData, snapshotIndexMetaData, renamedIndexName, partial); // Index exists and it's closed - open it in metadata and start recovery - IndexMetaData.Builder indexMdBuilder = IndexMetaData.builder(snapshotIndexMetaData) - .state(IndexMetaData.State.OPEN); - indexMdBuilder.version(Math.max(snapshotIndexMetaData.getVersion(), currentIndexMetaData.getVersion() + 1)); - indexMdBuilder.mappingVersion(Math.max(snapshotIndexMetaData.getMappingVersion(), - currentIndexMetaData.getMappingVersion() + 1)); - indexMdBuilder.settingsVersion(Math.max(snapshotIndexMetaData.getSettingsVersion(), - currentIndexMetaData.getSettingsVersion() + 1)); + IndexMetaData.Builder indexMdBuilder = + IndexMetaData.builder(snapshotIndexMetaData).state(IndexMetaData.State.OPEN); + indexMdBuilder.version( + Math.max(snapshotIndexMetaData.getVersion(), 1 + currentIndexMetaData.getVersion())); + indexMdBuilder.mappingVersion( + Math.max(snapshotIndexMetaData.getMappingVersion(), 1 + currentIndexMetaData.getMappingVersion())); + indexMdBuilder.settingsVersion( + Math.max(snapshotIndexMetaData.getSettingsVersion(), 1 + currentIndexMetaData.getSettingsVersion())); + indexMdBuilder.aliasesVersion( + Math.max(snapshotIndexMetaData.getAliasesVersion(), 1 + currentIndexMetaData.getAliasesVersion())); for (int shard = 0; shard < snapshotIndexMetaData.getNumberOfShards(); shard++) { indexMdBuilder.primaryTerm(shard, diff --git a/server/src/test/java/org/elasticsearch/aliases/IndexAliasesIT.java b/server/src/test/java/org/elasticsearch/aliases/IndexAliasesIT.java index a1058b03dacb0..ce7ea7fbb6bd0 100644 --- a/server/src/test/java/org/elasticsearch/aliases/IndexAliasesIT.java +++ b/server/src/test/java/org/elasticsearch/aliases/IndexAliasesIT.java @@ -39,6 +39,7 @@ import org.elasticsearch.common.xcontent.XContentType; import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.index.query.QueryBuilders; +import org.elasticsearch.index.query.TermQueryBuilder; import org.elasticsearch.rest.action.admin.indices.AliasesNotFoundException; import org.elasticsearch.search.SearchHit; import org.elasticsearch.search.SearchHits; @@ -49,6 +50,7 @@ import org.elasticsearch.test.ESIntegTestCase; import java.util.Arrays; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -81,14 +83,18 @@ import static org.hamcrest.Matchers.nullValue; public class IndexAliasesIT extends ESIntegTestCase { + public void testAliases() throws Exception { logger.info("--> creating index [test]"); createIndex("test"); ensureGreen(); - logger.info("--> aliasing index [test] with [alias1]"); - assertAcked(admin().indices().prepareAliases().addAlias("test", "alias1", false)); + assertAliasesVersionIncreases( + "test", () -> { + logger.info("--> aliasing index [test] with [alias1]"); + assertAcked(admin().indices().prepareAliases().addAlias("test", "alias1", false)); + }); logger.info("--> indexing against [alias1], should fail now"); IllegalArgumentException exception = expectThrows(IllegalArgumentException.class, @@ -98,8 +104,13 @@ public void testAliases() throws Exception { " The write index may be explicitly disabled using is_write_index=false or the alias points to multiple" + " indices without one being designated as a write index")); - logger.info("--> aliasing index [test] with [alias1]"); - assertAcked(admin().indices().prepareAliases().addAlias("test", "alias1")); + assertAliasesVersionIncreases( + "test", + () -> { + logger.info("--> aliasing index [test] with [alias1]"); + assertAcked(admin().indices().prepareAliases().addAlias("test", "alias1")); + } + ); logger.info("--> indexing against [alias1], should work now"); IndexResponse indexResponse = client().index(indexRequest("alias1").type("type1").id("1") @@ -111,8 +122,10 @@ public void testAliases() throws Exception { ensureGreen(); - logger.info("--> add index [test_x] with [alias1]"); - assertAcked(admin().indices().prepareAliases().addAlias("test_x", "alias1")); + assertAliasesVersionIncreases("test_x", () -> { + logger.info("--> add index [test_x] with [alias1]"); + assertAcked(admin().indices().prepareAliases().addAlias("test_x", "alias1")); + }); logger.info("--> indexing against [alias1], should fail now"); exception = expectThrows(IllegalArgumentException.class, @@ -129,16 +142,20 @@ public void testAliases() throws Exception { " The write index may be explicitly disabled using is_write_index=false or the alias points to multiple" + " indices without one being designated as a write index")); - logger.info("--> remove aliasing index [test_x] with [alias1]"); - assertAcked(admin().indices().prepareAliases().removeAlias("test_x", "alias1")); + assertAliasesVersionIncreases("test_x", () -> { + logger.info("--> remove aliasing index [test_x] with [alias1]"); + assertAcked(admin().indices().prepareAliases().removeAlias("test_x", "alias1")); + }); logger.info("--> indexing against [alias1], should work now"); indexResponse = client().index(indexRequest("alias1").type("type1").id("1") .source(source("1", "test"), XContentType.JSON)).actionGet(); assertThat(indexResponse.getIndex(), equalTo("test")); - logger.info("--> add index [test_x] with [alias1] as write-index"); - assertAcked(admin().indices().prepareAliases().addAlias("test_x", "alias1", true)); + assertAliasesVersionIncreases("test_x", () -> { + logger.info("--> add index [test_x] with [alias1] as write-index"); + assertAcked(admin().indices().prepareAliases().addAlias("test_x", "alias1", true)); + }); logger.info("--> indexing against [alias1], should work now"); indexResponse = client().index(indexRequest("alias1").type("type1").id("1") @@ -149,8 +166,10 @@ public void testAliases() throws Exception { DeleteResponse deleteResponse = client().delete(deleteRequest("alias1").type("type1").id("1")).actionGet(); assertThat(deleteResponse.getIndex(), equalTo("test_x")); - logger.info("--> remove [alias1], Aliasing index [test_x] with [alias1]"); - assertAcked(admin().indices().prepareAliases().removeAlias("test", "alias1").addAlias("test_x", "alias1")); + assertAliasesVersionIncreases("test_x", () -> { + logger.info("--> remove [alias1], Aliasing index [test_x] with [alias1]"); + assertAcked(admin().indices().prepareAliases().removeAlias("test", "alias1").addAlias("test_x", "alias1")); + }); logger.info("--> indexing against [alias1], should work against [test_x]"); indexResponse = client().index(indexRequest("alias1").type("type1").id("1") @@ -181,7 +200,7 @@ public void testFilteringAliases() throws Exception { logger.info("--> aliasing index [test] with [alias1] and filter [user:kimchy]"); QueryBuilder filter = termQuery("user", "kimchy"); - assertAcked(admin().indices().prepareAliases().addAlias("test", "alias1", filter)); + assertAliasesVersionIncreases("test", () -> assertAcked(admin().indices().prepareAliases().addAlias("test", "alias1", filter))); // For now just making sure that filter was stored with the alias logger.info("--> making sure that filter was stored with alias [alias1] and filter [user:kimchy]"); @@ -210,11 +229,18 @@ public void testSearchingFilteringAliasesSingleIndex() throws Exception { ensureGreen(); logger.info("--> adding filtering aliases to index [test]"); - assertAcked(admin().indices().prepareAliases().addAlias("test", "alias1")); - assertAcked(admin().indices().prepareAliases().addAlias("test", "alias2")); - assertAcked(admin().indices().prepareAliases().addAlias("test", "foos", termQuery("name", "foo"))); - assertAcked(admin().indices().prepareAliases().addAlias("test", "bars", termQuery("name", "bar"))); - assertAcked(admin().indices().prepareAliases().addAlias("test", "tests", termQuery("name", "test"))); + + assertAliasesVersionIncreases("test", () -> assertAcked(admin().indices().prepareAliases().addAlias("test", "alias1"))); + assertAliasesVersionIncreases("test", () -> assertAcked(admin().indices().prepareAliases().addAlias("test", "alias2"))); + assertAliasesVersionIncreases( + "test", + () -> assertAcked(admin().indices().prepareAliases().addAlias("test", "foos", termQuery("name", "foo")))); + assertAliasesVersionIncreases( + "test", + () -> assertAcked(admin().indices().prepareAliases().addAlias("test", "bars", termQuery("name", "bar")))); + assertAliasesVersionIncreases( + "test", + () -> assertAcked(admin().indices().prepareAliases().addAlias("test", "tests", termQuery("name", "test")))); logger.info("--> indexing against [test]"); client().index(indexRequest("test").type("type1").id("1").source(source("1", "foo test"), XContentType.JSON) @@ -295,15 +321,21 @@ public void testSearchingFilteringAliasesTwoIndices() throws Exception { ensureGreen(); logger.info("--> adding filtering aliases to index [test1]"); - assertAcked(admin().indices().prepareAliases().addAlias("test1", "aliasToTest1")); - assertAcked(admin().indices().prepareAliases().addAlias("test1", "aliasToTests")); - assertAcked(admin().indices().prepareAliases().addAlias("test1", "foos", termQuery("name", "foo"))); - assertAcked(admin().indices().prepareAliases().addAlias("test1", "bars", termQuery("name", "bar"))); + assertAliasesVersionIncreases("test1", () -> assertAcked(admin().indices().prepareAliases().addAlias("test1", "aliasToTest1"))); + assertAliasesVersionIncreases("test1", () -> assertAcked(admin().indices().prepareAliases().addAlias("test1", "aliasToTests"))); + assertAliasesVersionIncreases( + "test1", + () -> assertAcked(admin().indices().prepareAliases().addAlias("test1", "foos", termQuery("name", "foo")))); + assertAliasesVersionIncreases( + "test1", + () -> assertAcked(admin().indices().prepareAliases().addAlias("test1", "bars", termQuery("name", "bar")))); logger.info("--> adding filtering aliases to index [test2]"); - assertAcked(admin().indices().prepareAliases().addAlias("test2", "aliasToTest2")); - assertAcked(admin().indices().prepareAliases().addAlias("test2", "aliasToTests")); - assertAcked(admin().indices().prepareAliases().addAlias("test2", "foos", termQuery("name", "foo"))); + assertAliasesVersionIncreases("test2", () -> assertAcked(admin().indices().prepareAliases().addAlias("test2", "aliasToTest2"))); + assertAliasesVersionIncreases("test2", () -> assertAcked(admin().indices().prepareAliases().addAlias("test2", "aliasToTests"))); + assertAliasesVersionIncreases( + "test2", + () -> assertAcked(admin().indices().prepareAliases().addAlias("test2", "foos", termQuery("name", "foo")))); logger.info("--> indexing against [test1]"); client().index(indexRequest("test1").type("type1").id("1").source(source("1", "foo test"), XContentType.JSON)).get(); @@ -367,17 +399,27 @@ public void testSearchingFilteringAliasesMultipleIndices() throws Exception { ensureGreen(); logger.info("--> adding aliases to indices"); - assertAcked(admin().indices().prepareAliases().addAlias("test1", "alias12")); - assertAcked(admin().indices().prepareAliases().addAlias("test2", "alias12")); + assertAliasesVersionIncreases("test1", () -> assertAcked(admin().indices().prepareAliases().addAlias("test1", "alias12"))); + assertAliasesVersionIncreases("test2", () -> assertAcked(admin().indices().prepareAliases().addAlias("test2", "alias12"))); logger.info("--> adding filtering aliases to indices"); - assertAcked(admin().indices().prepareAliases().addAlias("test1", "filter1", termQuery("name", "test1"))); - - assertAcked(admin().indices().prepareAliases().addAlias("test2", "filter23", termQuery("name", "foo"))); - assertAcked(admin().indices().prepareAliases().addAlias("test3", "filter23", termQuery("name", "foo"))); - - assertAcked(admin().indices().prepareAliases().addAlias("test1", "filter13", termQuery("name", "baz"))); - assertAcked(admin().indices().prepareAliases().addAlias("test3", "filter13", termQuery("name", "baz"))); + assertAliasesVersionIncreases( + "test1", + () -> assertAcked(admin().indices().prepareAliases().addAlias("test1", "filter1", termQuery("name", "test1")))); + + assertAliasesVersionIncreases( + "test2", + () -> assertAcked(admin().indices().prepareAliases().addAlias("test2", "filter23", termQuery("name", "foo")))); + assertAliasesVersionIncreases( + "test3", + () -> assertAcked(admin().indices().prepareAliases().addAlias("test3", "filter23", termQuery("name", "foo")))); + + assertAliasesVersionIncreases( + "test1", + () -> assertAcked(admin().indices().prepareAliases().addAlias("test1", "filter13", termQuery("name", "baz")))); + assertAliasesVersionIncreases( + "test3", + () -> assertAcked(admin().indices().prepareAliases().addAlias("test3", "filter13", termQuery("name", "baz")))); logger.info("--> indexing against [test1]"); client().index(indexRequest("test1").type("type1").id("11").source(source("11", "foo test1"), XContentType.JSON)).get(); @@ -433,17 +475,27 @@ public void testDeletingByQueryFilteringAliases() throws Exception { ensureGreen(); logger.info("--> adding filtering aliases to index [test1]"); - assertAcked(admin().indices().prepareAliases().addAlias("test1", "aliasToTest1")); - assertAcked(admin().indices().prepareAliases().addAlias("test1", "aliasToTests")); - assertAcked(admin().indices().prepareAliases().addAlias("test1", "foos", termQuery("name", "foo"))); - assertAcked(admin().indices().prepareAliases().addAlias("test1", "bars", termQuery("name", "bar"))); - assertAcked(admin().indices().prepareAliases().addAlias("test1", "tests", termQuery("name", "test"))); + assertAliasesVersionIncreases("test1", () -> assertAcked(admin().indices().prepareAliases().addAlias("test1", "aliasToTest1"))); + assertAliasesVersionIncreases("test1", () -> assertAcked(admin().indices().prepareAliases().addAlias("test1", "aliasToTests"))); + assertAliasesVersionIncreases( + "test1", + () -> assertAcked(admin().indices().prepareAliases().addAlias("test1", "foos", termQuery("name", "foo")))); + assertAliasesVersionIncreases( + "test1", + () -> assertAcked(admin().indices().prepareAliases().addAlias("test1", "bars", termQuery("name", "bar")))); + assertAliasesVersionIncreases( + "test1", + () -> assertAcked(admin().indices().prepareAliases().addAlias("test1", "tests", termQuery("name", "test")))); logger.info("--> adding filtering aliases to index [test2]"); - assertAcked(admin().indices().prepareAliases().addAlias("test2", "aliasToTest2")); - assertAcked(admin().indices().prepareAliases().addAlias("test2", "aliasToTests")); - assertAcked(admin().indices().prepareAliases().addAlias("test2", "foos", termQuery("name", "foo"))); - assertAcked(admin().indices().prepareAliases().addAlias("test2", "tests", termQuery("name", "test"))); + assertAliasesVersionIncreases("test2", () -> assertAcked(admin().indices().prepareAliases().addAlias("test2", "aliasToTest2"))); + assertAliasesVersionIncreases("test2", () -> assertAcked(admin().indices().prepareAliases().addAlias("test2", "aliasToTests"))); + assertAliasesVersionIncreases( + "test2", + () -> assertAcked(admin().indices().prepareAliases().addAlias("test2", "foos", termQuery("name", "foo")))); + assertAliasesVersionIncreases( + "test2", + () -> assertAcked(admin().indices().prepareAliases().addAlias("test2", "tests", termQuery("name", "test")))); logger.info("--> indexing against [test1]"); client().index(indexRequest("test1").type("type1").id("1").source(source("1", "foo test"), XContentType.JSON)).get(); @@ -471,22 +523,30 @@ public void testDeleteAliases() throws Exception { ensureGreen(); logger.info("--> adding filtering aliases to index [test1]"); - assertAcked(admin().indices().prepareAliases().addAlias("test1", "aliasToTest1") - .addAlias("test1", "aliasToTests") - .addAlias("test1", "foos", termQuery("name", "foo")) - .addAlias("test1", "bars", termQuery("name", "bar")) - .addAlias("test1", "tests", termQuery("name", "test"))); + assertAliasesVersionIncreases( + "test1", + () -> assertAcked(admin().indices() + .prepareAliases() + .addAlias("test1", "aliasToTest1") + .addAlias("test1", "aliasToTests") + .addAlias("test1", "foos", termQuery("name", "foo")) + .addAlias("test1", "bars", termQuery("name", "bar")) + .addAlias("test1", "tests", termQuery("name", "test")))); logger.info("--> adding filtering aliases to index [test2]"); - assertAcked(admin().indices().prepareAliases().addAlias("test2", "aliasToTest2") - .addAlias("test2", "aliasToTests") - .addAlias("test2", "foos", termQuery("name", "foo")) - .addAlias("test2", "tests", termQuery("name", "test"))); + assertAliasesVersionIncreases( + "test2", + () -> assertAcked(admin().indices() + .prepareAliases() + .addAlias("test2", "aliasToTest2") + .addAlias("test2", "aliasToTests") + .addAlias("test2", "foos", termQuery("name", "foo")) + .addAlias("test2", "tests", termQuery("name", "test")))); String[] indices = {"test1", "test2"}; String[] aliases = {"aliasToTest1", "foos", "bars", "tests", "aliasToTest2", "aliasToTests"}; - admin().indices().prepareAliases().removeAlias(indices, aliases).get(); + assertAliasesVersionIncreases(indices, () -> admin().indices().prepareAliases().removeAlias(indices, aliases).get()); AliasesExistResponse response = admin().indices().prepareAliasesExist(aliases).get(); assertThat(response.exists(), equalTo(false)); @@ -497,10 +557,12 @@ public void testDeleteAliases() throws Exception { ensureGreen(); logger.info("--> adding [foo] alias to [foo_foo] and [bar_bar]"); - assertAcked(admin().indices().prepareAliases().addAlias("foo_foo", "foo")); - assertAcked(admin().indices().prepareAliases().addAlias("bar_bar", "foo")); + assertAliasesVersionIncreases("foo_foo", () -> assertAcked(admin().indices().prepareAliases().addAlias("foo_foo", "foo"))); + assertAliasesVersionIncreases("bar_bar", () -> assertAcked(admin().indices().prepareAliases().addAlias("bar_bar", "foo"))); - assertAcked(admin().indices().prepareAliases().addAliasAction(AliasActions.remove().index("foo*").alias("foo")).execute().get()); + assertAliasesVersionIncreases( + "foo_foo", + () -> assertAcked(admin().indices().prepareAliases().addAliasAction(AliasActions.remove().index("foo*").alias("foo")))); assertTrue(admin().indices().prepareAliasesExist("foo").get().exists()); assertFalse(admin().indices().prepareAliasesExist("foo").setIndices("foo_foo").get().exists()); @@ -518,8 +580,9 @@ public void testWaitForAliasCreationMultipleShards() throws Exception { ensureGreen(); for (int i = 0; i < 10; i++) { - assertAcked(admin().indices().prepareAliases().addAlias("test", "alias" + i)); - client().index(indexRequest("alias" + i).type("type1").id("1").source(source("1", "test"), XContentType.JSON)).get(); + final String aliasName = "alias" + i; + assertAliasesVersionIncreases("test", () -> assertAcked(admin().indices().prepareAliases().addAlias("test", aliasName))); + client().index(indexRequest(aliasName).type("type1").id("1").source(source("1", "test"), XContentType.JSON)).get(); } } @@ -533,8 +596,9 @@ public void testWaitForAliasCreationSingleShard() throws Exception { ensureGreen(); for (int i = 0; i < 10; i++) { - assertAcked(admin().indices().prepareAliases().addAlias("test", "alias" + i)); - client().index(indexRequest("alias" + i).type("type1").id("1").source(source("1", "test"), + final String aliasName = "alias" + i; + assertAliasesVersionIncreases("test", () -> assertAcked(admin().indices().prepareAliases().addAlias("test", aliasName))); + client().index(indexRequest(aliasName).type("type1").id("1").source(source("1", "test"), XContentType.JSON)).get(); } } @@ -553,7 +617,9 @@ public void testWaitForAliasSimultaneousUpdate() throws Exception { executor.submit(new Runnable() { @Override public void run() { - assertAcked(admin().indices().prepareAliases().addAlias("test", aliasName)); + assertAliasesVersionIncreases( + "test", + () -> assertAcked(admin().indices().prepareAliases().addAlias("test", aliasName))); client().index(indexRequest(aliasName).type("type1").id("1").source(source("1", "test"), XContentType.JSON)) .actionGet(); } @@ -573,27 +639,37 @@ public void testSameAlias() throws Exception { ensureGreen(); logger.info("--> creating alias1 "); - assertAcked((admin().indices().prepareAliases().addAlias("test", "alias1"))); + assertAliasesVersionIncreases("test", () -> assertAcked((admin().indices().prepareAliases().addAlias("test", "alias1")))); TimeValue timeout = TimeValue.timeValueSeconds(2); logger.info("--> recreating alias1 "); StopWatch stopWatch = new StopWatch(); stopWatch.start(); - assertAcked((admin().indices().prepareAliases().addAlias("test", "alias1").setTimeout(timeout))); + assertAliasesVersionUnchanged( + "test", + () -> assertAcked((admin().indices().prepareAliases().addAlias("test", "alias1").setTimeout(timeout)))); assertThat(stopWatch.stop().lastTaskTime().millis(), lessThan(timeout.millis())); logger.info("--> modifying alias1 to have a filter"); stopWatch.start(); - assertAcked((admin().indices().prepareAliases().addAlias("test", "alias1", termQuery("name", "foo")).setTimeout(timeout))); + final TermQueryBuilder fooFilter = termQuery("name", "foo"); + assertAliasesVersionIncreases( + "test", + () -> assertAcked(admin().indices().prepareAliases().addAlias("test", "alias1", fooFilter).setTimeout(timeout))); assertThat(stopWatch.stop().lastTaskTime().millis(), lessThan(timeout.millis())); logger.info("--> recreating alias1 with the same filter"); stopWatch.start(); - assertAcked((admin().indices().prepareAliases().addAlias("test", "alias1", termQuery("name", "foo")).setTimeout(timeout))); + assertAliasesVersionUnchanged( + "test", + () -> assertAcked((admin().indices().prepareAliases().addAlias("test", "alias1", fooFilter).setTimeout(timeout)))); assertThat(stopWatch.stop().lastTaskTime().millis(), lessThan(timeout.millis())); logger.info("--> recreating alias1 with a different filter"); stopWatch.start(); - assertAcked((admin().indices().prepareAliases().addAlias("test", "alias1", termQuery("name", "bar")).setTimeout(timeout))); + final TermQueryBuilder barFilter = termQuery("name", "bar"); + assertAliasesVersionIncreases( + "test", + () -> assertAcked((admin().indices().prepareAliases().addAlias("test", "alias1", barFilter).setTimeout(timeout)))); assertThat(stopWatch.stop().lastTaskTime().millis(), lessThan(timeout.millis())); logger.info("--> verify that filter was updated"); @@ -603,10 +679,10 @@ public void testSameAlias() throws Exception { logger.info("--> deleting alias1"); stopWatch.start(); - assertAcked((admin().indices().prepareAliases().removeAlias("test", "alias1").setTimeout(timeout))); + assertAliasesVersionIncreases( + "test", + () -> assertAcked((admin().indices().prepareAliases().removeAlias("test", "alias1").setTimeout(timeout)))); assertThat(stopWatch.stop().lastTaskTime().millis(), lessThan(timeout.millis())); - - } public void testIndicesRemoveNonExistingAliasResponds404() throws Exception { @@ -635,7 +711,9 @@ public void testIndicesGetAliases() throws Exception { ensureGreen(); logger.info("--> creating aliases [alias1, alias2]"); - assertAcked(admin().indices().prepareAliases().addAlias("foobar", "alias1").addAlias("foobar", "alias2")); + assertAliasesVersionIncreases( + "foobar", + () -> assertAcked(admin().indices().prepareAliases().addAlias("foobar", "alias1").addAlias("foobar", "alias2"))); logger.info("--> getting alias1"); GetAliasesResponse getResponse = admin().indices().prepareGetAliases("alias1").get(); @@ -670,13 +748,19 @@ public void testIndicesGetAliases() throws Exception { logger.info("--> creating aliases [bar, baz, foo]"); - assertAcked(admin().indices().prepareAliases() - .addAlias("bazbar", "bar") - .addAlias("bazbar", "bac", termQuery("field", "value")) - .addAlias("foobar", "foo")); - - assertAcked(admin().indices().prepareAliases() - .addAliasAction(AliasActions.add().index("foobar").alias("bac").routing("bla"))); + assertAliasesVersionIncreases( + new String[]{"bazbar", "foobar"}, + () -> assertAcked(admin().indices() + .prepareAliases() + .addAlias("bazbar", "bar") + .addAlias("bazbar", "bac", termQuery("field", "value")) + .addAlias("foobar", "foo"))); + + assertAliasesVersionIncreases( + "foobar", + () -> assertAcked(admin().indices() + .prepareAliases() + .addAliasAction(AliasActions.add().index("foobar").alias("bac").routing("bla")))); logger.info("--> getting bar and baz for index bazbar"); getResponse = admin().indices().prepareGetAliases("bar", "bac").addIndices("bazbar").get(); @@ -826,7 +910,9 @@ public void testGetAllAliasesWorks() { createIndex("index1"); createIndex("index2"); - assertAcked(admin().indices().prepareAliases().addAlias("index1", "alias1").addAlias("index2", "alias2")); + assertAliasesVersionIncreases( + new String[]{"index1", "index2"}, + () -> assertAcked(admin().indices().prepareAliases().addAlias("index1", "alias1").addAlias("index2", "alias2"))); GetAliasesResponse response = admin().indices().prepareGetAliases().get(); assertThat(response.getAliases(), hasKey("index1")); @@ -911,23 +997,41 @@ public void testAliasesCanBeAddedToIndicesOnly() throws Exception { // fields mentioned in filters don't need to exist in the mapping. public void testAddAliasWithFilterNoMapping() throws Exception { assertAcked(prepareCreate("test")); - client().admin().indices().prepareAliases() - .addAlias("test", "a", QueryBuilders.termQuery("field1", "term")) - .get(); - client().admin().indices().prepareAliases() - .addAlias("test", "a", QueryBuilders.rangeQuery("field2").from(0).to(1)) - .get(); - client().admin().indices().prepareAliases() - .addAlias("test", "a", QueryBuilders.matchAllQuery()) - .get(); + assertAliasesVersionIncreases( + "test", + () -> client().admin() + .indices() + .prepareAliases() + .addAlias("test", "a", QueryBuilders.termQuery("field1", "term")) + .get()); + assertAliasesVersionIncreases( + "test", + () -> client().admin() + .indices() + .prepareAliases() + .addAlias("test", "a", QueryBuilders.rangeQuery("field2").from(0).to(1)) + .get()); + assertAliasesVersionIncreases( + "test", + () -> client().admin() + .indices() + .prepareAliases() + .addAlias("test", "a", QueryBuilders.matchAllQuery()) + .get()); } public void testAliasFilterWithNowInRangeFilterAndQuery() throws Exception { assertAcked(prepareCreate("my-index").addMapping("my-type", "timestamp", "type=date")); - assertAcked(admin().indices().prepareAliases() - .addAlias("my-index", "filter1", rangeQuery("timestamp").from("2016-12-01").to("2016-12-31"))); - assertAcked(admin().indices().prepareAliases() - .addAlias("my-index", "filter2", rangeQuery("timestamp").from("2016-01-01").to("2016-12-31"))); + assertAliasesVersionIncreases( + "my-index", + () -> assertAcked(admin().indices() + .prepareAliases() + .addAlias("my-index", "filter1", rangeQuery("timestamp").from("2016-12-01").to("2016-12-31")))); + assertAliasesVersionIncreases( + "my-index", + () -> assertAcked(admin().indices() + .prepareAliases() + .addAlias("my-index", "filter2", rangeQuery("timestamp").from("2016-01-01").to("2016-12-31")))); final int numDocs = scaledRandomIntBetween(5, 52); for (int i = 1; i <= numDocs; i++) { @@ -951,8 +1055,10 @@ public void testAliasesWithBlocks() { try { enableIndexBlock("test", block); - assertAcked(admin().indices().prepareAliases().addAlias("test", "alias1").addAlias("test", "alias2")); - assertAcked(admin().indices().prepareAliases().removeAlias("test", "alias1")); + assertAliasesVersionIncreases( + "test", + () -> assertAcked(admin().indices().prepareAliases().addAlias("test", "alias1").addAlias("test", "alias2"))); + assertAliasesVersionIncreases("test", () -> assertAcked(admin().indices().prepareAliases().removeAlias("test", "alias1"))); assertThat(admin().indices().prepareGetAliases("alias2").execute().actionGet().getAliases().get("test").size(), equalTo(1)); assertThat(admin().indices().prepareAliasesExist("alias2").get().exists(), equalTo(true)); } finally { @@ -963,8 +1069,12 @@ public void testAliasesWithBlocks() { try { enableIndexBlock("test", SETTING_READ_ONLY); - assertBlocked(admin().indices().prepareAliases().addAlias("test", "alias3"), INDEX_READ_ONLY_BLOCK); - assertBlocked(admin().indices().prepareAliases().removeAlias("test", "alias2"), INDEX_READ_ONLY_BLOCK); + assertAliasesVersionUnchanged( + "test", + () -> assertBlocked(admin().indices().prepareAliases().addAlias("test", "alias3"), INDEX_READ_ONLY_BLOCK)); + assertAliasesVersionUnchanged( + "test", + () -> assertBlocked(admin().indices().prepareAliases().removeAlias("test", "alias2"), INDEX_READ_ONLY_BLOCK)); assertThat(admin().indices().prepareGetAliases("alias2").execute().actionGet().getAliases().get("test").size(), equalTo(1)); assertThat(admin().indices().prepareAliasesExist("alias2").get().exists(), equalTo(true)); @@ -975,8 +1085,12 @@ public void testAliasesWithBlocks() { try { enableIndexBlock("test", SETTING_BLOCKS_METADATA); - assertBlocked(admin().indices().prepareAliases().addAlias("test", "alias3"), INDEX_METADATA_BLOCK); - assertBlocked(admin().indices().prepareAliases().removeAlias("test", "alias2"), INDEX_METADATA_BLOCK); + assertAliasesVersionUnchanged( + "test", + () -> assertBlocked(admin().indices().prepareAliases().addAlias("test", "alias3"), INDEX_METADATA_BLOCK)); + assertAliasesVersionUnchanged( + "test", + () -> assertBlocked(admin().indices().prepareAliases().removeAlias("test", "alias2"), INDEX_METADATA_BLOCK)); assertBlocked(admin().indices().prepareGetAliases("alias2"), INDEX_METADATA_BLOCK); assertBlocked(admin().indices().prepareAliasesExist("alias2"), INDEX_METADATA_BLOCK); @@ -988,15 +1102,19 @@ public void testAliasesWithBlocks() { public void testAliasActionRemoveIndex() throws InterruptedException, ExecutionException { assertAcked(prepareCreate("foo_foo")); assertAcked(prepareCreate("bar_bar")); - assertAcked(admin().indices().prepareAliases().addAlias("foo_foo", "foo")); - assertAcked(admin().indices().prepareAliases().addAlias("bar_bar", "foo")); + assertAliasesVersionIncreases( + new String[]{"foo_foo", "bar_bar"}, + () -> { + assertAcked(admin().indices().prepareAliases().addAlias("foo_foo", "foo")); + assertAcked(admin().indices().prepareAliases().addAlias("bar_bar", "foo")); + }); IllegalArgumentException iae = expectThrows(IllegalArgumentException.class, () -> client().admin().indices().prepareAliases().removeIndex("foo").execute().actionGet()); assertEquals("The provided expression [foo] matches an alias, specify the corresponding concrete indices instead.", iae.getMessage()); - assertAcked(client().admin().indices().prepareAliases().removeIndex("foo*").execute().get()); + assertAcked(client().admin().indices().prepareAliases().removeIndex("foo*")); assertFalse(client().admin().indices().prepareExists("foo_foo").execute().actionGet().isExists()); assertTrue(admin().indices().prepareAliasesExist("foo").get().exists()); assertTrue(client().admin().indices().prepareExists("bar_bar").execute().actionGet().isExists()); @@ -1010,7 +1128,9 @@ public void testAliasActionRemoveIndex() throws InterruptedException, ExecutionE public void testRemoveIndexAndReplaceWithAlias() throws InterruptedException, ExecutionException { assertAcked(client().admin().indices().prepareCreate("test")); indexRandom(true, client().prepareIndex("test_2", "test", "test").setSource("test", "test")); - assertAcked(client().admin().indices().prepareAliases().addAlias("test_2", "test").removeIndex("test")); + assertAliasesVersionIncreases( + "test_2", + () -> assertAcked(client().admin().indices().prepareAliases().addAlias("test_2", "test").removeIndex("test"))); assertHitCount(client().prepareSearch("test").get(), 1); } @@ -1052,4 +1172,31 @@ private void assertHits(SearchHits hits, String... ids) { private String source(String id, String nameValue) { return "{ \"id\" : \"" + id + "\", \"name\" : \"" + nameValue + "\" }"; } + + private void assertAliasesVersionIncreases(final String index, final Runnable runnable) { + assertAliasesVersionIncreases(new String[]{index}, runnable); + } + + private void assertAliasesVersionIncreases(final String[] indices, final Runnable runnable) { + final var beforeAliasesVersions = new HashMap(indices.length); + final var beforeMetaData = admin().cluster().prepareState().get().getState().metaData(); + for (final var index : indices) { + beforeAliasesVersions.put(index, beforeMetaData.index(index).getAliasesVersion()); + } + runnable.run(); + final var afterMetaData = admin().cluster().prepareState().get().getState().metaData(); + for (final String index : indices) { + assertThat(afterMetaData.index(index).getAliasesVersion(), equalTo(1 + beforeAliasesVersions.get(index))); + } + } + + private void assertAliasesVersionUnchanged(final String index, final Runnable runnable) { + final long beforeAliasesVersion = + admin().cluster().prepareState().get().getState().metaData().index(index).getAliasesVersion(); + runnable.run(); + final long afterAliasesVersion = + admin().cluster().prepareState().get().getState().metaData().index(index).getAliasesVersion(); + assertThat(afterAliasesVersion, equalTo(beforeAliasesVersion)); + } + } diff --git a/server/src/test/java/org/elasticsearch/cluster/metadata/MetaDataIndexAliasesServiceTests.java b/server/src/test/java/org/elasticsearch/cluster/metadata/MetaDataIndexAliasesServiceTests.java index 9b2d58ac28758..e07865f308ef5 100644 --- a/server/src/test/java/org/elasticsearch/cluster/metadata/MetaDataIndexAliasesServiceTests.java +++ b/server/src/test/java/org/elasticsearch/cluster/metadata/MetaDataIndexAliasesServiceTests.java @@ -23,14 +23,17 @@ import org.elasticsearch.cluster.ClusterName; import org.elasticsearch.cluster.ClusterState; import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.util.set.Sets; import org.elasticsearch.index.Index; import org.elasticsearch.index.IndexNotFoundException; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.VersionUtils; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.HashSet; import java.util.List; import static java.util.Collections.singletonList; @@ -74,6 +77,7 @@ public void testAddAndRemove() { assertNotNull(alias); assertTrue(alias.isAlias()); assertThat(alias.getIndices(), contains(after.metaData().index(index))); + assertAliasesVersionIncreased(index, before, after); // Remove the alias from it while adding another one before = after; @@ -85,12 +89,102 @@ public void testAddAndRemove() { assertNotNull(alias); assertTrue(alias.isAlias()); assertThat(alias.getIndices(), contains(after.metaData().index(index))); + assertAliasesVersionIncreased(index, before, after); // Now just remove on its own before = after; after = service.innerExecute(before, singletonList(new AliasAction.Remove(index, "test_2"))); assertNull(after.metaData().getAliasAndIndexLookup().get("test")); assertNull(after.metaData().getAliasAndIndexLookup().get("test_2")); + assertAliasesVersionIncreased(index, before, after); + } + + public void testMultipleIndices() { + final var length = randomIntBetween(2, 8); + final var indices = new HashSet(length); + var before = ClusterState.builder(ClusterName.DEFAULT).build(); + final var addActions = new ArrayList(length); + for (int i = 0; i < length; i++) { + final String index = randomValueOtherThanMany(v -> indices.add(v) == false, () -> randomAlphaOfLength(8)); + before = createIndex(before, index); + addActions.add(new AliasAction.Add(index, "alias-" + index, null, null, null, null)); + } + final var afterAddingAliasesToAll = service.innerExecute(before, addActions); + assertAliasesVersionIncreased(indices.toArray(new String[0]), before, afterAddingAliasesToAll); + + // now add some aliases randomly + final var randomIndices = new HashSet(length); + final var randomAddActions = new ArrayList(length); + for (var index : indices) { + if (randomBoolean()) { + randomAddActions.add(new AliasAction.Add(index, "random-alias-" + index, null, null, null, null)); + randomIndices.add(index); + } + } + final var afterAddingRandomAliases = service.innerExecute(afterAddingAliasesToAll, randomAddActions); + assertAliasesVersionIncreased(randomIndices.toArray(new String[0]), afterAddingAliasesToAll, afterAddingRandomAliases); + assertAliasesVersionUnchanged( + Sets.difference(indices, randomIndices).toArray(new String[0]), + afterAddingAliasesToAll, + afterAddingRandomAliases); + } + + public void testChangingWriteAliasStateIncreasesAliasesVersion() { + final String index = randomAlphaOfLength(8); + final ClusterState before = createIndex(ClusterState.builder(ClusterName.DEFAULT).build(), index); + + final ClusterState afterAddWriteAlias = + service.innerExecute(before, singletonList(new AliasAction.Add(index, "test", null, null, null, true))); + assertAliasesVersionIncreased(index, before, afterAddWriteAlias); + + final ClusterState afterChangeWriteAliasToNonWriteAlias = + service.innerExecute(afterAddWriteAlias, singletonList(new AliasAction.Add(index, "test", null, null, null, false))); + assertAliasesVersionIncreased(index, afterAddWriteAlias, afterChangeWriteAliasToNonWriteAlias); + + final ClusterState afterChangeNonWriteAliasToWriteAlias = + service.innerExecute( + afterChangeWriteAliasToNonWriteAlias, + singletonList(new AliasAction.Add(index, "test", null, null, null, true))); + assertAliasesVersionIncreased(index, afterChangeWriteAliasToNonWriteAlias, afterChangeNonWriteAliasToWriteAlias); + } + + public void testAddingAliasMoreThanOnceShouldOnlyIncreaseAliasesVersionByOne() { + final String index = randomAlphaOfLength(8); + final ClusterState before = createIndex(ClusterState.builder(ClusterName.DEFAULT).build(), index); + + // add an alias to the index multiple times + final int length = randomIntBetween(2, 8); + final var addActions = new ArrayList(length); + for (int i = 0; i < length; i++) { + addActions.add(new AliasAction.Add(index, "test", null, null, null, null)); + } + final ClusterState afterAddingAliases = service.innerExecute(before, addActions); + + assertAliasesVersionIncreased(index, before, afterAddingAliases); + } + + public void testAliasesVersionUnchangedWhenActionsAreIdempotent() { + final String index = randomAlphaOfLength(8); + final ClusterState before = createIndex(ClusterState.builder(ClusterName.DEFAULT).build(), index); + + // add some aliases to the index + final int length = randomIntBetween(1, 8); + final var aliasNames = new HashSet(); + final var addActions = new ArrayList(length); + for (int i = 0; i < length; i++) { + final String aliasName = randomValueOtherThanMany(v -> aliasNames.add(v) == false, () -> randomAlphaOfLength(8)); + addActions.add(new AliasAction.Add(index, aliasName, null, null, null, null)); + } + final ClusterState afterAddingAlias = service.innerExecute(before, addActions); + + // now perform a remove and add for each alias which is idempotent, the resulting aliases are unchanged + final var removeAndAddActions = new ArrayList(2 * length); + for (final var aliasName : aliasNames) { + removeAndAddActions.add(new AliasAction.Remove(index, aliasName)); + removeAndAddActions.add(new AliasAction.Add(index, aliasName, null, null, null, null)); + } + final ClusterState afterRemoveAndAddAlias = service.innerExecute(afterAddingAlias, removeAndAddActions); + assertAliasesVersionUnchanged(index, afterAddingAlias, afterRemoveAndAddAlias); } public void testSwapIndexWithAlias() { @@ -106,6 +200,7 @@ public void testSwapIndexWithAlias() { assertNotNull(alias); assertTrue(alias.isAlias()); assertThat(alias.getIndices(), contains(after.metaData().index("test_2"))); + assertAliasesVersionIncreased("test_2", before, after); } public void testAddAliasToRemovedIndex() { @@ -137,18 +232,21 @@ public void testAddWriteOnlyWithNoExistingAliases() { new AliasAction.Add("test", "alias", null, null, null, false))); assertFalse(after.metaData().index("test").getAliases().get("alias").writeIndex()); assertNull(((AliasOrIndex.Alias) after.metaData().getAliasAndIndexLookup().get("alias")).getWriteIndex()); + assertAliasesVersionIncreased("test", before, after); after = service.innerExecute(before, Arrays.asList( new AliasAction.Add("test", "alias", null, null, null, null))); assertNull(after.metaData().index("test").getAliases().get("alias").writeIndex()); assertThat(((AliasOrIndex.Alias) after.metaData().getAliasAndIndexLookup().get("alias")).getWriteIndex(), equalTo(after.metaData().index("test"))); + assertAliasesVersionIncreased("test", before, after); after = service.innerExecute(before, Arrays.asList( new AliasAction.Add("test", "alias", null, null, null, true))); assertTrue(after.metaData().index("test").getAliases().get("alias").writeIndex()); assertThat(((AliasOrIndex.Alias) after.metaData().getAliasAndIndexLookup().get("alias")).getWriteIndex(), equalTo(after.metaData().index("test"))); + assertAliasesVersionIncreased("test", before, after); } public void testAddWriteOnlyWithExistingWriteIndex() { @@ -165,6 +263,8 @@ public void testAddWriteOnlyWithExistingWriteIndex() { assertNull(after.metaData().index("test").getAliases().get("alias").writeIndex()); assertThat(((AliasOrIndex.Alias) after.metaData().getAliasAndIndexLookup().get("alias")).getWriteIndex(), equalTo(after.metaData().index("test2"))); + assertAliasesVersionIncreased("test", before, after); + assertAliasesVersionUnchanged("test2", before, after); Exception exception = expectThrows(IllegalStateException.class, () -> service.innerExecute(before, Arrays.asList( new AliasAction.Add("test", "alias", null, null, null, true)))); @@ -191,6 +291,8 @@ public void testSwapWriteOnlyIndex() { assertTrue(after.metaData().index("test2").getAliases().get("alias").writeIndex()); assertThat(((AliasOrIndex.Alias) after.metaData().getAliasAndIndexLookup().get("alias")).getWriteIndex(), equalTo(after.metaData().index("test2"))); + assertAliasesVersionIncreased("test", before, after); + assertAliasesVersionIncreased("test2", before, after); } public void testAddWriteOnlyWithExistingNonWriteIndices() { @@ -212,7 +314,9 @@ public void testAddWriteOnlyWithExistingNonWriteIndices() { assertTrue(after.metaData().index("test3").getAliases().get("alias").writeIndex()); assertThat(((AliasOrIndex.Alias) after.metaData().getAliasAndIndexLookup().get("alias")).getWriteIndex(), equalTo(after.metaData().index("test3"))); - + assertAliasesVersionUnchanged("test", before, after); + assertAliasesVersionUnchanged("test2", before, after); + assertAliasesVersionIncreased("test3", before, after); } public void testAddWriteOnlyWithIndexRemoved() { @@ -233,6 +337,7 @@ public void testAddWriteOnlyWithIndexRemoved() { assertNull(after.metaData().index("test2").getAliases().get("alias").writeIndex()); assertThat(((AliasOrIndex.Alias) after.metaData().getAliasAndIndexLookup().get("alias")).getWriteIndex(), equalTo(after.metaData().index("test2"))); + assertAliasesVersionUnchanged("test2", before, after); } public void testAddWriteOnlyValidatesAgainstMetaDataBuilder() { @@ -260,4 +365,29 @@ private ClusterState createIndex(ClusterState state, String index) { .metaData(MetaData.builder(state.metaData()).put(indexMetaData, false)) .build(); } + + private void assertAliasesVersionUnchanged(final String index, final ClusterState before, final ClusterState after) { + assertAliasesVersionUnchanged(new String[]{index}, before, after); + } + + private void assertAliasesVersionUnchanged(final String[] indices, final ClusterState before, final ClusterState after) { + for (final var index : indices) { + final long expected = before.metaData().index(index).getAliasesVersion(); + final long actual = after.metaData().index(index).getAliasesVersion(); + assertThat("index metadata aliases version mismatch", actual, equalTo(expected)); + } + } + + private void assertAliasesVersionIncreased(final String index, final ClusterState before, final ClusterState after) { + assertAliasesVersionIncreased(new String[]{index}, before, after); + } + + private void assertAliasesVersionIncreased(final String[] indices, final ClusterState before, final ClusterState after) { + for (final var index : indices) { + final long expected = 1 + before.metaData().index(index).getAliasesVersion(); + final long actual = after.metaData().index(index).getAliasesVersion(); + assertThat("index metadata aliases version mismatch", actual, equalTo(expected)); + } + } + } From f92bd80a1c91b4c5c89cfb912dcae60e189a4470 Mon Sep 17 00:00:00 2001 From: Jason Tedor Date: Sat, 20 Apr 2019 17:14:51 -0400 Subject: [PATCH 2/3] Fix checkstyle --- .../main/java/org/elasticsearch/snapshots/RestoreService.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/server/src/main/java/org/elasticsearch/snapshots/RestoreService.java b/server/src/main/java/org/elasticsearch/snapshots/RestoreService.java index 5e77dcc18628e..cb9e7fee04249 100644 --- a/server/src/main/java/org/elasticsearch/snapshots/RestoreService.java +++ b/server/src/main/java/org/elasticsearch/snapshots/RestoreService.java @@ -308,7 +308,9 @@ public ClusterState execute(ClusterState currentState) { indexMdBuilder.mappingVersion( Math.max(snapshotIndexMetaData.getMappingVersion(), 1 + currentIndexMetaData.getMappingVersion())); indexMdBuilder.settingsVersion( - Math.max(snapshotIndexMetaData.getSettingsVersion(), 1 + currentIndexMetaData.getSettingsVersion())); + Math.max( + snapshotIndexMetaData.getSettingsVersion(), + 1 + currentIndexMetaData.getSettingsVersion())); indexMdBuilder.aliasesVersion( Math.max(snapshotIndexMetaData.getAliasesVersion(), 1 + currentIndexMetaData.getAliasesVersion())); From ac13531e3877b1ae25603677e953010748e3640c Mon Sep 17 00:00:00 2001 From: Jason Tedor Date: Sat, 20 Apr 2019 20:43:22 -0400 Subject: [PATCH 3/3] Update server/src/main/java/org/elasticsearch/cluster/metadata/IndexMetaData.java --- .../java/org/elasticsearch/cluster/metadata/IndexMetaData.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/main/java/org/elasticsearch/cluster/metadata/IndexMetaData.java b/server/src/main/java/org/elasticsearch/cluster/metadata/IndexMetaData.java index 6b465648d972a..f3c0af84a06c9 100644 --- a/server/src/main/java/org/elasticsearch/cluster/metadata/IndexMetaData.java +++ b/server/src/main/java/org/elasticsearch/cluster/metadata/IndexMetaData.java @@ -714,7 +714,7 @@ private static class IndexMetaDataDiff implements Diff { if (in.getVersion().onOrAfter(Version.V_8_0_0)) { aliasesVersion = in.readVLong(); } else { - aliasesVersion = 1; + aliasesVersion = 0; } state = State.fromId(in.readByte()); settings = Settings.readSettingsFromStream(in);