Skip to content

Commit 0a5a0bc

Browse files
anthonykuzmich7Anton Kuzmich
andauthored
Fix SentinelChannel to pass ACL credentials to master_for() (#2426)
* Fix SentinelChannel to pass ACL credentials to master_for() When using Redis Sentinel with ACL authentication (username + password), the SentinelChannel failed to pass credentials to the Redis master connection. The _connparams() method correctly extracts username and password, but they were only passed to sentinel.Sentinel() (for sentinel authentication), NOT to master_for() (for Redis master authentication). This fix ensures that ACL credentials are forwarded to master_for() so that Celery workers can connect to Redis Sentinel brokers that use ACL authentication (Redis 6.0+ feature). Fixes celery/celery#6301 * Remove commented-out code in Redis Sentinel tests for clarity * Add test to validate Redis Sentinel connection parameters This commit adds a test to ensure that the Redis Sentinel connection parameters are correctly passed to the connection class. The test verifies that the patched connection is called with the expected arguments, including the specified host, port, and authentication details. --------- Co-authored-by: Anton Kuzmich <anton.kuzmich@fairmarkit.com>
1 parent f204769 commit 0a5a0bc

2 files changed

Lines changed: 78 additions & 3 deletions

File tree

kombu/transport/redis.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1477,9 +1477,15 @@ def _sentinel_managed_pool(self, asynchronous=False):
14771477
"'master_name' transport option must be specified."
14781478
)
14791479

1480+
master_kwargs = {
1481+
k: additional_params[k]
1482+
for k in ('username', 'password') if k in additional_params
1483+
}
1484+
14801485
return sentinel_inst.master_for(
14811486
master_name,
14821487
redis.Redis,
1488+
**master_kwargs,
14831489
).connection_pool
14841490

14851491
def _get_pool(self, asynchronous=False):

t/unit/transport/test_redis.py

Lines changed: 72 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1934,7 +1934,10 @@ def test_getting_master_from_sentinel(self):
19341934

19351935
master_for = patched.return_value.master_for
19361936
master_for.assert_called()
1937-
master_for.assert_called_with('not_important', ANY)
1937+
master_for.assert_called_with(
1938+
'not_important', ANY,
1939+
username=None, password=None
1940+
)
19381941
master_for().connection_pool.get_connection.assert_called()
19391942

19401943
def test_getting_master_from_sentinel_single_node(self):
@@ -1957,7 +1960,10 @@ def test_getting_master_from_sentinel_single_node(self):
19571960

19581961
master_for = patched.return_value.master_for
19591962
master_for.assert_called()
1960-
master_for.assert_called_with('not_important', ANY)
1963+
master_for.assert_called_with(
1964+
'not_important', ANY,
1965+
username=None, password=None
1966+
)
19611967
master_for().connection_pool.get_connection.assert_called()
19621968

19631969
def test_getting_master_from_sentinel_with_client_name(self):
@@ -1985,7 +1991,70 @@ def test_getting_master_from_sentinel_with_client_name(self):
19851991

19861992
master_for = patched.return_value.master_for
19871993
master_for.assert_called()
1988-
master_for.assert_called_with('not_important', ANY)
1994+
master_for.assert_called_with(
1995+
'not_important', ANY,
1996+
username=None, password=None
1997+
)
1998+
master_for().connection_pool.get_connection.assert_called()
1999+
2000+
def test_getting_master_from_sentinel_with_acl_credentials(self):
2001+
with patch('redis.sentinel.Sentinel') as patched:
2002+
connection = Connection(
2003+
'sentinel://myuser:mypassword@localhost:65532/',
2004+
transport_options={
2005+
'master_name': 'not_important',
2006+
},
2007+
)
2008+
2009+
connection.channel()
2010+
2011+
patched.assert_called_once_with(
2012+
[
2013+
('localhost', 65532),
2014+
],
2015+
connection_class=ANY, db=0, max_connections=10,
2016+
min_other_sentinels=0, password='mypassword',
2017+
sentinel_kwargs=None,
2018+
socket_connect_timeout=None, socket_keepalive=None,
2019+
socket_keepalive_options=None, socket_timeout=None,
2020+
username='myuser', retry_on_timeout=None, client_name=None)
2021+
2022+
master_for = patched.return_value.master_for
2023+
master_for.assert_called()
2024+
master_for.assert_called_with(
2025+
'not_important', ANY,
2026+
username='myuser', password='mypassword'
2027+
)
2028+
master_for().connection_pool.get_connection.assert_called()
2029+
2030+
def test_getting_master_from_sentinel_with_password_only(self):
2031+
with patch('redis.sentinel.Sentinel') as patched:
2032+
connection = Connection(
2033+
'sentinel://:mypassword@localhost:65532/',
2034+
transport_options={
2035+
'master_name': 'not_important',
2036+
},
2037+
)
2038+
2039+
connection.channel()
2040+
2041+
patched.assert_called_once_with(
2042+
[
2043+
('localhost', 65532),
2044+
],
2045+
connection_class=ANY, db=0, max_connections=10,
2046+
min_other_sentinels=0, password='mypassword',
2047+
sentinel_kwargs=None,
2048+
socket_connect_timeout=None, socket_keepalive=None,
2049+
socket_keepalive_options=None, socket_timeout=None,
2050+
username=None, retry_on_timeout=None, client_name=None)
2051+
2052+
master_for = patched.return_value.master_for
2053+
master_for.assert_called()
2054+
master_for.assert_called_with(
2055+
'not_important', ANY,
2056+
username=None, password='mypassword'
2057+
)
19892058
master_for().connection_pool.get_connection.assert_called()
19902059

19912060
def test_can_create_connection(self):

0 commit comments

Comments
 (0)