diff --git a/.gitignore b/.gitignore
index 2151e666ea209..03e2446ec4f13 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,7 +12,7 @@ out/
!.idea/eclipseCodeFormatter.xml
!.idea/externalDependencies.xml
!.idea/inspectionProfiles/Project_Default.xml
-!.idea/runConfigurations/Debug_Elasticsearch.xml
+!.idea/runConfigurations/
!.idea/scopes/x_pack.xml
# These files are generated in the main tree by IntelliJ
diff --git a/.idea/runConfigurations/Debug_Elasticsearch__node_2_.xml b/.idea/runConfigurations/Debug_Elasticsearch__node_2_.xml
new file mode 100644
index 0000000000000..94bb079398ffd
--- /dev/null
+++ b/.idea/runConfigurations/Debug_Elasticsearch__node_2_.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations/Debug_Elasticsearch__node_3_.xml b/.idea/runConfigurations/Debug_Elasticsearch__node_3_.xml
new file mode 100644
index 0000000000000..aaef20fec729b
--- /dev/null
+++ b/.idea/runConfigurations/Debug_Elasticsearch__node_3_.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/TESTING.asciidoc b/TESTING.asciidoc
index 186ac155000d5..f574633a90eca 100644
--- a/TESTING.asciidoc
+++ b/TESTING.asciidoc
@@ -392,7 +392,8 @@ port of `5007`.
NOTE: In the case of test clusters using multiple nodes, multiple debuggers
will need to be attached on incrementing ports. For example, for a 3 node
cluster ports `5007`, `5008`, and `5009` will attempt to attach to a listening
-debugger.
+debugger. You can use the "Debug Elasticsearch (node 2)" and "(node 3)" run
+configurations should you need to debug a multi-node cluster.
You can also use a combination of both flags to debug both tests and server.
This is only applicable to Java REST tests.
diff --git a/build-tools-internal/src/main/groovy/elasticsearch.runtime-jdk-provision.gradle b/build-tools-internal/src/main/groovy/elasticsearch.runtime-jdk-provision.gradle
index 5b87a40ffb211..4a35fd9d447da 100644
--- a/build-tools-internal/src/main/groovy/elasticsearch.runtime-jdk-provision.gradle
+++ b/build-tools-internal/src/main/groovy/elasticsearch.runtime-jdk-provision.gradle
@@ -61,6 +61,7 @@ configure(allprojects) {
project.getTasks().withType(ThirdPartyAuditTask.class).configureEach {
if (BuildParams.getIsRuntimeJavaHomeSet() == false) {
javaHome.set(providers.provider(() -> "${project.jdks.provisioned_runtime.javaHomePath}"))
+ targetCompatibility.set(providers.provider(() -> JavaVersion.toVersion(project.jdks.provisioned_runtime.major)))
}
}
}
diff --git a/docs/changelog/94000.yaml b/docs/changelog/94000.yaml
new file mode 100644
index 0000000000000..debbf2fd205c7
--- /dev/null
+++ b/docs/changelog/94000.yaml
@@ -0,0 +1,6 @@
+pr: 94000
+summary: Introduce redirect method on IngestDocument
+area: Ingest Node
+type: enhancement
+issues:
+ - 83653
diff --git a/modules/dlm/src/internalClusterTest/java/org/elasticsearch/dlm/DataLifecycleServiceIT.java b/modules/dlm/src/internalClusterTest/java/org/elasticsearch/dlm/DataLifecycleServiceIT.java
index d42679ddb13e9..c9cd33c5a2b62 100644
--- a/modules/dlm/src/internalClusterTest/java/org/elasticsearch/dlm/DataLifecycleServiceIT.java
+++ b/modules/dlm/src/internalClusterTest/java/org/elasticsearch/dlm/DataLifecycleServiceIT.java
@@ -9,7 +9,6 @@
import org.elasticsearch.action.DocWriteRequest;
import org.elasticsearch.action.admin.indices.refresh.RefreshRequest;
-import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsRequest;
import org.elasticsearch.action.admin.indices.template.put.PutComposableIndexTemplateAction;
import org.elasticsearch.action.bulk.BulkItemResponse;
import org.elasticsearch.action.bulk.BulkRequest;
@@ -240,11 +239,8 @@ public void testErrorRecordingOnRetention() throws Exception {
String firstGenerationIndex = DataStream.getDefaultBackingIndexName(dataStreamName, 1L);
// mark the first generation index as read-only so deletion fails when we enable the retention configuration
- UpdateSettingsRequest updateSettingsRequest = new UpdateSettingsRequest(firstGenerationIndex);
- updateSettingsRequest.settings(Settings.builder().put(READ_ONLY.settingName(), true));
+ updateIndexSettings(Settings.builder().put(READ_ONLY.settingName(), true), firstGenerationIndex);
try {
- client().admin().indices().updateSettings(updateSettingsRequest);
-
// TODO replace this with an API call to update the lifecycle for the data stream once available
PlainActionFuture.get(
fut -> internalCluster().getCurrentMasterNodeInstance(ClusterService.class)
diff --git a/modules/dlm/src/main/java/org/elasticsearch/dlm/DataLifecycleErrorStore.java b/modules/dlm/src/main/java/org/elasticsearch/dlm/DataLifecycleErrorStore.java
index 27a8c5ed5943a..4b1febc67ca41 100644
--- a/modules/dlm/src/main/java/org/elasticsearch/dlm/DataLifecycleErrorStore.java
+++ b/modules/dlm/src/main/java/org/elasticsearch/dlm/DataLifecycleErrorStore.java
@@ -11,6 +11,7 @@
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.core.Nullable;
+import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@@ -23,38 +24,45 @@
*/
public class DataLifecycleErrorStore {
- private final ConcurrentMap targetToError = new ConcurrentHashMap<>();
+ private final ConcurrentMap indexNameToError = new ConcurrentHashMap<>();
/**
- * Records a string representation of the provided exception for the provided target.
- * If an error was already recorded for the provided target this will override that error.
+ * Records a string representation of the provided exception for the provided index.
+ * If an error was already recorded for the provided index this will override that error.
*/
- public void recordError(String target, Exception e) {
- targetToError.put(target, org.elasticsearch.common.Strings.toString(((builder, params) -> {
+ public void recordError(String indexName, Exception e) {
+ indexNameToError.put(indexName, org.elasticsearch.common.Strings.toString(((builder, params) -> {
ElasticsearchException.generateThrowableXContent(builder, EMPTY_PARAMS, e);
return builder;
})));
}
/**
- * Clears the recorded error for the provided target (if any exists)
+ * Clears the recorded error for the provided index (if any exists)
*/
- public void clearRecordedError(String target) {
- targetToError.remove(target);
+ public void clearRecordedError(String indexName) {
+ indexNameToError.remove(indexName);
}
/**
* Clears all the errors recorded in the store.
*/
public void clearStore() {
- targetToError.clear();
+ indexNameToError.clear();
}
/**
- * Retrieves the recorderd error for the provided target.
+ * Retrieves the recorderd error for the provided index.
*/
@Nullable
- public String getError(String target) {
- return targetToError.get(target);
+ public String getError(String indexName) {
+ return indexNameToError.get(indexName);
+ }
+
+ /**
+ * Return an immutable view (a snapshot) of the tracked indices at the moment this method is called.
+ */
+ public List getAllIndices() {
+ return List.copyOf(indexNameToError.keySet());
}
}
diff --git a/modules/dlm/src/main/java/org/elasticsearch/dlm/DataLifecycleService.java b/modules/dlm/src/main/java/org/elasticsearch/dlm/DataLifecycleService.java
index 0259d1e0f605c..3d52e53e4ece5 100644
--- a/modules/dlm/src/main/java/org/elasticsearch/dlm/DataLifecycleService.java
+++ b/modules/dlm/src/main/java/org/elasticsearch/dlm/DataLifecycleService.java
@@ -47,8 +47,6 @@
import java.util.List;
import java.util.Locale;
import java.util.Map;
-import java.util.function.BiConsumer;
-import java.util.function.Consumer;
import java.util.function.LongSupplier;
/**
@@ -136,13 +134,6 @@ public void clusterChanged(ClusterChangedEvent event) {
errorStore.clearStore();
}
}
- if (event.localNodeMaster()) {
- // only execute if we're the master
- List indicesDeleted = event.indicesDeleted();
- for (Index deleted : indicesDeleted) {
- errorStore.clearRecordedError(deleted.getName());
- }
- }
}
@Override
@@ -210,9 +201,12 @@ void run(ClusterState state) {
*/
private void clearErrorStoreForUnmanagedIndices(DataStream dataStream) {
Metadata metadata = clusterService.state().metadata();
- for (Index index : dataStream.getIndices()) {
- if (dataStream.isIndexManagedByDLM(index, metadata::index) == false) {
- errorStore.clearRecordedError(index.getName());
+ for (String indexName : errorStore.getAllIndices()) {
+ IndexMetadata indexMeta = metadata.index(indexName);
+ if (indexMeta == null) {
+ errorStore.clearRecordedError(indexName);
+ } else if (dataStream.isIndexManagedByDLM(indexMeta.getIndex(), metadata::index) == false) {
+ errorStore.clearRecordedError(indexName);
}
}
}
@@ -223,7 +217,7 @@ private void maybeExecuteRollover(ClusterState state, DataStream dataStream) {
RolloverRequest rolloverRequest = getDefaultRolloverRequest(dataStream.getName());
transportActionsDeduplicator.executeOnce(
rolloverRequest,
- new ErrorRecordingActionListener(writeIndex.getName(), errorStore::recordError, errorStore::clearRecordedError),
+ new ErrorRecordingActionListener(writeIndex.getName(), errorStore),
(req, reqListener) -> rolloverDataStream(writeIndex.getName(), rolloverRequest, reqListener)
);
}
@@ -247,7 +241,7 @@ private void maybeExecuteRetention(ClusterState state, DataStream dataStream) {
// time to delete the index
transportActionsDeduplicator.executeOnce(
deleteRequest,
- new ErrorRecordingActionListener(indexName, errorStore::recordError, errorStore::clearRecordedError),
+ new ErrorRecordingActionListener(indexName, errorStore),
(req, reqListener) -> deleteIndex(deleteRequest, retention, reqListener)
);
}
@@ -348,23 +342,21 @@ static TimeValue getRetentionConfiguration(DataStream dataStream) {
*/
static class ErrorRecordingActionListener implements ActionListener {
private final String targetIndex;
- private final BiConsumer recordError;
- private final Consumer clearErrorRecord;
+ private final DataLifecycleErrorStore errorStore;
- ErrorRecordingActionListener(String targetIndex, BiConsumer recordError, Consumer clearErrorRecord) {
+ ErrorRecordingActionListener(String targetIndex, DataLifecycleErrorStore errorStore) {
this.targetIndex = targetIndex;
- this.recordError = recordError;
- this.clearErrorRecord = clearErrorRecord;
+ this.errorStore = errorStore;
}
@Override
public void onResponse(Void unused) {
- clearErrorRecord.accept(targetIndex);
+ errorStore.clearRecordedError(targetIndex);
}
@Override
public void onFailure(Exception e) {
- recordError.accept(targetIndex, e);
+ errorStore.recordError(targetIndex, e);
}
}
diff --git a/modules/dlm/src/test/java/org/elasticsearch/dlm/DataLifecycleErrorStoreTests.java b/modules/dlm/src/test/java/org/elasticsearch/dlm/DataLifecycleErrorStoreTests.java
index be4b94d736b45..570a266603bfb 100644
--- a/modules/dlm/src/test/java/org/elasticsearch/dlm/DataLifecycleErrorStoreTests.java
+++ b/modules/dlm/src/test/java/org/elasticsearch/dlm/DataLifecycleErrorStoreTests.java
@@ -11,6 +11,10 @@
import org.elasticsearch.test.ESTestCase;
import org.junit.Before;
+import java.util.List;
+import java.util.stream.Stream;
+
+import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
@@ -27,6 +31,8 @@ public void setupServices() {
public void testRecordAndRetrieveError() {
errorStore.recordError("test", new NullPointerException("testing"));
assertThat(errorStore.getError("test"), is(notNullValue()));
+ assertThat(errorStore.getAllIndices().size(), is(1));
+ assertThat(errorStore.getAllIndices().get(0), is("test"));
}
public void testRetrieveAfterClear() {
@@ -34,4 +40,32 @@ public void testRetrieveAfterClear() {
errorStore.clearStore();
assertThat(errorStore.getError("test"), is(nullValue()));
}
+
+ public void testGetAllIndicesIsASnapshotViewOfTheStore() {
+ Stream.iterate(0, i -> i + 1).limit(5).forEach(i -> errorStore.recordError("test" + i, new NullPointerException("testing")));
+ List initialAllIndices = errorStore.getAllIndices();
+ assertThat(initialAllIndices.size(), is(5));
+ assertThat(
+ initialAllIndices,
+ containsInAnyOrder(Stream.iterate(0, i -> i + 1).limit(5).map(i -> "test" + i).toArray(String[]::new))
+ );
+
+ // let's add some more items to the store and clear a couple of the initial ones
+ Stream.iterate(5, i -> i + 1).limit(5).forEach(i -> errorStore.recordError("test" + i, new NullPointerException("testing")));
+ errorStore.clearRecordedError("test0");
+ errorStore.clearRecordedError("test1");
+ // the initial list should remain unchanged
+ assertThat(initialAllIndices.size(), is(5));
+ assertThat(
+ initialAllIndices,
+ containsInAnyOrder(Stream.iterate(0, i -> i + 1).limit(5).map(i -> "test" + i).toArray(String[]::new))
+ );
+
+ // calling getAllIndices again should reflect the latest state
+ assertThat(errorStore.getAllIndices().size(), is(8));
+ assertThat(
+ errorStore.getAllIndices(),
+ containsInAnyOrder(Stream.iterate(2, i -> i + 1).limit(8).map(i -> "test" + i).toArray(String[]::new))
+ );
+ }
}
diff --git a/modules/dlm/src/test/java/org/elasticsearch/dlm/DataLifecycleServiceTests.java b/modules/dlm/src/test/java/org/elasticsearch/dlm/DataLifecycleServiceTests.java
index 2679d514acccd..5f92e8c8e6eb7 100644
--- a/modules/dlm/src/test/java/org/elasticsearch/dlm/DataLifecycleServiceTests.java
+++ b/modules/dlm/src/test/java/org/elasticsearch/dlm/DataLifecycleServiceTests.java
@@ -17,7 +17,6 @@
import org.elasticsearch.action.admin.indices.rollover.MaxAgeCondition;
import org.elasticsearch.action.admin.indices.rollover.RolloverInfo;
import org.elasticsearch.action.admin.indices.rollover.RolloverRequest;
-import org.elasticsearch.cluster.ClusterChangedEvent;
import org.elasticsearch.cluster.ClusterName;
import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.metadata.DataLifecycle;
@@ -36,7 +35,6 @@
import org.elasticsearch.core.Nullable;
import org.elasticsearch.core.TimeValue;
import org.elasticsearch.index.Index;
-import org.elasticsearch.test.ClusterServiceUtils;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.test.client.NoOpClient;
import org.elasticsearch.threadpool.TestThreadPool;
@@ -58,6 +56,8 @@
import java.util.concurrent.CopyOnWriteArrayList;
import static org.elasticsearch.cluster.metadata.DataStreamTestHelper.newInstance;
+import static org.elasticsearch.test.ClusterServiceUtils.createClusterService;
+import static org.elasticsearch.test.ClusterServiceUtils.setState;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
@@ -70,6 +70,7 @@ public class DataLifecycleServiceTests extends ESTestCase {
private DataLifecycleService dataLifecycleService;
private List clientSeenRequests;
private NoOpClient client;
+ private ClusterService clusterService;
@Before
public void setupServices() {
@@ -77,7 +78,7 @@ public void setupServices() {
Set> builtInClusterSettings = new HashSet<>(ClusterSettings.BUILT_IN_CLUSTER_SETTINGS);
builtInClusterSettings.add(DataLifecycleService.DLM_POLL_INTERVAL_SETTING);
ClusterSettings clusterSettings = new ClusterSettings(Settings.EMPTY, builtInClusterSettings);
- ClusterService clusterService = ClusterServiceUtils.createClusterService(threadPool, clusterSettings);
+ clusterService = createClusterService(threadPool, clusterSettings);
now = System.currentTimeMillis();
Clock clock = Clock.fixed(Instant.ofEpochMilli(now), ZoneId.of(randomFrom(ZoneId.getAvailableZoneIds())));
@@ -100,6 +101,7 @@ public void setupServices() {
public void cleanup() {
clientSeenRequests.clear();
dataLifecycleService.close();
+ clusterService.close();
threadPool.shutdownNow();
client.close();
}
@@ -218,8 +220,8 @@ public void testDeletedIndicesAreRemovedFromTheErrorStore() throws IOException {
builder,
dataStreamName,
numBackingIndices,
- Settings.builder().put(IndexMetadata.LIFECYCLE_NAME, "ILM_policy").put(IndexMetadata.SETTING_VERSION_CREATED, Version.CURRENT),
- null
+ Settings.builder().put(IndexMetadata.SETTING_VERSION_CREATED, Version.CURRENT),
+ new DataLifecycle()
);
builder.put(dataStream);
String nodeId = "localNode";
@@ -247,9 +249,9 @@ public void testDeletedIndicesAreRemovedFromTheErrorStore() throws IOException {
}
newStateBuilder.metadata(metaBuilder);
ClusterState stateWithDeletedIndices = newStateBuilder.nodes(buildNodes(nodeId).masterNodeId(nodeId)).build();
- ClusterChangedEvent event = new ClusterChangedEvent("_na_", stateWithDeletedIndices, previousState);
+ setState(clusterService, stateWithDeletedIndices);
- dataLifecycleService.clusterChanged(event);
+ dataLifecycleService.run(stateWithDeletedIndices);
for (Index deletedIndex : deletedIndices) {
assertThat(dataLifecycleService.getErrorStore().getError(deletedIndex.getName()), nullValue());
@@ -258,54 +260,6 @@ public void testDeletedIndicesAreRemovedFromTheErrorStore() throws IOException {
assertThat(dataLifecycleService.getErrorStore().getError(dataStream.getWriteIndex().getName()), notNullValue());
}
- public void testErrorStoreIsNotUpdatedIfWeAreNotMaster() {
- String dataStreamName = randomAlphaOfLength(10).toLowerCase(Locale.ROOT);
- int numBackingIndices = 3;
- Metadata.Builder builder = Metadata.builder();
- DataStream dataStream = createDataStream(
- builder,
- dataStreamName,
- numBackingIndices,
- Settings.builder().put(IndexMetadata.LIFECYCLE_NAME, "ILM_policy").put(IndexMetadata.SETTING_VERSION_CREATED, Version.CURRENT),
- null
- );
- builder.put(dataStream);
- String localNode = "localNode";
- String masterNodeId = "some_other_node";
- DiscoveryNodes.Builder nodesBuilder = buildNodes(localNode).add(getNode(masterNodeId)).masterNodeId(masterNodeId);
- ClusterState previousState = ClusterState.builder(ClusterName.DEFAULT).metadata(builder).nodes(nodesBuilder).build();
-
- // all backing indices are in the error store
- for (Index index : dataStream.getIndices()) {
- dataLifecycleService.getErrorStore().recordError(index.getName(), new NullPointerException("bad"));
- }
- Index writeIndex = dataStream.getWriteIndex();
- // all indices but the write index are deleted
- List deletedIndices = dataStream.getIndices().stream().filter(index -> index.equals(writeIndex) == false).toList();
-
- ClusterState.Builder newStateBuilder = ClusterState.builder(previousState);
- newStateBuilder.stateUUID(UUIDs.randomBase64UUID());
- Metadata.Builder metaBuilder = Metadata.builder(previousState.metadata());
- for (Index index : deletedIndices) {
- metaBuilder.remove(index.getName());
- IndexGraveyard.Builder graveyardBuilder = IndexGraveyard.builder(metaBuilder.indexGraveyard());
- graveyardBuilder.addTombstone(index);
- metaBuilder.indexGraveyard(graveyardBuilder.build());
- }
- newStateBuilder.metadata(metaBuilder);
- ClusterState stateWithDeletedIndices = newStateBuilder.nodes(
- buildNodes(localNode).add(getNode(masterNodeId)).masterNodeId(masterNodeId)
- ).build();
- ClusterChangedEvent event = new ClusterChangedEvent("_na_", stateWithDeletedIndices, previousState);
-
- dataLifecycleService.clusterChanged(event);
-
- for (Index index : dataStream.getIndices()) {
- // all the errors shoudl still be in the error store as the node where DLM runs is not the master node
- assertThat(dataLifecycleService.getErrorStore().getError(index.getName()), notNullValue());
- }
- }
-
public void testErrorStoreIsClearedOnBackingIndexBecomingUnmanaged() {
String dataStreamName = randomAlphaOfLength(10).toLowerCase(Locale.ROOT);
int numBackingIndices = 3;
diff --git a/modules/ingest-common/src/yamlRestTest/resources/rest-api-spec/test/ingest/230_change_target_index.yml b/modules/ingest-common/src/yamlRestTest/resources/rest-api-spec/test/ingest/230_change_target_index.yml
index 6a6e8f071024b..d9154174379bd 100644
--- a/modules/ingest-common/src/yamlRestTest/resources/rest-api-spec/test/ingest/230_change_target_index.yml
+++ b/modules/ingest-common/src/yamlRestTest/resources/rest-api-spec/test/ingest/230_change_target_index.yml
@@ -87,11 +87,7 @@ teardown:
index: foo
id: "1"
- match: { _source.a: true }
-# The next is commented out because there's a bug where the final_pipeline is executed twice under certain circumstances
-# (See issue https://github.com/elastic/elasticsearch/issues/83653).
-# TODO: Uncomment after the issue is fixed, and remove the repeated value test of the current behavior
-#- match: { _source.accumulator: [ "non-repeated-value" ] }
-- match: { _source.accumulator: [ "non-repeated-value", "non-repeated-value" ] }
+- match: { _source.accumulator: [ "non-repeated-value" ] }
# only the foo index
- do:
@@ -150,11 +146,7 @@ teardown:
index: foo
id: "1"
- match: { _source.a: true }
-# The next is commented out because there's a bug where the final_pipeline is executed twice under certain circumstances
-# (See issue https://github.com/elastic/elasticsearch/issues/83653).
-# TODO: Uncomment after the issue is fixed, and remove the repeated value test of the current behavior
-#- match: { _source.accumulator: [ "non-repeated-value" ] }
-- match: { _source.accumulator: [ "non-repeated-value", "non-repeated-value" ] }
+- match: { _source.accumulator: [ "non-repeated-value" ] }
# only the foo index
- do:
diff --git a/qa/ccs-common-rest/src/yamlRestTest/java/org/elasticsearch/test/rest/yaml/RcsCcsCommonYamlTestSuiteIT.java b/qa/ccs-common-rest/src/yamlRestTest/java/org/elasticsearch/test/rest/yaml/RcsCcsCommonYamlTestSuiteIT.java
index 2a191223b42fb..6b681d5ef1143 100644
--- a/qa/ccs-common-rest/src/yamlRestTest/java/org/elasticsearch/test/rest/yaml/RcsCcsCommonYamlTestSuiteIT.java
+++ b/qa/ccs-common-rest/src/yamlRestTest/java/org/elasticsearch/test/rest/yaml/RcsCcsCommonYamlTestSuiteIT.java
@@ -17,8 +17,10 @@
import org.apache.lucene.tests.util.TimeUnits;
import org.elasticsearch.Version;
import org.elasticsearch.client.Request;
+import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.Response;
import org.elasticsearch.client.RestClient;
+import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.settings.SecureString;
import org.elasticsearch.common.settings.Settings;
@@ -38,9 +40,11 @@
import org.junit.rules.TestRule;
import java.io.IOException;
+import java.io.UncheckedIOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.atomic.AtomicReference;
import static java.util.Collections.unmodifiableList;
import static org.elasticsearch.test.rest.yaml.CcsCommonYamlTestSuiteIT.CCS_APIS;
@@ -65,6 +69,7 @@ public class RcsCcsCommonYamlTestSuiteIT extends ESClientYamlSuiteTestCase {
private static TestCandidateAwareClient searchYamlTestClient;
// the remote cluster is the one we write index operations etc... to
private static final String REMOTE_CLUSTER_NAME = "remote_cluster";
+ private static final AtomicReference