Initialize RedisAdmin with correct config command

Redis at deployment time, for security reasons will hide
the 'CONFIG' command from end users by mangling its name.
The mangled config command name will be written to the
config file, and also applied runtime.. When it restarts,
guestagent will use the default config command instead of
the correct one in the configuration file, then will lead
to failure. The patch will initialize RedisAdmin with
the correct config command

Closes-Bug: #1726341

Change-Id: I35c60d085ac53475683c993a0b9a053a07ae763f
This commit is contained in:
jiansong 2017-10-25 23:35:15 -07:00 committed by Luke Browning
parent 989451ae91
commit 3a6a3b44ba
4 changed files with 27 additions and 5 deletions

View File

@ -107,8 +107,10 @@ class RedisApp(object):
def _build_admin_client(self):
password = self.get_configuration_property('requirepass')
socket = self.get_configuration_property('unixsocket')
cmd = self.get_config_command_name()
return RedisAdmin(password=password, unix_socket_path=socket)
return RedisAdmin(password=password, unix_socket_path=socket,
config_cmd=cmd)
def install_if_needed(self, packages):
"""
@ -406,10 +408,10 @@ class RedisAdmin(object):
DEFAULT_CONFIG_CMD = 'CONFIG'
def __init__(self, password=None, unix_socket_path=None):
def __init__(self, password=None, unix_socket_path=None, config_cmd=None):
self.__client = redis.StrictRedis(
password=password, unix_socket_path=unix_socket_path)
self.__config_cmd_name = self.DEFAULT_CONFIG_CMD
self.__config_cmd_name = config_cmd or self.DEFAULT_CONFIG_CMD
def set_config_command_name(self, name):
"""Set name of the 'CONFIG' command or None for default.

View File

@ -28,6 +28,7 @@ from trove.conductor import api as conductor_api
from trove.guestagent.backup import backupagent
from trove.guestagent.common import configuration
from trove.guestagent.common.configuration import ImportOverrideStrategy
from trove.guestagent.datastore.experimental.redis.service import RedisApp
from trove.guestagent.strategies.backup.base import BackupRunner
from trove.guestagent.strategies.backup.base import UnknownBackupType
from trove.guestagent.strategies.backup.experimental import couchbase_impl
@ -283,6 +284,8 @@ class BackupAgentTest(trove_testtools.TestCase):
@patch.object(configuration.ConfigurationManager, 'parse_configuration',
Mock(return_value={'dir': '/var/lib/redis',
'dbfilename': 'dump.rdb'}))
@patch.object(RedisApp, 'get_config_command_name',
Mock(return_value='fakeconfig'))
def test_backup_impl_RedisBackup(self, *mocks):
netutils.get_my_ipv4 = Mock(return_value="1.1.1.1")
redis_backup = redis_impl.RedisBackup('redisbackup', extra_opts='')

View File

@ -26,6 +26,7 @@ from trove.guestagent.datastore.experimental.cassandra import (
)
from trove.guestagent.datastore.experimental.db2 import (
service as db2_service)
from trove.guestagent.datastore.experimental.redis.service import RedisApp
from trove.guestagent.strategies.backup import base as backupBase
from trove.guestagent.strategies.backup.experimental import db2_impl
from trove.guestagent.strategies.backup.experimental.postgresql_impl \
@ -401,6 +402,8 @@ class GuestAgentBackupTest(trove_testtools.TestCase):
@patch.object(configuration.ConfigurationManager, 'parse_configuration',
mock.Mock(return_value={'dir': '/var/lib/redis',
'dbfilename': 'dump.rdb'}))
@patch.object(RedisApp, 'get_config_command_name',
Mock(return_value='fakeconfig'))
def test_backup_encrypted_redisbackup_command(self, *mocks):
backupBase.BackupRunner.encrypt_key = CRYPTO_KEY
RunnerClass = utils.import_class(BACKUP_REDIS_CLS)
@ -414,6 +417,8 @@ class GuestAgentBackupTest(trove_testtools.TestCase):
@patch.object(configuration.ConfigurationManager, 'parse_configuration',
mock.Mock(return_value={'dir': '/var/lib/redis',
'dbfilename': 'dump.rdb'}))
@patch.object(RedisApp, 'get_config_command_name',
Mock(return_value='fakeconfig'))
def test_backup_not_encrypted_redisbackup_command(self, *mocks):
backupBase.BackupRunner.is_encrypted = False
backupBase.BackupRunner.encrypt_key = CRYPTO_KEY
@ -428,6 +433,8 @@ class GuestAgentBackupTest(trove_testtools.TestCase):
'dbfilename': 'dump.rdb'}))
@patch.object(operating_system, 'chown')
@patch.object(operating_system, 'create_directory')
@patch.object(RedisApp, 'get_config_command_name',
Mock(return_value='fakeconfig'))
def test_restore_decrypted_redisbackup_command(self, *mocks):
restoreBase.RestoreRunner.is_encrypted = False
RunnerClass = utils.import_class(RESTORE_REDIS_CLS)
@ -440,6 +447,8 @@ class GuestAgentBackupTest(trove_testtools.TestCase):
'dbfilename': 'dump.rdb'}))
@patch.object(operating_system, 'chown')
@patch.object(operating_system, 'create_directory')
@patch.object(RedisApp, 'get_config_command_name',
Mock(return_value='fakeconfig'))
def test_restore_encrypted_redisbackup_command(self, *mocks):
restoreBase.RestoreRunner.decrypt_key = CRYPTO_KEY
RunnerClass = utils.import_class(RESTORE_REDIS_CLS)
@ -851,6 +860,8 @@ class RedisBackupTests(trove_testtools.TestCase):
def tearDown(self):
super(RedisBackupTests, self).tearDown()
@patch.object(RedisApp, 'get_config_command_name',
Mock(return_value='fakeconfig'))
def test_backup_success(self):
with self.backup_runner(12345):
pass
@ -859,6 +870,8 @@ class RedisBackupTests(trove_testtools.TestCase):
self.backup_runner_mocks['_run'].assert_called_once_with()
self.backup_runner_mocks['_run_post_backup'].assert_called_once_with()
@patch.object(RedisApp, 'get_config_command_name',
Mock(return_value='fakeconfig'))
def test_backup_failed_due_to_run_backup(self):
self.backup_runner_mocks['_run'].configure_mock(
side_effect=exception.TroveError('test')
@ -873,7 +886,8 @@ class RedisBackupTests(trove_testtools.TestCase):
class RedisRestoreTests(trove_testtools.TestCase):
@patch.object(RedisApp, 'get_config_command_name',
Mock(return_value='fakeconfig'))
def setUp(self):
super(RedisRestoreTests, self).setUp()
self.conf_man_patch = patch.object(

View File

@ -12,7 +12,7 @@
# License for the specific language governing permissions and limitations
# under the License.
from mock import DEFAULT, MagicMock, patch
from mock import DEFAULT, MagicMock, Mock, patch
from trove.guestagent import backup
from trove.guestagent.common import configuration
@ -177,6 +177,9 @@ class RedisGuestAgentManagerTest(DatastoreManagerTest):
'dbfilename': 'dump.rdb'}))
@patch.object(operating_system, 'chown')
@patch.object(operating_system, 'create_directory')
@patch.object(redis_service.RedisApp,
'get_config_command_name',
Mock(return_value='fakeconfig'))
def test_create_backup(self, *mocks):
backup.backup = MagicMock(return_value=None)
RedisManager().create_backup(self.context, 'backup_id_123')