Skip to content

Commit 8c4eee6

Browse files
Update RemoteClusterService skip_unavailable handling for CPS (#132478)
In serverless cross-project search (CPS) skip_unavailable will not be used and should always be true. This PR adds a settings validator that rejects setting skip_unavailable when CPS is enabled. Resolves: ES-12267
1 parent 2b60a2f commit 8c4eee6

File tree

4 files changed

+78
-99
lines changed

4 files changed

+78
-99
lines changed

server/src/main/java/org/elasticsearch/transport/RemoteClusterService.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,8 @@ public void skipUnavailableChanged(
300300
String linkedProjectAlias,
301301
boolean skipUnavailable
302302
) {
303+
assert crossProjectEnabled == false
304+
: "Cannot configure setting [" + RemoteClusterSettings.REMOTE_CLUSTER_SKIP_UNAVAILABLE.getKey() + "] in CPS environments.";
303305
final var remote = getConnectionsMapForProject(originProjectId).get(linkedProjectAlias);
304306
if (remote != null) {
305307
remote.setSkipUnavailable(skipUnavailable);

server/src/main/java/org/elasticsearch/transport/RemoteClusterSettings.java

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import org.elasticsearch.cluster.metadata.ProjectId;
1414
import org.elasticsearch.cluster.node.DiscoveryNode;
1515
import org.elasticsearch.common.Strings;
16+
import org.elasticsearch.common.collect.Iterators;
1617
import org.elasticsearch.common.settings.SecureSetting;
1718
import org.elasticsearch.common.settings.SecureString;
1819
import org.elasticsearch.common.settings.Setting;
@@ -70,7 +71,7 @@ public class RemoteClusterSettings {
7071
(ns, key) -> boolSetting(
7172
key,
7273
DEFAULT_SKIP_UNAVAILABLE,
73-
new RemoteConnectionEnabled<>(ns, key),
74+
new UnsupportedInCPSValidator<>(ns, key),
7475
Setting.Property.Dynamic,
7576
Setting.Property.NodeScope
7677
)
@@ -390,6 +391,10 @@ private RemoteConnectionEnabled(String clusterAlias, String key) {
390391
this.key = key;
391392
}
392393

394+
protected String getKey() {
395+
return key;
396+
}
397+
393398
@Override
394399
public void validate(T value) {}
395400

@@ -483,4 +488,25 @@ public Iterator<Setting<?>> settings() {
483488
return settingStream.iterator();
484489
}
485490
}
491+
492+
private static class UnsupportedInCPSValidator<T> extends RemoteConnectionEnabled<T> {
493+
private final Setting<Boolean> cpsSetting = Setting.boolSetting("serverless.cross_project.enabled", false);
494+
495+
private UnsupportedInCPSValidator(String clusterAlias, String key) {
496+
super(clusterAlias, key);
497+
}
498+
499+
@Override
500+
public void validate(T value, Map<Setting<?>, Object> settings, boolean isPresent) {
501+
if (isPresent && (Boolean) settings.get(cpsSetting)) {
502+
throw new IllegalArgumentException("setting [" + getKey() + "] is unavailable when CPS is enabled");
503+
}
504+
super.validate(value, settings, isPresent);
505+
}
506+
507+
@Override
508+
public Iterator<Setting<?>> settings() {
509+
return Iterators.concat(super.settings(), Iterators.single(cpsSetting));
510+
}
511+
}
486512
}

server/src/test/java/org/elasticsearch/transport/RemoteClusterSettingsTests.java

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@
2222

2323
import static org.elasticsearch.test.NodeRoles.nonRemoteClusterClientNode;
2424
import static org.elasticsearch.test.NodeRoles.remoteClusterClientNode;
25+
import static org.elasticsearch.transport.RemoteClusterSettings.ProxyConnectionStrategySettings.PROXY_ADDRESS;
2526
import static org.elasticsearch.transport.RemoteClusterSettings.REMOTE_CLUSTER_CREDENTIALS;
2627
import static org.elasticsearch.transport.RemoteClusterSettings.REMOTE_CLUSTER_SKIP_UNAVAILABLE;
28+
import static org.elasticsearch.transport.RemoteClusterSettings.REMOTE_CONNECTION_MODE;
2729
import static org.elasticsearch.transport.RemoteClusterSettings.REMOTE_INITIAL_CONNECTION_TIMEOUT_SETTING;
2830
import static org.elasticsearch.transport.RemoteClusterSettings.REMOTE_NODE_ATTRIBUTE;
2931
import static org.elasticsearch.transport.RemoteClusterSettings.SniffConnectionStrategySettings.REMOTE_CLUSTERS_PROXY;
@@ -95,4 +97,51 @@ public void testProxyDefault() {
9597
final String alias = randomAlphaOfLength(8);
9698
assertThat(REMOTE_CLUSTERS_PROXY.getConcreteSettingForNamespace(alias).get(Settings.EMPTY), equalTo(""));
9799
}
100+
101+
public void testSkipUnavailableAlwaysTrueIfCPSEnabled() {
102+
final var alias = randomAlphaOfLength(8);
103+
final var skipUnavailableSetting = REMOTE_CLUSTER_SKIP_UNAVAILABLE.getConcreteSettingForNamespace(alias);
104+
final var modeSetting = REMOTE_CONNECTION_MODE.getConcreteSettingForNamespace(alias);
105+
final var proxyAddressSetting = PROXY_ADDRESS.getConcreteSettingForNamespace(alias);
106+
final var cpsEnabledSettings = Settings.builder().put("serverless.cross_project.enabled", true).build();
107+
final var proxyEnabledSettings = Settings.builder()
108+
.put(modeSetting.getKey(), RemoteConnectionStrategy.ConnectionStrategy.PROXY.toString())
109+
.put(proxyAddressSetting.getKey(), "localhost:9400")
110+
.build();
111+
112+
// Ensure the validator still throws in non-CPS environment if a connection mode is not set.
113+
var exception = expectThrows(
114+
IllegalArgumentException.class,
115+
() -> skipUnavailableSetting.get(Settings.builder().put(skipUnavailableSetting.getKey(), true).build())
116+
);
117+
assertThat(
118+
exception.getMessage(),
119+
equalTo("Cannot configure setting [" + skipUnavailableSetting.getKey() + "] if remote cluster is not enabled.")
120+
);
121+
122+
// Ensure we can still get the set value in non-CPS environment.
123+
final var randomSkipUnavailableSettingValue = randomBoolean();
124+
assertThat(
125+
skipUnavailableSetting.get(
126+
Settings.builder().put(proxyEnabledSettings).put(skipUnavailableSetting.getKey(), randomSkipUnavailableSettingValue).build()
127+
),
128+
equalTo(randomSkipUnavailableSettingValue)
129+
);
130+
131+
// Check the validator rejects the skip_unavailable setting if present when CPS is enabled.
132+
exception = expectThrows(
133+
IllegalArgumentException.class,
134+
() -> skipUnavailableSetting.get(
135+
Settings.builder()
136+
.put(cpsEnabledSettings)
137+
.put(proxyEnabledSettings)
138+
.put(skipUnavailableSetting.getKey(), randomBoolean())
139+
.build()
140+
)
141+
);
142+
assertThat(exception.getMessage(), equalTo("setting [" + skipUnavailableSetting.getKey() + "] is unavailable when CPS is enabled"));
143+
144+
// Should not throw if the setting is not present, returning the expected default value of true.
145+
assertTrue(skipUnavailableSetting.get(Settings.builder().put(cpsEnabledSettings).put(proxyEnabledSettings).build()));
146+
}
98147
}

x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/action/EsqlCpsDoesNotUseSkipUnavailableIT.java

Lines changed: 0 additions & 98 deletions
This file was deleted.

0 commit comments

Comments
 (0)