Skip to content

Commit 674587c

Browse files
committed
Fix interoperability with < 6.3 transport clients (#30971)
With the default distribution changing in 6.3, clusters might now contain custom metadata that a pure OSS transport client cannot deserialize. As this can break transport clients when accessing the cluster state or reroute APIs, we've decided to exclude any custom metadata that the transport client might not be able to deserialize. This will ensure compatibility between a < 6.3 transport client and a 6.3 default distribution cluster. Note that this PR only covers interoperability with older clients, another follow-up PR will cover full interoperability for >= 6.3 transport clients where we will make it possible again to get the custom metadata from the cluster state. Relates to #30731
1 parent 23d497e commit 674587c

File tree

4 files changed

+71
-2
lines changed

4 files changed

+71
-2
lines changed

server/src/main/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteResponse.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@
1919

2020
package org.elasticsearch.action.admin.cluster.reroute;
2121

22+
import org.elasticsearch.Version;
2223
import org.elasticsearch.action.support.master.AcknowledgedResponse;
24+
import org.elasticsearch.cluster.ClusterModule;
2325
import org.elasticsearch.cluster.ClusterState;
2426
import org.elasticsearch.cluster.routing.allocation.RoutingExplanations;
2527
import org.elasticsearch.common.io.stream.StreamInput;
@@ -70,7 +72,11 @@ public void readFrom(StreamInput in) throws IOException {
7072
@Override
7173
public void writeTo(StreamOutput out) throws IOException {
7274
super.writeTo(out);
73-
state.writeTo(out);
75+
if (out.getVersion().onOrAfter(Version.V_6_3_0)) {
76+
state.writeTo(out);
77+
} else {
78+
ClusterModule.filterCustomsForPre63Clients(state).writeTo(out);
79+
}
7480
writeAcknowledged(out);
7581
RoutingExplanations.writeTo(explanations, out);
7682
}

server/src/main/java/org/elasticsearch/action/admin/cluster/state/ClusterStateResponse.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
import org.elasticsearch.Version;
2323
import org.elasticsearch.action.ActionResponse;
24+
import org.elasticsearch.cluster.ClusterModule;
2425
import org.elasticsearch.cluster.ClusterName;
2526
import org.elasticsearch.cluster.ClusterState;
2627
import org.elasticsearch.common.io.stream.StreamInput;
@@ -94,7 +95,11 @@ public void readFrom(StreamInput in) throws IOException {
9495
public void writeTo(StreamOutput out) throws IOException {
9596
super.writeTo(out);
9697
clusterName.writeTo(out);
97-
clusterState.writeTo(out);
98+
if (out.getVersion().onOrAfter(Version.V_6_3_0)) {
99+
clusterState.writeTo(out);
100+
} else {
101+
ClusterModule.filterCustomsForPre63Clients(clusterState).writeTo(out);
102+
}
98103
if (out.getVersion().onOrAfter(Version.V_6_0_0_alpha1)) {
99104
totalCompressedSize.writeTo(out);
100105
}

server/src/main/java/org/elasticsearch/cluster/ClusterModule.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
import org.elasticsearch.common.settings.Setting;
6767
import org.elasticsearch.common.settings.Setting.Property;
6868
import org.elasticsearch.common.settings.Settings;
69+
import org.elasticsearch.common.util.set.Sets;
6970
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
7071
import org.elasticsearch.gateway.GatewayAllocator;
7172
import org.elasticsearch.ingest.IngestMetadata;
@@ -84,6 +85,7 @@
8485
import java.util.List;
8586
import java.util.Map;
8687
import java.util.Objects;
88+
import java.util.Set;
8789
import java.util.function.Function;
8890
import java.util.function.Supplier;
8991

@@ -150,6 +152,35 @@ public static List<Entry> getNamedWriteables() {
150152
return entries;
151153
}
152154

155+
static final Set<String> PRE_6_3_METADATA_CUSTOMS_WHITE_LIST = Collections.unmodifiableSet(Sets.newHashSet(
156+
IndexGraveyard.TYPE, IngestMetadata.TYPE, RepositoriesMetaData.TYPE, ScriptMetaData.TYPE));
157+
158+
static final Set<String> PRE_6_3_CLUSTER_CUSTOMS_WHITE_LIST = Collections.unmodifiableSet(Sets.newHashSet(
159+
RestoreInProgress.TYPE, SnapshotDeletionsInProgress.TYPE, SnapshotsInProgress.TYPE));
160+
161+
/**
162+
* For interoperability with transport clients older than 6.3, we need to strip customs
163+
* from the cluster state that the client might not be able to deserialize
164+
*
165+
* @param clusterState the cluster state to filter the customs from
166+
* @return the adapted cluster state
167+
*/
168+
public static ClusterState filterCustomsForPre63Clients(ClusterState clusterState) {
169+
final ClusterState.Builder builder = ClusterState.builder(clusterState);
170+
clusterState.customs().keysIt().forEachRemaining(name -> {
171+
if (PRE_6_3_CLUSTER_CUSTOMS_WHITE_LIST.contains(name) == false) {
172+
builder.removeCustom(name);
173+
}
174+
});
175+
final MetaData.Builder metaBuilder = MetaData.builder(clusterState.metaData());
176+
clusterState.metaData().customs().keysIt().forEachRemaining(name -> {
177+
if (PRE_6_3_METADATA_CUSTOMS_WHITE_LIST.contains(name) == false) {
178+
metaBuilder.removeCustom(name);
179+
}
180+
});
181+
return builder.metaData(metaBuilder).build();
182+
}
183+
153184
public static List<NamedXContentRegistry.Entry> getNamedXWriteables() {
154185
List<NamedXContentRegistry.Entry> entries = new ArrayList<>();
155186
// Metadata

server/src/test/java/org/elasticsearch/cluster/ClusterModuleTests.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919

2020
package org.elasticsearch.cluster;
2121

22+
import org.elasticsearch.cluster.metadata.MetaData;
23+
import org.elasticsearch.cluster.metadata.RepositoriesMetaData;
2224
import org.elasticsearch.cluster.routing.ShardRouting;
2325
import org.elasticsearch.cluster.routing.allocation.RoutingAllocation;
2426
import org.elasticsearch.cluster.routing.allocation.ShardAllocationDecision;
@@ -251,4 +253,29 @@ public Map<String, Supplier<ClusterState.Custom>> getInitialClusterStateCustomSu
251253
assertEquals(ise.getMessage(), "custom supplier key [foo] is registered more than once");
252254
}
253255
}
256+
257+
public void testPre63CustomsFiltering() {
258+
final String whiteListedClusterCustom = randomFrom(ClusterModule.PRE_6_3_CLUSTER_CUSTOMS_WHITE_LIST);
259+
final String whiteListedMetaDataCustom = randomFrom(ClusterModule.PRE_6_3_METADATA_CUSTOMS_WHITE_LIST);
260+
final ClusterState clusterState = ClusterState.builder(ClusterName.DEFAULT)
261+
.putCustom(whiteListedClusterCustom, new RestoreInProgress())
262+
.putCustom("other", new RestoreInProgress())
263+
.metaData(MetaData.builder()
264+
.putCustom(whiteListedMetaDataCustom, new RepositoriesMetaData(Collections.emptyList()))
265+
.putCustom("other", new RepositoriesMetaData(Collections.emptyList()))
266+
.build())
267+
.build();
268+
269+
assertNotNull(clusterState.custom(whiteListedClusterCustom));
270+
assertNotNull(clusterState.custom("other"));
271+
assertNotNull(clusterState.metaData().custom(whiteListedMetaDataCustom));
272+
assertNotNull(clusterState.metaData().custom("other"));
273+
274+
final ClusterState fixedClusterState = ClusterModule.filterCustomsForPre63Clients(clusterState);
275+
276+
assertNotNull(fixedClusterState.custom(whiteListedClusterCustom));
277+
assertNull(fixedClusterState.custom("other"));
278+
assertNotNull(fixedClusterState.metaData().custom(whiteListedMetaDataCustom));
279+
assertNull(fixedClusterState.metaData().custom("other"));
280+
}
254281
}

0 commit comments

Comments
 (0)