CCR: Do not follow if leader does not have soft-deletes (#34767)
We should not create a follower index and abort a follow request if the leader does not have soft-deletes. Moreover, we also should not auto-follow an index if it does not have soft-deletes.
This commit is contained in:
parent
0a85997cb0
commit
d73768f812
|
@ -26,6 +26,7 @@ import org.elasticsearch.common.unit.TimeValue;
|
||||||
import org.elasticsearch.common.util.concurrent.AtomicArray;
|
import org.elasticsearch.common.util.concurrent.AtomicArray;
|
||||||
import org.elasticsearch.common.util.concurrent.CountDown;
|
import org.elasticsearch.common.util.concurrent.CountDown;
|
||||||
import org.elasticsearch.index.Index;
|
import org.elasticsearch.index.Index;
|
||||||
|
import org.elasticsearch.index.IndexSettings;
|
||||||
import org.elasticsearch.license.LicenseUtils;
|
import org.elasticsearch.license.LicenseUtils;
|
||||||
import org.elasticsearch.threadpool.ThreadPool;
|
import org.elasticsearch.threadpool.ThreadPool;
|
||||||
import org.elasticsearch.xpack.ccr.CcrLicenseChecker;
|
import org.elasticsearch.xpack.ccr.CcrLicenseChecker;
|
||||||
|
@ -370,7 +371,9 @@ public class AutoFollowCoordinator implements ClusterStateApplier {
|
||||||
// has a leader index uuid custom metadata entry that matches with uuid of leaderIndexMetaData variable
|
// has a leader index uuid custom metadata entry that matches with uuid of leaderIndexMetaData variable
|
||||||
// If so then handle it differently: not follow it, but just add an entry to
|
// If so then handle it differently: not follow it, but just add an entry to
|
||||||
// AutoFollowMetadata#followedLeaderIndexUUIDs
|
// AutoFollowMetadata#followedLeaderIndexUUIDs
|
||||||
leaderIndicesToFollow.add(leaderIndexMetaData.getIndex());
|
if (leaderIndexMetaData.getSettings().getAsBoolean(IndexSettings.INDEX_SOFT_DELETES_SETTING.getKey(), false)) {
|
||||||
|
leaderIndicesToFollow.add(leaderIndexMetaData.getIndex());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -125,6 +125,10 @@ public final class TransportPutFollowAction
|
||||||
listener.onFailure(new IllegalArgumentException("leader index [" + request.getLeaderIndex() + "] does not exist"));
|
listener.onFailure(new IllegalArgumentException("leader index [" + request.getLeaderIndex() + "] does not exist"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (leaderIndexMetaData.getSettings().getAsBoolean(IndexSettings.INDEX_SOFT_DELETES_SETTING.getKey(), false) == false) {
|
||||||
|
listener.onFailure(
|
||||||
|
new IllegalArgumentException("leader index [" + request.getLeaderIndex() + "] does not have soft deletes enabled"));
|
||||||
|
}
|
||||||
|
|
||||||
ActionListener<Boolean> handler = ActionListener.wrap(
|
ActionListener<Boolean> handler = ActionListener.wrap(
|
||||||
result -> {
|
result -> {
|
||||||
|
|
|
@ -67,6 +67,21 @@ public class LocalIndexFollowingIT extends CcrSingleNodeTestCase {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testDoNotCreateFollowerIfLeaderDoesNotHaveSoftDeletes() throws Exception {
|
||||||
|
final String leaderIndexSettings = getIndexSettings(2, 0,
|
||||||
|
singletonMap(IndexSettings.INDEX_SOFT_DELETES_SETTING.getKey(), "false"));
|
||||||
|
assertAcked(client().admin().indices().prepareCreate("leader-index").setSource(leaderIndexSettings, XContentType.JSON));
|
||||||
|
ResumeFollowAction.Request followRequest = getResumeFollowRequest();
|
||||||
|
followRequest.setFollowerIndex("follower-index");
|
||||||
|
PutFollowAction.Request putFollowRequest = getPutFollowRequest();
|
||||||
|
putFollowRequest.setLeaderIndex("leader-index");
|
||||||
|
putFollowRequest.setFollowRequest(followRequest);
|
||||||
|
IllegalArgumentException error = expectThrows(IllegalArgumentException.class,
|
||||||
|
() -> client().execute(PutFollowAction.INSTANCE, putFollowRequest).actionGet());
|
||||||
|
assertThat(error.getMessage(), equalTo("leader index [leader-index] does not have soft deletes enabled"));
|
||||||
|
assertThat(client().admin().indices().prepareExists("follower-index").get().isExists(), equalTo(false));
|
||||||
|
}
|
||||||
|
|
||||||
private String getIndexSettings(final int numberOfShards, final int numberOfReplicas,
|
private String getIndexSettings(final int numberOfShards, final int numberOfReplicas,
|
||||||
final Map<String, String> additionalIndexSettings) throws IOException {
|
final Map<String, String> additionalIndexSettings) throws IOException {
|
||||||
final String settings;
|
final String settings;
|
||||||
|
|
|
@ -15,6 +15,7 @@ import org.elasticsearch.cluster.service.ClusterService;
|
||||||
import org.elasticsearch.common.collect.Tuple;
|
import org.elasticsearch.common.collect.Tuple;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
import org.elasticsearch.common.settings.Settings;
|
||||||
import org.elasticsearch.index.Index;
|
import org.elasticsearch.index.Index;
|
||||||
|
import org.elasticsearch.index.IndexSettings;
|
||||||
import org.elasticsearch.test.ESTestCase;
|
import org.elasticsearch.test.ESTestCase;
|
||||||
import org.elasticsearch.xpack.ccr.CcrLicenseChecker;
|
import org.elasticsearch.xpack.ccr.CcrLicenseChecker;
|
||||||
import org.elasticsearch.xpack.ccr.action.AutoFollowCoordinator.AutoFollower;
|
import org.elasticsearch.xpack.ccr.action.AutoFollowCoordinator.AutoFollower;
|
||||||
|
@ -50,7 +51,7 @@ public class AutoFollowCoordinatorTests extends ESTestCase {
|
||||||
|
|
||||||
ClusterState leaderState = ClusterState.builder(new ClusterName("remote"))
|
ClusterState leaderState = ClusterState.builder(new ClusterName("remote"))
|
||||||
.metaData(MetaData.builder().put(IndexMetaData.builder("logs-20190101")
|
.metaData(MetaData.builder().put(IndexMetaData.builder("logs-20190101")
|
||||||
.settings(settings(Version.CURRENT))
|
.settings(settings(Version.CURRENT).put(IndexSettings.INDEX_SOFT_DELETES_SETTING.getKey(), true))
|
||||||
.numberOfShards(1)
|
.numberOfShards(1)
|
||||||
.numberOfReplicas(0)))
|
.numberOfReplicas(0)))
|
||||||
.build();
|
.build();
|
||||||
|
@ -172,7 +173,7 @@ public class AutoFollowCoordinatorTests extends ESTestCase {
|
||||||
|
|
||||||
ClusterState leaderState = ClusterState.builder(new ClusterName("remote"))
|
ClusterState leaderState = ClusterState.builder(new ClusterName("remote"))
|
||||||
.metaData(MetaData.builder().put(IndexMetaData.builder("logs-20190101")
|
.metaData(MetaData.builder().put(IndexMetaData.builder("logs-20190101")
|
||||||
.settings(settings(Version.CURRENT))
|
.settings(settings(Version.CURRENT).put(IndexSettings.INDEX_SOFT_DELETES_SETTING.getKey(), true))
|
||||||
.numberOfShards(1)
|
.numberOfShards(1)
|
||||||
.numberOfReplicas(0)))
|
.numberOfReplicas(0)))
|
||||||
.build();
|
.build();
|
||||||
|
@ -235,7 +236,7 @@ public class AutoFollowCoordinatorTests extends ESTestCase {
|
||||||
|
|
||||||
ClusterState leaderState = ClusterState.builder(new ClusterName("remote"))
|
ClusterState leaderState = ClusterState.builder(new ClusterName("remote"))
|
||||||
.metaData(MetaData.builder().put(IndexMetaData.builder("logs-20190101")
|
.metaData(MetaData.builder().put(IndexMetaData.builder("logs-20190101")
|
||||||
.settings(settings(Version.CURRENT))
|
.settings(settings(Version.CURRENT).put(IndexSettings.INDEX_SOFT_DELETES_SETTING.getKey(), true))
|
||||||
.numberOfShards(1)
|
.numberOfShards(1)
|
||||||
.numberOfReplicas(0)))
|
.numberOfReplicas(0)))
|
||||||
.build();
|
.build();
|
||||||
|
@ -306,7 +307,8 @@ public class AutoFollowCoordinatorTests extends ESTestCase {
|
||||||
for (int i = 0; i < 5; i++) {
|
for (int i = 0; i < 5; i++) {
|
||||||
Settings.Builder builder = Settings.builder()
|
Settings.Builder builder = Settings.builder()
|
||||||
.put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT)
|
.put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT)
|
||||||
.put(IndexMetaData.SETTING_INDEX_UUID, "metrics-" + i);
|
.put(IndexMetaData.SETTING_INDEX_UUID, "metrics-" + i)
|
||||||
|
.put(IndexSettings.INDEX_SOFT_DELETES_SETTING.getKey(), i % 2 == 0);
|
||||||
imdBuilder.put(IndexMetaData.builder("metrics-" + i)
|
imdBuilder.put(IndexMetaData.builder("metrics-" + i)
|
||||||
.settings(builder)
|
.settings(builder)
|
||||||
.numberOfShards(1)
|
.numberOfShards(1)
|
||||||
|
@ -324,21 +326,17 @@ public class AutoFollowCoordinatorTests extends ESTestCase {
|
||||||
List<Index> result = AutoFollower.getLeaderIndicesToFollow("remote", autoFollowPattern, leaderState, followerState,
|
List<Index> result = AutoFollower.getLeaderIndicesToFollow("remote", autoFollowPattern, leaderState, followerState,
|
||||||
Collections.emptyList());
|
Collections.emptyList());
|
||||||
result.sort(Comparator.comparing(Index::getName));
|
result.sort(Comparator.comparing(Index::getName));
|
||||||
assertThat(result.size(), equalTo(5));
|
assertThat(result.size(), equalTo(3));
|
||||||
assertThat(result.get(0).getName(), equalTo("metrics-0"));
|
assertThat(result.get(0).getName(), equalTo("metrics-0"));
|
||||||
assertThat(result.get(1).getName(), equalTo("metrics-1"));
|
assertThat(result.get(1).getName(), equalTo("metrics-2"));
|
||||||
assertThat(result.get(2).getName(), equalTo("metrics-2"));
|
assertThat(result.get(2).getName(), equalTo("metrics-4"));
|
||||||
assertThat(result.get(3).getName(), equalTo("metrics-3"));
|
|
||||||
assertThat(result.get(4).getName(), equalTo("metrics-4"));
|
|
||||||
|
|
||||||
List<String> followedIndexUUIDs = Collections.singletonList(leaderState.metaData().index("metrics-2").getIndexUUID());
|
List<String> followedIndexUUIDs = Collections.singletonList(leaderState.metaData().index("metrics-2").getIndexUUID());
|
||||||
result = AutoFollower.getLeaderIndicesToFollow("remote", autoFollowPattern, leaderState, followerState, followedIndexUUIDs);
|
result = AutoFollower.getLeaderIndicesToFollow("remote", autoFollowPattern, leaderState, followerState, followedIndexUUIDs);
|
||||||
result.sort(Comparator.comparing(Index::getName));
|
result.sort(Comparator.comparing(Index::getName));
|
||||||
assertThat(result.size(), equalTo(4));
|
assertThat(result.size(), equalTo(2));
|
||||||
assertThat(result.get(0).getName(), equalTo("metrics-0"));
|
assertThat(result.get(0).getName(), equalTo("metrics-0"));
|
||||||
assertThat(result.get(1).getName(), equalTo("metrics-1"));
|
assertThat(result.get(1).getName(), equalTo("metrics-4"));
|
||||||
assertThat(result.get(2).getName(), equalTo("metrics-3"));
|
|
||||||
assertThat(result.get(3).getName(), equalTo("metrics-4"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testGetFollowerIndexName() {
|
public void testGetFollowerIndexName() {
|
||||||
|
|
Loading…
Reference in New Issue