Add sentinel redis support

Redis client has an ability to connect to Redis server
using Sentinel[1] (especially important for Redis clusters),
but this ability was missing here.

Allow to pass 'sentinel' variable to Redis conf, extend
_make_client to use sentinel for that case.

[1] - https://github.com/andymccurdy/redis-py#sentinel-support

Change-Id: Ia8cc98e701435fd0231da3724f5d7108fc4f96f4
This commit is contained in:
Ann Taraday 2020-07-28 17:29:54 +04:00
parent cf327a2e2d
commit f17252de50
3 changed files with 54 additions and 1 deletions

View File

@ -0,0 +1,6 @@
---
features:
- |
Allow to use Sentinel for Redis connections. New variable *sentinel* can be
passed to Redis jobboard. It is None by default, Sentinel name should be passed
to enable this functionality.

View File

@ -29,6 +29,7 @@ from oslo_utils import strutils
from oslo_utils import timeutils
from oslo_utils import uuidutils
from redis import exceptions as redis_exceptions
from redis import sentinel
import six
from six.moves import range as compat_range
@ -567,7 +568,19 @@ return cmsgpack.pack(result)
client_conf[key] = value_type_converter(conf[key])
else:
client_conf[key] = conf[key]
return ru.RedisClient(**client_conf)
if conf.get('sentinel') is not None:
sentinel_conf = {}
# sentinel do not have ssl kwargs
for key in client_conf:
if 'ssl' not in key:
sentinel_conf[key] = client_conf[key]
s = sentinel.Sentinel([(sentinel_conf.pop('host'),
sentinel_conf.pop('port'))],
sentinel_kwargs=conf.get('sentinel_kwargs'),
**sentinel_conf)
return s.master_for(conf['sentinel'])
else:
return ru.RedisClient(**client_conf)
def __init__(self, name, conf,
client=None, persistence=None):

View File

@ -15,6 +15,7 @@
# under the License.
import time
from unittest import mock
from oslo_utils import uuidutils
import six
@ -102,3 +103,36 @@ class RedisJobboardTest(test.TestCase, base.BoardTestMixin):
def setUp(self):
super(RedisJobboardTest, self).setUp()
self.client, self.board = self.create_board()
def test__make_client(self):
conf = {'host': '127.0.0.1',
'port': 6379,
'password': 'secret',
'namespace': 'test'
}
test_conf = {
'host': '127.0.0.1',
'port': 6379,
'password': 'secret',
}
with mock.patch('taskflow.utils.redis_utils.RedisClient') as mock_ru:
impl_redis.RedisJobBoard('test-board', conf)
mock_ru.assert_called_once_with(**test_conf)
def test__make_client_sentinel(self):
conf = {'host': '127.0.0.1',
'port': 26379,
'password': 'secret',
'namespace': 'test',
'sentinel': 'mymaster',
'sentinel_kwargs': {'password': 'senitelsecret'}}
with mock.patch('redis.sentinel.Sentinel') as mock_sentinel:
impl_redis.RedisJobBoard('test-board', conf)
test_conf = {
'password': 'secret',
}
mock_sentinel.assert_called_once_with(
[('127.0.0.1', 26379)],
sentinel_kwargs={'password': 'senitelsecret'},
**test_conf)
mock_sentinel().master_for.assert_called_once_with('mymaster')