Skip to content

Commit

Permalink
Improve error message on SSL errors
Browse files Browse the repository at this point in the history
With this commit we check for SSL-related errors when waiting for the
REST layer to be available and provide a better error message when the
user attempts to connect via SSL to a http endpoint.

Closes elastic#757
Relates elastic#758
  • Loading branch information
danielmitterdorfer authored and novosibman committed Oct 2, 2019
1 parent 97e1681 commit 7b9e03c
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 4 deletions.
9 changes: 7 additions & 2 deletions esrally/mechanic/launcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

from esrally import config, time, exceptions, client
from esrally.mechanic import telemetry, cluster, java_resolver
from esrally.utils import process, jvm
from esrally.utils import process


def wait_for_rest_layer(es, max_attempts=20):
Expand All @@ -34,8 +34,13 @@ def wait_for_rest_layer(es, max_attempts=20):
try:
es.info()
return True
except elasticsearch.ConnectionError as e:
if "SSL: UNKNOWN_PROTOCOL" in str(e):
raise exceptions.LaunchError("Could not connect to cluster via https. Is this a https endpoint?", e)
else:
time.sleep(1)
except elasticsearch.TransportError as e:
if e.status_code == 503 or isinstance(e, elasticsearch.ConnectionError):
if e.status_code == 503:
time.sleep(1)
elif e.status_code == 401:
time.sleep(1)
Expand Down
49 changes: 47 additions & 2 deletions tests/mechanic/launcher_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
import tempfile
from datetime import datetime
import io, os
import uuid
Expand Down Expand Up @@ -78,7 +77,7 @@ def __init__(self, client_options):
def info(self):
if self.client_options.get("raise-error-on-info", False):
import elasticsearch
raise elasticsearch.ConnectionError("Unittest error")
raise elasticsearch.TransportError(401, "Unauthorized")
return self._info

def search(self, *args, **kwargs):
Expand Down Expand Up @@ -314,3 +313,49 @@ def test_error_on_cluster_launch(self, sleep):
with self.assertRaisesRegex(exceptions.LaunchError,
"Elasticsearch REST API layer is not available. Forcefully terminated cluster."):
cluster_launcher.start()


class RestLayerTests(TestCase):
@mock.patch("elasticsearch.Elasticsearch", autospec=True)
def test_successfully_waits_for_rest_layer(self, es):
self.assertTrue(launcher.wait_for_rest_layer(es, max_attempts=3))

# don't sleep in realtime
@mock.patch("time.sleep")
@mock.patch("elasticsearch.Elasticsearch", autospec=True)
def test_retries_on_transport_errors(self, es, sleep):
import elasticsearch

es.info.side_effect = [
elasticsearch.TransportError(503, "Service Unavailable"),
elasticsearch.TransportError(401, "Unauthorized"),
{
"version": {
"number": "5.0.0",
"build_hash": "abc123"
}
}
]
self.assertTrue(launcher.wait_for_rest_layer(es, max_attempts=3))

# don't sleep in realtime
@mock.patch("time.sleep")
@mock.patch("elasticsearch.Elasticsearch", autospec=True)
def test_dont_retries_eternally_on_transport_errors(self, es, sleep):
import elasticsearch

es.info.side_effect = elasticsearch.TransportError(401, "Unauthorized")
self.assertFalse(launcher.wait_for_rest_layer(es, max_attempts=3))

@mock.patch("elasticsearch.Elasticsearch", autospec=True)
def test_ssl_error(self, es):
import elasticsearch
import urllib3.exceptions

es.info.side_effect = elasticsearch.ConnectionError("N/A",
"[SSL: UNKNOWN_PROTOCOL] unknown protocol (_ssl.c:719)",
urllib3.exceptions.SSLError(
"[SSL: UNKNOWN_PROTOCOL] unknown protocol (_ssl.c:719)"))
with self.assertRaisesRegex(expected_exception=exceptions.LaunchError,
expected_regex="Could not connect to cluster via https. Is this a https endpoint?"):
launcher.wait_for_rest_layer(es, max_attempts=3)

0 comments on commit 7b9e03c

Please sign in to comment.