Allow reindexing into write alias (#41677)
Fixes an issue where reindex currently fails if the destination is an alias pointing to multiple indices, even it is using a write index. Closes #41667
This commit is contained in:
parent
5b71baa100
commit
785ae09101
|
@ -186,7 +186,7 @@ public class TransportReindexAction extends HandledTransportAction<ReindexReques
|
||||||
* it. This is the same sort of dance that TransportIndexRequest
|
* it. This is the same sort of dance that TransportIndexRequest
|
||||||
* uses to decide to autocreate the index.
|
* uses to decide to autocreate the index.
|
||||||
*/
|
*/
|
||||||
target = indexNameExpressionResolver.concreteIndexNames(clusterState, destination)[0];
|
target = indexNameExpressionResolver.concreteWriteIndex(clusterState, destination).getName();
|
||||||
}
|
}
|
||||||
for (String sourceIndex : indexNameExpressionResolver.concreteIndexNames(clusterState, source)) {
|
for (String sourceIndex : indexNameExpressionResolver.concreteIndexNames(clusterState, source)) {
|
||||||
if (sourceIndex.equals(target)) {
|
if (sourceIndex.equals(target)) {
|
||||||
|
|
|
@ -30,6 +30,7 @@ import org.elasticsearch.cluster.metadata.AliasMetaData;
|
||||||
import org.elasticsearch.cluster.metadata.IndexMetaData;
|
import org.elasticsearch.cluster.metadata.IndexMetaData;
|
||||||
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
|
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
|
||||||
import org.elasticsearch.cluster.metadata.MetaData;
|
import org.elasticsearch.cluster.metadata.MetaData;
|
||||||
|
import org.elasticsearch.common.Nullable;
|
||||||
import org.elasticsearch.common.bytes.BytesArray;
|
import org.elasticsearch.common.bytes.BytesArray;
|
||||||
import org.elasticsearch.common.settings.ClusterSettings;
|
import org.elasticsearch.common.settings.ClusterSettings;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
import org.elasticsearch.common.settings.Settings;
|
||||||
|
@ -48,6 +49,9 @@ public class ReindexSourceTargetValidationTests extends ESTestCase {
|
||||||
private static final ClusterState STATE = ClusterState.builder(new ClusterName("test")).metaData(MetaData.builder()
|
private static final ClusterState STATE = ClusterState.builder(new ClusterName("test")).metaData(MetaData.builder()
|
||||||
.put(index("target", "target_alias", "target_multi"), true)
|
.put(index("target", "target_alias", "target_multi"), true)
|
||||||
.put(index("target2", "target_multi"), true)
|
.put(index("target2", "target_multi"), true)
|
||||||
|
.put(index("target_with_write_index", true, "target_multi_with_write_index"), true)
|
||||||
|
.put(index("target2_without_write_index", "target_multi_with_write_index"), true)
|
||||||
|
.put(index("qux", false, "target_alias_with_write_index_disabled"), true)
|
||||||
.put(index("foo"), true)
|
.put(index("foo"), true)
|
||||||
.put(index("bar"), true)
|
.put(index("bar"), true)
|
||||||
.put(index("baz"), true)
|
.put(index("baz"), true)
|
||||||
|
@ -78,12 +82,26 @@ public class ReindexSourceTargetValidationTests extends ESTestCase {
|
||||||
succeeds("target", "source", "source2", "source_multi");
|
succeeds("target", "source", "source2", "source_multi");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testTargetIsAlias() {
|
public void testTargetIsAliasToMultipleIndicesWithoutWriteAlias() {
|
||||||
Exception e = expectThrows(IllegalArgumentException.class, () -> succeeds("target_multi", "foo"));
|
Exception e = expectThrows(IllegalArgumentException.class, () -> succeeds("target_multi", "foo"));
|
||||||
assertThat(e.getMessage(), containsString("Alias [target_multi] has more than one indices associated with it [["));
|
assertThat(e.getMessage(), containsString("no write index is defined for alias [target_multi]. The write index may be explicitly " +
|
||||||
// The index names can come in either order
|
"disabled using is_write_index=false or the alias points to multiple indices without one being designated as a " +
|
||||||
assertThat(e.getMessage(), containsString("target"));
|
"write index"));
|
||||||
assertThat(e.getMessage(), containsString("target2"));
|
}
|
||||||
|
|
||||||
|
public void testTargetIsAliasWithWriteIndexDisabled() {
|
||||||
|
Exception e = expectThrows(IllegalArgumentException.class, () -> succeeds("target_alias_with_write_index_disabled", "foo"));
|
||||||
|
assertThat(e.getMessage(), containsString("no write index is defined for alias [target_alias_with_write_index_disabled]. " +
|
||||||
|
"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"));
|
||||||
|
succeeds("qux", "foo"); // writing directly into the index of which this is the alias works though
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testTargetIsWriteAlias() {
|
||||||
|
succeeds("target_multi_with_write_index", "foo");
|
||||||
|
succeeds("target_multi_with_write_index", "target2_without_write_index");
|
||||||
|
fails("target_multi_with_write_index", "target_multi_with_write_index");
|
||||||
|
fails("target_multi_with_write_index", "target_with_write_index");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testRemoteInfoSkipsValidation() {
|
public void testRemoteInfoSkipsValidation() {
|
||||||
|
@ -97,7 +115,7 @@ public class ReindexSourceTargetValidationTests extends ESTestCase {
|
||||||
|
|
||||||
private void fails(String target, String... sources) {
|
private void fails(String target, String... sources) {
|
||||||
Exception e = expectThrows(ActionRequestValidationException.class, () -> succeeds(target, sources));
|
Exception e = expectThrows(ActionRequestValidationException.class, () -> succeeds(target, sources));
|
||||||
assertThat(e.getMessage(), containsString("reindex cannot write into an index its reading from [target]"));
|
assertThat(e.getMessage(), containsString("reindex cannot write into an index its reading from"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void succeeds(String target, String... sources) {
|
private void succeeds(String target, String... sources) {
|
||||||
|
@ -110,12 +128,16 @@ public class ReindexSourceTargetValidationTests extends ESTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IndexMetaData index(String name, String... aliases) {
|
private static IndexMetaData index(String name, String... aliases) {
|
||||||
|
return index(name, null, aliases);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IndexMetaData index(String name, @Nullable Boolean writeIndex, String... aliases) {
|
||||||
IndexMetaData.Builder builder = IndexMetaData.builder(name).settings(Settings.builder()
|
IndexMetaData.Builder builder = IndexMetaData.builder(name).settings(Settings.builder()
|
||||||
.put("index.version.created", Version.CURRENT.id)
|
.put("index.version.created", Version.CURRENT.id)
|
||||||
.put("index.number_of_shards", 1)
|
.put("index.number_of_shards", 1)
|
||||||
.put("index.number_of_replicas", 1));
|
.put("index.number_of_replicas", 1));
|
||||||
for (String alias: aliases) {
|
for (String alias: aliases) {
|
||||||
builder.putAlias(AliasMetaData.builder(alias).build());
|
builder.putAlias(AliasMetaData.builder(alias).writeIndex(writeIndex).build());
|
||||||
}
|
}
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue