Skip to content

Commit 8dae2c3

Browse files
authored
Detect serverless operator status automatically (#1768)
1 parent 50ebcb6 commit 8dae2c3

4 files changed

Lines changed: 26 additions & 11 deletions

File tree

esrally/client/factory.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -332,12 +332,13 @@ def cluster_distribution_version(hosts, client_options, client_factory=EsClientF
332332
:param client_options: The client options to customize the Elasticsearch client.
333333
:param client_factory: Factory class that creates the Elasticsearch client.
334334
:return: The cluster's build flavor, version number, and build hash. For Serverless Elasticsearch these may all be
335-
the build flavor value.
335+
the build flavor value. Also returns the operator status (always False for stateful).
336336
"""
337337
# no way for us to know whether we're talking to a serverless elasticsearch or not, so we default to the sync client
338338
es = client_factory(hosts, client_options).create()
339-
# unconditionally wait for the REST layer - if it's not up by then, we'll intentionally raise the original error
340-
wait_for_rest_layer(es)
339+
340+
# wait_for_rest_layer calls the Cluster Health API, which is not available for unprivileged users on Serverless
341+
# As a result, we need to call the info API first to know if we can call wait_for_rest_layer().
341342
version = es.info()["version"]
342343

343344
version_build_flavor = version.get("build_flavor", "oss")
@@ -346,7 +347,16 @@ def cluster_distribution_version(hosts, client_options, client_factory=EsClientF
346347
# version number does not exist for serverless
347348
version_number = version.get("number", version_build_flavor)
348349

349-
return version_build_flavor, version_number, version_build_hash
350+
serverless_operator = False
351+
if versions.is_serverless(version_build_flavor):
352+
authentication_info = es.perform_request(method="GET", path="/_security/_authenticate")
353+
serverless_operator = authentication_info.body.get("operator", False)
354+
355+
if not versions.is_serverless(version_build_flavor) or serverless_operator is True:
356+
# if available, unconditionally wait for the REST layer - if it's not up, we'll intentionally raise the original error
357+
wait_for_rest_layer(es)
358+
359+
return version_build_flavor, version_number, version_build_hash, serverless_operator
350360

351361

352362
def create_api_key(es, client_id, max_attempts=5):

esrally/metrics.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,9 @@ def __init__(self, cfg):
264264

265265
# TODO #1335: Use version-specific support for metrics stores after 7.8.0.
266266
if self.probe_version:
267-
distribution_flavor, distribution_version, _ = client.cluster_distribution_version(hosts=hosts, client_options=client_options)
267+
distribution_flavor, distribution_version, _, _ = client.cluster_distribution_version(
268+
hosts=hosts, client_options=client_options
269+
)
268270
self._cluster_version = distribution_version
269271

270272
factory = client.EsClientFactory(

esrally/racecontrol.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -186,9 +186,12 @@ def setup(self, sources=False):
186186
if not sources and not self.cfg.exists("mechanic", "distribution.version"):
187187
hosts = self.cfg.opts("client", "hosts").default
188188
client_options = self.cfg.opts("client", "options").default
189-
distribution_flavor, distribution_version, distribution_build_hash = client.factory.cluster_distribution_version(
190-
hosts, client_options
191-
)
189+
(
190+
distribution_flavor,
191+
distribution_version,
192+
distribution_build_hash,
193+
serverless_operator,
194+
) = client.factory.cluster_distribution_version(hosts, client_options)
192195

193196
self.logger.info(
194197
"Automatically derived distribution flavor [%s], version [%s], and build hash [%s]",
@@ -203,8 +206,8 @@ def setup(self, sources=False):
203206
self.cfg.add(config.Scope.benchmark, "driver", "serverless.mode", True)
204207

205208
if not self.cfg.exists("driver", "serverless.operator"):
206-
# operator privileges assumed for now
207-
self.cfg.add(config.Scope.benchmark, "driver", "serverless.operator", True)
209+
self.cfg.add(config.Scope.benchmark, "driver", "serverless.operator", serverless_operator)
210+
console.info(f"Detected Elasticsearch Serverless mode with operator=[{serverless_operator}].")
208211
else:
209212
min_es_version = versions.Version.from_string(version.minimum_es_version())
210213
specified_version = versions.Version.from_string(distribution_version)

esrally/tracker/tracker.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ def create_track(cfg):
7878
client_options = cfg.opts("client", "options").default
7979
data_streams = cfg.opts("generator", "data_streams")
8080

81-
distribution_flavor, distribution_version, _ = factory.cluster_distribution_version(target_hosts, client_options)
81+
distribution_flavor, distribution_version, _, _ = factory.cluster_distribution_version(target_hosts, client_options)
8282
client = factory.EsClientFactory(
8383
hosts=target_hosts,
8484
client_options=client_options,

0 commit comments

Comments
 (0)