Repository: elastic/rally

Issue:
datastore.secure boolean values seem to be case sensitive in rally.ini
Specifying `datastore.secure = true` in `rally.ini` gives the misleading error message:

```
esrally.exceptions.SystemSetupError: ('Could not connect to your Elasticsearch metrics store. Please check that it is running on host [https://<url>] at port [9243] or fix the configuration in [<home_dir>/.rally/rally.ini].', None)
].
```
It works when setting it to `True`, but we should be case insensitive when parsing boolean values in this file.

Discussion:

Patch:
diff --git a/esrally/metrics.py b/esrally/metrics.py
index c01be1c2..7da700de 100644
--- a/esrally/metrics.py
+++ b/esrally/metrics.py
@@ -9,7 +9,7 @@ from enum import Enum, IntEnum
 
 import tabulate
 from esrally import time, exceptions, config, version, paths
-from esrally.utils import console, io, versions
+from esrally.utils import convert, console, io, versions
 from http.client import responses
 
 
@@ -123,8 +123,7 @@ class EsClientFactory:
         self._config = cfg
         host = self._config.opts("reporting", "datastore.host")
         port = self._config.opts("reporting", "datastore.port")
-        # poor man's boolean conversion
-        secure = self._config.opts("reporting", "datastore.secure") == "True"
+        secure = convert.to_bool(self._config.opts("reporting", "datastore.secure"))
         user = self._config.opts("reporting", "datastore.user")
         password = self._config.opts("reporting", "datastore.password")
         verify = self._config.opts("reporting", "datastore.ssl.verification_mode", default_value="full", mandatory=False) != "none"


Test patch:
diff --git a/tests/metrics_test.py b/tests/metrics_test.py
index ee646c45..68413848 100644
--- a/tests/metrics_test.py
+++ b/tests/metrics_test.py
@@ -3,6 +3,7 @@ import datetime
 import logging
 import unittest.mock as mock
 import random
+import string
 from unittest import TestCase
 import elasticsearch.exceptions
 
@@ -120,6 +121,39 @@ class EsClientTests(TestCase):
         def __init__(self, hosts):
             self.transport = EsClientTests.TransportMock(hosts)
 
+    @mock.patch("esrally.client.EsClientFactory")
+    def test_config_opts_parsing(self, client_esclientfactory):
+        cfg = config.Config()
+
+        _datastore_host = ".".join([str(random.randint(1,254)) for _ in range(4)])
+        _datastore_port = random.randint(1024,65535)
+        _datastore_secure = random.choice(["True", "true"])
+        _datastore_user = "".join([random.choice(string.ascii_letters) for _ in range(8)])
+        _datastore_password = "".join([random.choice(string.ascii_letters + string.digits + "_-@#$/") for _ in range(12)])
+        _datastore_verify_certs = random.choice([True, False])
+
+        cfg.add(config.Scope.applicationOverride, "reporting", "datastore.host", _datastore_host)
+        cfg.add(config.Scope.applicationOverride, "reporting", "datastore.port", _datastore_port)
+        cfg.add(config.Scope.applicationOverride, "reporting", "datastore.secure", _datastore_secure)
+        cfg.add(config.Scope.applicationOverride, "reporting", "datastore.user", _datastore_user)
+        cfg.add(config.Scope.applicationOverride, "reporting", "datastore.password", _datastore_password)
+        if not _datastore_verify_certs:
+            cfg.add(config.Scope.applicationOverride, "reporting", "datastore.ssl.verification_mode", "none")
+
+        f = metrics.EsClientFactory(cfg)
+        expected_client_options = {
+            "use_ssl": True,
+            "timeout": 120,
+            "basic_auth_user": _datastore_user,
+            "basic_auth_password": _datastore_password,
+            "verify_certs": _datastore_verify_certs
+        }
+
+        client_esclientfactory.assert_called_with(
+            hosts=[{"host": _datastore_host, "port": _datastore_port}],
+            client_options=expected_client_options
+        )
+
     def test_raises_sytem_setup_error_on_connection_problems(self):
         def raise_connection_error():
             raise elasticsearch.exceptions.ConnectionError("unit-test")