From c385180df2338a52e89b1dfdf4d59dd698eaba67 Mon Sep 17 00:00:00 2001
From: Dean Troyer <dtroyer@gmail.com>
Date: Mon, 29 Jul 2013 11:29:16 -0500
Subject: [PATCH] Remove tenant round 2 - Identity API

Rename everything in the Identity v2 code including the file and classes.
* role, tenant, user

Change-Id: I0b99c60a24f5875120136d2f216aa3b6bce1c641
---
 .../identity/v2_0/{tenant.py => project.py}   | 133 ++++++++++--------
 openstackclient/identity/v2_0/role.py         |  69 +++++----
 openstackclient/identity/v2_0/user.py         | 107 +++++++++++---
 setup.cfg                                     |  12 +-
 4 files changed, 205 insertions(+), 116 deletions(-)
 rename openstackclient/identity/v2_0/{tenant.py => project.py} (59%)

diff --git a/openstackclient/identity/v2_0/tenant.py b/openstackclient/identity/v2_0/project.py
similarity index 59%
rename from openstackclient/identity/v2_0/tenant.py
rename to openstackclient/identity/v2_0/project.py
index d535716cac..d2d74ed004 100644
--- a/openstackclient/identity/v2_0/tenant.py
+++ b/openstackclient/identity/v2_0/project.py
@@ -13,11 +13,10 @@
 #   under the License.
 #
 
-"""Tenant action implementations"""
+"""Identity v2 Project action implementations"""
 
 import logging
 import six
-import sys
 
 from cliff import command
 from cliff import lister
@@ -26,82 +25,90 @@ from cliff import show
 from openstackclient.common import utils
 
 
-class CreateTenant(show.ShowOne):
-    """Create tenant command"""
+class CreateProject(show.ShowOne):
+    """Create new project"""
 
-    log = logging.getLogger(__name__ + '.CreateTenant')
+    log = logging.getLogger(__name__ + '.CreateProject')
 
     def get_parser(self, prog_name):
-        parser = super(CreateTenant, self).get_parser(prog_name)
+        parser = super(CreateProject, self).get_parser(prog_name)
         parser.add_argument(
-            'tenant_name',
-            metavar='<tenant-name>',
-            help='New tenant name')
+            'project_name',
+            metavar='<project-name>',
+            help='New project name',
+        )
         parser.add_argument(
             '--description',
-            metavar='<tenant-description>',
-            help='New tenant description')
+            metavar='<project-description>',
+            help='New project description',
+        )
         enable_group = parser.add_mutually_exclusive_group()
         enable_group.add_argument(
             '--enable',
             dest='enabled',
             action='store_true',
             default=True,
-            help='Enable tenant')
+            help='Enable project',
+        )
         enable_group.add_argument(
             '--disable',
             dest='enabled',
             action='store_false',
-            help='Disable tenant')
+            help='Disable project',
+        )
         return parser
 
     def take_action(self, parsed_args):
         self.log.debug('take_action(%s)' % parsed_args)
         identity_client = self.app.client_manager.identity
-        tenant = identity_client.tenants.create(
-            parsed_args.tenant_name,
+        project = identity_client.tenants.create(
+            parsed_args.project_name,
             description=parsed_args.description,
             enabled=parsed_args.enabled)
 
         info = {}
-        info.update(tenant._info)
+        info.update(project._info)
         return zip(*sorted(six.iteritems(info)))
 
 
-class DeleteTenant(command.Command):
-    """Delete tenant command"""
+class DeleteProject(command.Command):
+    """Delete project"""
 
-    log = logging.getLogger(__name__ + '.DeleteTenant')
+    log = logging.getLogger(__name__ + '.DeleteProject')
 
     def get_parser(self, prog_name):
-        parser = super(DeleteTenant, self).get_parser(prog_name)
+        parser = super(DeleteProject, self).get_parser(prog_name)
         parser.add_argument(
-            'tenant',
-            metavar='<tenant>',
-            help='Name or ID of tenant to delete')
+            'project',
+            metavar='<project>',
+            help='Project to delete (name or ID)',
+        )
         return parser
 
     def take_action(self, parsed_args):
         self.log.debug('take_action(%s)' % parsed_args)
         identity_client = self.app.client_manager.identity
-        tenant = utils.find_resource(identity_client.tenants,
-                                     parsed_args.tenant)
-        identity_client.tenants.delete(tenant.id)
+        project = utils.find_resource(
+            identity_client.tenants,
+            parsed_args.project,
+        )
+        identity_client.tenants.delete(project.id)
         return
 
 
-class ListTenant(lister.Lister):
-    """List tenant command"""
+class ListProject(lister.Lister):
+    """List projects"""
 
-    log = logging.getLogger(__name__ + '.ListTenant')
+    log = logging.getLogger(__name__ + '.ListProject')
 
     def get_parser(self, prog_name):
-        parser = super(ListTenant, self).get_parser(prog_name)
+        parser = super(ListProject, self).get_parser(prog_name)
         parser.add_argument(
             '--long',
             action='store_true',
             default=False,
-            help='Additional fields are listed in output')
+            help='List additional fields in output',
+        )
         return parser
 
     def take_action(self, parsed_args):
@@ -118,44 +125,51 @@ class ListTenant(lister.Lister):
                 ) for s in data))
 
 
-class SetTenant(command.Command):
-    """Set tenant command"""
+class SetProject(command.Command):
+    """Set project properties"""
 
-    log = logging.getLogger(__name__ + '.SetTenant')
+    log = logging.getLogger(__name__ + '.SetProject')
 
     def get_parser(self, prog_name):
-        parser = super(SetTenant, self).get_parser(prog_name)
+        parser = super(SetProject, self).get_parser(prog_name)
         parser.add_argument(
-            'tenant',
-            metavar='<tenant>',
-            help='Name or ID of tenant to change')
+            'project',
+            metavar='<project>',
+            help='Project to change (name or ID)',
+        )
         parser.add_argument(
             '--name',
-            metavar='<new-tenant-name>',
-            help='New tenant name')
+            metavar='<new-project-name>',
+            help='New project name',
+        )
         parser.add_argument(
             '--description',
-            metavar='<tenant-description>',
-            help='New tenant description')
+            metavar='<project-description>',
+            help='New project description',
+        )
         enable_group = parser.add_mutually_exclusive_group()
         enable_group.add_argument(
             '--enable',
             dest='enabled',
             action='store_true',
             default=True,
-            help='Enable tenant (default)')
+            help='Enable project (default)',
+        )
         enable_group.add_argument(
             '--disable',
             dest='enabled',
             action='store_false',
-            help='Disable tenant')
+            help='Disable project',
+        )
         return parser
 
     def take_action(self, parsed_args):
         self.log.debug('take_action(%s)' % parsed_args)
         identity_client = self.app.client_manager.identity
-        tenant = utils.find_resource(identity_client.tenants,
-                                     parsed_args.tenant)
+        project = utils.find_resource(
+            identity_client.tenants,
+            parsed_args.project,
+        )
         kwargs = {}
         if parsed_args.name:
             kwargs['name'] = parsed_args.name
@@ -164,32 +178,31 @@ class SetTenant(command.Command):
         if 'enabled' in parsed_args:
             kwargs['enabled'] = parsed_args.enabled
 
-        if kwargs == {}:
-            sys.stdout.write("Tenant not updated, no arguments present")
-            return 0
-        tenant.update(**kwargs)
+        project.update(**kwargs)
         return
 
 
-class ShowTenant(show.ShowOne):
-    """Show tenant command"""
+class ShowProject(show.ShowOne):
+    """Show project details"""
 
-    log = logging.getLogger(__name__ + '.ShowTenant')
+    log = logging.getLogger(__name__ + '.ShowProject')
 
     def get_parser(self, prog_name):
-        parser = super(ShowTenant, self).get_parser(prog_name)
+        parser = super(ShowProject, self).get_parser(prog_name)
         parser.add_argument(
-            'tenant',
-            metavar='<tenant>',
-            help='Name or ID of tenant to display')
+            'project',
+            metavar='<project>',
+            help='Project to display (name or ID)')
         return parser
 
     def take_action(self, parsed_args):
         self.log.debug('take_action(%s)' % parsed_args)
         identity_client = self.app.client_manager.identity
-        tenant = utils.find_resource(identity_client.tenants,
-                                     parsed_args.tenant)
+        project = utils.find_resource(
+            identity_client.tenants,
+            parsed_args.project,
+        )
 
         info = {}
-        info.update(tenant._info)
+        info.update(project._info)
         return zip(*sorted(six.iteritems(info)))
diff --git a/openstackclient/identity/v2_0/role.py b/openstackclient/identity/v2_0/role.py
index 61a83af575..580525367c 100644
--- a/openstackclient/identity/v2_0/role.py
+++ b/openstackclient/identity/v2_0/role.py
@@ -13,7 +13,7 @@
 #   under the License.
 #
 
-"""Role action implementations"""
+"""Identity v2 Role action implementations"""
 
 import logging
 import six
@@ -26,7 +26,7 @@ from openstackclient.common import utils
 
 
 class AddRole(show.ShowOne):
-    """Add role to tenant:user"""
+    """Add role to project:user"""
 
     log = logging.getLogger(__name__ + '.AddRole')
 
@@ -37,10 +37,11 @@ class AddRole(show.ShowOne):
             metavar='<role>',
             help='Role name or ID to add to user')
         parser.add_argument(
-            '--tenant',
-            metavar='<tenant>',
+            '--project',
+            metavar='<project>',
             required=True,
-            help='Name or ID of tenant to include')
+            help='Include project (name or ID)',
+        )
         parser.add_argument(
             '--user',
             metavar='<user>',
@@ -52,13 +53,15 @@ class AddRole(show.ShowOne):
         self.log.debug('take_action(%s)' % parsed_args)
         identity_client = self.app.client_manager.identity
         role = utils.find_resource(identity_client.roles, parsed_args.role)
-        tenant = utils.find_resource(identity_client.tenants,
-                                     parsed_args.tenant)
+        project = utils.find_resource(
+            identity_client.tenants,
+            parsed_args.project,
+        )
         user = utils.find_resource(identity_client.users, parsed_args.user)
         role = identity_client.roles.add_user_role(
             user,
             role,
-            tenant)
+            project)
 
         info = {}
         info.update(role._info)
@@ -138,34 +141,43 @@ class ListUserRole(lister.Lister):
             nargs='?',
             help='Name or ID of user to include')
         parser.add_argument(
-            '--tenant',
-            metavar='<tenant>',
-            help='Name or ID of tenant to include')
+            '--project',
+            metavar='<project>',
+            help='Include project (name or ID)',
+        )
         return parser
 
     def take_action(self, parsed_args):
         self.log.debug('take_action(%s)' % parsed_args)
-        columns = ('ID', 'Name', 'Tenant ID', 'User ID')
         identity_client = self.app.client_manager.identity
 
         # user-only roles are not supported in KSL so we are
-        # required to have a user and tenant; default to the
+        # required to have a user and project; default to the
         # values used for authentication if not specified
-        if not parsed_args.tenant:
-            parsed_args.tenant = identity_client.auth_tenant_id
+        if not parsed_args.project:
+            parsed_args.project = identity_client.auth_tenant_id
         if not parsed_args.user:
             parsed_args.user = identity_client.auth_user_id
 
-        tenant = utils.find_resource(identity_client.tenants,
-                                     parsed_args.tenant)
+        project = utils.find_resource(
+            identity_client.tenants,
+            parsed_args.project,
+        )
         user = utils.find_resource(identity_client.users, parsed_args.user)
 
-        data = identity_client.roles.roles_for_user(user.id, tenant.id)
+        data = identity_client.roles.roles_for_user(user.id, project.id)
+
+        columns = (
+            'ID',
+            'Name',
+            'Project',
+            'User',
+        )
 
         # Add the names to the output even though they will be constant
         for role in data:
-            role.user_id = user.name
-            role.tenant_id = tenant.name
+            role.user = user.name
+            role.project = project.name
 
         return (columns,
                 (utils.get_item_properties(
@@ -175,7 +187,7 @@ class ListUserRole(lister.Lister):
 
 
 class RemoveRole(command.Command):
-    """Remove role from tenant:user"""
+    """Remove role from project:user"""
 
     log = logging.getLogger(__name__ + '.RemoveRole')
 
@@ -186,10 +198,11 @@ class RemoveRole(command.Command):
             metavar='<role>',
             help='Role name or ID to remove from user')
         parser.add_argument(
-            '--tenant',
-            metavar='<tenant>',
+            '--project',
+            metavar='<project>',
             required=True,
-            help='Name or ID of tenant')
+            help='Project to include (name or ID)',
+        )
         parser.add_argument(
             '--user',
             metavar='<user>',
@@ -201,13 +214,15 @@ class RemoveRole(command.Command):
         self.log.debug('take_action(%s)' % parsed_args)
         identity_client = self.app.client_manager.identity
         role = utils.find_resource(identity_client.roles, parsed_args.role)
-        tenant = utils.find_resource(identity_client.tenants,
-                                     parsed_args.tenant)
+        project = utils.find_resource(
+            identity_client.tenants,
+            parsed_args.project,
+        )
         user = utils.find_resource(identity_client.users, parsed_args.user)
         identity_client.roles.remove_user_role(
             user.id,
             role.id,
-            tenant.id)
+            project.id)
 
 
 class ShowRole(show.ShowOne):
diff --git a/openstackclient/identity/v2_0/user.py b/openstackclient/identity/v2_0/user.py
index 8c8e2622db..78f2164637 100644
--- a/openstackclient/identity/v2_0/user.py
+++ b/openstackclient/identity/v2_0/user.py
@@ -46,9 +46,10 @@ class CreateUser(show.ShowOne):
             metavar='<user-email>',
             help='New user email address')
         parser.add_argument(
-            '--tenant',
-            metavar='<tenant>',
-            help='New default tenant name or ID')
+            '--project',
+            metavar='<project>',
+            help='Set default project (name or ID)',
+        )
         enable_group = parser.add_mutually_exclusive_group()
         enable_group.add_argument(
             '--enable',
@@ -66,17 +67,23 @@ class CreateUser(show.ShowOne):
     def take_action(self, parsed_args):
         self.log.debug('take_action(%s)' % parsed_args)
         identity_client = self.app.client_manager.identity
-        if parsed_args.tenant:
-            tenant_id = utils.find_resource(identity_client.tenants,
-                                            parsed_args.tenant).id
+        if parsed_args.project:
+            project_id = utils.find_resource(
+                identity_client.tenants,
+                parsed_args.project,
+            ).id
         else:
-            tenant_id = None
+            project_id = None
         user = identity_client.users.create(
             parsed_args.name,
             parsed_args.password,
             parsed_args.email,
-            tenant_id=tenant_id,
-            enabled=parsed_args.enabled)
+            tenant_id=project_id,
+            enabled=parsed_args.enabled,
+        )
+        user._info.update(
+            {'project_id': user._info.pop('tenantId')}
+        )
 
         info = {}
         info.update(user._info)
@@ -112,9 +119,10 @@ class ListUser(lister.Lister):
     def get_parser(self, prog_name):
         parser = super(ListUser, self).get_parser(prog_name)
         parser.add_argument(
-            '--tenant',
-            metavar='<tenant>',
-            help='Name or ID of tenant to filter users')
+            '--project',
+            metavar='<project>',
+            help='Filter users by project (name or ID)',
+        )
         parser.add_argument(
             '--long',
             action='store_true',
@@ -124,15 +132,57 @@ class ListUser(lister.Lister):
 
     def take_action(self, parsed_args):
         self.log.debug('take_action(%s)' % parsed_args)
+
+        def _format_project(project):
+            if not project:
+                return ""
+            if project in project_cache.keys():
+                return project_cache[project].name
+            else:
+                return project
+
         if parsed_args.long:
-            columns = ('ID', 'Name', 'Tenant Id', 'Email', 'Enabled')
+            columns = (
+                'ID',
+                'Name',
+                'tenantId',
+                'Email',
+                'Enabled',
+            )
+            column_headers = (
+                'ID',
+                'Name',
+                'Project',
+                'Email',
+                'Enabled',
+            )
+            # Cache the project list
+            project_cache = {}
+            try:
+                for p in self.app.client_manager.identity.tenants.list():
+                    project_cache[p.id] = p
+            except Exception:
+                # Just forget it if there's any trouble
+                pass
         else:
-            columns = ('ID', 'Name')
+            columns = column_headers = ('ID', 'Name')
         data = self.app.client_manager.identity.users.list()
-        return (columns,
+
+        if parsed_args.long:
+            # FIXME(dtroyer): Sometimes user objects have 'tenant_id' instead
+            #                 of 'tenantId'.  Why?  Dunno yet, but until that
+            #                 is fixed we need to handle it; auth_token.py
+            #                 only looks for 'tenantId'.
+            for d in data:
+                if 'tenant_id' in d._info:
+                    d._info['tenantId'] = d._info.pop('tenant_id')
+                    d._add_details(d._info)
+
+        return (column_headers,
                 (utils.get_item_properties(
                     s, columns,
-                    formatters={},
+                    mixed_case_fields=('tenantId',),
+                    formatters={'tenantId': _format_project},
                 ) for s in data))
 
 
@@ -160,9 +210,10 @@ class SetUser(command.Command):
             metavar='<user-email>',
             help='New user email address')
         parser.add_argument(
-            '--tenant',
-            metavar='<tenant>',
-            help='New default tenant name or ID')
+            '--project',
+            metavar='<project>',
+            help='New default project (name or ID)',
+        )
         enable_group = parser.add_mutually_exclusive_group()
         enable_group.add_argument(
             '--enable',
@@ -186,10 +237,12 @@ class SetUser(command.Command):
             kwargs['name'] = parsed_args.name
         if parsed_args.email:
             kwargs['email'] = parsed_args.email
-        if parsed_args.tenant:
-            tenant_id = utils.find_resource(identity_client.tenants,
-                                            parsed_args.tenant).id
-            kwargs['tenantId'] = tenant_id
+        if parsed_args.project:
+            project = utils.find_resource(
+                identity_client.tenants,
+                parsed_args.project,
+            )
+            kwargs['tenantId'] = project.id
         if 'enabled' in parsed_args:
             kwargs['enabled'] = parsed_args.enabled
 
@@ -217,6 +270,14 @@ class ShowUser(show.ShowOne):
         self.log.debug('take_action(%s)' % parsed_args)
         identity_client = self.app.client_manager.identity
         user = utils.find_resource(identity_client.users, parsed_args.user)
+        if 'tenantId' in user._info:
+            user._info.update(
+                {'project_id': user._info.pop('tenantId')}
+            )
+        if 'tenant_id' in user._info:
+            user._info.update(
+                {'project_id': user._info.pop('tenant_id')}
+            )
 
         info = {}
         info.update(user._info)
diff --git a/setup.cfg b/setup.cfg
index f1f5cf82f2..34da1631b2 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -47,6 +47,12 @@ openstack.identity.v2_0 =
     endpoint_list = openstackclient.identity.v2_0.endpoint:ListEndpoint
     endpoint_show = openstackclient.identity.v2_0.endpoint:ShowEndpoint
 
+    project_create = openstackclient.identity.v2_0.project:CreateProject
+    project_delete = openstackclient.identity.v2_0.project:DeleteProject
+    project_list = openstackclient.identity.v2_0.project:ListProject
+    project_set = openstackclient.identity.v2_0.project:SetProject
+    project_show = openstackclient.identity.v2_0.project:ShowProject
+
     role_add = openstackclient.identity.v2_0.role:AddRole
     role_create = openstackclient.identity.v2_0.role:CreateRole
     role_delete = openstackclient.identity.v2_0.role:DeleteRole
@@ -59,12 +65,6 @@ openstack.identity.v2_0 =
     service_list =openstackclient.identity.v2_0.service:ListService
     service_show =openstackclient.identity.v2_0.service:ShowService
 
-    tenant_create = openstackclient.identity.v2_0.tenant:CreateTenant
-    tenant_delete = openstackclient.identity.v2_0.tenant:DeleteTenant
-    tenant_list = openstackclient.identity.v2_0.tenant:ListTenant
-    tenant_set = openstackclient.identity.v2_0.tenant:SetTenant
-    tenant_show = openstackclient.identity.v2_0.tenant:ShowTenant
-
     user_role_list = openstackclient.identity.v2_0.role:ListUserRole
 
     user_create = openstackclient.identity.v2_0.user:CreateUser