diff options
| author | Peter Stachowski <peter@tesora.com> | 2016-11-04 10:45:27 -0400 |
|---|---|---|
| committer | Peter Stachowski <peter@tesora.com> | 2017-01-05 00:11:59 +0000 |
| commit | 714c6e781c0bf6ad84015061c397bedce8eccd1e (patch) | |
| tree | 7e7a384a3cb20573bb661044cd6a5aac002466aa | |
| parent | d273969fa33a78a11a27ffe1128860dcba0fad47 (diff) | |
| download | python-troveclient-714c6e781c0bf6ad84015061c397bedce8eccd1e.tar.gz | |
Add module-instance-count command
Added a --count_only flag to the call for module instances
to return a summary of the applied instances
based on the MD5 of the module (this is most useful
for live_update modules, to see which ones haven't been
updated).
Added a new module-instance-count command. This was done
to facilitate getting the summary, since it returns
a different result set. It basically calls the
same python interface as module-instances, but adds
the --count_only flag.
Also added some missing tests.
Change-Id: Iea661166bf3a4f3520a590da5954aedcd0036243
Partial-Bug: #1554900
Depends-On: I4caf4a57226dd711575cde766076fa25d16792e2
| -rw-r--r-- | releasenotes/notes/add_mod_inst_count-ce532a2187b.yaml | 6 | ||||
| -rw-r--r-- | troveclient/tests/fakes.py | 13 | ||||
| -rw-r--r-- | troveclient/tests/test_instances.py | 50 | ||||
| -rw-r--r-- | troveclient/tests/test_modules.py | 22 | ||||
| -rw-r--r-- | troveclient/tests/test_v1_shell.py | 15 | ||||
| -rw-r--r-- | troveclient/v1/modules.py | 4 | ||||
| -rw-r--r-- | troveclient/v1/shell.py | 33 |
7 files changed, 137 insertions, 6 deletions
diff --git a/releasenotes/notes/add_mod_inst_count-ce532a2187b.yaml b/releasenotes/notes/add_mod_inst_count-ce532a2187b.yaml new file mode 100644 index 0000000..27b7a06 --- /dev/null +++ b/releasenotes/notes/add_mod_inst_count-ce532a2187b.yaml @@ -0,0 +1,6 @@ +--- +fixes: + - Add module-instance-count support to list + a count of all instances having a specific + module applied. Bug 1554900 + diff --git a/troveclient/tests/fakes.py b/troveclient/tests/fakes.py index eaab7c8..a3816d0 100644 --- a/troveclient/tests/fakes.py +++ b/troveclient/tests/fakes.py @@ -178,6 +178,17 @@ class FakeHTTPClient(base_client.HTTPClient): "region": "regionOne", "datastore": {"version": "5.6", "type": "mysql"}}]}) + def get_instance_counts(self, **kw): + return (200, {}, {"instances": [ + { + "module_id": "4321", + "module_name": "mod1", + "min_date": "2015-05-02T11:06:16", + "max_date": "2015-05-02T11:06:19", + "module_md5": "9db783b92a9355f70c41806659fcb77d", + "current": True, + "count": 1}]}) + def get_instances_1234(self, **kw): r = {'instance': self.get_instances()[2]['instances'][0]} return (200, {}, r) @@ -479,6 +490,8 @@ class FakeHTTPClient(base_client.HTTPClient): return (200, {}, {"modules": [{"module": {}}]}) def get_modules_4321_instances(self, **kw): + if kw.get('count_only', False): + return self.get_instance_counts() return self.get_instances() def get_instances_modules(self, **kw): diff --git a/troveclient/tests/test_instances.py b/troveclient/tests/test_instances.py index 21ef2d8..b65583d 100644 --- a/troveclient/tests/test_instances.py +++ b/troveclient/tests/test_instances.py @@ -233,6 +233,56 @@ class InstancesTest(testtools.TestCase): resp.status_code = 500 self.assertRaises(Exception, self.instances.edit, 'instance1') + def test_module_apply(self): + resp = mock.Mock() + resp.status_code = 200 + body = {'modules': []} + self.instances.api.client.post = mock.Mock(return_value=(resp, body)) + self.instances.module_apply(self.instance_with_id, "mod_id") + resp.status_code = 500 + self.assertRaises(Exception, self.instances.module_apply, + 'instance1', 'mod1') + + def test_module_remove(self): + resp = mock.Mock() + resp.status_code = 200 + body = {'modules': []} + self.instances.api.client.delete = mock.Mock(return_value=(resp, body)) + self.instances.module_remove(self.instance_with_id, "mod_id") + resp.status_code = 500 + self.assertRaises(Exception, self.instances.module_remove, + 'instance1', 'mod1') + + def test_module_query(self): + resp = mock.Mock() + resp.status_code = 200 + body = {'modules': []} + self.instances.api.client.get = mock.Mock(return_value=(resp, body)) + self.instances.module_query(self.instance_with_id) + resp.status_code = 500 + self.assertRaises(Exception, self.instances.module_query, + 'instance1') + + def test_module_retrieve(self): + resp = mock.Mock() + resp.status_code = 200 + body = {'modules': []} + self.instances.api.client.get = mock.Mock(return_value=(resp, body)) + self.instances.module_retrieve(self.instance_with_id) + resp.status_code = 500 + self.assertRaises(Exception, self.instances.module_retrieve, + 'instance1') + + def test_module_list_instance(self): + resp = mock.Mock() + resp.status_code = 200 + body = {'modules': []} + self.instances.api.client.get = mock.Mock(return_value=(resp, body)) + self.instances.modules(self.instance_with_id) + resp.status_code = 500 + self.assertRaises(Exception, self.instances.modules, + 'instance1') + def test_upgrade(self): resp = mock.Mock() resp.status_code = 200 diff --git a/troveclient/tests/test_modules.py b/troveclient/tests/test_modules.py index ebd2802..bffc1f6 100644 --- a/troveclient/tests/test_modules.py +++ b/troveclient/tests/test_modules.py @@ -123,3 +123,25 @@ class TestModules(testtools.TestCase): self.modules.delete(self.module) resp.status_code = 500 self.assertRaises(Exception, self.modules.delete, self.module_name) + + def _test_instances(self, expected_query=None): + page_mock = mock.Mock() + self.modules._paginated = page_mock + limit = "test-limit" + marker = "test-marker" + if not expected_query: + expected_query = {} + self.modules.instances(self.module_name, limit, marker, + **expected_query) + page_mock.assert_called_with("/modules/mod_1/instances", + "instances", limit, marker, + query_strings=expected_query) + + def test_instance_count(self): + expected_query = {'include_clustered': True, + 'count_only': True} + self._test_instances(expected_query) + + def test_instances(self): + expected_query = {'include_clustered': True} + self._test_instances(expected_query) diff --git a/troveclient/tests/test_v1_shell.py b/troveclient/tests/test_v1_shell.py index 0e55947..04af36c 100644 --- a/troveclient/tests/test_v1_shell.py +++ b/troveclient/tests/test_v1_shell.py @@ -722,6 +722,21 @@ class ShellTest(utils.TestCase): 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_cluster_modules(self): self.run_command('cluster-modules cls-1234') self.assert_called_anytime('GET', '/clusters/cls-1234') diff --git a/troveclient/v1/modules.py b/troveclient/v1/modules.py index c8a74c3..9508608 100644 --- a/troveclient/v1/modules.py +++ b/troveclient/v1/modules.py @@ -157,11 +157,13 @@ class Modules(base.ManagerWithFind): common.check_for_exceptions(resp, body, url) def instances(self, module, limit=None, marker=None, - include_clustered=False): + include_clustered=False, count_only=False): """Get a list of all instances this module has been applied to.""" url = "/modules/%s/instances" % base.getid(module) query_strings = {} if include_clustered: query_strings['include_clustered'] = include_clustered + if count_only: + query_strings['count_only'] = count_only return self._paginated(url, "instances", limit, marker, query_strings=query_strings) diff --git a/troveclient/v1/shell.py b/troveclient/v1/shell.py index 0788fac..9131ff3 100644 --- a/troveclient/v1/shell.py +++ b/troveclient/v1/shell.py @@ -260,7 +260,7 @@ def do_list(cs, args): _print_instances(instances) -def _print_instances(instances): +def _print_instances(instances, is_admin=False): for instance in instances: setattr(instance, 'flavor_id', instance.flavor['id']) if hasattr(instance, 'volume'): @@ -272,9 +272,12 @@ def _print_instances(instances): setattr(instance, 'datastore_version', instance.datastore['version']) setattr(instance, 'datastore', instance.datastore['type']) - utils.print_list(instances, ['id', 'name', 'datastore', - 'datastore_version', 'status', - 'flavor_id', 'size', 'region']) + fields = ['id', 'name', 'datastore', + 'datastore_version', 'status', + 'flavor_id', 'size', 'region'] + if is_admin: + fields.append('tenant_id') + utils.print_list(instances, fields) @utils.arg('--limit', metavar='<limit>', type=int, default=None, @@ -1964,7 +1967,27 @@ def do_module_instances(cs, args): while not args.limit and items.next: items = cs.modules.instances(module, marker=items.next) instance_list += items - _print_instances(instance_list) + _print_instances(instance_list, utils.is_admin(cs)) + + +@utils.arg('module', metavar='<module>', type=str, + help=_('ID or name of the module.')) +@utils.arg('--include_clustered', action="store_true", default=False, + help=_("Include instances that are part of a cluster " + "(default %(default)s).")) +@utils.service_type('database') +def do_module_instance_count(cs, args): + """Lists a count of the instances for each module md5.""" + module = _find_module(cs, args.module) + count_list = cs.modules.instances( + module, include_clustered=args.include_clustered, + count_only=True) + field_list = ['module_name', 'min_updated_date', 'max_updated_date', + 'module_md5', 'current', 'instance_count'] + utils.print_list(count_list, field_list, + labels={'module_md5': 'Module MD5', + 'instance_count': 'Count', + 'module_id': 'Module ID'}) @utils.arg('cluster', metavar='<cluster>', |
