From 9fbeefd6046a901fe1b653d84c2f01c13a2094ec Mon Sep 17 00:00:00 2001 From: dHannasch Date: Fri, 13 Nov 2020 16:39:44 -0700 Subject: [PATCH] Distinguish a bad --redis-password from any other Redis error (#11893) --- python/ray/_private/services.py | 11 +++++++++++ python/ray/tests/test_ray_init.py | 17 +++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/python/ray/_private/services.py b/python/ray/_private/services.py index f15ca5aa7..b8d63b7b3 100644 --- a/python/ray/_private/services.py +++ b/python/ray/_private/services.py @@ -608,6 +608,17 @@ def wait_for_redis_to_start(redis_ip_address, redis_port, password=None): "Waiting for redis server at {}:{} to respond...".format( redis_ip_address, redis_port)) redis_client.client_list() + # If the Redis service is delayed getting set up for any reason, we may + # get a redis.ConnectionError: Error 111 connecting to host:port. + # Connection refused. + # Unfortunately, redis.ConnectionError is also the base class of + # redis.AuthenticationError. We *don't* want to obscure a + # redis.AuthenticationError, because that indicates the user provided a + # bad password. Thus a double except clause to ensure a + # redis.AuthenticationError isn't trapped here. + except redis.AuthenticationError as authEx: + raise RuntimeError("Unable to connect to Redis at {}:{}.".format( + redis_ip_address, redis_port)) from authEx except redis.ConnectionError: # Wait a little bit. time.sleep(delay) diff --git a/python/ray/tests/test_ray_init.py b/python/ray/tests/test_ray_init.py index ad9f96ca2..5c42678d0 100644 --- a/python/ray/tests/test_ray_init.py +++ b/python/ray/tests/test_ray_init.py @@ -3,6 +3,7 @@ import pytest import redis import ray +import ray._private.services from ray.cluster_utils import Cluster @@ -33,6 +34,22 @@ class TestRedisPassword: host=redis_ip, port=redis_port, password=None) with pytest.raises(redis.exceptions.AuthenticationError): redis_client.ping() + # We want to simulate how this is called by ray.scripts.start(). + try: + ray._private.services.wait_for_redis_to_start( + redis_ip, redis_port, password="wrong password") + # We catch a generic Exception here in case someone later changes the + # type of the exception. + except Exception as ex: + if not isinstance(ex.__cause__, redis.AuthenticationError): + raise + # By contrast, we may be fairly confident the exact string + # 'invalid password' won't go away, because redis-py simply wraps + # the exact error from the Redis library. + # https://github.com/andymccurdy/redis-py/blob/master/ + # redis/connection.py#L132 + if "invalid password" not in str(ex.__cause__): + raise # Check that we can connect to Redis using the provided password redis_client = redis.StrictRedis(