From cb343c16877be9cb198057e40ddea7cf51f141b8 Mon Sep 17 00:00:00 2001 From: Johannes Freden Jansson Date: Thu, 9 Oct 2025 10:14:01 +0200 Subject: [PATCH 1/3] Remove ES version dependency in bwc tests --- .../upgrades/AbstractUpgradeTestCase.java | 117 +++++++++++++----- .../ApiKeyBackwardsCompatibilityIT.java | 38 +++--- .../QueryableBuiltInRolesUpgradeIT.java | 76 +----------- .../RolesBackwardsCompatibilityIT.java | 15 +-- 4 files changed, 112 insertions(+), 134 deletions(-) diff --git a/x-pack/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/AbstractUpgradeTestCase.java b/x-pack/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/AbstractUpgradeTestCase.java index d86a61a6f6ac9..75e0cb738f576 100644 --- a/x-pack/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/AbstractUpgradeTestCase.java +++ b/x-pack/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/AbstractUpgradeTestCase.java @@ -7,7 +7,9 @@ package org.elasticsearch.upgrades; import org.apache.http.HttpHost; +import org.apache.http.client.methods.HttpGet; import org.elasticsearch.Build; +import org.elasticsearch.TransportVersion; import org.elasticsearch.client.Request; import org.elasticsearch.client.Response; import org.elasticsearch.client.RestClient; @@ -16,6 +18,7 @@ import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.util.concurrent.ThreadContext; import org.elasticsearch.core.Booleans; +import org.elasticsearch.rest.RestStatus; import org.elasticsearch.test.XContentTestUtils; import org.elasticsearch.test.rest.ESRestTestCase; import org.elasticsearch.test.rest.ObjectPath; @@ -23,15 +26,17 @@ import org.junit.Before; import java.io.IOException; -import java.util.ArrayList; import java.util.Collection; import java.util.Collections; -import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.function.Function; +import java.util.Set; +import java.util.function.Predicate; import java.util.stream.Collectors; +import static org.elasticsearch.common.xcontent.support.XContentMapValues.extractValue; +import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.notNullValue; public abstract class AbstractUpgradeTestCase extends ESRestTestCase { @@ -194,43 +199,93 @@ protected void closeClientsByVersion() throws IOException { } @SuppressWarnings("unchecked") - protected Map getRestClientByCapability(Function, Boolean> capabilityChecker) - throws IOException { + protected Map getRestClientById() throws IOException { Response response = client().performRequest(new Request("GET", "_nodes")); assertOK(response); ObjectPath objectPath = ObjectPath.createFromResponse(response); Map nodesAsMap = objectPath.evaluate("nodes"); - Map> hostsByCapability = new HashMap<>(); - - for (Map.Entry entry : nodesAsMap.entrySet()) { - Map nodeDetails = (Map) entry.getValue(); - var capabilitySupported = capabilityChecker.apply(nodeDetails); + return nodesAsMap.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> { + Map nodeDetails = (Map) e.getValue(); Map httpInfo = (Map) nodeDetails.get("http"); - hostsByCapability.computeIfAbsent(capabilitySupported, k -> new ArrayList<>()) - .add(HttpHost.create((String) httpInfo.get("publish_address"))); - } - - Map clientsByCapability = new HashMap<>(); - for (var entry : hostsByCapability.entrySet()) { - clientsByCapability.put(entry.getKey(), buildClient(restClientSettings(), entry.getValue().toArray(new HttpHost[0]))); - } - return clientsByCapability; - } - - protected void createClientsByCapability(Function, Boolean> capabilityChecker) throws IOException { - var clientsByCapability = getRestClientByCapability(capabilityChecker); - if (clientsByCapability.size() == 2) { - for (Map.Entry client : clientsByCapability.entrySet()) { - if (client.getKey() == false) { - oldVersionClient = client.getValue(); - } else { - newVersionClient = client.getValue(); - } + try { + return buildClient(restClientSettings(), new HttpHost[] { HttpHost.create((String) httpInfo.get("publish_address")) }); + } catch (IOException ex) { + throw new RuntimeException(ex); } + })); + } + + protected void createClientsByCapability(Predicate capabilityChecker) throws IOException { + var testNodesByCapability = collectNodeInfos(adminClient()).stream().collect(Collectors.partitioningBy(capabilityChecker)); + if (testNodesByCapability.size() == 2) { + oldVersionClient = testNodesByCapability.get(false).getFirst().restClient(); + newVersionClient = testNodesByCapability.get(true).getFirst().restClient(); assertThat(oldVersionClient, notNullValue()); assertThat(newVersionClient, notNullValue()); } else { - fail("expected 2 versions during rolling upgrade but got: " + clientsByCapability.size()); + fail("expected 2 versions during rolling upgrade but got: " + testNodesByCapability.size()); + } + } + + protected Set collectNodeInfos(RestClient adminClient) throws IOException { + final Request request = new Request("GET", "_cluster/state"); + request.addParameter("filter_path", "nodes_features"); + + final Response response = adminClient.performRequest(request); + + final Map> nodeFeatures; + var responseData = responseAsMap(response); + if (responseData.get("nodes_features") instanceof List nodesFeatures) { + nodeFeatures = nodesFeatures.stream() + .map(Map.class::cast) + .collect(Collectors.toUnmodifiableMap(nodeFeatureMap -> nodeFeatureMap.get("node_id").toString(), nodeFeatureMap -> { + @SuppressWarnings("unchecked") + var features = (List) nodeFeatureMap.get("features"); + return new HashSet<>(features); + })); + } else { + nodeFeatures = Map.of(); + } + var restClientById = getRestClientById(); + return nodeInfoById().entrySet().stream().map(entry -> { + var version = (String) extractValue((Map) entry.getValue(), "version"); + var transportVersion = (String) extractValue((Map) entry.getValue(), "transport_version"); + return new TestNodeInfo( + entry.getKey(), + version, + TransportVersion.fromString(transportVersion), + nodeFeatures.getOrDefault(entry.getKey(), Set.of()), + restClientById.get(entry.getKey()) + ); + }).collect(Collectors.toSet()); + } + + @SuppressWarnings("unchecked") + private static Map nodeInfoById() throws IOException { + final Response response = client().performRequest(new Request(HttpGet.METHOD_NAME, "_nodes/_all")); + assertThat(response.getStatusLine().getStatusCode(), equalTo(RestStatus.OK.getStatus())); + final Map nodes = (Map) extractValue(responseAsMap(response), "nodes"); + assertNotNull("Nodes info is null", nodes); + return nodes; + } + + protected record TestNodeInfo( + String nodeId, + String version, + TransportVersion transportVersion, + Set features, + RestClient restClient + ) { + public boolean isOriginalVersionCluster() { + return AbstractUpgradeTestCase.isOriginalCluster(this.version()); + } + + public boolean isUpgradedVersionCluster() { + return false == isOriginalVersionCluster(); + } + + public boolean supportsFeature(String feature) { + return features().contains(feature); } } diff --git a/x-pack/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/ApiKeyBackwardsCompatibilityIT.java b/x-pack/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/ApiKeyBackwardsCompatibilityIT.java index 715d0eaaaf0a3..6a217ad9beda0 100644 --- a/x-pack/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/ApiKeyBackwardsCompatibilityIT.java +++ b/x-pack/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/ApiKeyBackwardsCompatibilityIT.java @@ -37,6 +37,7 @@ import java.util.Set; import java.util.function.Consumer; +import static java.util.stream.Collectors.toSet; import static org.elasticsearch.transport.RemoteClusterPortSettings.TRANSPORT_VERSION_ADVANCED_REMOTE_CLUSTER_SECURITY; import static org.elasticsearch.xpack.core.security.authz.RoleDescriptorTestHelper.randomApplicationPrivileges; import static org.elasticsearch.xpack.core.security.authz.RoleDescriptorTestHelper.randomIndicesPrivileges; @@ -53,6 +54,7 @@ public class ApiKeyBackwardsCompatibilityIT extends AbstractUpgradeTestCase { private static final Version UPGRADE_FROM_VERSION = Version.fromString(System.getProperty("tests.upgrade_from_version")); + private static final String CERTIFICATE_IDENTITY_FIELD_FEATURE = "certificate_identity_field"; public void testQueryRestTypeKeys() throws IOException { assumeTrue( @@ -201,10 +203,20 @@ public void testCreatingAndUpdatingApiKeys() throws Exception { } public void testCertificateIdentityBackwardsCompatibility() throws Exception { + final Set nodes = collectNodeInfos(adminClient()); + + final Set newVersionNodes = nodes.stream().filter(TestNodeInfo::isUpgradedVersionCluster).collect(toSet()); + final Set oldVersionNodes = nodes.stream().filter(TestNodeInfo::isOriginalVersionCluster).collect(toSet()); + + assumeTrue( + "Old version nodes must not support certificate identity feature", + oldVersionNodes.stream().noneMatch(info -> info.supportsFeature(CERTIFICATE_IDENTITY_FIELD_FEATURE)) + ); assumeTrue( - "certificate identity backwards compatibility only relevant when upgrading from pre-9.2.0", - UPGRADE_FROM_VERSION.before(Version.V_9_2_0) + "New version nodes must support certificate identity feature", + newVersionNodes.stream().allMatch(info -> info.supportsFeature(CERTIFICATE_IDENTITY_FIELD_FEATURE)) ); + switch (CLUSTER_TYPE) { case OLD -> { var exception = expectThrows(Exception.class, () -> createCrossClusterApiKeyWithCertIdentity("CN=test-.*")); @@ -373,22 +385,15 @@ private static String randomRoleDescriptors(boolean includeRemoteDescriptors) { } } - boolean nodeSupportApiKeyRemoteIndices(Map nodeDetails) { - String nodeVersionString = (String) nodeDetails.get("version"); - TransportVersion transportVersion = getTransportVersionWithFallback( - nodeVersionString, - nodeDetails.get("transport_version"), - () -> TransportVersion.zero() - ); - - if (transportVersion.equals(TransportVersion.zero())) { + boolean nodeSupportApiKeyRemoteIndices(TestNodeInfo testNodeInfo) { + if (testNodeInfo.transportVersion().equals(TransportVersion.zero())) { // In cases where we were not able to find a TransportVersion, a pre-8.8.0 node answered about a newer (upgraded) node. // In that case, the node will be current (upgraded), and remote indices are supported for sure. - var nodeIsCurrent = nodeVersionString.equals(Build.current().version()); + var nodeIsCurrent = testNodeInfo.version().equals(Build.current().version()); assertTrue(nodeIsCurrent); return true; } - return transportVersion.onOrAfter(RemoteClusterPortSettings.TRANSPORT_VERSION_ADVANCED_REMOTE_CLUSTER_SECURITY); + return testNodeInfo.transportVersion().onOrAfter(RemoteClusterPortSettings.TRANSPORT_VERSION_ADVANCED_REMOTE_CLUSTER_SECURITY); } private static RoleDescriptor randomRoleDescriptor(boolean includeRemoteDescriptors) { @@ -426,11 +431,8 @@ private void assertQuery(RestClient restClient, String body, Consumer nodeDetails) { - String nodeVersionString = (String) nodeDetails.get("version"); - Version nodeVersion = Version.fromString(nodeVersionString); - // Certificate identity was introduced in 9.3.0 - return nodeVersion.onOrAfter(Version.V_9_3_0); + private boolean nodeSupportsCertificateIdentity(TestNodeInfo nodeDetails) { + return nodeDetails.supportsFeature(CERTIFICATE_IDENTITY_FIELD_FEATURE); } private Tuple createCrossClusterApiKeyWithCertIdentity(String certificateIdentity) throws IOException { diff --git a/x-pack/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/QueryableBuiltInRolesUpgradeIT.java b/x-pack/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/QueryableBuiltInRolesUpgradeIT.java index f9fce670bcd8c..3a922d55a5688 100644 --- a/x-pack/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/QueryableBuiltInRolesUpgradeIT.java +++ b/x-pack/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/QueryableBuiltInRolesUpgradeIT.java @@ -10,23 +10,17 @@ import org.apache.http.client.methods.HttpGet; import org.elasticsearch.client.Request; import org.elasticsearch.client.Response; -import org.elasticsearch.client.RestClient; -import org.elasticsearch.common.util.Maps; import org.elasticsearch.rest.RestStatus; import org.elasticsearch.test.rest.ObjectPath; import org.elasticsearch.xpack.core.security.authz.store.ReservedRolesStore; import org.junit.Before; import java.io.IOException; -import java.util.HashSet; -import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; import static java.util.stream.Collectors.toSet; -import static org.elasticsearch.common.xcontent.support.XContentMapValues.extractValue; import static org.elasticsearch.xpack.core.security.test.TestRestrictedIndices.INTERNAL_SECURITY_MAIN_INDEX_7; import static org.hamcrest.Matchers.containsInAnyOrder; import static org.hamcrest.Matchers.equalTo; @@ -59,11 +53,11 @@ public void testBuiltInRolesSyncedOnClusterUpgrade() throws Exception { assumeTrue( "Old version nodes must not support queryable feature", - oldVersionNodes.stream().noneMatch(TestNodeInfo::supportsQueryableBuiltInRolesFeature) + oldVersionNodes.stream().noneMatch(info -> info.supportsFeature(QUERYABLE_BUILT_IN_ROLES_NODE_FEATURE)) ); assumeTrue( "New version nodes must support queryable feature", - newVersionNodes.stream().allMatch(TestNodeInfo::supportsQueryableBuiltInRolesFeature) + newVersionNodes.stream().allMatch(info -> info.supportsFeature(QUERYABLE_BUILT_IN_ROLES_NODE_FEATURE)) ); switch (CLUSTER_TYPE) { @@ -80,59 +74,6 @@ public void testBuiltInRolesSyncedOnClusterUpgrade() throws Exception { } } - record TestNodeInfo(String nodeId, String version, Set features) { - - public boolean isOriginalVersionCluster() { - return AbstractUpgradeTestCase.isOriginalCluster(this.version()); - } - - public boolean isUpgradedVersionCluster() { - return false == isOriginalVersionCluster(); - } - - public boolean supportsQueryableBuiltInRolesFeature() { - return features().contains(QUERYABLE_BUILT_IN_ROLES_NODE_FEATURE); - } - - } - - private static Set collectNodeInfos(RestClient adminClient) throws IOException { - final Request request = new Request("GET", "_cluster/state"); - request.addParameter("filter_path", "nodes_features"); - - final Response response = adminClient.performRequest(request); - - Map> nodeFeatures = null; - var responseData = responseAsMap(response); - if (responseData.get("nodes_features") instanceof List nodesFeatures) { - nodeFeatures = nodesFeatures.stream() - .map(Map.class::cast) - .collect(Collectors.toUnmodifiableMap(nodeFeatureMap -> nodeFeatureMap.get("node_id").toString(), nodeFeatureMap -> { - @SuppressWarnings("unchecked") - var features = (List) nodeFeatureMap.get("features"); - return new HashSet<>(features); - })); - } - - Map nodeVersions = nodesVersions(); - assertThat(nodeVersions, is(notNullValue())); - // old cluster may not support node features, so we can treat it as if no features are supported - if (nodeFeatures == null) { - Set nodes = new HashSet<>(nodeVersions.size()); - for (String nodeId : nodeVersions.keySet()) { - nodes.add(new TestNodeInfo(nodeId, nodeVersions.get(nodeId), Set.of())); - } - return nodes; - } else { - assertThat(nodeVersions.keySet(), containsInAnyOrder(nodeFeatures.keySet().toArray())); - Set nodes = new HashSet<>(nodeVersions.size()); - for (String nodeId : nodeVersions.keySet()) { - nodes.add(new TestNodeInfo(nodeId, nodeVersions.get(nodeId), nodeFeatures.get(nodeId))); - } - return nodes; - } - } - private static void waitForNodes(int numberOfNodes) throws IOException { final Request request = new Request(HttpGet.METHOD_NAME, "/_cluster/health"); request.addParameter("wait_for_nodes", String.valueOf(numberOfNodes)); @@ -140,19 +81,6 @@ private static void waitForNodes(int numberOfNodes) throws IOException { assertThat(response.getStatusLine().getStatusCode(), equalTo(RestStatus.OK.getStatus())); } - @SuppressWarnings("unchecked") - private static Map nodesVersions() throws IOException { - final Response response = client().performRequest(new Request(HttpGet.METHOD_NAME, "_nodes/_all")); - assertThat(response.getStatusLine().getStatusCode(), equalTo(RestStatus.OK.getStatus())); - final Map nodes = (Map) extractValue(responseAsMap(response), "nodes"); - assertNotNull("Nodes info is null", nodes); - final Map nodesVersions = Maps.newMapWithExpectedSize(nodes.size()); - for (Map.Entry node : nodes.entrySet()) { - nodesVersions.put(node.getKey(), (String) extractValue((Map) node.getValue(), "version")); - } - return nodesVersions; - } - private void assertBuiltInRolesIndexed(Set expectedBuiltInRoles) throws IOException { final Map builtInRoles = readSecurityIndexBuiltInRolesMetadata(); assertThat(builtInRoles, is(notNullValue())); diff --git a/x-pack/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/RolesBackwardsCompatibilityIT.java b/x-pack/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/RolesBackwardsCompatibilityIT.java index 191025a7c7ed6..8e26b4fcf80dd 100644 --- a/x-pack/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/RolesBackwardsCompatibilityIT.java +++ b/x-pack/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/RolesBackwardsCompatibilityIT.java @@ -303,22 +303,15 @@ private static String randomRoleDescriptorSerialized(boolean includeDescription, } } - private boolean nodeSupportTransportVersion(Map nodeDetails, TransportVersion transportVersion) { - String nodeVersionString = (String) nodeDetails.get("version"); - TransportVersion nodeTransportVersion = getTransportVersionWithFallback( - nodeVersionString, - nodeDetails.get("transport_version"), - () -> TransportVersion.zero() - ); - - if (nodeTransportVersion.equals(TransportVersion.zero())) { + private boolean nodeSupportTransportVersion(TestNodeInfo testNodeInfo, TransportVersion transportVersion) { + if (testNodeInfo.transportVersion().equals(TransportVersion.zero())) { // In cases where we were not able to find a TransportVersion, a pre-8.8.0 node answered about a newer (upgraded) node. // In that case, the node will be current (upgraded), and remote indices are supported for sure. - var nodeIsCurrent = nodeVersionString.equals(Build.current().version()); + var nodeIsCurrent = testNodeInfo.version().equals(Build.current().version()); assertTrue(nodeIsCurrent); return true; } - return nodeTransportVersion.onOrAfter(transportVersion); + return testNodeInfo.transportVersion().onOrAfter(transportVersion); } private static RoleDescriptor randomRoleDescriptor(boolean includeDescription, boolean includeManageRoles) { From 50b1c3632a627e1cfc2e6d5501c5cd60f3331b00 Mon Sep 17 00:00:00 2001 From: Johannes Freden Jansson Date: Thu, 9 Oct 2025 10:30:20 +0200 Subject: [PATCH 2/3] fixup! --- .../org/elasticsearch/upgrades/AbstractUpgradeTestCase.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/x-pack/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/AbstractUpgradeTestCase.java b/x-pack/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/AbstractUpgradeTestCase.java index 75e0cb738f576..3e7fd3fcc5643 100644 --- a/x-pack/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/AbstractUpgradeTestCase.java +++ b/x-pack/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/AbstractUpgradeTestCase.java @@ -249,11 +249,13 @@ protected Set collectNodeInfos(RestClient adminClient) throws IOEx var restClientById = getRestClientById(); return nodeInfoById().entrySet().stream().map(entry -> { var version = (String) extractValue((Map) entry.getValue(), "version"); - var transportVersion = (String) extractValue((Map) entry.getValue(), "transport_version"); + assertNotNull(version); + var transportVersion = (Integer) extractValue((Map) entry.getValue(), "transport_version"); + assertNotNull(transportVersion); return new TestNodeInfo( entry.getKey(), version, - TransportVersion.fromString(transportVersion), + TransportVersion.fromId(transportVersion), nodeFeatures.getOrDefault(entry.getKey(), Set.of()), restClientById.get(entry.getKey()) ); From 882c5917644a248b98688f48ad684feeec62e779 Mon Sep 17 00:00:00 2001 From: Johannes Freden Jansson Date: Thu, 9 Oct 2025 11:31:10 +0200 Subject: [PATCH 3/3] Fix leaking rest clients --- .../upgrades/AbstractUpgradeTestCase.java | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/x-pack/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/AbstractUpgradeTestCase.java b/x-pack/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/AbstractUpgradeTestCase.java index 3e7fd3fcc5643..241c4811ba0e6 100644 --- a/x-pack/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/AbstractUpgradeTestCase.java +++ b/x-pack/qa/rolling-upgrade/src/test/java/org/elasticsearch/upgrades/AbstractUpgradeTestCase.java @@ -199,7 +199,7 @@ protected void closeClientsByVersion() throws IOException { } @SuppressWarnings("unchecked") - protected Map getRestClientById() throws IOException { + protected Map getRestEndpointByIdNodeId() throws IOException { Response response = client().performRequest(new Request("GET", "_nodes")); assertOK(response); ObjectPath objectPath = ObjectPath.createFromResponse(response); @@ -207,19 +207,21 @@ protected Map getRestClientById() throws IOException { return nodesAsMap.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> { Map nodeDetails = (Map) e.getValue(); Map httpInfo = (Map) nodeDetails.get("http"); - try { - return buildClient(restClientSettings(), new HttpHost[] { HttpHost.create((String) httpInfo.get("publish_address")) }); - } catch (IOException ex) { - throw new RuntimeException(ex); - } + return (String) httpInfo.get("publish_address"); })); } protected void createClientsByCapability(Predicate capabilityChecker) throws IOException { var testNodesByCapability = collectNodeInfos(adminClient()).stream().collect(Collectors.partitioningBy(capabilityChecker)); if (testNodesByCapability.size() == 2) { - oldVersionClient = testNodesByCapability.get(false).getFirst().restClient(); - newVersionClient = testNodesByCapability.get(true).getFirst().restClient(); + oldVersionClient = buildClient( + restClientSettings(), + new HttpHost[] { HttpHost.create(testNodesByCapability.get(false).getFirst().restEndpoint) } + ); + newVersionClient = buildClient( + restClientSettings(), + new HttpHost[] { HttpHost.create(testNodesByCapability.get(true).getFirst().restEndpoint) } + ); assertThat(oldVersionClient, notNullValue()); assertThat(newVersionClient, notNullValue()); } else { @@ -246,7 +248,8 @@ protected Set collectNodeInfos(RestClient adminClient) throws IOEx } else { nodeFeatures = Map.of(); } - var restClientById = getRestClientById(); + var restEndpointByNodeId = getRestEndpointByIdNodeId(); + return nodeInfoById().entrySet().stream().map(entry -> { var version = (String) extractValue((Map) entry.getValue(), "version"); assertNotNull(version); @@ -257,7 +260,7 @@ protected Set collectNodeInfos(RestClient adminClient) throws IOEx version, TransportVersion.fromId(transportVersion), nodeFeatures.getOrDefault(entry.getKey(), Set.of()), - restClientById.get(entry.getKey()) + restEndpointByNodeId.get(entry.getKey()) ); }).collect(Collectors.toSet()); } @@ -276,7 +279,7 @@ protected record TestNodeInfo( String version, TransportVersion transportVersion, Set features, - RestClient restClient + String restEndpoint ) { public boolean isOriginalVersionCluster() { return AbstractUpgradeTestCase.isOriginalCluster(this.version());