in esrally/client/factory.py [0:0]
def __init__(self, hosts, client_options, distribution_version=None, distribution_flavor=None):
def host_string(host):
# protocol can be set at either host or client opts level
protocol = "https" if client_options.get("use_ssl") or host.get("use_ssl") else "http"
return f"{protocol}://{host['host']}:{host['port']}"
self.hosts = [host_string(h) for h in hosts]
self.client_options = dict(client_options)
self.ssl_context = None
# This attribute is necessary for the backwards-compatibility logic contained in
# RallySyncElasticsearch.perform_request() and RallyAsyncElasticsearch.perform_request(), and also for
# identification of whether or not a client is 'serverless'.
self.distribution_version = distribution_version
self.distribution_flavor = distribution_flavor
self.logger = logging.getLogger(__name__)
masked_client_options = dict(client_options)
if "basic_auth_password" in masked_client_options:
masked_client_options["basic_auth_password"] = "*****"
if "http_auth" in masked_client_options:
masked_client_options["http_auth"] = (masked_client_options["http_auth"][0], "*****")
if "api_key" in masked_client_options:
masked_client_options["api_key"] = "*****"
self.logger.info("Creating ES client connected to %s with options [%s]", hosts, masked_client_options)
# we're using an SSL context now and it is not allowed to have use_ssl present in client options anymore
if self.client_options.pop("use_ssl", False):
# pylint: disable=import-outside-toplevel
import ssl
self.logger.debug("SSL support: on")
self.ssl_context = ssl.create_default_context(
ssl.Purpose.SERVER_AUTH, cafile=self.client_options.pop("ca_certs", certifi.where())
)
# We call get() here instead of pop() in order to pass verify_certs through as a kwarg
# to the elasticsearch.Elasticsearch constructor. Setting the ssl_context's verify_mode to
# ssl.CERT_NONE is insufficient with version 8.0+ of elasticsearch-py.
if not self.client_options.get("verify_certs", True):
self.logger.debug("SSL certificate verification: off")
# order matters to avoid ValueError: check_hostname needs a SSL context with either CERT_OPTIONAL or CERT_REQUIRED
self.ssl_context.check_hostname = False
self.ssl_context.verify_mode = ssl.CERT_NONE
self.client_options["ssl_show_warn"] = False
self.logger.debug(
"User has enabled SSL but disabled certificate verification. This is dangerous but may be ok for a benchmark."
)
else:
# check_hostname should not be set when host is an IP address
self.ssl_context.check_hostname = self._only_hostnames(hosts)
self.ssl_context.verify_mode = ssl.CERT_REQUIRED
self.logger.debug("SSL certificate verification: on")
# When using SSL_context, all SSL related kwargs in client options get ignored
client_cert = self.client_options.pop("client_cert", False)
client_key = self.client_options.pop("client_key", False)
if not client_cert and not client_key:
self.logger.debug("SSL client authentication: off")
elif bool(client_cert) != bool(client_key):
self.logger.error("Supplied client-options contain only one of client_cert/client_key. ")
defined_client_ssl_option = "client_key" if client_key else "client_cert"
missing_client_ssl_option = "client_cert" if client_key else "client_key"
console.println(
"'{}' is missing from client-options but '{}' has been specified.\n"
"If your Elasticsearch setup requires client certificate verification both need to be supplied.\n"
"Read the documentation at {}\n".format(
missing_client_ssl_option,
defined_client_ssl_option,
console.format.link(doc_link("command_line_reference.html#client-options")),
)
)
raise exceptions.SystemSetupError(
"Cannot specify '{}' without also specifying '{}' in client-options.".format(
defined_client_ssl_option, missing_client_ssl_option
)
)
elif client_cert and client_key:
self.logger.debug("SSL client authentication: on")
self.ssl_context.load_cert_chain(certfile=client_cert, keyfile=client_key)
else:
self.logger.debug("SSL support: off")
if self._is_set(self.client_options, "create_api_key_per_client"):
self.client_options.pop("create_api_key_per_client")
basic_auth_user = self.client_options.get("basic_auth_user", False)
basic_auth_password = self.client_options.get("basic_auth_password", False)
provided_auth = {"basic_auth_user": basic_auth_user, "basic_auth_password": basic_auth_password}
missing_auth = [k for k, v in provided_auth.items() if not v]
if missing_auth:
console.println(
"Basic auth credentials are required in order to create API keys.\n"
f"Missing basic auth client options are: {missing_auth}\n"
f"Read the documentation at {console.format.link(doc_link('command_line_reference.html#client-options'))}"
)
raise exceptions.SystemSetupError(
"You must provide the 'basic_auth_user' and 'basic_auth_password' client options in addition "
"to 'create_api_key_per_client' in order to create client API keys."
)
self.logger.debug("Automatic creation of client API keys: on")
else:
self.logger.debug("Automatic creation of client API keys: off")
if self._is_set(self.client_options, "basic_auth_user") and self._is_set(self.client_options, "basic_auth_password"):
self.client_options["basic_auth"] = (self.client_options.pop("basic_auth_user"), self.client_options.pop("basic_auth_password"))
self.logger.debug("HTTP basic authentication: on")
else:
self.logger.debug("HTTP basic authentication: off")
if self._is_set(self.client_options, "api_key"):
self.logger.debug("API key authentication: on")
else:
self.logger.debug("API key authentication: off")
if self._is_set(self.client_options, "compressed"):
console.warn("You set the deprecated client option 'compressed‘. Please use 'http_compress' instead.", logger=self.logger)
self.client_options["http_compress"] = self.client_options.pop("compressed")
if self._is_set(self.client_options, "http_compress"):
self.logger.debug("HTTP compression: on")
else:
self.logger.debug("HTTP compression: off")
self.enable_cleanup_closed = convert.to_bool(self.client_options.pop("enable_cleanup_closed", True))
self.max_connections = max(256, self.client_options.pop("max_connections", 0))
self.static_responses = self.client_options.pop("static_responses", None)
if self._is_set(self.client_options, "timeout"):
self.client_options["request_timeout"] = self.client_options.pop("timeout")