Merge "Implementation for project unset cmd for python-openstackclient."
This commit is contained in:
		| @@ -156,6 +156,8 @@ Set project properties | ||||
|     Set a property on :ref:`\<project\> <project_set-project>` | ||||
|     (repeat option to set multiple properties) | ||||
|  | ||||
|     *Identity version 2 only* | ||||
|  | ||||
| .. _project_set-project: | ||||
| .. describe:: <project> | ||||
|  | ||||
| @@ -195,3 +197,25 @@ Display project details | ||||
| .. describe:: <project> | ||||
|  | ||||
|     Project to display (name or ID) | ||||
|  | ||||
| project unset | ||||
| ------------- | ||||
|  | ||||
| Unset project properties | ||||
|  | ||||
| *Identity version 2 only* | ||||
|  | ||||
| .. program:: project unset | ||||
| .. code:: bash | ||||
|  | ||||
|     os project unset | ||||
|         --property <key> [--property <key> ...] | ||||
|         <project> | ||||
|  | ||||
| .. option:: --property <key> | ||||
|  | ||||
|     Property key to remove from project (repeat option to remove multiple properties) | ||||
|  | ||||
| .. describe:: <project> | ||||
|  | ||||
|     Project to modify (name or ID) | ||||
|   | ||||
| @@ -68,12 +68,12 @@ class ProjectTests(test_identity.IdentityTests): | ||||
|         ) | ||||
|         items = self.parse_show(raw_output) | ||||
|         fields = list(self.PROJECT_FIELDS) | ||||
|         fields.extend(['k0']) | ||||
|         fields.extend(['properties']) | ||||
|         self.assert_show_fields(items, fields) | ||||
|         project = self.parse_show_as_object(raw_output) | ||||
|         self.assertEqual(new_project_name, project['name']) | ||||
|         self.assertEqual('False', project['enabled']) | ||||
|         self.assertEqual('v0', project['k0']) | ||||
|         self.assertEqual("k0='v0'", project['properties']) | ||||
|  | ||||
|     def test_project_show(self): | ||||
|         project_name = self._create_dummy_project() | ||||
| @@ -81,4 +81,6 @@ class ProjectTests(test_identity.IdentityTests): | ||||
|             'project show %s' % project_name | ||||
|         ) | ||||
|         items = self.parse_show(raw_output) | ||||
|         self.assert_show_fields(items, self.PROJECT_FIELDS) | ||||
|         fields = list(self.PROJECT_FIELDS) | ||||
|         fields.extend(['properties']) | ||||
|         self.assert_show_fields(items, fields) | ||||
|   | ||||
| @@ -282,4 +282,60 @@ class ShowProject(show.ShowOne): | ||||
|  | ||||
|         # TODO(stevemar): Remove the line below when we support multitenancy | ||||
|         info.pop('parent_id', None) | ||||
|  | ||||
|         # NOTE(stevemar): Property handling isn't really supported in Keystone | ||||
|         # and needs a lot of extra handling. Let's reserve the properties that | ||||
|         # the API has and handle the extra top level properties. | ||||
|         reserved = ('name', 'id', 'enabled', 'description') | ||||
|         properties = {} | ||||
|         for k, v in info.items(): | ||||
|             if k not in reserved: | ||||
|                 # If a key is not in `reserved` it's a property, pop it | ||||
|                 info.pop(k) | ||||
|                 # If a property has been "unset" it's `None`, so don't show it | ||||
|                 if v is not None: | ||||
|                     properties[k] = v | ||||
|  | ||||
|         info['properties'] = utils.format_dict(properties) | ||||
|         return zip(*sorted(six.iteritems(info))) | ||||
|  | ||||
|  | ||||
| class UnsetProject(command.Command): | ||||
|     """Unset project properties""" | ||||
|  | ||||
|     log = logging.getLogger(__name__ + '.UnsetProject') | ||||
|  | ||||
|     def get_parser(self, prog_name): | ||||
|         parser = super(UnsetProject, self).get_parser(prog_name) | ||||
|         parser.add_argument( | ||||
|             'project', | ||||
|             metavar='<project>', | ||||
|             help=_('Project to modify (name or ID)'), | ||||
|         ) | ||||
|         parser.add_argument( | ||||
|             '--property', | ||||
|             metavar='<key>', | ||||
|             action='append', | ||||
|             default=[], | ||||
|             help=_('Unset a project property ' | ||||
|                    '(repeat option to unset multiple properties)'), | ||||
|             required=True, | ||||
|         ) | ||||
|         return parser | ||||
|  | ||||
|     @utils.log_method(log) | ||||
|     def take_action(self, parsed_args): | ||||
|         identity_client = self.app.client_manager.identity | ||||
|         project = utils.find_resource( | ||||
|             identity_client.tenants, | ||||
|             parsed_args.project, | ||||
|         ) | ||||
|         if not parsed_args.property: | ||||
|             self.app.log.error("No changes requested\n") | ||||
|         else: | ||||
|             kwargs = project._info | ||||
|             for key in parsed_args.property: | ||||
|                 if key in kwargs: | ||||
|                     kwargs[key] = None | ||||
|             identity_client.tenants.update(project.id, **kwargs) | ||||
|         return | ||||
|   | ||||
| @@ -592,12 +592,58 @@ class TestProjectShow(TestProject): | ||||
|             identity_fakes.project_id, | ||||
|         ) | ||||
|  | ||||
|         collist = ('description', 'enabled', 'id', 'name') | ||||
|         collist = ('description', 'enabled', 'id', 'name', 'properties') | ||||
|         self.assertEqual(collist, columns) | ||||
|         datalist = ( | ||||
|             identity_fakes.project_description, | ||||
|             True, | ||||
|             identity_fakes.project_id, | ||||
|             identity_fakes.project_name, | ||||
|             '', | ||||
|         ) | ||||
|         self.assertEqual(datalist, data) | ||||
|  | ||||
|  | ||||
| class TestProjectUnset(TestProject): | ||||
|  | ||||
|     def setUp(self): | ||||
|         super(TestProjectUnset, self).setUp() | ||||
|  | ||||
|         project_dict = {'fee': 'fi', 'fo': 'fum'} | ||||
|         project_dict.update(identity_fakes.PROJECT) | ||||
|         self.projects_mock.get.return_value = fakes.FakeResource( | ||||
|             None, | ||||
|             copy.deepcopy(project_dict), | ||||
|             loaded=True, | ||||
|         ) | ||||
|  | ||||
|         # Get the command object to test | ||||
|         self.cmd = project.UnsetProject(self.app, None) | ||||
|  | ||||
|     def test_project_unset_key(self): | ||||
|         arglist = [ | ||||
|             '--property', 'fee', | ||||
|             '--property', 'fo', | ||||
|             identity_fakes.project_name, | ||||
|         ] | ||||
|         verifylist = [ | ||||
|             ('property', ['fee', 'fo']), | ||||
|         ] | ||||
|  | ||||
|         parsed_args = self.check_parser(self.cmd, arglist, verifylist) | ||||
|  | ||||
|         self.cmd.run(parsed_args) | ||||
|         # Set expected values | ||||
|         kwargs = { | ||||
|             'description': identity_fakes.project_description, | ||||
|             'enabled': True, | ||||
|             'fee': None, | ||||
|             'fo': None, | ||||
|             'id': identity_fakes.project_id, | ||||
|             'name': identity_fakes.project_name, | ||||
|         } | ||||
|  | ||||
|         self.projects_mock.update.assert_called_with( | ||||
|             identity_fakes.project_id, | ||||
|             **kwargs | ||||
|         ) | ||||
|   | ||||
| @@ -163,6 +163,7 @@ openstack.identity.v2 = | ||||
|     project_list = openstackclient.identity.v2_0.project:ListProject | ||||
|     project_set = openstackclient.identity.v2_0.project:SetProject | ||||
|     project_show = openstackclient.identity.v2_0.project:ShowProject | ||||
|     project_unset = openstackclient.identity.v2_0.project:UnsetProject | ||||
|  | ||||
|     role_add = openstackclient.identity.v2_0.role:AddRole | ||||
|     role_create = openstackclient.identity.v2_0.role:CreateRole | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Jenkins
					Jenkins