diff --git a/releasenotes/notes/add-cluster-modules-to-osc-647a0564dafcef24.yaml b/releasenotes/notes/add-cluster-modules-to-osc-647a0564dafcef24.yaml new file mode 100644 index 00000000..eb82dddf --- /dev/null +++ b/releasenotes/notes/add-cluster-modules-to-osc-647a0564dafcef24.yaml @@ -0,0 +1,6 @@ +--- +features: + - | + The command ``trove cluster-modules`` is now available to use in + the python-openstackclient CLI as ``openstack database cluster + modules``. diff --git a/setup.cfg b/setup.cfg index eaa3de09..ced55476 100644 --- a/setup.cfg +++ b/setup.cfg @@ -41,6 +41,7 @@ openstack.database.v1 = database_cluster_grow = troveclient.osc.v1.database_clusters:GrowDatabaseCluster database_cluster_list = troveclient.osc.v1.database_clusters:ListDatabaseClusters database_cluster_list_instances = troveclient.osc.v1.database_clusters:ListDatabaseClusterInstances + database_cluster_modules = troveclient.osc.v1.database_clusters:ListDatabaseClusterModules database_cluster_reset_status = troveclient.osc.v1.database_clusters:ResetDatabaseClusterStatus database_cluster_show = troveclient.osc.v1.database_clusters:ShowDatabaseCluster database_cluster_shrink = troveclient.osc.v1.database_clusters:ShrinkDatabaseCluster diff --git a/troveclient/osc/v1/database_clusters.py b/troveclient/osc/v1/database_clusters.py index c647d9f6..bd73802b 100644 --- a/troveclient/osc/v1/database_clusters.py +++ b/troveclient/osc/v1/database_clusters.py @@ -347,3 +347,37 @@ class ShrinkDatabaseCluster(command.Command): for instance in parsed_args.instances ] db_clusters.shrink(cluster, instances) + + +class ListDatabaseClusterModules(command.Lister): + + _description = _("Lists all modules for each instance of a cluster.") + columns = ['instance_name', 'Module Name', 'Module Type', 'md5', + 'created', 'updated'] + + def get_parser(self, prog_name): + parser = (super(ListDatabaseClusterModules, self) + .get_parser(prog_name)) + parser.add_argument( + 'cluster', + metavar='', + help=_('ID or name of the cluster.')) + return parser + + def take_action(self, parsed_args): + database_clusters = self.app.client_manager.database.clusters + database_instances = self.app.client_manager.database.instances + cluster = utils.find_resource(database_clusters, parsed_args.cluster) + instances = cluster._info['instances'] + modules = [] + for instance in instances: + new_list = database_instances.modules(instance['id']) + for item in new_list: + item.instance_id = instance['id'] + item.instance_name = instance['name'] + item.module_name = item.name + item.module_type = item.type + modules += new_list + modules = [utils.get_item_properties(module, self.columns) + for module in modules] + return self.columns, modules diff --git a/troveclient/tests/fakes.py b/troveclient/tests/fakes.py index ac9c9e5e..78640547 100644 --- a/troveclient/tests/fakes.py +++ b/troveclient/tests/fakes.py @@ -384,6 +384,45 @@ class FakeHTTPClient(base_client.HTTPClient): "datastore": {"version": "7.1", "type": "vertica"}, "id": "cls-1234"}}) + def get_cluster_instance_modules(self, **kw): + return (200, {}, { + "modules": [ + { + "auto_apply": False, + "contents": None, + "created": "2018-04-17 05:34:02.84", + "datastore": "mariadb", + "datastore_version": "all", + "id": "module-1", + "is_admin": False, + "md5": "md5-1", + "message": "Module.V1", + "name": "mymod1", + "removed": None, + "status": "OK", + "tenant": "7f1f041fc291455b83a0b3eb98140808", + "type": "ping", + "updated": "2018-04-17 05:34:02.84", + "visible": True}, + + { + "auto_apply": False, + "contents": None, + "created": "2018-04-17 05:34:02.84", + "datastore": "mariadb", + "datastore_version": "all", + "id": "module-2", + "is_admin": False, + "md5": "md5-2", + "message": "Module.V1", + "name": "mymod2", + "removed": None, + "status": "OK", + "tenant": "7f1f041fc291455b83a0b3eb98140808", + "type": "ping", + "updated": "2018-04-17 05:34:02.84", + "visible": True}]}) + def delete_instances_1234(self, **kw): return (202, {}, None) diff --git a/troveclient/tests/osc/v1/fakes.py b/troveclient/tests/osc/v1/fakes.py index be069683..057c4468 100644 --- a/troveclient/tests/osc/v1/fakes.py +++ b/troveclient/tests/osc/v1/fakes.py @@ -23,6 +23,7 @@ from troveclient.v1 import datastores from troveclient.v1 import flavors from troveclient.v1 import instances from troveclient.v1 import limits +from troveclient.v1 import modules from troveclient.v1 import quota from troveclient.v1 import users @@ -52,6 +53,9 @@ class FakeClusters(object): fake_cluster = (fakes.FakeHTTPClient() .get_clusters_cls_1234()[2]['cluster']) fake_cluster_member = fake_cluster['instances'][1] + fake_cluster_instance_modules = (fakes.FakeHTTPClient(). + get_cluster_instance_modules()[2] + ['modules']) def get_clusters_cls_1234(self): return clusters.Cluster(None, self.fake_cluster) @@ -59,6 +63,10 @@ class FakeClusters(object): def get_clusters_member_2(self): return instances.Instance(None, self.fake_cluster_member) + def cluster_instance_modules(self): + return [[modules.Module(None, mod)] + for mod in self.fake_cluster_instance_modules] + class FakeConfigurations(object): fake_config = (fakes.FakeHTTPClient().get_configurations() diff --git a/troveclient/tests/osc/v1/test_database_clusters.py b/troveclient/tests/osc/v1/test_database_clusters.py index 5919b8b0..9eb5f9ae 100644 --- a/troveclient/tests/osc/v1/test_database_clusters.py +++ b/troveclient/tests/osc/v1/test_database_clusters.py @@ -27,6 +27,7 @@ class TestClusters(fakes.TestDatabasev1): super(TestClusters, self).setUp() self.mock_client = self.app.client_manager.database self.cluster_client = self.app.client_manager.database.clusters + self.instance_client = self.app.client_manager.database.instances class TestClusterList(TestClusters): @@ -289,3 +290,30 @@ class TestDatabaseClusterShrink(TestClusters): self.cluster_client.shrink.assert_called_with('test-clstr', [{'id': 'member-2'}]) self.assertIsNone(result) + + +class TestClusterListModules(TestClusters): + + columns = (database_clusters + .ListDatabaseClusterModules.columns) + values = [('test-clstr-member-1', 'mymod1', 'ping', 'md5-1', + '2018-04-17 05:34:02.84', '2018-04-17 05:34:02.84'), + ('test-clstr-member-2', 'mymod2', 'ping', 'md5-2', + '2018-04-17 05:34:02.84', '2018-04-17 05:34:02.84')] + + def setUp(self): + super(TestClusterListModules, self).setUp() + self.cmd = (database_clusters + .ListDatabaseClusterModules(self.app, None)) + self.data = self.fake_clusters.get_clusters_cls_1234() + self.instance_client.modules.side_effect = ( + self.fake_clusters.cluster_instance_modules()) + + @mock.patch.object(utils, 'find_resource') + def test_cluster_list_modules(self, mock_find_resource): + mock_find_resource.return_value = self.data + args = ['cls-1234'] + parsed_args = self.check_parser(self.cmd, args, []) + columns, data = self.cmd.take_action(parsed_args) + self.assertEqual(self.columns, columns) + self.assertEqual(self.values, data)