From fbe83c8a7b49df25d599792817e1ad52469cf129 Mon Sep 17 00:00:00 2001 From: Takashi Kajinami Date: Sat, 6 Apr 2024 20:53:06 +0900 Subject: [PATCH] Support authentication with Redis Sentinel ... so that users can enable authentication in both Redis and Redis Sentinel. Change-Id: I3e68e23cf89081cca829d4f78f1d1b35a11d9496 --- ...tinel-authentication-93fa9b1846979e41.yaml | 6 ++++ zaqar/storage/redis/driver.py | 11 ++++--- zaqar/tests/unit/storage/test_impl_redis.py | 29 +++++++++++++++++++ 3 files changed, 42 insertions(+), 4 deletions(-) create mode 100644 releasenotes/notes/redis-sentinel-authentication-93fa9b1846979e41.yaml diff --git a/releasenotes/notes/redis-sentinel-authentication-93fa9b1846979e41.yaml b/releasenotes/notes/redis-sentinel-authentication-93fa9b1846979e41.yaml new file mode 100644 index 000000000..1143e9e49 --- /dev/null +++ b/releasenotes/notes/redis-sentinel-authentication-93fa9b1846979e41.yaml @@ -0,0 +1,6 @@ +--- +features: + - | + Now Redis driver supports authentication with Redis Sentinel. To use this + feature, add the ``redis_password`` query to the Redis URI. + The ``redis_username`` can be used when ACL feature is enabled. diff --git a/zaqar/storage/redis/driver.py b/zaqar/storage/redis/driver.py index d3f09032c..173299008 100644 --- a/zaqar/storage/redis/driver.py +++ b/zaqar/storage/redis/driver.py @@ -85,6 +85,8 @@ class ConnectionURI(object): # Sentinel self.master = None self.sentinels = [] + self.sentinel_username = query_params.get('sentinel_username') + self.sentinel_password = query_params.get('sentinel_password') if 'master' in query_params: # NOTE(prashanthr_): Configure redis driver in sentinel mode @@ -322,11 +324,12 @@ def _get_redis_client(driver): db=connection_uri.dbid, username=connection_uri.username, password=connection_uri.password, + sentinel_kwargs={ + 'socket_timeout': connection_uri.socket_timeout, + 'username': connection_uri.sentinel_username, + 'password': connection_uri.sentinel_password + }, socket_timeout=connection_uri.socket_timeout) - - # NOTE(prashanthr_): The socket_timeout parameter being generic - # to all redis connections is inherited from the parameters for - # sentinel. return sentinel.master_for(connection_uri.master) elif connection_uri.strategy == STRATEGY_TCP: diff --git a/zaqar/tests/unit/storage/test_impl_redis.py b/zaqar/tests/unit/storage/test_impl_redis.py index 63fac9f5a..339d3ad0c 100644 --- a/zaqar/tests/unit/storage/test_impl_redis.py +++ b/zaqar/tests/unit/storage/test_impl_redis.py @@ -337,6 +337,8 @@ class RedisDriverTest(testing.TestBase): self.assertEqual(0, uri.dbid) self.assertIsNone(uri.username) self.assertIsNone(uri.password) + self.assertIsNone(uri.sentinel_username) + self.assertIsNone(uri.sentinel_password) uri = driver.ConnectionURI('redis://s1,s2?master=dumbledore') self.assertEqual(driver.STRATEGY_SENTINEL, uri.strategy) @@ -346,6 +348,8 @@ class RedisDriverTest(testing.TestBase): self.assertEqual(0, uri.dbid) self.assertIsNone(uri.username) self.assertIsNone(uri.password) + self.assertIsNone(uri.sentinel_username) + self.assertIsNone(uri.sentinel_password) uri = driver.ConnectionURI('redis://s1:26389,s1?master=dumbledore') self.assertEqual(driver.STRATEGY_SENTINEL, uri.strategy) @@ -355,6 +359,8 @@ class RedisDriverTest(testing.TestBase): self.assertEqual(0, uri.dbid) self.assertIsNone(uri.username) self.assertIsNone(uri.password) + self.assertIsNone(uri.sentinel_username) + self.assertIsNone(uri.sentinel_password) uri = driver.ConnectionURI( 'redis://[::1]:26389,[::2]?master=dumbledore') @@ -365,6 +371,8 @@ class RedisDriverTest(testing.TestBase): self.assertEqual(0, uri.dbid) self.assertIsNone(uri.username) self.assertIsNone(uri.password) + self.assertIsNone(uri.sentinel_username) + self.assertIsNone(uri.sentinel_password) uri = driver.ConnectionURI( 'redis://s1?master=dumbledore&socket_timeout=0.5') @@ -375,6 +383,8 @@ class RedisDriverTest(testing.TestBase): self.assertEqual(0, uri.dbid) self.assertIsNone(uri.username) self.assertIsNone(uri.password) + self.assertIsNone(uri.sentinel_username) + self.assertIsNone(uri.sentinel_password) uri = driver.ConnectionURI( 'redis://:test123@s1?master=dumbledore&socket_timeout=0.5&dbid=5') @@ -385,6 +395,8 @@ class RedisDriverTest(testing.TestBase): self.assertEqual(5, uri.dbid) self.assertIsNone(uri.username) self.assertEqual('test123', uri.password) + self.assertIsNone(uri.sentinel_username) + self.assertIsNone(uri.sentinel_password) # NOTE(tkajinam): Test fallback for backword compatibility uri = driver.ConnectionURI( @@ -396,6 +408,8 @@ class RedisDriverTest(testing.TestBase): self.assertEqual(0, uri.dbid) self.assertIsNone(uri.username) self.assertEqual('test123', uri.password) + self.assertIsNone(uri.sentinel_username) + self.assertIsNone(uri.sentinel_password) uri = driver.ConnectionURI( 'redis://default:test123@s1?master=dumbledore') @@ -406,6 +420,21 @@ class RedisDriverTest(testing.TestBase): self.assertEqual(0, uri.dbid) self.assertEqual('default', uri.username) self.assertEqual('test123', uri.password) + self.assertIsNone(uri.sentinel_username) + self.assertIsNone(uri.sentinel_password) + + uri = driver.ConnectionURI( + 'redis://default:test123@s1?master=dumbledore' + '&sentinel_username=sentinel&sentinel_password=test456') + self.assertEqual(driver.STRATEGY_SENTINEL, uri.strategy) + self.assertEqual([('s1', 26379)], uri.sentinels) + self.assertEqual('dumbledore', uri.master) + self.assertEqual(0.1, uri.socket_timeout) + self.assertEqual(0, uri.dbid) + self.assertEqual('default', uri.username) + self.assertEqual('test123', uri.password) + self.assertEqual('sentinel', uri.sentinel_username) + self.assertEqual('test456', uri.sentinel_password) @testing.requires_redis