summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLingxian Kong <anlin.kong@gmail.com>2020-06-03 11:21:12 +1200
committerLingxian Kong <anlin.kong@gmail.com>2020-06-03 15:23:55 +1200
commit99126428cef64e5b985c66903d3c8444beed0f91 (patch)
treeb28fd4cac92e49d067b26680d4e1c27e1206ef36
parente2bf7cff227eb464550aac1f94b504265c5ed26a (diff)
downloadpython-troveclient-99126428cef64e5b985c66903d3c8444beed0f91.tar.gz
Support role for listing instances4.0.0
Change-Id: Ia3e8d5d65bc134f3c7bc62ca9c170018be54660c
-rw-r--r--releasenotes/notes/victoria-add-role-for-instances.yaml4
-rw-r--r--troveclient/osc/v1/database_instances.py20
-rw-r--r--troveclient/tests/fakes.py1
-rw-r--r--troveclient/tests/osc/v1/test_database_instances.py13
-rw-r--r--troveclient/tests/test_v1_shell.py965
5 files changed, 26 insertions, 977 deletions
diff --git a/releasenotes/notes/victoria-add-role-for-instances.yaml b/releasenotes/notes/victoria-add-role-for-instances.yaml
new file mode 100644
index 0000000..9c4371a
--- /dev/null
+++ b/releasenotes/notes/victoria-add-role-for-instances.yaml
@@ -0,0 +1,4 @@
+---
+features:
+ - Add replication 'Role' for listing instances to indicate if the instance is
+ a master or a replica.
diff --git a/troveclient/osc/v1/database_instances.py b/troveclient/osc/v1/database_instances.py
index 9eecb18..f363cb1 100644
--- a/troveclient/osc/v1/database_instances.py
+++ b/troveclient/osc/v1/database_instances.py
@@ -34,16 +34,24 @@ def set_attributes_for_print(instances):
else:
setattr(instance, 'size', '-')
+ if hasattr(instance, 'ip'):
+ addresses = ', '.join(instance.ip)
+ setattr(instance, 'addresses', addresses)
+
+ # If 'replica_of' not in instance, the client will invoke a GET
+ # instance request to API.
+ if hasattr(instance, 'replica_of'):
+ setattr(instance, 'role', 'replica')
+
+ if hasattr(instance, 'replicas'):
+ setattr(instance, 'role', 'master')
+
if hasattr(instance, 'datastore'):
if instance.datastore.get('version'):
setattr(instance, 'datastore_version',
instance.datastore['version'])
setattr(instance, 'datastore', instance.datastore['type'])
- if hasattr(instance, 'ip'):
- addresses = ', '.join(instance.ip)
- setattr(instance, 'addresses', addresses)
-
return instances
@@ -82,10 +90,10 @@ def set_attributes_for_print_detail(instance):
class ListDatabaseInstances(command.Lister):
_description = _("List database instances")
columns = ['ID', 'Name', 'Datastore', 'Datastore Version', 'Status',
- 'Addresses', 'Flavor ID', 'Size', 'Region']
+ 'Addresses', 'Flavor ID', 'Size', 'Region', 'Role']
admin_columns = [
'ID', 'Name', 'Tenant ID', 'Datastore', 'Datastore Version', 'Status',
- 'Addresses', 'Flavor ID', 'Size'
+ 'Addresses', 'Flavor ID', 'Size', 'Role'
]
def get_parser(self, prog_name):
diff --git a/troveclient/tests/fakes.py b/troveclient/tests/fakes.py
index a863623..979bc6b 100644
--- a/troveclient/tests/fakes.py
+++ b/troveclient/tests/fakes.py
@@ -173,6 +173,7 @@ class FakeHTTPClient(base_client.HTTPClient):
"region": "regionOne",
"datastore": {"version": "5.6", "type": "mysql"},
"tenant_id": "fake_tenant_id",
+ "replica_of": {"id": "fake_master_id"}
},
{
"id": "5678",
diff --git a/troveclient/tests/osc/v1/test_database_instances.py b/troveclient/tests/osc/v1/test_database_instances.py
index dbe6f3f..c08a089 100644
--- a/troveclient/tests/osc/v1/test_database_instances.py
+++ b/troveclient/tests/osc/v1/test_database_instances.py
@@ -56,9 +56,9 @@ class TestInstanceList(TestInstances):
values = [
('1234', 'test-member-1', 'mysql', '5.6', 'ACTIVE', '10.0.0.13',
- '02', 2, 'regionOne'),
+ '02', 2, 'regionOne', 'replica'),
('5678', 'test-member-2', 'mysql', '5.6', 'ACTIVE', '10.0.0.14',
- '2', 2, 'regionOne')
+ '2', 2, 'regionOne', '')
]
self.assertEqual(values, data)
@@ -77,16 +77,16 @@ class TestInstanceList(TestInstances):
expected_instances = [
('1234', 'test-member-1', 'fake_tenant_id', 'mysql', '5.6',
- 'ACTIVE', '10.0.0.13', '02', 2),
+ 'ACTIVE', '10.0.0.13', '02', 2, 'replica'),
('5678', 'test-member-2', 'fake_tenant_id', 'mysql', '5.6',
- 'ACTIVE', '10.0.0.14', '2', 2)
+ 'ACTIVE', '10.0.0.14', '2', 2, '')
]
self.assertEqual(expected_instances, instances)
class TestInstanceShow(TestInstances):
- values = ('mysql', '5.6', '02', '1234', '10.0.0.13',
- 'test-member-1', 'regionOne', 'ACTIVE', 'fake_tenant_id', 2)
+ values = ('mysql', '5.6', '02', '1234', '10.0.0.13', 'test-member-1',
+ 'regionOne', 'fake_master_id', 'ACTIVE', 'fake_tenant_id', 2)
def setUp(self):
super(TestInstanceShow, self).setUp()
@@ -101,6 +101,7 @@ class TestInstanceShow(TestInstances):
'ip',
'name',
'region',
+ 'replica_of',
'status',
'tenant_id',
'volume',
diff --git a/troveclient/tests/test_v1_shell.py b/troveclient/tests/test_v1_shell.py
deleted file mode 100644
index fc26e66..0000000
--- a/troveclient/tests/test_v1_shell.py
+++ /dev/null
@@ -1,965 +0,0 @@
-# Copyright [2015] Hewlett-Packard Development Company, L.P.
-# All Rights Reserved.
-#
-# 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 base64
-from unittest import mock
-
-import fixtures
-import re
-import six
-import testtools
-
-import troveclient.client
-from troveclient import exceptions
-import troveclient.shell
-from troveclient.tests import fakes
-from troveclient.tests import utils
-import troveclient.v1.modules
-import troveclient.v1.shell
-
-
-class ShellFixture(fixtures.Fixture):
-
- def setUp(self):
- super(ShellFixture, self).setUp()
- self.shell = troveclient.shell.OpenStackTroveShell()
-
- def tearDown(self):
- if hasattr(self.shell, 'cs'):
- self.shell.cs.clear_callstack()
- super(ShellFixture, self).tearDown()
-
-
-class ShellTest(utils.TestCase):
- FAKE_ENV = {
- 'OS_USERNAME': 'username',
- 'OS_PASSWORD': 'password',
- 'OS_PROJECT_ID': 'project_id',
- 'OS_AUTH_URL': 'http://no.where/v2.0',
- }
-
- def setUp(self, *args):
- """Run before each test."""
- super(ShellTest, self).setUp()
-
- for var in self.FAKE_ENV:
- self.useFixture(fixtures.EnvironmentVariable(var,
- self.FAKE_ENV[var]))
- self.shell = self.useFixture(ShellFixture()).shell
-
- @mock.patch('sys.stdout', new_callable=six.StringIO)
- @mock.patch('troveclient.client.get_version_map',
- return_value=fakes.get_version_map())
- @mock.patch('troveclient.v1.shell._find_instance_or_cluster',
- return_value=('1234', 'instance'))
- def run_command(self, cmd, mock_find_instance_or_cluster,
- mock_get_version_map, mock_stdout):
- if isinstance(cmd, list):
- self.shell.main(cmd)
- else:
- self.shell.main(cmd.split())
- return mock_stdout.getvalue()
-
- @mock.patch('sys.stdout', new_callable=six.StringIO)
- @mock.patch('troveclient.client.get_version_map',
- return_value=fakes.get_version_map())
- @mock.patch('troveclient.v1.shell._find_instance_or_cluster',
- return_value=('cls-1234', 'cluster'))
- def run_command_clusters(self, cmd, mock_find_instance_or_cluster,
- mock_get_version_map, mock_stdout):
- if isinstance(cmd, list):
- self.shell.main(cmd)
- else:
- self.shell.main(cmd.split())
- return mock_stdout.getvalue()
-
- def assert_called(self, method, url, body=None, **kwargs):
- return self.shell.cs.assert_called(method, url, body, **kwargs)
-
- def assert_called_anytime(self, method, url, body=None):
- return self.shell.cs.assert_called_anytime(method, url, body)
-
- def test__strip_option(self):
- # Format is: opt_name, opt_string, _strip_options_kwargs,
- # expected_value, expected_opt_string, exception_msg
- data = [
- ["volume", "volume=10",
- {}, "10", "", None],
- ["volume", ",volume=10,,type=mine,",
- {}, "10", "type=mine", None],
- ["volume", "type=mine",
- {}, "", "type=mine", "Missing option 'volume'.*"],
- ["volume", "type=mine",
- {'is_required': False}, None, "type=mine", None],
- ["volume", "volume=1, volume=2",
- {}, "", "", "Option 'volume' found more than once.*"],
- ["volume", "volume=1, volume=2",
- {'allow_multiple': True}, ['1', '2'], "", None],
- ["volume", "volume=1, volume=2,, volume=4, volume=6",
- {'allow_multiple': True}, ['1', '2', '4', '6'], "", None],
- ["module", ",flavor=10,,nic='net-id=net',module=test, module=test",
- {'allow_multiple': True}, ['test'],
- "flavor=10,,nic='net-id=net'", None],
- ["nic", ",flavor=10,,nic=net-id=net, module=test",
- {'quotes_required': True}, "", "",
- "Invalid 'nic' option. The value must be quoted.*"],
- ["nic", ",flavor=10,,nic='net-id=net', module=test",
- {'quotes_required': True}, "net-id=net",
- "flavor=10,, module=test", None],
- ["nic",
- ",nic='port-id=port',flavor=10,,nic='net-id=net', module=test",
- {'quotes_required': True, 'allow_multiple': True},
- ["net-id=net", "port-id=port"],
- "flavor=10,, module=test", None],
- ]
-
- count = 0
- for datum in data:
- count += 1
- opt_name = datum[0]
- opts_str = datum[1]
- kwargs = datum[2]
- expected_value = datum[3]
- expected_opt_string = datum[4]
- exception_msg = datum[5]
- msg = "Error (test data line %s): " % count
- try:
- value, opt_string = troveclient.v1.shell._strip_option(
- opts_str, opt_name, **kwargs)
- if exception_msg:
- self.assertEqual(True, False,
- "%sException not thrown, expecting %s" %
- (msg, exception_msg))
- if isinstance(expected_value, list):
- self.assertEqual(
- set(value), set(expected_value),
- "%sValue not correct" % msg)
- else:
- self.assertEqual(value, expected_value,
- "%sValue not correct" % msg)
- self.assertEqual(opt_string, expected_opt_string,
- "%sOption string not correct" % msg)
- except Exception as ex:
- if exception_msg:
- msg = ex.message if hasattr(ex, 'message') else str(ex)
- self.assertThat(msg,
- testtools.matchers.MatchesRegex(
- exception_msg, re.DOTALL),
- exception_msg, "%sWrong ex" % msg)
- else:
- raise
-
- def test_instance_list(self):
- self.run_command('list')
- self.assert_called('GET', '/instances?include_clustered=False')
-
- def test_instance_show(self):
- self.run_command('show 1234')
- self.assert_called('GET', '/instances/1234')
-
- def test_reset_status(self):
- self.run_command('reset-status 1234')
- self.assert_called('POST', '/instances/1234/action')
-
- def test_instance_delete(self):
- self.run_command('delete 1234')
- self.assert_called('DELETE', '/instances/1234')
-
- def test_instance_force_delete(self):
- self.run_command('force-delete 1234')
- self.assert_called('DELETE', '/instances/1234')
-
- def test_instance_update(self):
- self.run_command('update 1234')
- self.assert_called('PATCH', '/instances/1234')
-
- def test_resize_instance(self):
- self.run_command('resize-instance 1234 1')
- self.assert_called('POST', '/instances/1234/action')
-
- def test_resize_volume(self):
- self.run_command('resize-volume 1234 3')
- self.assert_called('POST', '/instances/1234/action')
-
- def test_restart(self):
- self.run_command('restart 1234')
- self.assert_called('POST', '/instances/1234/action')
-
- def test_detach_replica(self):
- self.run_command('detach-replica 1234')
- self.assert_called('PATCH', '/instances/1234')
-
- def test_promote_to_replica_source(self):
- self.run_command('promote-to-replica-source 1234')
- self.assert_called('POST', '/instances/1234/action')
-
- def test_eject_replica_source(self):
- self.run_command('eject-replica-source 1234')
- self.assert_called('POST', '/instances/1234/action')
-
- def test_volume_type_list(self):
- self.run_command('volume-type-list')
- self.assert_called('GET', '/volume-types')
-
- def test_volume_type_list_with_datastore(self):
- cmd = ('volume-type-list --datastore_type mysql '
- '--datastore_version_id some-version-id')
- self.run_command(cmd)
- self.assert_called(
- 'GET', '/datastores/mysql/versions/some-version-id/volume-types')
-
- def test_volume_type_list_error(self):
- cmd = 'volume-type-list --datastore_type mysql'
- exepcted_error_msg = (r'Missing argument\(s\): '
- 'datastore_type, datastore_version_id')
- self.assertRaisesRegex(
- exceptions.MissingArgs, exepcted_error_msg, self.run_command,
- cmd)
-
- def test_volume_type_show(self):
- self.run_command('volume-type-show 1')
- self.assert_called('GET', '/volume-types/1')
-
- def test_cluster_list(self):
- self.run_command('cluster-list')
- self.assert_called('GET', '/clusters')
-
- def test_cluster_show(self):
- self.run_command('cluster-show cls-1234')
- self.assert_called('GET', '/clusters/cls-1234')
-
- def test_cluster_instances(self):
- self.run_command('cluster-instances cls-1234')
- self.assert_called('GET', '/clusters/cls-1234')
-
- def test_cluster_reset_status(self):
- self.run_command('cluster-reset-status cls-1234')
- self.assert_called('POST', '/clusters/cls-1234')
-
- def test_cluster_delete(self):
- self.run_command('cluster-delete cls-1234')
- self.assert_called('DELETE', '/clusters/cls-1234')
-
- def test_cluster_force_delete(self):
- self.run_command('cluster-force-delete cls-1234')
- self.assert_called('DELETE', '/clusters/cls-1234')
-
- def test_boot_fail_with_size_0(self):
- self.assertRaises(exceptions.ValidationError, self.run_command,
- 'create test-member-1 1 --size 0 --volume_type lvm')
-
- def test_boot(self):
- self.run_command('create test-member-1 1 --size 1 --volume_type lvm')
- self.assert_called_anytime(
- 'POST', '/instances',
- {'instance': {
- 'volume': {'size': 1, 'type': 'lvm'},
- 'flavorRef': '1',
- 'name': 'test-member-1'
- }})
-
- def test_boot_with_modules(self):
- self.run_command('create test-member-1 1 --size 1 --volume_type lvm '
- '--module 4321 --module 8765')
- self.assert_called_anytime(
- 'POST', '/instances',
- {'instance': {
- 'volume': {'size': 1, 'type': 'lvm'},
- 'flavorRef': '1',
- 'name': 'test-member-1',
- 'modules': [{'id': '4321'}, {'id': '8765'}]
- }})
-
- def test_boot_by_flavor_name(self):
- self.run_command(
- 'create test-member-1 1 --size 1 --volume_type lvm')
- self.assert_called_anytime(
- 'POST', '/instances',
- {'instance': {
- 'volume': {'size': 1, 'type': 'lvm'},
- 'flavorRef': '1',
- 'name': 'test-member-1'
- }})
-
- def test_boot_by_flavor_leading_zero(self):
- self.run_command(
- 'create test-member-zero 02 --size 1 --volume_type lvm')
- self.assert_called_anytime(
- 'POST', '/instances',
- {'instance': {
- 'volume': {'size': 1, 'type': 'lvm'},
- 'flavorRef': '02',
- 'name': 'test-member-zero'
- }})
-
- def test_boot_repl_set(self):
- self.run_command('create repl-1 1 --size 1 --locality=anti-affinity '
- '--replica_count=4')
- self.assert_called_anytime(
- 'POST', '/instances',
- {'instance': {
- 'volume': {'size': 1, 'type': None},
- 'flavorRef': '1',
- 'name': 'repl-1',
- 'replica_count': 4,
- 'locality': 'anti-affinity'
- }})
-
- def test_boot_replica(self):
- self.run_command('create slave-1 1 --size 1 --replica_of=master_1')
- self.assert_called_anytime(
- 'POST', '/instances',
- {'instance': {
- 'volume': {'size': 1, 'type': None},
- 'flavorRef': '1',
- 'name': 'slave-1',
- 'replica_of': 'myid',
- 'replica_count': 1
- }})
-
- def test_boot_replica_count(self):
- self.run_command('create slave-1 1 --size 1 --replica_of=master_1 '
- '--replica_count=3')
- self.assert_called_anytime(
- 'POST', '/instances',
- {'instance': {
- 'volume': {'size': 1, 'type': None},
- 'flavorRef': '1',
- 'name': 'slave-1',
- 'replica_of': 'myid',
- 'replica_count': 3
- }})
-
- def test_boot_locality(self):
- self.run_command('create master-1 1 --size 1 --locality=affinity')
- self.assert_called_anytime(
- 'POST', '/instances',
- {'instance': {
- 'volume': {'size': 1, 'type': None},
- 'flavorRef': '1',
- 'name': 'master-1',
- 'locality': 'affinity'
- }})
-
- def test_boot_locality_error(self):
- cmd = ('create slave-1 1 --size 1 --locality=affinity '
- '--replica_of=master_1')
- self.assertRaisesRegex(
- exceptions.ValidationError,
- 'Cannot specify locality when adding replicas to existing '
- 'master.',
- self.run_command, cmd)
-
- def test_boot_nic_error(self):
- cmd = ('create test-member-1 1 --size 1 --volume_type lvm '
- '--nic net-id=some-id,port-id=some-id')
- self.assertRaisesRegex(
- exceptions.ValidationError,
- 'Invalid NIC argument: nic=\'net-id=some-id,port-id=some-id\'',
- self.run_command, cmd)
-
- def test_boot_restore_by_id(self):
- self.run_command('create test-restore-1 1 --size 1 --backup bk_1234')
- self.assert_called_anytime(
- 'POST', '/instances',
- {'instance': {
- 'volume': {'size': 1, 'type': None},
- 'flavorRef': '1',
- 'name': 'test-restore-1',
- 'restorePoint': {'backupRef': 'bk-1234'},
- }})
-
- def test_boot_restore_by_name(self):
- self.run_command('create test-restore-1 1 --size 1 --backup bkp_1')
- self.assert_called_anytime(
- 'POST', '/instances',
- {'instance': {
- 'volume': {'size': 1, 'type': None},
- 'flavorRef': '1',
- 'name': 'test-restore-1',
- 'restorePoint': {'backupRef': 'bk-1234'},
- }})
-
- def test_cluster_create(self):
- cmd = ('cluster-create test-clstr vertica 7.1 '
- '--instance flavor=02,volume=2 '
- '--instance flavor=2,volume=1 '
- '--instance flavor=2,volume=1,volume_type=my-type-1')
- self.run_command(cmd)
- self.assert_called_anytime(
- 'POST', '/clusters',
- {'cluster': {
- 'instances': [
- {
- 'volume': {'size': '2'},
- 'flavorRef': '02'
- },
- {
- 'volume': {'size': '1'},
- 'flavorRef': '2'
- },
- {
- 'volume': {'size': '1', 'type': 'my-type-1'},
- 'flavorRef': '2'
- }],
- 'datastore': {'version': '7.1', 'type': 'vertica'},
- 'name': 'test-clstr'}})
-
- def test_cluster_create_by_flavor_name(self):
- cmd = ('cluster-create test-clstr vertica 7.1 '
- '--instance flavor=2,volume=2 '
- '--instance flavor=02,volume=1')
- self.run_command(cmd)
- self.assert_called_anytime(
- 'POST', '/clusters',
- {'cluster': {
- 'instances': [
- {
- 'volume': {'size': '2'},
- 'flavorRef': '2'
- },
- {
- 'volume': {'size': '1'},
- 'flavorRef': '02'
- }],
- 'datastore': {'version': '7.1', 'type': 'vertica'},
- 'name': 'test-clstr'}})
-
- def test_cluster_create_error(self):
- cmd = ('cluster-create test-clstr vertica 7.1 --instance volume=2 '
- '--instance flavor=2,volume=1')
- self.assertRaisesRegex(
- exceptions.MissingArgs, "Missing option 'flavor'",
- self.run_command, cmd)
-
- def test_cluster_grow(self):
- cmd = ('cluster-grow cls-1234 '
- '--instance flavor=2,volume=2 '
- '--instance flavor=02,volume=1')
- self.run_command(cmd)
- self.assert_called('POST', '/clusters/cls-1234')
-
- def test_cluster_shrink(self):
- cmd = ('cluster-shrink cls-1234 1234')
- self.run_command(cmd)
- self.assert_called('POST', '/clusters/cls-1234')
-
- def test_cluster_upgrade(self):
- cmd = ('cluster-upgrade cls-1234 1234')
- self.run_command(cmd)
- self.assert_called('POST', '/clusters/cls-1234')
-
- def test_cluster_create_with_locality(self):
- cmd = ('cluster-create test-clstr2 redis 3.0 --locality=affinity '
- '--instance flavor=2,volume=1 '
- '--instance flavor=02,volume=1 '
- '--instance flavor=2,volume=1 ')
- self.run_command(cmd)
- self.assert_called_anytime(
- 'POST', '/clusters',
- {'cluster': {
- 'instances': [
- {'flavorRef': '2',
- 'volume': {'size': '1'}},
- {'flavorRef': '02',
- 'volume': {'size': '1'}},
- {'flavorRef': '2',
- 'volume': {'size': '1'}},
- ],
- 'datastore': {'version': '3.0', 'type': 'redis'},
- 'name': 'test-clstr2',
- 'locality': 'affinity'}})
-
- def test_cluster_create_with_configuration(self):
- cmd = ('cluster-create test-clstr2 redis 3.0 '
- '--configuration=config01 '
- '--instance flavor=2,volume=1 '
- '--instance flavor=02,volume=1 '
- '--instance flavor=2,volume=1 ')
- self.run_command(cmd)
- self.assert_called_anytime(
- 'POST', '/clusters',
- {'cluster': {
- 'instances': [
- {'flavorRef': '2',
- 'volume': {'size': '1'}},
- {'flavorRef': '02',
- 'volume': {'size': '1'}},
- {'flavorRef': '2',
- 'volume': {'size': '1'}},
- ],
- 'datastore': {'version': '3.0', 'type': 'redis'},
- 'name': 'test-clstr2',
- 'configuration': 'config01'}})
-
- def test_cluster_create_with_extended_properties(self):
- cmd = ('cluster-create test-clstr3 mongodb 4.0 '
- '--instance flavor=2,volume=1 '
- '--instance flavor=02,volume=1 '
- '--instance flavor=2,volume=1 '
- '--extended_properties num_mongos=3')
- self.run_command(cmd)
- self.assert_called_anytime(
- 'POST', '/clusters',
- {'cluster': {
- 'instances': [
- {'flavorRef': '2',
- 'volume': {'size': '1'}},
- {'flavorRef': '02',
- 'volume': {'size': '1'}},
- {'flavorRef': '2',
- 'volume': {'size': '1'}},
- ],
- 'datastore': {'version': '4.0', 'type': 'mongodb'},
- 'name': 'test-clstr3',
- 'extended_properties': {'num_mongos': '3'}}})
-
- def test_cluster_create_with_nic_az(self):
- cmd = ('cluster-create test-clstr1 vertica 7.1 '
- '--instance flavor=2,volume=2,nic=\'net-id=some-id\','
- 'availability_zone=2 '
- '--instance flavor=2,volume=2,nic=\'net-id=some-id\','
- 'availability_zone=2')
- self.run_command(cmd)
- self.assert_called_anytime(
- 'POST', '/clusters',
- {'cluster': {
- 'instances': [
- {
- 'flavorRef': '2',
- 'volume': {'size': '2'},
- 'nics': [{'net-id': 'some-id'}],
- 'availability_zone': '2'
- },
- {
- 'flavorRef': '2',
- 'volume': {'size': '2'},
- 'nics': [{'net-id': 'some-id'}],
- 'availability_zone': '2'
- }],
- 'datastore': {'version': '7.1', 'type': 'vertica'},
- 'name': 'test-clstr1'}})
-
- def test_cluster_create_with_nic_az_error(self):
- cmd = ('cluster-create test-clstr vertica 7.1 '
- '--instance flavor=2,volume=2,nic=net-id=some-id,'
- 'port-id=some-port-id,availability_zone=2 '
- '--instance flavor=2,volume=1,nic=net-id=some-id,'
- 'port-id=some-port-id,availability_zone=2')
- self.assertRaisesRegex(
- exceptions.ValidationError, "Invalid 'nic' option. "
- "The value must be quoted.",
- self.run_command, cmd)
-
- def test_cluster_create_with_nic_az_error_again(self):
- cmd = ('cluster-create test-clstr vertica 7.1 '
- '--instance flavor=2,volume=2,nic=\'v4-fixed-ip=10.0.0.1\','
- 'availability_zone=2 '
- '--instance flavor=2,volume=1,nic=\'v4-fixed-ip=10.0.0.1\','
- 'availability_zone=2')
- self.assertRaisesRegex(
- exceptions.ValidationError, 'Invalid NIC argument',
- self.run_command, cmd)
-
- def test_datastore_list(self):
- self.run_command('datastore-list')
- self.assert_called('GET', '/datastores')
-
- def test_datastore_show(self):
- self.run_command('datastore-show d-123')
- self.assert_called('GET', '/datastores/d-123')
-
- def test_datastore_version_list(self):
- self.run_command('datastore-version-list d-123')
- self.assert_called('GET', '/datastores/d-123/versions')
-
- def test_datastore_version_show(self):
- self.run_command('datastore-version-show v-56 --datastore d-123')
- self.assert_called('GET', '/datastores/d-123/versions/v-56')
-
- def test_datastore_version_show_error(self):
- expected_error_msg = ('The datastore name or id is required to '
- 'retrieve a datastore version by name.')
- self.assertRaisesRegex(exceptions.NoUniqueMatch, expected_error_msg,
- self.run_command,
- 'datastore-version-show v-56')
-
- def test_configuration_list(self):
- self.run_command('configuration-list')
- self.assert_called('GET', '/configurations')
-
- def test_configuration_show(self):
- self.run_command('configuration-show c-123')
- self.assert_called('GET', '/configurations/c-123')
-
- def test_configuration_create(self):
- cmd = "configuration-create c-123 some-thing"
- self.assertRaises(ValueError, self.run_command, cmd)
-
- def test_configuration_update(self):
- cmd = "configuration-update c-123 some-thing"
- self.assertRaises(ValueError, self.run_command, cmd)
-
- def test_configuration_patch(self):
- cmd = "configuration-patch c-123 some-thing"
- self.assertRaises(ValueError, self.run_command, cmd)
-
- def test_configuration_parameter_list(self):
- cmd = 'configuration-parameter-list v-156 --datastore d-123'
- self.run_command(cmd)
- self.assert_called('GET',
- '/datastores/d-123/versions/v-156/parameters')
-
- def test_configuration_parameter_list_error(self):
- expected_error_msg = ('The datastore name or id is required to '
- 'retrieve the parameters for the configuration '
- 'group by name')
- self.assertRaisesRegex(
- exceptions.NoUniqueMatch, expected_error_msg,
- self.run_command, 'configuration-parameter-list v-156')
-
- def test_configuration_parameter_show(self):
- cmd = ('configuration-parameter-show v_56 '
- 'max_connections --datastore d_123')
- self.run_command(cmd)
- self.assert_called(
- 'GET',
- '/datastores/d_123/versions/v_56/parameters/max_connections')
-
- def test_configuration_instances(self):
- cmd = 'configuration-instances c-123'
- self.run_command(cmd)
- self.assert_called('GET', '/configurations/c-123/instances')
-
- def test_configuration_delete(self):
- self.run_command('configuration-delete c-123')
- self.assert_called('DELETE', '/configurations/c-123')
-
- def test_configuration_default(self):
- self.run_command('configuration-default 1234')
- self.assert_called('GET', '/instances/1234/configuration')
-
- def test_configuration_attach(self):
- self.run_command('configuration-attach 1234 c-123')
- self.assert_called('PUT', '/instances/1234')
-
- def test_configuration_detach(self):
- self.run_command('configuration-detach 1234')
- self.assert_called('PUT', '/instances/1234')
-
- def test_upgrade(self):
- self.run_command('upgrade 1234 c-123')
- self.assert_called('PATCH', '/instances/1234')
-
- def test_metadata_edit(self):
- self.run_command('metadata-edit 1234 key-123 value-123')
- self.assert_called('PATCH', '/instances/1234/metadata/key-123')
-
- def test_metadata_update(self):
- self.run_command('metadata-update 1234 key-123 key-456 value-123')
- self.assert_called('PUT', '/instances/1234/metadata/key-123')
-
- def test_metadata_delete(self):
- self.run_command('metadata-delete 1234 key-123')
- self.assert_called('DELETE', '/instances/1234/metadata/key-123')
-
- def test_metadata_create(self):
- self.run_command('metadata-create 1234 key123 value123')
- self.assert_called_anytime(
- 'POST', '/instances/1234/metadata/key123',
- {'metadata': {'value': 'value123'}})
-
- def test_metadata_list(self):
- self.run_command('metadata-list 1234')
- self.assert_called('GET', '/instances/1234/metadata')
-
- def test_metadata_show(self):
- self.run_command('metadata-show 1234 key123')
- self.assert_called('GET', '/instances/1234/metadata/key123')
-
- def test_module_list(self):
- self.run_command('module-list')
- self.assert_called('GET', '/modules')
-
- def test_module_list_datastore(self):
- self.run_command('module-list --datastore all')
- self.assert_called('GET', '/modules?datastore=all')
-
- def test_module_show(self):
- self.run_command('module-show 4321')
- self.assert_called('GET', '/modules/4321')
-
- def test_module_create(self):
- with mock.patch('argparse.open'):
- return_value = b'mycontents'
- expected_contents = str(return_value.decode('utf-8'))
- mock_encode = mock.Mock(return_value=return_value)
- with mock.patch.object(base64, 'b64encode', mock_encode):
- self.run_command('module-create mod1 type filename')
- self.assert_called_anytime(
- 'POST', '/modules',
- {'module': {'contents': expected_contents,
- 'all_tenants': 0,
- 'module_type': 'type', 'visible': 1,
- 'auto_apply': 0, 'live_update': 0,
- 'name': 'mod1', 'priority_apply': 0,
- 'apply_order': 5}})
-
- def test_module_update(self):
- with mock.patch.object(troveclient.v1.modules.Module, '__repr__',
- mock.Mock(return_value='4321')):
- self.run_command('module-update 4321 --name mod3')
- self.assert_called_anytime(
- 'PUT', '/modules/4321',
- {'module': {'name': 'mod3'}})
-
- def test_module_delete(self):
- with mock.patch.object(troveclient.v1.modules.Module, '__repr__',
- mock.Mock(return_value='4321')):
- self.run_command('module-delete 4321')
- self.assert_called_anytime('DELETE', '/modules/4321')
-
- def test_module_list_instance(self):
- self.run_command('module-list-instance 1234')
- self.assert_called_anytime('GET', '/instances/1234/modules')
-
- def test_module_instances(self):
- with mock.patch.object(troveclient.v1.modules.Module, '__repr__',
- mock.Mock(return_value='4321')):
- self.run_command('module-instances 4321')
- self.assert_called_anytime('GET', '/modules/4321/instances')
-
- def test_module_instances_clustered(self):
- with mock.patch.object(troveclient.v1.modules.Module, '__repr__',
- mock.Mock(return_value='4321')):
- self.run_command('module-instances 4321 --include_clustered')
- self.assert_called_anytime(
- 'GET', '/modules/4321/instances?include_clustered=True')
-
- def test_module_instance_count(self):
- with mock.patch.object(troveclient.v1.modules.Module, '__repr__',
- mock.Mock(return_value='4321')):
- self.run_command('module-instance-count 4321')
- self.assert_called(
- 'GET', '/modules/4321/instances?count_only=True')
-
- def test_module_instance_count_clustered(self):
- with mock.patch.object(troveclient.v1.modules.Module, '__repr__',
- mock.Mock(return_value='4321')):
- self.run_command('module-instance-count 4321 --include_clustered')
- self.assert_called(
- 'GET', '/modules/4321/instances?count_only=True&'
- 'include_clustered=True')
-
- def test_module_reapply(self):
- with mock.patch.object(troveclient.v1.modules.Module, '__repr__',
- mock.Mock(return_value='4321')):
- self.run_command('module-reapply 4321 --delay=5')
- self.assert_called_anytime('PUT', '/modules/4321/instances')
-
- def test_cluster_modules(self):
- self.run_command('cluster-modules cls-1234')
- self.assert_called_anytime('GET', '/clusters/cls-1234')
-
- def test_module_apply(self):
- self.run_command('module-apply 1234 4321 8765')
- self.assert_called_anytime('POST', '/instances/1234/modules',
- {'modules':
- [{'id': '4321'}, {'id': '8765'}]})
-
- def test_module_remove(self):
- self.run_command('module-remove 1234 4321')
- self.assert_called_anytime('DELETE', '/instances/1234/modules/4321')
-
- def test_module_query(self):
- self.run_command('module-query 1234')
- self.assert_called('GET', '/instances/1234/modules?from_guest=True')
-
- def test_module_retrieve(self):
- with mock.patch.object(troveclient.v1.modules.Module, '__getattr__',
- mock.Mock(return_value='4321')):
- with mock.patch('troveclient.v1.instances.open'):
- self.run_command('module-retrieve 1234')
- self.assert_called(
- 'GET',
- '/instances/1234/modules?'
- 'include_contents=True&from_guest=True')
-
- def test_limit_list(self):
- self.run_command('limit-list')
- self.assert_called('GET', '/limits')
-
- def test_backup_list(self):
- self.run_command('backup-list')
- self.assert_called('GET', '/backups')
-
- def test_backup_show(self):
- self.run_command('backup-show bk-1234')
- self.assert_called('GET', '/backups/bk-1234')
-
- def test_backup_list_instance(self):
- self.run_command('backup-list-instance 1234')
- self.assert_called('GET', '/instances/1234/backups')
-
- def test_backup_delete(self):
- self.run_command('backup-delete bk-1234')
- self.assert_called('DELETE', '/backups/bk-1234')
-
- def test_backup_create(self):
- self.run_command('backup-create 1234 bkp_1')
- self.assert_called_anytime(
- 'POST', '/backups',
- {'backup': {
- 'instance': '1234',
- 'name': 'bkp_1',
- 'incremental': False
- }})
-
- def test_database_list(self):
- self.run_command('database-list 1234')
- self.assert_called('GET', '/instances/1234/databases')
-
- def test_database_delete(self):
- self.run_command('database-delete 1234 db_1')
- self.assert_called('DELETE', '/instances/1234/databases/db_1')
-
- def test_database_create(self):
- cmd = ('database-create 1234 db_1 --character_set utf8 '
- '--collate utf8_general_ci')
- self.run_command(cmd)
- self.assert_called_anytime(
- 'POST', '/instances/1234/databases',
- {'databases': [{'character_set': 'utf8',
- 'name': 'db_1',
- 'collate': 'utf8_general_ci'}]})
-
- def test_user_list(self):
- self.run_command('user-list 1234')
- self.assert_called('GET', '/instances/1234/users')
-
- def test_user_show(self):
- self.run_command('user-show 1234 jacob')
- self.assert_called('GET', '/instances/1234/users/jacob')
-
- def test_user_delete(self):
- self.run_command('user-delete 1234 jacob')
- self.assert_called('DELETE', '/instances/1234/users/jacob')
-
- def test_user_create(self):
- self.run_command('user-create 1234 jacob password')
- self.assert_called_anytime(
- 'POST', '/instances/1234/users',
- {'users': [{
- 'password': 'password',
- 'name': 'jacob',
- 'databases': []}]})
-
- def test_user_show_access(self):
- self.run_command('user-show-access 1234 jacob')
- self.assert_called('GET', '/instances/1234/users/jacob/databases')
-
- def test_user_update_host(self):
- cmd = 'user-update-attributes 1234 jacob --new_host 10.0.0.1'
- self.run_command(cmd)
- self.assert_called('PUT', '/instances/1234/users/jacob')
-
- def test_user_update_name(self):
- self.run_command('user-update-attributes 1234 jacob --new_name sam')
- self.assert_called('PUT', '/instances/1234/users/jacob')
-
- def test_user_update_password(self):
- cmd = 'user-update-attributes 1234 jacob --new_password new_pwd'
- self.run_command(cmd)
- self.assert_called('PUT', '/instances/1234/users/jacob')
-
- def test_user_grant_access(self):
- self.run_command('user-grant-access 1234 jacob db1 db2')
- self.assert_called('PUT', '/instances/1234/users/jacob/databases')
-
- def test_user_revoke_access(self):
- self.run_command('user-revoke-access 1234 jacob db1')
- self.assert_called('DELETE',
- '/instances/1234/users/jacob/databases/db1')
-
- def test_root_enable_instance(self):
- self.run_command('root-enable 1234')
- self.assert_called_anytime('POST', '/instances/1234/root')
-
- def test_root_enable_cluster(self):
- self.run_command_clusters('root-enable cls-1234')
- self.assert_called_anytime('POST', '/clusters/cls-1234/root')
-
- def test_root_disable_instance(self):
- self.run_command('root-disable 1234')
- self.assert_called_anytime('DELETE', '/instances/1234/root')
-
- def test_root_show_instance(self):
- self.run_command('root-show 1234')
- self.assert_called('GET', '/instances/1234/root')
-
- def test_root_show_cluster(self):
- self.run_command_clusters('root-show cls-1234')
- self.assert_called('GET', '/clusters/cls-1234/root')
-
- def test_secgroup_list(self):
- self.run_command('secgroup-list')
- self.assert_called('GET', '/security-groups')
-
- def test_secgroup_show(self):
- self.run_command('secgroup-show 2')
- self.assert_called('GET', '/security-groups/2')
-
- def test_secgroup_list_rules(self):
- self.run_command('secgroup-list-rules 2')
- self.assert_called('GET', '/security-groups/2')
-
- def test_secgroup_delete_rule(self):
- self.run_command('secgroup-delete-rule 2')
- self.assert_called('DELETE', '/security-group-rules/2')
-
- def test_secgroup_add_rule(self):
- self.run_command('secgroup-add-rule 2 15.0.0.0/24')
- self.assert_called_anytime(
- 'POST', '/security-group-rules',
- {'security_group_rule': {
- 'cidr': '15.0.0.0/24',
- 'group_id': '2',
- }})
-
- @mock.patch('sys.stdout', new_callable=six.StringIO)
- @mock.patch('troveclient.client.get_version_map',
- return_value=fakes.get_version_map())
- @mock.patch('troveclient.v1.shell._find_instance',
- side_effect=exceptions.CommandError)
- @mock.patch('troveclient.v1.shell._find_cluster',
- return_value='cls-1234')
- def test_find_instance_or_cluster_find_cluster(self, mock_find_cluster,
- mock_find_instance,
- mock_get_version_map,
- mock_stdout):
- cmd = 'root-show cls-1234'
- self.shell.main(cmd.split())
- self.assert_called('GET', '/clusters/cls-1234/root')
-
- @mock.patch('sys.stdout', new_callable=six.StringIO)
- @mock.patch('troveclient.client.get_version_map',
- return_value=fakes.get_version_map())
- @mock.patch('troveclient.v1.shell._find_instance',
- return_value='1234')
- def test_find_instance_or_cluster(self, mock_find_instance,
- mock_get_version_map, mock_stdout):
- cmd = 'root-show 1234'
- self.shell.main(cmd.split())
- self.assert_called('GET', '/instances/1234/root')