Merge "Add datastore configuration parameter support"
This commit is contained in:
commit
44ca384d8a
7 files changed
+253
No files matched your search
@@ -0,0 +1,7 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Added ``openstack datastore configuration set`` and
|
||||
``openstack datastore configuration delete`` commands. These commands
|
||||
allow operators to maintain datastore validation rules through the API
|
||||
without direct access to the Trove control plane.
|
||||
@@ -116,3 +116,5 @@ openstack.database.v1 =
|
||||
database_backup_strategy_list = troveclient.osc.v1.database_backup_strategy:ListDatabaseBackupStrategies
|
||||
database_backup_strategy_create = troveclient.osc.v1.database_backup_strategy:CreateDatabaseBackupStrategy
|
||||
database_backup_strategy_delete = troveclient.osc.v1.database_backup_strategy:DeleteDatabaseBackupStrategy
|
||||
datastore_configuration_set = troveclient.osc.v1.datastore_configurations:UpdateAllDatastoreConfiguration
|
||||
datastore_configuration_delete = troveclient.osc.v1.datastore_configurations:DeleteAllDatastoreConfiguration
|
||||
@@ -0,0 +1,82 @@
|
||||
# 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.
|
||||
|
||||
"""Database v1 Datastores action implementations"""
|
||||
|
||||
import json
|
||||
|
||||
from osc_lib.command import command
|
||||
|
||||
from troveclient import exceptions
|
||||
from troveclient.i18n import _
|
||||
|
||||
|
||||
class UpdateAllDatastoreConfiguration(command.Command):
|
||||
|
||||
_description = _("Updates all configuration parameters for "
|
||||
"a datastore version.")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(
|
||||
UpdateAllDatastoreConfiguration, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
'datastore_version',
|
||||
metavar='<datastore_version>',
|
||||
help=_('ID of the datastore version.')
|
||||
)
|
||||
parser.add_argument(
|
||||
'configuration_file',
|
||||
metavar='<configuration_file>',
|
||||
help=_('Path to a JSON with validation rules.')
|
||||
)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
client = self.app.client_manager.database.mgmt_configs
|
||||
|
||||
try:
|
||||
with open(parsed_args.configuration_file,
|
||||
encoding='utf-8') as config_file:
|
||||
body = json.load(config_file)
|
||||
|
||||
client.update_all(parsed_args.datastore_version,
|
||||
body['configuration-parameters'])
|
||||
except Exception as exc:
|
||||
msg = _("Failed to update datastore configuration parameters: "
|
||||
"%s") % exc
|
||||
raise exceptions.CommandError(msg)
|
||||
|
||||
|
||||
class DeleteAllDatastoreConfiguration(command.Command):
|
||||
|
||||
_description = _("Deletes all configuration parameters for "
|
||||
"a datastore version.")
|
||||
|
||||
def get_parser(self, prog_name):
|
||||
parser = super(
|
||||
DeleteAllDatastoreConfiguration, self).get_parser(prog_name)
|
||||
parser.add_argument(
|
||||
'datastore_version',
|
||||
metavar='<datastore_version>',
|
||||
help=_('ID of the datastore version.')
|
||||
)
|
||||
return parser
|
||||
|
||||
def take_action(self, parsed_args):
|
||||
client = self.app.client_manager.database.mgmt_configs
|
||||
|
||||
try:
|
||||
client.delete_all(parsed_args.datastore_version)
|
||||
except Exception as exc:
|
||||
msg = _("Failed to delete datastore configuration parameters: "
|
||||
"%s") % exc
|
||||
raise exceptions.CommandError(msg)
|
||||
@@ -0,0 +1,116 @@
|
||||
# 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.
|
||||
|
||||
import json
|
||||
from unittest import mock
|
||||
|
||||
from troveclient import exceptions
|
||||
from troveclient.osc.v1 import datastore_configurations
|
||||
from troveclient.tests.osc.v1 import fakes
|
||||
|
||||
|
||||
class TestDatastoreConfigurations(fakes.TestDatabasev1):
|
||||
|
||||
def setUp(self):
|
||||
super(TestDatastoreConfigurations, self).setUp()
|
||||
self.configuration_client = (
|
||||
self.app.client_manager.database.mgmt_configs
|
||||
)
|
||||
|
||||
|
||||
class TestUpdateAllDatastoreConfiguration(TestDatastoreConfigurations):
|
||||
|
||||
def setUp(self):
|
||||
super(TestUpdateAllDatastoreConfiguration, self).setUp()
|
||||
self.cmd = datastore_configurations.UpdateAllDatastoreConfiguration(
|
||||
self.app, None)
|
||||
|
||||
def test_update_all(self):
|
||||
body = {
|
||||
'configuration-parameters': [{
|
||||
'name': 'config_name',
|
||||
'restart_required': False,
|
||||
'type': 'integer',
|
||||
'max': 1000,
|
||||
'min': 1,
|
||||
}]
|
||||
}
|
||||
args = ['version-id', 'validation-rules.json']
|
||||
verifylist = [
|
||||
('datastore_version', 'version-id'),
|
||||
('configuration_file', 'validation-rules.json'),
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, args, verifylist)
|
||||
|
||||
mock_file = mock.mock_open(read_data=json.dumps(body))
|
||||
with mock.patch('builtins.open', mock_file):
|
||||
result = self.cmd.take_action(parsed_args)
|
||||
|
||||
mock_file.assert_called_once_with(
|
||||
'validation-rules.json', encoding='utf-8')
|
||||
self.configuration_client.update_all.assert_called_once_with(
|
||||
'version-id', body['configuration-parameters'])
|
||||
self.assertIsNone(result)
|
||||
|
||||
def test_update_all_invalid_json(self):
|
||||
args = ['version-id', 'validation-rules.json']
|
||||
parsed_args = self.check_parser(self.cmd, args, [])
|
||||
|
||||
mock_file = mock.mock_open(read_data='{invalid-json')
|
||||
with mock.patch('builtins.open', mock_file):
|
||||
self.assertRaises(
|
||||
exceptions.CommandError, self.cmd.take_action, parsed_args)
|
||||
|
||||
self.configuration_client.update_all.assert_not_called()
|
||||
|
||||
def test_update_all_error(self):
|
||||
body = {'configuration-parameters': []}
|
||||
args = ['version-id', 'validation-rules.json']
|
||||
parsed_args = self.check_parser(self.cmd, args, [])
|
||||
self.configuration_client.update_all.side_effect = (
|
||||
exceptions.CommandError)
|
||||
|
||||
mock_file = mock.mock_open(read_data=json.dumps(body))
|
||||
with mock.patch('builtins.open', mock_file):
|
||||
self.assertRaises(
|
||||
exceptions.CommandError, self.cmd.take_action, parsed_args)
|
||||
|
||||
self.configuration_client.update_all.assert_called_once_with(
|
||||
'version-id', [])
|
||||
|
||||
|
||||
class TestDeleteAllDatastoreConfiguration(TestDatastoreConfigurations):
|
||||
|
||||
def setUp(self):
|
||||
super(TestDeleteAllDatastoreConfiguration, self).setUp()
|
||||
self.cmd = datastore_configurations.DeleteAllDatastoreConfiguration(
|
||||
self.app, None)
|
||||
|
||||
def test_delete_all(self):
|
||||
args = ['version-id']
|
||||
verifylist = [
|
||||
('datastore_version', 'version-id'),
|
||||
]
|
||||
parsed_args = self.check_parser(self.cmd, args, verifylist)
|
||||
|
||||
result = self.cmd.take_action(parsed_args)
|
||||
self.configuration_client.delete_all.assert_called_once_with(
|
||||
'version-id')
|
||||
self.assertIsNone(result)
|
||||
|
||||
def test_delete_all_error(self):
|
||||
args = ['version-id']
|
||||
parsed_args = self.check_parser(self.cmd, args, [])
|
||||
self.configuration_client.delete_all.side_effect = (
|
||||
exceptions.CommandError)
|
||||
self.assertRaises(
|
||||
exceptions.CommandError, self.cmd.take_action, parsed_args)
|
||||
@@ -255,3 +255,31 @@ class MgmtConfigurationParametersTest(testtools.TestCase):
|
||||
self.assertEqual('/mgmt/datastores/versions/id/parameters/param_id',
|
||||
self._url)
|
||||
self.assertIsNone(self._body)
|
||||
|
||||
def test_update_all(self):
|
||||
self.config_params.api.client.patch = self._get_mock_method()
|
||||
self._resp.status_code = 202
|
||||
parameters = [{
|
||||
'name': 'config_name',
|
||||
'restart_required': False,
|
||||
'type': 'integer',
|
||||
'max': 1000,
|
||||
'min': 1,
|
||||
}]
|
||||
self.config_params.update_all('version-id', parameters)
|
||||
|
||||
expected_url = (
|
||||
'/mgmt/datastores/versions/version-id/parameters/update_all')
|
||||
self.assertEqual(expected_url, self._url)
|
||||
self.assertEqual({'configuration-parameters': parameters}, self._body)
|
||||
|
||||
def test_delete_all(self):
|
||||
self.config_params.api.client.delete = self._get_mock_method()
|
||||
self._resp.status_code = 204
|
||||
|
||||
self.config_params.delete_all('version-id')
|
||||
|
||||
expected_url = (
|
||||
'/mgmt/datastores/versions/version-id/parameters/delete_all')
|
||||
self.assertEqual(expected_url, self._url)
|
||||
self.assertIsNone(self._body)
|
||||
@@ -87,6 +87,7 @@ class Client(object):
|
||||
self.quota = quota.Quotas(self)
|
||||
self.mgmt_instances = management.Management(self)
|
||||
self.mgmt_ds_versions = management.MgmtDatastoreVersions(self)
|
||||
self.mgmt_configs = management.MgmtConfigurationParameters(self)
|
||||
|
||||
# Add in any extensions...
|
||||
if extensions:
|
||||
|
||||
@@ -252,6 +252,23 @@ class MgmtConfigurationParameters(configurations.ConfigurationParameters):
|
||||
resp, body = self.api.client.delete(url)
|
||||
common.check_for_exceptions(resp, body, url)
|
||||
|
||||
def update_all(self, version, configuration_parameters):
|
||||
"""Mgmt call to update all configuration parameters."""
|
||||
body = {
|
||||
'configuration-parameters': configuration_parameters
|
||||
}
|
||||
url = ("/mgmt/datastores/versions/%s/parameters/"
|
||||
"update_all" % version)
|
||||
resp, resp_body = self.api.client.patch(url, body=body)
|
||||
common.check_for_exceptions(resp, resp_body, url)
|
||||
|
||||
def delete_all(self, version):
|
||||
"""Mgmt call to delete all configuration parameters."""
|
||||
url = ("/mgmt/datastores/versions/%s/parameters/"
|
||||
"delete_all" % version)
|
||||
resp, body = self.api.client.delete(url)
|
||||
common.check_for_exceptions(resp, body, url)
|
||||
|
||||
|
||||
class MgmtDatastoreVersions(base.ManagerWithFind):
|
||||
"""Manage :class:`DatastoreVersion` resources."""
|
||||
|
||||
Reference in new issue
Block a user