Merge "jobboard: Support authentication and SSL for Redis Sentinel"
This commit is contained in:
commit
7974e755e1
@ -578,6 +578,10 @@ task_flow_opts = [
|
|||||||
'job id and claims for it.'),
|
'job id and claims for it.'),
|
||||||
cfg.StrOpt('jobboard_redis_sentinel', default=None,
|
cfg.StrOpt('jobboard_redis_sentinel', default=None,
|
||||||
help='Sentinel name if it is used for Redis.'),
|
help='Sentinel name if it is used for Redis.'),
|
||||||
|
cfg.StrOpt('jobboard_redis_sentinel_username',
|
||||||
|
help='Redis Sentinel server user name'),
|
||||||
|
cfg.StrOpt('jobboard_redis_sentinel_password', secret=True,
|
||||||
|
help='Redis Sentinel server password'),
|
||||||
cfg.DictOpt('jobboard_redis_backend_ssl_options',
|
cfg.DictOpt('jobboard_redis_backend_ssl_options',
|
||||||
help='Redis jobboard backend ssl configuration options.',
|
help='Redis jobboard backend ssl configuration options.',
|
||||||
default={'ssl': False,
|
default={'ssl': False,
|
||||||
@ -585,6 +589,13 @@ task_flow_opts = [
|
|||||||
'ssl_certfile': None,
|
'ssl_certfile': None,
|
||||||
'ssl_ca_certs': None,
|
'ssl_ca_certs': None,
|
||||||
'ssl_cert_reqs': 'required'}),
|
'ssl_cert_reqs': 'required'}),
|
||||||
|
cfg.DictOpt('jobboard_redis_sentinel_ssl_options',
|
||||||
|
help='Redis sentinel ssl configuration options.',
|
||||||
|
default={'ssl': False,
|
||||||
|
'ssl_keyfile': None,
|
||||||
|
'ssl_certfile': None,
|
||||||
|
'ssl_ca_certs': None,
|
||||||
|
'ssl_cert_reqs': 'required'}),
|
||||||
cfg.DictOpt('jobboard_zookeeper_ssl_options',
|
cfg.DictOpt('jobboard_zookeeper_ssl_options',
|
||||||
help='Zookeeper jobboard backend ssl configuration options.',
|
help='Zookeeper jobboard backend ssl configuration options.',
|
||||||
default={'use_ssl': False,
|
default={'use_ssl': False,
|
||||||
|
@ -15,6 +15,7 @@ import contextlib
|
|||||||
|
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_log import log
|
from oslo_log import log
|
||||||
|
from oslo_utils import strutils
|
||||||
from taskflow.jobs import backends as job_backends
|
from taskflow.jobs import backends as job_backends
|
||||||
from taskflow.persistence import backends as persistence_backends
|
from taskflow.persistence import backends as persistence_backends
|
||||||
|
|
||||||
@ -113,6 +114,19 @@ class RedisTaskFlowDriver(JobboardTaskFlowDriver):
|
|||||||
CONF.task_flow.jobboard_backend_password)
|
CONF.task_flow.jobboard_backend_password)
|
||||||
jobboard_backend_conf.update(
|
jobboard_backend_conf.update(
|
||||||
CONF.task_flow.jobboard_redis_backend_ssl_options)
|
CONF.task_flow.jobboard_redis_backend_ssl_options)
|
||||||
|
|
||||||
|
sentinel_kwargs = CONF.task_flow.jobboard_redis_sentinel_ssl_options
|
||||||
|
if 'ssl' in sentinel_kwargs:
|
||||||
|
sentinel_kwargs['ssl'] = strutils.bool_from_string(
|
||||||
|
sentinel_kwargs['ssl'])
|
||||||
|
if CONF.task_flow.jobboard_redis_sentinel_username is not None:
|
||||||
|
sentinel_kwargs['username'] = (
|
||||||
|
CONF.task_flow.jobboard_redis_sentinel_username)
|
||||||
|
if CONF.task_flow.jobboard_redis_sentinel_password is not None:
|
||||||
|
sentinel_kwargs['password'] = (
|
||||||
|
CONF.task_flow.jobboard_redis_sentinel_password)
|
||||||
|
jobboard_backend_conf['sentinel_kwargs'] = sentinel_kwargs
|
||||||
|
|
||||||
return job_backends.backend(
|
return job_backends.backend(
|
||||||
CONF.task_flow.jobboard_backend_namespace,
|
CONF.task_flow.jobboard_backend_namespace,
|
||||||
jobboard_backend_conf,
|
jobboard_backend_conf,
|
||||||
|
@ -35,6 +35,7 @@ class TestCase(testtools.TestCase):
|
|||||||
config.register_cli_opts()
|
config.register_cli_opts()
|
||||||
self.addCleanup(mock.patch.stopall)
|
self.addCleanup(mock.patch.stopall)
|
||||||
self.addCleanup(self.clean_caches)
|
self.addCleanup(self.clean_caches)
|
||||||
|
self.addCleanup(cfg.CONF.reset)
|
||||||
|
|
||||||
self.warning_fixture = self.useFixture(oc_fixtures.WarningsFixture())
|
self.warning_fixture = self.useFixture(oc_fixtures.WarningsFixture())
|
||||||
|
|
||||||
|
@ -0,0 +1,348 @@
|
|||||||
|
# Copyright 2024 NTT DATA Group Corporation
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
# not use this file except in compliance with the License. You may obtain
|
||||||
|
# a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
# License for the specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
#
|
||||||
|
from unittest import mock
|
||||||
|
|
||||||
|
from oslo_config import cfg
|
||||||
|
|
||||||
|
from octavia.controller.worker.v2 import taskflow_jobboard_driver
|
||||||
|
import octavia.tests.unit.base as base
|
||||||
|
|
||||||
|
|
||||||
|
class TestRedisTaskFlowDriver(base.TestCase):
|
||||||
|
|
||||||
|
@mock.patch('octavia.controller.worker.v2.taskflow_jobboard_driver.'
|
||||||
|
'job_backends')
|
||||||
|
def test_job_board_default(self, mock_job_backends):
|
||||||
|
driver = taskflow_jobboard_driver.RedisTaskFlowDriver(mock.Mock())
|
||||||
|
driver.job_board(None)
|
||||||
|
mock_job_backends.backend.assert_called_once_with(
|
||||||
|
'octavia_jobboard',
|
||||||
|
{
|
||||||
|
'board': 'redis',
|
||||||
|
'host': '127.0.0.1',
|
||||||
|
'port': 6379,
|
||||||
|
'namespace': 'octavia_jobboard',
|
||||||
|
'sentinel': None,
|
||||||
|
'sentinel_fallbacks': [],
|
||||||
|
'ssl': False,
|
||||||
|
'ssl_keyfile': None,
|
||||||
|
'ssl_certfile': None,
|
||||||
|
'ssl_ca_certs': None,
|
||||||
|
'ssl_cert_reqs': 'required',
|
||||||
|
'sentinel_kwargs': {
|
||||||
|
'ssl': False,
|
||||||
|
'ssl_keyfile': None,
|
||||||
|
'ssl_certfile': None,
|
||||||
|
'ssl_ca_certs': None,
|
||||||
|
'ssl_cert_reqs': 'required',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
persistence=None
|
||||||
|
)
|
||||||
|
|
||||||
|
@mock.patch('octavia.controller.worker.v2.taskflow_jobboard_driver.'
|
||||||
|
'job_backends')
|
||||||
|
def test_job_board_password(self, mock_job_backends):
|
||||||
|
driver = taskflow_jobboard_driver.RedisTaskFlowDriver(mock.Mock())
|
||||||
|
cfg.CONF.set_override('jobboard_backend_password', 'redispass',
|
||||||
|
group='task_flow')
|
||||||
|
driver.job_board(None)
|
||||||
|
mock_job_backends.backend.assert_called_once_with(
|
||||||
|
'octavia_jobboard',
|
||||||
|
{
|
||||||
|
'board': 'redis',
|
||||||
|
'host': '127.0.0.1',
|
||||||
|
'port': 6379,
|
||||||
|
'namespace': 'octavia_jobboard',
|
||||||
|
'password': 'redispass',
|
||||||
|
'sentinel': None,
|
||||||
|
'sentinel_fallbacks': [],
|
||||||
|
'ssl': False,
|
||||||
|
'ssl_keyfile': None,
|
||||||
|
'ssl_certfile': None,
|
||||||
|
'ssl_ca_certs': None,
|
||||||
|
'ssl_cert_reqs': 'required',
|
||||||
|
'sentinel_kwargs': {
|
||||||
|
'ssl': False,
|
||||||
|
'ssl_keyfile': None,
|
||||||
|
'ssl_certfile': None,
|
||||||
|
'ssl_ca_certs': None,
|
||||||
|
'ssl_cert_reqs': 'required',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
persistence=None
|
||||||
|
)
|
||||||
|
|
||||||
|
@mock.patch('octavia.controller.worker.v2.taskflow_jobboard_driver.'
|
||||||
|
'job_backends')
|
||||||
|
def test_job_board_username(self, mock_job_backends):
|
||||||
|
driver = taskflow_jobboard_driver.RedisTaskFlowDriver(mock.Mock())
|
||||||
|
cfg.CONF.set_override('jobboard_backend_password', 'redispass',
|
||||||
|
group='task_flow')
|
||||||
|
cfg.CONF.set_override('jobboard_backend_username', 'redisuser',
|
||||||
|
group='task_flow')
|
||||||
|
driver.job_board(None)
|
||||||
|
mock_job_backends.backend.assert_called_once_with(
|
||||||
|
'octavia_jobboard',
|
||||||
|
{
|
||||||
|
'board': 'redis',
|
||||||
|
'host': '127.0.0.1',
|
||||||
|
'port': 6379,
|
||||||
|
'namespace': 'octavia_jobboard',
|
||||||
|
'username': 'redisuser',
|
||||||
|
'password': 'redispass',
|
||||||
|
'sentinel': None,
|
||||||
|
'sentinel_fallbacks': [],
|
||||||
|
'ssl': False,
|
||||||
|
'ssl_keyfile': None,
|
||||||
|
'ssl_certfile': None,
|
||||||
|
'ssl_ca_certs': None,
|
||||||
|
'ssl_cert_reqs': 'required',
|
||||||
|
'sentinel_kwargs': {
|
||||||
|
'ssl': False,
|
||||||
|
'ssl_keyfile': None,
|
||||||
|
'ssl_certfile': None,
|
||||||
|
'ssl_ca_certs': None,
|
||||||
|
'ssl_cert_reqs': 'required',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
persistence=None
|
||||||
|
)
|
||||||
|
|
||||||
|
@mock.patch('octavia.controller.worker.v2.taskflow_jobboard_driver.'
|
||||||
|
'job_backends')
|
||||||
|
def test_job_board_ssl(self, mock_job_backends):
|
||||||
|
driver = taskflow_jobboard_driver.RedisTaskFlowDriver(mock.Mock())
|
||||||
|
cfg.CONF.set_override(
|
||||||
|
'jobboard_redis_backend_ssl_options',
|
||||||
|
{
|
||||||
|
'ssl': True,
|
||||||
|
'ssl_keyfile': 'rediskey',
|
||||||
|
'ssl_certfile': 'rediscert',
|
||||||
|
'ssl_ca_certs': 'redisca',
|
||||||
|
'ssl_cert_reqs': 'required'
|
||||||
|
},
|
||||||
|
group='task_flow')
|
||||||
|
driver.job_board(None)
|
||||||
|
mock_job_backends.backend.assert_called_once_with(
|
||||||
|
'octavia_jobboard',
|
||||||
|
{
|
||||||
|
'board': 'redis',
|
||||||
|
'host': '127.0.0.1',
|
||||||
|
'port': 6379,
|
||||||
|
'namespace': 'octavia_jobboard',
|
||||||
|
'sentinel': None,
|
||||||
|
'sentinel_fallbacks': [],
|
||||||
|
'ssl': True,
|
||||||
|
'ssl_keyfile': 'rediskey',
|
||||||
|
'ssl_certfile': 'rediscert',
|
||||||
|
'ssl_ca_certs': 'redisca',
|
||||||
|
'ssl_cert_reqs': 'required',
|
||||||
|
'sentinel_kwargs': {
|
||||||
|
'ssl': False,
|
||||||
|
'ssl_keyfile': None,
|
||||||
|
'ssl_certfile': None,
|
||||||
|
'ssl_ca_certs': None,
|
||||||
|
'ssl_cert_reqs': 'required',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
persistence=None
|
||||||
|
)
|
||||||
|
|
||||||
|
@mock.patch('octavia.controller.worker.v2.taskflow_jobboard_driver.'
|
||||||
|
'job_backends')
|
||||||
|
def test_job_board_sentinel(self, mock_job_backends):
|
||||||
|
driver = taskflow_jobboard_driver.RedisTaskFlowDriver(mock.Mock())
|
||||||
|
cfg.CONF.set_override('jobboard_redis_sentinel', 'mymaster',
|
||||||
|
group='task_flow')
|
||||||
|
cfg.CONF.set_override('jobboard_backend_hosts',
|
||||||
|
['host1', 'host2', 'host3'],
|
||||||
|
group='task_flow')
|
||||||
|
cfg.CONF.set_override('jobboard_backend_port', 26379,
|
||||||
|
group='task_flow')
|
||||||
|
driver.job_board(None)
|
||||||
|
mock_job_backends.backend.assert_called_once_with(
|
||||||
|
'octavia_jobboard',
|
||||||
|
{
|
||||||
|
'board': 'redis',
|
||||||
|
'host': 'host1',
|
||||||
|
'port': 26379,
|
||||||
|
'namespace': 'octavia_jobboard',
|
||||||
|
'sentinel': 'mymaster',
|
||||||
|
'sentinel_fallbacks': ['host2:26379', 'host3:26379'],
|
||||||
|
'ssl': False,
|
||||||
|
'ssl_keyfile': None,
|
||||||
|
'ssl_certfile': None,
|
||||||
|
'ssl_ca_certs': None,
|
||||||
|
'ssl_cert_reqs': 'required',
|
||||||
|
'sentinel_kwargs': {
|
||||||
|
'ssl': False,
|
||||||
|
'ssl_keyfile': None,
|
||||||
|
'ssl_certfile': None,
|
||||||
|
'ssl_ca_certs': None,
|
||||||
|
'ssl_cert_reqs': 'required',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
persistence=None
|
||||||
|
)
|
||||||
|
|
||||||
|
@mock.patch('octavia.controller.worker.v2.taskflow_jobboard_driver.'
|
||||||
|
'job_backends')
|
||||||
|
def test_job_board_sentinel_password(self, mock_job_backends):
|
||||||
|
driver = taskflow_jobboard_driver.RedisTaskFlowDriver(mock.Mock())
|
||||||
|
cfg.CONF.set_override('jobboard_redis_sentinel', 'mymaster',
|
||||||
|
group='task_flow')
|
||||||
|
cfg.CONF.set_override('jobboard_backend_hosts',
|
||||||
|
['host1', 'host2', 'host3'],
|
||||||
|
group='task_flow')
|
||||||
|
cfg.CONF.set_override('jobboard_backend_port', 26379,
|
||||||
|
group='task_flow')
|
||||||
|
cfg.CONF.set_override('jobboard_backend_password', 'redispass',
|
||||||
|
group='task_flow')
|
||||||
|
cfg.CONF.set_override('jobboard_redis_sentinel_password',
|
||||||
|
'sentinelpass', group='task_flow')
|
||||||
|
driver.job_board(None)
|
||||||
|
mock_job_backends.backend.assert_called_once_with(
|
||||||
|
'octavia_jobboard',
|
||||||
|
{
|
||||||
|
'board': 'redis',
|
||||||
|
'host': 'host1',
|
||||||
|
'port': 26379,
|
||||||
|
'namespace': 'octavia_jobboard',
|
||||||
|
'password': 'redispass',
|
||||||
|
'sentinel': 'mymaster',
|
||||||
|
'sentinel_fallbacks': ['host2:26379', 'host3:26379'],
|
||||||
|
'ssl': False,
|
||||||
|
'ssl_keyfile': None,
|
||||||
|
'ssl_certfile': None,
|
||||||
|
'ssl_ca_certs': None,
|
||||||
|
'ssl_cert_reqs': 'required',
|
||||||
|
'sentinel_kwargs': {
|
||||||
|
'password': 'sentinelpass',
|
||||||
|
'ssl': False,
|
||||||
|
'ssl_keyfile': None,
|
||||||
|
'ssl_certfile': None,
|
||||||
|
'ssl_ca_certs': None,
|
||||||
|
'ssl_cert_reqs': 'required',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
persistence=None
|
||||||
|
)
|
||||||
|
|
||||||
|
@mock.patch('octavia.controller.worker.v2.taskflow_jobboard_driver.'
|
||||||
|
'job_backends')
|
||||||
|
def test_job_board_sentinel_username(self, mock_job_backends):
|
||||||
|
driver = taskflow_jobboard_driver.RedisTaskFlowDriver(mock.Mock())
|
||||||
|
cfg.CONF.set_override('jobboard_redis_sentinel', 'mymaster',
|
||||||
|
group='task_flow')
|
||||||
|
cfg.CONF.set_override('jobboard_backend_hosts',
|
||||||
|
['host1', 'host2', 'host3'],
|
||||||
|
group='task_flow')
|
||||||
|
cfg.CONF.set_override('jobboard_backend_port', 26379,
|
||||||
|
group='task_flow')
|
||||||
|
cfg.CONF.set_override('jobboard_backend_username', 'redisuser',
|
||||||
|
group='task_flow')
|
||||||
|
cfg.CONF.set_override('jobboard_backend_password', 'redispass',
|
||||||
|
group='task_flow')
|
||||||
|
cfg.CONF.set_override('jobboard_redis_sentinel_username',
|
||||||
|
'sentineluser', group='task_flow')
|
||||||
|
cfg.CONF.set_override('jobboard_redis_sentinel_password',
|
||||||
|
'sentinelpass', group='task_flow')
|
||||||
|
driver.job_board(None)
|
||||||
|
mock_job_backends.backend.assert_called_once_with(
|
||||||
|
'octavia_jobboard',
|
||||||
|
{
|
||||||
|
'board': 'redis',
|
||||||
|
'host': 'host1',
|
||||||
|
'port': 26379,
|
||||||
|
'namespace': 'octavia_jobboard',
|
||||||
|
'username': 'redisuser',
|
||||||
|
'password': 'redispass',
|
||||||
|
'sentinel': 'mymaster',
|
||||||
|
'sentinel_fallbacks': ['host2:26379', 'host3:26379'],
|
||||||
|
'ssl': False,
|
||||||
|
'ssl_keyfile': None,
|
||||||
|
'ssl_certfile': None,
|
||||||
|
'ssl_ca_certs': None,
|
||||||
|
'ssl_cert_reqs': 'required',
|
||||||
|
'sentinel_kwargs': {
|
||||||
|
'username': 'sentineluser',
|
||||||
|
'password': 'sentinelpass',
|
||||||
|
'ssl': False,
|
||||||
|
'ssl_keyfile': None,
|
||||||
|
'ssl_certfile': None,
|
||||||
|
'ssl_ca_certs': None,
|
||||||
|
'ssl_cert_reqs': 'required',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
persistence=None
|
||||||
|
)
|
||||||
|
|
||||||
|
@mock.patch('octavia.controller.worker.v2.taskflow_jobboard_driver.'
|
||||||
|
'job_backends')
|
||||||
|
def test_job_board_sentinel_ssl(self, mock_job_backends):
|
||||||
|
driver = taskflow_jobboard_driver.RedisTaskFlowDriver(mock.Mock())
|
||||||
|
cfg.CONF.set_override('jobboard_redis_sentinel', 'mymaster',
|
||||||
|
group='task_flow')
|
||||||
|
cfg.CONF.set_override('jobboard_backend_hosts',
|
||||||
|
['host1', 'host2', 'host3'],
|
||||||
|
group='task_flow')
|
||||||
|
cfg.CONF.set_override('jobboard_backend_port', 26379,
|
||||||
|
group='task_flow')
|
||||||
|
cfg.CONF.set_override(
|
||||||
|
'jobboard_redis_backend_ssl_options',
|
||||||
|
{
|
||||||
|
'ssl': True,
|
||||||
|
'ssl_keyfile': 'rediskey',
|
||||||
|
'ssl_certfile': 'rediscert',
|
||||||
|
'ssl_ca_certs': 'redisca',
|
||||||
|
'ssl_cert_reqs': 'required'
|
||||||
|
},
|
||||||
|
group='task_flow')
|
||||||
|
cfg.CONF.set_override(
|
||||||
|
'jobboard_redis_sentinel_ssl_options',
|
||||||
|
{
|
||||||
|
'ssl': True,
|
||||||
|
'ssl_keyfile': 'sentinelkey',
|
||||||
|
'ssl_certfile': 'sentinelcert',
|
||||||
|
'ssl_ca_certs': 'sentinelca',
|
||||||
|
'ssl_cert_reqs': 'required'
|
||||||
|
},
|
||||||
|
group='task_flow')
|
||||||
|
driver.job_board(None)
|
||||||
|
mock_job_backends.backend.assert_called_once_with(
|
||||||
|
'octavia_jobboard',
|
||||||
|
{
|
||||||
|
'board': 'redis',
|
||||||
|
'host': 'host1',
|
||||||
|
'port': 26379,
|
||||||
|
'namespace': 'octavia_jobboard',
|
||||||
|
'sentinel': 'mymaster',
|
||||||
|
'sentinel_fallbacks': ['host2:26379', 'host3:26379'],
|
||||||
|
'ssl': True,
|
||||||
|
'ssl_keyfile': 'rediskey',
|
||||||
|
'ssl_certfile': 'rediscert',
|
||||||
|
'ssl_ca_certs': 'redisca',
|
||||||
|
'ssl_cert_reqs': 'required',
|
||||||
|
'sentinel_kwargs': {
|
||||||
|
'ssl': True,
|
||||||
|
'ssl_keyfile': 'sentinelkey',
|
||||||
|
'ssl_certfile': 'sentinelcert',
|
||||||
|
'ssl_ca_certs': 'sentinelca',
|
||||||
|
'ssl_cert_reqs': 'required'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
persistence=None
|
||||||
|
)
|
@ -0,0 +1,13 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
The following options, to enable authentication in Redis Sentinel, have
|
||||||
|
been added.
|
||||||
|
|
||||||
|
- ``[task_flow] jobboard_redis_sentinel_username``
|
||||||
|
- ``[task_flow] jobboard_redis_sentinel_password``
|
||||||
|
|
||||||
|
- |
|
||||||
|
The new ``[task_flow] jobboard_redis_sentinel_ssl_options`` option has
|
||||||
|
been added. This option controls SSL settings for connections to Redis
|
||||||
|
Sentinel.
|
Loading…
Reference in New Issue
Block a user