Add sort support to project list
Add sort support to project list by sorting items in the client side. By default list will be sorted by name. Change-Id: I00011406846b4003aff075eeeb88ac18fa5e2820 Closes-Bug: #1596818
This commit is contained in:
		 Tom Jose Kalapura
					Tom Jose Kalapura
				
			
				
					committed by
					
						 Mike Perez
						Mike Perez
					
				
			
			
				
	
			
			
			 Mike Perez
						Mike Perez
					
				
			
						parent
						
							ed4454c5bb
						
					
				
				
					commit
					6c1b03bf73
				
			| @@ -96,6 +96,7 @@ List projects | |||||||
|         [--domain <domain>] |         [--domain <domain>] | ||||||
|         [--user <user>] |         [--user <user>] | ||||||
|         [--long] |         [--long] | ||||||
|  |         [--sort <key>[:<direction>,<key>:<direction>,..]] | ||||||
|  |  | ||||||
| .. option:: --domain <domain> | .. option:: --domain <domain> | ||||||
|  |  | ||||||
| @@ -113,6 +114,12 @@ List projects | |||||||
|  |  | ||||||
|     List additional fields in output |     List additional fields in output | ||||||
|  |  | ||||||
|  | .. option:: --sort <key>[:<direction>,<key>:<direction>,..] | ||||||
|  |  | ||||||
|  |     Sort output by selected keys and directions (asc or desc) (default: asc), | ||||||
|  |     multiple keys and directions can be specified --sort | ||||||
|  |     <key>[:<direction>,<key>:<direction>,..] | ||||||
|  |  | ||||||
| project set | project set | ||||||
| ----------- | ----------- | ||||||
|  |  | ||||||
|   | |||||||
| @@ -136,6 +136,13 @@ class ListProject(command.Lister): | |||||||
|             default=False, |             default=False, | ||||||
|             help=_('List additional fields in output'), |             help=_('List additional fields in output'), | ||||||
|         ) |         ) | ||||||
|  |         parser.add_argument( | ||||||
|  |             '--sort', | ||||||
|  |             metavar='<key>[:<direction>]', | ||||||
|  |             help=_('Sort output by selected keys and directions (asc or desc) ' | ||||||
|  |                    '(default: asc), repeat this option to specify multiple ' | ||||||
|  |                    'keys and directions.'), | ||||||
|  |         ) | ||||||
|         return parser |         return parser | ||||||
|  |  | ||||||
|     def take_action(self, parsed_args): |     def take_action(self, parsed_args): | ||||||
| @@ -144,6 +151,8 @@ class ListProject(command.Lister): | |||||||
|         else: |         else: | ||||||
|             columns = ('ID', 'Name') |             columns = ('ID', 'Name') | ||||||
|         data = self.app.client_manager.identity.tenants.list() |         data = self.app.client_manager.identity.tenants.list() | ||||||
|  |         if parsed_args.sort: | ||||||
|  |             data = utils.sort_items(data, parsed_args.sort) | ||||||
|         return (columns, |         return (columns, | ||||||
|                 (utils.get_item_properties( |                 (utils.get_item_properties( | ||||||
|                     s, columns, |                     s, columns, | ||||||
|   | |||||||
| @@ -180,6 +180,13 @@ class ListProject(command.Lister): | |||||||
|             default=False, |             default=False, | ||||||
|             help=_('List additional fields in output'), |             help=_('List additional fields in output'), | ||||||
|         ) |         ) | ||||||
|  |         parser.add_argument( | ||||||
|  |             '--sort', | ||||||
|  |             metavar='<key>[:<direction>]', | ||||||
|  |             help=_('Sort output by selected keys and directions (asc or desc) ' | ||||||
|  |                    '(default: asc), repeat this option to specify multiple ' | ||||||
|  |                    'keys and directions.'), | ||||||
|  |         ) | ||||||
|         return parser |         return parser | ||||||
|  |  | ||||||
|     def take_action(self, parsed_args): |     def take_action(self, parsed_args): | ||||||
| @@ -208,6 +215,8 @@ class ListProject(command.Lister): | |||||||
|             kwargs['user'] = user_id |             kwargs['user'] = user_id | ||||||
|  |  | ||||||
|         data = identity_client.projects.list(**kwargs) |         data = identity_client.projects.list(**kwargs) | ||||||
|  |         if parsed_args.sort: | ||||||
|  |             data = utils.sort_items(data, parsed_args.sort) | ||||||
|         return (columns, |         return (columns, | ||||||
|                 (utils.get_item_properties( |                 (utils.get_item_properties( | ||||||
|                     s, columns, |                     s, columns, | ||||||
|   | |||||||
| @@ -23,6 +23,7 @@ from openstackclient.tests.unit.identity.v2_0 import fakes as identity_fakes | |||||||
| class TestProject(identity_fakes.TestIdentityv2): | class TestProject(identity_fakes.TestIdentityv2): | ||||||
|  |  | ||||||
|     fake_project = identity_fakes.FakeProject.create_one_project() |     fake_project = identity_fakes.FakeProject.create_one_project() | ||||||
|  |     fake_projects = identity_fakes.FakeProject.create_projects() | ||||||
|  |  | ||||||
|     columns = ( |     columns = ( | ||||||
|         'description', |         'description', | ||||||
| @@ -36,6 +37,12 @@ class TestProject(identity_fakes.TestIdentityv2): | |||||||
|         fake_project.id, |         fake_project.id, | ||||||
|         fake_project.name, |         fake_project.name, | ||||||
|     ) |     ) | ||||||
|  |     datalists = ( | ||||||
|  |         (fake_projects[0].description, True, | ||||||
|  |          fake_projects[0].id, fake_projects[0].name,), | ||||||
|  |         (fake_projects[1].description, True, | ||||||
|  |          fake_projects[1].id, fake_projects[1].name,), | ||||||
|  |     ) | ||||||
|  |  | ||||||
|     def setUp(self): |     def setUp(self): | ||||||
|         super(TestProject, self).setUp() |         super(TestProject, self).setUp() | ||||||
| @@ -357,6 +364,35 @@ class TestProjectList(TestProject): | |||||||
|         ), ) |         ), ) | ||||||
|         self.assertEqual(datalist, tuple(data)) |         self.assertEqual(datalist, tuple(data)) | ||||||
|  |  | ||||||
|  |     def test_project_list_sort(self): | ||||||
|  |         self.projects_mock.list.return_value = self.fake_projects | ||||||
|  |  | ||||||
|  |         arglist = ['--sort', 'name:asc', ] | ||||||
|  |         verifylist = [] | ||||||
|  |         parsed_args = self.check_parser(self.cmd, arglist, verifylist) | ||||||
|  |  | ||||||
|  |         # In base command class Lister in cliff, abstract method take_action() | ||||||
|  |         # returns a tuple containing the column names and an iterable | ||||||
|  |         # containing the data to be listed. | ||||||
|  |         (columns, data) = self.cmd.take_action(parsed_args) | ||||||
|  |         self.projects_mock.list.assert_called_with() | ||||||
|  |  | ||||||
|  |         collist = ('ID', 'Name') | ||||||
|  |         self.assertEqual(collist, columns) | ||||||
|  |  | ||||||
|  |         if self.fake_projects[0].name > self.fake_projects[1].name: | ||||||
|  |             datalists = ( | ||||||
|  |                 (self.fake_projects[1].id, self.fake_projects[1].name), | ||||||
|  |                 (self.fake_projects[0].id, self.fake_projects[0].name), | ||||||
|  |             ) | ||||||
|  |         else: | ||||||
|  |             datalists = ( | ||||||
|  |                 (self.fake_projects[0].id, self.fake_projects[0].name), | ||||||
|  |                 (self.fake_projects[1].id, self.fake_projects[1].name), | ||||||
|  |             ) | ||||||
|  |  | ||||||
|  |         self.assertEqual(datalists, tuple(data)) | ||||||
|  |  | ||||||
|  |  | ||||||
| class TestProjectSet(TestProject): | class TestProjectSet(TestProject): | ||||||
|  |  | ||||||
|   | |||||||
| @@ -622,6 +622,23 @@ class FakeProject(object): | |||||||
|                                      loaded=True) |                                      loaded=True) | ||||||
|         return project |         return project | ||||||
|  |  | ||||||
|  |     @staticmethod | ||||||
|  |     def create_projects(attrs=None, count=2): | ||||||
|  |         """Create multiple fake projects. | ||||||
|  |  | ||||||
|  |         :param Dictionary attrs: | ||||||
|  |             A dictionary with all attributes | ||||||
|  |         :param int count: | ||||||
|  |             The number of projects to fake | ||||||
|  |         :return: | ||||||
|  |             A list of FakeResource objects faking the projects | ||||||
|  |         """ | ||||||
|  |  | ||||||
|  |         projects = [] | ||||||
|  |         for i in range(0, count): | ||||||
|  |             projects.append(FakeProject.create_one_project(attrs)) | ||||||
|  |         return projects | ||||||
|  |  | ||||||
|  |  | ||||||
| class FakeDomain(object): | class FakeDomain(object): | ||||||
|     """Fake one or more domain.""" |     """Fake one or more domain.""" | ||||||
|   | |||||||
| @@ -451,6 +451,7 @@ class TestProjectList(TestProject): | |||||||
|     domain = identity_fakes.FakeDomain.create_one_domain() |     domain = identity_fakes.FakeDomain.create_one_domain() | ||||||
|     project = identity_fakes.FakeProject.create_one_project( |     project = identity_fakes.FakeProject.create_one_project( | ||||||
|         attrs={'domain_id': domain.id}) |         attrs={'domain_id': domain.id}) | ||||||
|  |     projects = identity_fakes.FakeProject.create_projects() | ||||||
|  |  | ||||||
|     columns = ( |     columns = ( | ||||||
|         'ID', |         'ID', | ||||||
| @@ -462,6 +463,12 @@ class TestProjectList(TestProject): | |||||||
|             project.name, |             project.name, | ||||||
|         ), |         ), | ||||||
|     ) |     ) | ||||||
|  |     datalists = ( | ||||||
|  |         (projects[0].description, True, | ||||||
|  |          projects[0].id, projects[0].name,), | ||||||
|  |         (projects[1].description, True, | ||||||
|  |          projects[1].id, projects[1].name,), | ||||||
|  |     ) | ||||||
|  |  | ||||||
|     def setUp(self): |     def setUp(self): | ||||||
|         super(TestProjectList, self).setUp() |         super(TestProjectList, self).setUp() | ||||||
| @@ -552,6 +559,36 @@ class TestProjectList(TestProject): | |||||||
|         self.assertEqual(self.columns, columns) |         self.assertEqual(self.columns, columns) | ||||||
|         self.assertEqual(self.datalist, tuple(data)) |         self.assertEqual(self.datalist, tuple(data)) | ||||||
|  |  | ||||||
|  |     def test_project_list_sort(self): | ||||||
|  |         self.projects_mock.list.return_value = self.projects | ||||||
|  |  | ||||||
|  |         arglist = ['--sort', 'name:asc', ] | ||||||
|  |         verifylist = [] | ||||||
|  |  | ||||||
|  |         parsed_args = self.check_parser(self.cmd, arglist, verifylist) | ||||||
|  |  | ||||||
|  |         # In base command class Lister in cliff, abstract method take_action() | ||||||
|  |         # returns a tuple containing the column names and an iterable | ||||||
|  |         # containing the data to be listed. | ||||||
|  |         (columns, data) = self.cmd.take_action(parsed_args) | ||||||
|  |         self.projects_mock.list.assert_called_with() | ||||||
|  |  | ||||||
|  |         collist = ('ID', 'Name') | ||||||
|  |         self.assertEqual(collist, columns) | ||||||
|  |  | ||||||
|  |         if self.projects[0].name > self.projects[1].name: | ||||||
|  |             datalists = ( | ||||||
|  |                 (self.projects[1].id, self.projects[1].name), | ||||||
|  |                 (self.projects[0].id, self.projects[0].name), | ||||||
|  |             ) | ||||||
|  |         else: | ||||||
|  |             datalists = ( | ||||||
|  |                 (self.projects[0].id, self.projects[0].name), | ||||||
|  |                 (self.projects[1].id, self.projects[1].name), | ||||||
|  |             ) | ||||||
|  |  | ||||||
|  |         self.assertEqual(datalists, tuple(data)) | ||||||
|  |  | ||||||
|  |  | ||||||
| class TestProjectSet(TestProject): | class TestProjectSet(TestProject): | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										6
									
								
								releasenotes/notes/bug-1596818-d4cd93dd4d38d3d6.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								releasenotes/notes/bug-1596818-d4cd93dd4d38d3d6.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | |||||||
|  | --- | ||||||
|  | features: | ||||||
|  |   - | | ||||||
|  |     Add ``--sort`` support to ``project list`` by sorting items in client side | ||||||
|  |     By default project list will be sorted by name. | ||||||
|  |     [Bug `1596818 <https://bugs.launchpad.net/bugs/1596818>`_] | ||||||
		Reference in New Issue
	
	Block a user