Skip to content

Commit 2cbe1b9

Browse files
committed
Snapshot/Restore: Make sure indices cannot be renamed into restored aliases
Fixes #7915
1 parent 384114f commit 2cbe1b9

File tree

2 files changed

+64
-6
lines changed

2 files changed

+64
-6
lines changed

src/main/java/org/elasticsearch/snapshots/RestoreService.java

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,12 @@
4646
import org.elasticsearch.transport.*;
4747

4848
import java.io.IOException;
49-
import java.util.ArrayList;
50-
import java.util.HashMap;
51-
import java.util.List;
52-
import java.util.Map;
49+
import java.util.*;
5350
import java.util.concurrent.CopyOnWriteArrayList;
5451

5552
import static com.google.common.collect.Lists.newArrayList;
5653
import static com.google.common.collect.Maps.newHashMap;
54+
import static com.google.common.collect.Sets.newHashSet;
5755
import static org.elasticsearch.cluster.metadata.MetaDataIndexStateService.INDEX_CLOSED_BLOCK;
5856

5957
/**
@@ -146,6 +144,7 @@ public ClusterState execute(ClusterState currentState) {
146144
ClusterBlocks.Builder blocks = ClusterBlocks.builder().blocks(currentState.blocks());
147145
RoutingTable.Builder rtBuilder = RoutingTable.builder(currentState.routingTable());
148146
final ImmutableMap<ShardId, RestoreMetaData.ShardRestoreStatus> shards;
147+
Set<String> aliases = newHashSet();
149148
if (!renamedIndices.isEmpty()) {
150149
// We have some indices to restore
151150
ImmutableMap.Builder<ShardId, RestoreMetaData.ShardRestoreStatus> shardsBuilder = ImmutableMap.builder();
@@ -166,6 +165,10 @@ public ClusterState execute(ClusterState currentState) {
166165
if (!request.includeAliases() && !snapshotIndexMetaData.aliases().isEmpty()) {
167166
// Remove all aliases - they shouldn't be restored
168167
indexMdBuilder.removeAllAliases();
168+
} else {
169+
for (ObjectCursor<String> alias : snapshotIndexMetaData.aliases().keys()) {
170+
aliases.add(alias.value);
171+
}
169172
}
170173
IndexMetaData updatedIndexMetaData = indexMdBuilder.build();
171174
if (partial) {
@@ -187,6 +190,10 @@ public ClusterState execute(ClusterState currentState) {
187190
for (ObjectCursor<AliasMetaData> alias : currentIndexMetaData.aliases().values()) {
188191
indexMdBuilder.putAlias(alias.value);
189192
}
193+
} else {
194+
for (ObjectCursor<String> alias : snapshotIndexMetaData.aliases().keys()) {
195+
aliases.add(alias.value);
196+
}
190197
}
191198
IndexMetaData updatedIndexMetaData = indexMdBuilder.index(renamedIndex).build();
192199
rtBuilder.addAsRestore(updatedIndexMetaData, restoreSource);
@@ -209,12 +216,14 @@ public ClusterState execute(ClusterState currentState) {
209216
shards = ImmutableMap.of();
210217
}
211218

219+
checkAliasNameConflicts(renamedIndices, aliases);
220+
212221
// Restore global state if needed
213222
restoreGlobalStateIfRequested(mdBuilder);
214223

215224
if (completed(shards)) {
216225
// We don't have any indices to restore - we are done
217-
restoreInfo = new RestoreInfo(request.name(), ImmutableList.<String>copyOf(renamedIndices.keySet()),
226+
restoreInfo = new RestoreInfo(request.name(), ImmutableList.copyOf(renamedIndices.keySet()),
218227
shards.size(), shards.size() - failedShards(shards));
219228
}
220229

@@ -223,6 +232,14 @@ public ClusterState execute(ClusterState currentState) {
223232
return ClusterState.builder(updatedState).routingResult(routingResult).build();
224233
}
225234

235+
private void checkAliasNameConflicts(Map<String, String> renamedIndices, Set<String> aliases) {
236+
for(Map.Entry<String, String> renamedIndex: renamedIndices.entrySet()) {
237+
if (aliases.contains(renamedIndex.getKey())) {
238+
throw new SnapshotRestoreException(snapshotId, "cannot rename index [" + renamedIndex.getValue() + "] into [" + renamedIndex.getKey() + "] because of conflict with an alias with the same name");
239+
}
240+
}
241+
}
242+
226243
private void populateIgnoredShards(String index, IntSet ignoreShards) {
227244
for (SnapshotShardFailure failure : snapshot.shardFailures()) {
228245
if (index.equals(failure.index())) {

src/test/java/org/elasticsearch/snapshots/SharedClusterSnapshotRestoreTests.java

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -776,9 +776,15 @@ public void renameOnRestoreTest() throws Exception {
776776
.setType("fs").setSettings(ImmutableSettings.settingsBuilder()
777777
.put("location", newTempDir(LifecycleScope.SUITE))));
778778

779-
createIndex("test-idx-1", "test-idx-2");
779+
createIndex("test-idx-1", "test-idx-2", "test-idx-3");
780780
ensureGreen();
781781

782+
assertAcked(client.admin().indices().prepareAliases()
783+
.addAlias("test-idx-1", "alias-1")
784+
.addAlias("test-idx-2", "alias-2")
785+
.addAlias("test-idx-3", "alias-3")
786+
);
787+
782788
logger.info("--> indexing some data");
783789
for (int i = 0; i < 100; i++) {
784790
index("test-idx-1", "doc", Integer.toString(i), "foo", "bar" + i);
@@ -823,6 +829,9 @@ public void renameOnRestoreTest() throws Exception {
823829
.setRenamePattern("(.+-2)").setRenameReplacement("$1-copy").setWaitForCompletion(true).execute().actionGet();
824830
assertThat(restoreSnapshotResponse.getRestoreInfo().totalShards(), greaterThan(0));
825831

832+
logger.info("--> delete indices");
833+
cluster().wipeIndices("test-idx-1", "test-idx-1-copy", "test-idx-2", "test-idx-2-copy");
834+
826835
logger.info("--> try renaming indices using the same name");
827836
try {
828837
client.admin().cluster().prepareRestoreSnapshot("test-repo", "test-snap").setRenamePattern("(.+)").setRenameReplacement("same-name").setWaitForCompletion(true).execute().actionGet();
@@ -846,6 +855,38 @@ public void renameOnRestoreTest() throws Exception {
846855
} catch (InvalidIndexNameException ex) {
847856
// Expected
848857
}
858+
859+
logger.info("--> try renaming indices into existing alias name");
860+
try {
861+
client.admin().cluster().prepareRestoreSnapshot("test-repo", "test-snap").setIndices("test-idx-1").setRenamePattern(".+").setRenameReplacement("alias-3").setWaitForCompletion(true).execute().actionGet();
862+
fail("Shouldn't be here");
863+
} catch (InvalidIndexNameException ex) {
864+
// Expected
865+
}
866+
867+
logger.info("--> try renaming indices into existing alias of itself");
868+
try {
869+
client.admin().cluster().prepareRestoreSnapshot("test-repo", "test-snap").setIndices("test-idx-1").setRenamePattern("test-idx").setRenameReplacement("alias").setWaitForCompletion(true).execute().actionGet();
870+
fail("Shouldn't be here");
871+
} catch (SnapshotRestoreException ex) {
872+
// Expected
873+
}
874+
875+
logger.info("--> try renaming indices into existing alias of another restored index");
876+
try {
877+
client.admin().cluster().prepareRestoreSnapshot("test-repo", "test-snap").setIndices("test-idx-1", "test-idx-2").setRenamePattern("test-idx-1").setRenameReplacement("alias-2").setWaitForCompletion(true).execute().actionGet();
878+
fail("Shouldn't be here");
879+
} catch (SnapshotRestoreException ex) {
880+
// Expected
881+
}
882+
883+
logger.info("--> try renaming indices into existing alias of itself, but don't restore aliases ");
884+
restoreSnapshotResponse = client.admin().cluster().prepareRestoreSnapshot("test-repo", "test-snap")
885+
.setIndices("test-idx-1").setRenamePattern("test-idx").setRenameReplacement("alias")
886+
.setWaitForCompletion(true).setIncludeAliases(false).execute().actionGet();
887+
assertThat(restoreSnapshotResponse.getRestoreInfo().totalShards(), greaterThan(0));
888+
889+
849890
}
850891

851892
@Test

0 commit comments

Comments
 (0)