Hello community,

here is the log from the commit of package azure-cli-role for openSUSE:Factory 
checked in at 2018-10-15 10:47:04
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/azure-cli-role (Old)
 and      /work/SRC/openSUSE:Factory/.azure-cli-role.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "azure-cli-role"

Mon Oct 15 10:47:04 2018 rev:4 rq:641213 version:2.1.4

Changes:
--------
--- /work/SRC/openSUSE:Factory/azure-cli-role/azure-cli-role.changes    
2018-05-13 16:03:09.862492425 +0200
+++ /work/SRC/openSUSE:Factory/.azure-cli-role.new/azure-cli-role.changes       
2018-10-15 10:47:05.375156242 +0200
@@ -1,0 +2,9 @@
+Wed Sep 19 09:12:47 UTC 2018 - John Paul Adrian Glaubitz 
<adrian.glaub...@suse.com>
+
+- New upstream release
+  + Version 2.1.4
+  + For detailed information about changes see the
+    HISTORY.txt file provided with this package
+- Update Requires from setup.py
+
+-------------------------------------------------------------------

Old:
----
  azure-cli-role-2.0.22.tar.gz

New:
----
  azure-cli-role-2.1.4.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ azure-cli-role.spec ++++++
--- /var/tmp/diff_new_pack.h3JeT7/_old  2018-10-15 10:47:07.131154367 +0200
+++ /var/tmp/diff_new_pack.h3JeT7/_new  2018-10-15 10:47:07.131154367 +0200
@@ -12,12 +12,12 @@
 # license that conforms to the Open Source Definition (Version 1.9)
 # published by the Open Source Initiative.
 
-# Please submit bugfixes or comments via http://bugs.opensuse.org/
+# Please submit bugfixes or comments via https://bugs.opensuse.org/
 #
 
 
 Name:           azure-cli-role
-Version:        2.0.22
+Version:        2.1.4
 Release:        0
 Summary:        Microsoft Azure CLI 'role' Command Module for Role-Based 
Access Control (RBAC)
 License:        MIT
@@ -35,9 +35,9 @@
 Requires:       azure-cli-core
 Requires:       azure-cli-nspkg
 Requires:       python3-azure-graphrbac >= 0.40.0
-Requires:       python3-azure-keyvault >= 0.3.7
-Requires:       python3-azure-mgmt-authorization >= 0.40.0
-Requires:       python3-azure-mgmt-monitor >= 0.5.0
+Requires:       python3-azure-keyvault >= 1.1.0
+Requires:       python3-azure-mgmt-authorization >= 0.50.0
+Requires:       python3-azure-mgmt-monitor >= 0.5.2
 Requires:       python3-azure-nspkg
 Requires:       python3-pytz
 Conflicts:      azure-cli < 2.0.0

++++++ azure-cli-role-2.0.22.tar.gz -> azure-cli-role-2.1.4.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/azure-cli-role-2.0.22/HISTORY.rst 
new/azure-cli-role-2.1.4/HISTORY.rst
--- old/azure-cli-role-2.0.22/HISTORY.rst       2018-04-06 19:33:13.000000000 
+0200
+++ new/azure-cli-role-2.1.4/HISTORY.rst        2018-08-23 01:07:57.000000000 
+0200
@@ -2,10 +2,55 @@
 
 Release History
 ===============
+2.1.4
+++++++
+* Minor fixes.
 
-2.0.22
+
+2.1.3
+++++++
+* role assignment: fix a recent regression that principalName is missing
+
+2.1.2
+++++++
+* support for stack profile 2017-03-09-profile
+
+2.1.1
++++++
+* `ad app update`: Fixes issue where generic update parameters would not work 
correctly.
+
+2.1.0
++++++
+* BREAKING CHANGE: 'show' commands log error message and fail with exit code 
of 3 upon a missing resource.
+
+2.0.27
+++++++
+* Minor fixes.
+
+2.0.26
 ++++++
+* Minor fixes.
 
+2.0.25
+++++++
+* ad: remove stack traces from graph exceptions before surface to users
+* ad sp create: do not throw if CLI can't resolve app id
+
+2.0.25
+++++++
+* Minor fixes.
+
+2.0.24
+++++++
+* ad app update: add generic update support
+
+2.0.23
+++++++
+* BREAKING CHANGE: remove deprecated `az ad sp reset-credentials`
+* Minor fixes.
+
+2.0.22
+++++++
 * `sdist` is now compatible with wheel 0.31.0
 
 2.0.21
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/azure-cli-role-2.0.22/PKG-INFO 
new/azure-cli-role-2.1.4/PKG-INFO
--- old/azure-cli-role-2.0.22/PKG-INFO  2018-04-06 19:33:56.000000000 +0200
+++ new/azure-cli-role-2.1.4/PKG-INFO   2018-08-23 01:09:56.000000000 +0200
@@ -1,12 +1,11 @@
 Metadata-Version: 1.1
 Name: azure-cli-role
-Version: 2.0.22
+Version: 2.1.4
 Summary: Microsoft Azure Command-Line Tools Role Command Module
 Home-page: https://github.com/Azure/azure-cli
 Author: Microsoft Corporation
 Author-email: azpy...@microsoft.com
 License: MIT
-Description-Content-Type: UNKNOWN
 Description: Microsoft Azure CLI 'role' Command Module for Role-Based Access 
Control (RBAC)
         
==============================================================================
         
@@ -20,10 +19,55 @@
         
         Release History
         ===============
+        2.1.4
+        ++++++
+        * Minor fixes.
         
-        2.0.22
+        
+        2.1.3
+        ++++++
+        * role assignment: fix a recent regression that principalName is 
missing
+        
+        2.1.2
+        ++++++
+        * support for stack profile 2017-03-09-profile
+        
+        2.1.1
+        +++++
+        * `ad app update`: Fixes issue where generic update parameters would 
not work correctly.
+        
+        2.1.0
+        +++++
+        * BREAKING CHANGE: 'show' commands log error message and fail with 
exit code of 3 upon a missing resource.
+        
+        2.0.27
+        ++++++
+        * Minor fixes.
+        
+        2.0.26
         ++++++
+        * Minor fixes.
         
+        2.0.25
+        ++++++
+        * ad: remove stack traces from graph exceptions before surface to users
+        * ad sp create: do not throw if CLI can't resolve app id
+        
+        2.0.25
+        ++++++
+        * Minor fixes.
+        
+        2.0.24
+        ++++++
+        * ad app update: add generic update support
+        
+        2.0.23
+        ++++++
+        * BREAKING CHANGE: remove deprecated `az ad sp reset-credentials`
+        * Minor fixes.
+        
+        2.0.22
+        ++++++
         * `sdist` is now compatible with wheel 0.31.0
         
         2.0.21
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/azure-cli-role-2.0.22/azure/cli/command_modules/role/__init__.py 
new/azure-cli-role-2.1.4/azure/cli/command_modules/role/__init__.py
--- old/azure-cli-role-2.0.22/azure/cli/command_modules/role/__init__.py        
2018-04-06 19:33:13.000000000 +0200
+++ new/azure-cli-role-2.1.4/azure/cli/command_modules/role/__init__.py 
2018-08-23 01:07:57.000000000 +0200
@@ -4,6 +4,7 @@
 # 
--------------------------------------------------------------------------------------------
 
 from azure.cli.core import AzCommandsLoader
+from azure.cli.core.profiles import ResourceType
 
 import azure.cli.command_modules.role._help  # pylint: disable=unused-import
 
@@ -13,7 +14,10 @@
     def __init__(self, cli_ctx=None):
         from azure.cli.core.commands import CliCommandType
         role_custom = 
CliCommandType(operations_tmpl='azure.cli.command_modules.role.custom#{}')
-        super(RoleCommandsLoader, self).__init__(cli_ctx=cli_ctx, 
custom_command_type=role_custom)
+        super(RoleCommandsLoader, self).__init__(cli_ctx=cli_ctx,
+                                                 
resource_type=ResourceType.MGMT_AUTHORIZATION,
+                                                 
operation_group='role_assignments',
+                                                 
custom_command_type=role_custom)
 
     def load_command_table(self, args):
         from azure.cli.command_modules.role.commands import load_command_table
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/azure-cli-role-2.0.22/azure/cli/command_modules/role/_client_factory.py 
new/azure-cli-role-2.1.4/azure/cli/command_modules/role/_client_factory.py
--- old/azure-cli-role-2.0.22/azure/cli/command_modules/role/_client_factory.py 
2018-04-06 19:33:13.000000000 +0200
+++ new/azure-cli-role-2.1.4/azure/cli/command_modules/role/_client_factory.py  
2018-08-23 01:07:57.000000000 +0200
@@ -6,14 +6,14 @@
 
 def _auth_client_factory(cli_ctx, scope=None):
     import re
+    from azure.cli.core.profiles import ResourceType
     from azure.cli.core.commands.client_factory import get_mgmt_service_client
-    from azure.mgmt.authorization import AuthorizationManagementClient
     subscription_id = None
     if scope:
         matched = re.match('/subscriptions/(?P<subscription>[^/]*)/', scope)
         if matched:
             subscription_id = matched.groupdict()['subscription']
-    return get_mgmt_service_client(cli_ctx, AuthorizationManagementClient, 
subscription_id=subscription_id)
+    return get_mgmt_service_client(cli_ctx, ResourceType.MGMT_AUTHORIZATION, 
subscription_id=subscription_id)
 
 
 def _graph_client_factory(cli_ctx, **_):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/azure-cli-role-2.0.22/azure/cli/command_modules/role/_help.py 
new/azure-cli-role-2.1.4/azure/cli/command_modules/role/_help.py
--- old/azure-cli-role-2.0.22/azure/cli/command_modules/role/_help.py   
2018-04-06 19:33:13.000000000 +0200
+++ new/azure-cli-role-2.1.4/azure/cli/command_modules/role/_help.py    
2018-08-23 01:07:57.000000000 +0200
@@ -1,3 +1,4 @@
+# coding=utf-8
 # 
--------------------------------------------------------------------------------------------
 # Copyright (c) Microsoft Corporation. All rights reserved.
 # Licensed under the MIT License. See License.txt in the project root for 
license information.
@@ -72,11 +73,6 @@
     short-summary: delete a service principal's credential.
 """
 
-helps['ad sp reset-credentials'] = """
-    type: command
-    short-summary: (Deprecated, use "az ad sp credential reset")
-"""
-
 helps['ad sp credential reset'] = """
     type: command
     short-summary: Reset a service principal credential.
@@ -117,14 +113,14 @@
     type: command
     short-summary: Get the details of a service principal.
 """
+helps['ad app'] = """
+    type: group
+    short-summary: Manage applications with AAD Graph.
+"""
 helps['ad app delete'] = """
     type: command
     short-summary: Delete an application.
 """
-helps['ad app create'] = """
-    type: command
-    short-summary: Create an application.
-"""
 helps['ad app list'] = """
     type: command
     short-summary: List applications.
@@ -136,6 +132,24 @@
 helps['ad app update'] = """
     type: command
     short-summary: Update an application.
+    examples:
+        - name: update a native application with delegated permission of 
"access the AAD directory as the signed-in user"
+          text: |
+                az ad app update --id e042ec79-34cd-498f-9d9f-123456781234 
--required-resource-accesses @manifest.json
+                ("manifest.json" contains the following content)
+                [{
+                    "resourceAppId": "00000002-0000-0000-c000-000000000000",
+                    "resourceAccess": [
+                        {
+                            "id": "a42657d6-7f20-40e3-b6f0-cee03008a62a",
+                            "type": "Scope"
+                        }
+                   ]
+                }]
+        - name: update an application's group membership claims to "All"
+          text: >
+                az ad app update --id e042ec79-34cd-498f-9d9f-123456781234 
--set groupMembershipClaims=All
+
 """
 helps['ad user list'] = """
     type: command
@@ -165,6 +179,10 @@
     short-summary: List role assignments.
     long-summary: By default, only assignments scoped to subscription will be 
displayed. To view assignments scoped by resource or group, use `--all`.
 """
+helps['role assignment list-changelogs'] = """
+    type: command
+    short-summary: List changelogs for role assignments.
+"""
 helps['role definition'] = """
     type: group
     short-summary: Manage role definitions.
@@ -223,35 +241,6 @@
         - name: --role-definition
           type: string
           short-summary: Description of a role as JSON, or a path to a file 
containing a JSON description.
-    examples:
-        - name: Create a role with read-only access to storage and network 
resources, and the ability to start or restart VMs.
-          text: |
-                az role definition create --role-definition '{
-                    "Name": "Contoso On-call",
-                    "Description": "Perform VM actions and read storage and 
network information."
-                    "Actions": [
-                        "Microsoft.Compute/*/read",
-                        "Microsoft.Compute/virtualMachines/start/action",
-                        "Microsoft.Compute/virtualMachines/restart/action",
-                        "Microsoft.Network/*/read",
-                        "Microsoft.Storage/*/read",
-                        "Microsoft.Authorization/*/read",
-                        
"Microsoft.Resources/subscriptions/resourceGroups/read",
-                        
"Microsoft.Resources/subscriptions/resourceGroups/resources/read",
-                        "Microsoft.Insights/alertRules/*",
-                        "Microsoft.Support/*"
-                    ],
-                    "DataActions": [
-                        
"Microsoft.Storage/storageAccounts/blobServices/containers/blobs/*"
-                    ],
-                    "NotDataActions": [
-                        
"Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write"
-                    ],
-                    "AssignableScopes": 
["/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"]
-                }'
-        - name: Create a role from a file containing a JSON description.
-          text: >
-            az role definition create --role-definition ad-role.json
 """
 helps['ad'] = """
     type: group
@@ -261,9 +250,9 @@
     type: command
     short-summary: Create a web application, web API or native application
     examples:
-        - name: Create a native application with delegated permission of 
"access the AAD directory as the signed-in user
+        - name: Create a native application with delegated permission of 
"access the AAD directory as the signed-in user"
           text: |
-                az ad app create --display-name my-native --native-app 
--requiredResourceAccess @manifest.json
+                az ad app create --display-name my-native --native-app 
--required-resource-accesses @manifest.json
                 ("manifest.json" contains the following content)
                 [{
                     "resourceAppId": "00000002-0000-0000-c000-000000000000",
@@ -279,10 +268,18 @@
     type: group
     short-summary: Manage Azure Active Directory groups.
 """
+helps['ad group create'] = """
+    type: command
+    short-summary: Create a group in the directory.
+"""
 helps['ad group member'] = """
     type: group
     short-summary: Manage Azure Active Directory group members.
 """
+helps['ad group member check'] = """
+    type: command
+    short-summary: Check if a member is in a group.
+"""
 helps['ad sp'] = """
     type: group
     short-summary: Manage Azure Active Directory service principals for 
automation authentication.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/azure-cli-role-2.0.22/azure/cli/command_modules/role/_params.py 
new/azure-cli-role-2.1.4/azure/cli/command_modules/role/_params.py
--- old/azure-cli-role-2.0.22/azure/cli/command_modules/role/_params.py 
2018-04-06 19:33:13.000000000 +0200
+++ new/azure-cli-role-2.1.4/azure/cli/command_modules/role/_params.py  
2018-08-23 01:07:57.000000000 +0200
@@ -18,6 +18,9 @@
 
 # pylint: disable=too-many-statements
 def load_arguments(self, _):
+    with self.argument_context('ad') as c:
+        c.argument('_subscription')  # hide global subscription param
+
     with self.argument_context('ad app') as c:
         c.argument('app_id', help='application id')
         c.argument('application_object_id', options_list=('--object-id',))
@@ -39,9 +42,6 @@
                    help="resource scopes and roles the application requires 
access to. Should be in manifest json format. See examples below for details")
         c.argument('native_app', arg_type=get_three_state_flag(), help="an 
application which can be installed on a user's device or computer")
 
-    with self.argument_context('ad') as c:
-        c.ignore('additional_properties')
-
     with self.argument_context('ad sp') as c:
         c.argument('identifier', options_list=['--id'], help='service 
principal name, or object id')
 
@@ -54,7 +54,7 @@
         c.argument('skip_assignment', arg_type=get_three_state_flag(), 
help='do not create default assignment')
         c.argument('show_auth_for_sdk', options_list='--sdk-auth', 
help='output result in compatible with Azure SDK auth file', 
arg_type=get_three_state_flag())
 
-    for item in ['create-for-rbac', 'reset-credentials', 'ad sp']:
+    for item in ['create-for-rbac', 'credential reset']:
         with self.argument_context('ad sp {}'.format(item)) as c:
             c.argument('name', name_arg_type)
             c.argument('cert', arg_group='Credential', validator=validate_cert)
@@ -64,6 +64,11 @@
             c.argument('keyvault', arg_group='Credential')
             c.argument('append', action='store_true', help='Append the new 
credential instead of overwriting.')
 
+    for item in ['delete', 'list']:
+        with self.argument_context('ad sp credential {}'.format(item)) as c:
+            c.argument('key_id', help='credential key id')
+            c.argument('cert', action='store_true', help='a certificate based 
credential')
+
     with self.argument_context('ad') as c:
         c.argument('display_name', help='object\'s display name or its prefix')
         c.argument('identifier_uri', help='graph application identifier, must 
be in uri format')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/azure-cli-role-2.0.22/azure/cli/command_modules/role/commands.py 
new/azure-cli-role-2.1.4/azure/cli/command_modules/role/commands.py
--- old/azure-cli-role-2.0.22/azure/cli/command_modules/role/commands.py        
2018-04-06 19:33:13.000000000 +0200
+++ new/azure-cli-role-2.1.4/azure/cli/command_modules/role/commands.py 
2018-08-23 01:07:57.000000000 +0200
@@ -9,8 +9,6 @@
 from azure.cli.core.profiles import PROFILE_TYPE
 from azure.cli.core.commands import CliCommandType
 
-from azure.cli.core.util import empty_on_404
-
 from ._client_factory import (_auth_client_factory, _graph_client_factory)
 
 
@@ -25,9 +23,12 @@
                          ('Scope', r['scope'])]) for r in result]
 
 
-def get_role_definition_op(operation_name):
-    return 'azure.mgmt.authorization.operations.role_definitions_operations' \
-           '#RoleDefinitionsOperations.{}'.format(operation_name)
+def graph_err_handler(ex):
+    from azure.graphrbac.models.graph_error import GraphErrorException
+    if isinstance(ex, GraphErrorException):
+        from knack.util import CLIError
+        raise CLIError(ex.message)
+    raise ex
 
 
 def get_role_definitions(cli_ctx, _):
@@ -63,6 +64,8 @@
         client_factory=get_graph_client_groups
     )
 
+    role_custom = 
CliCommandType(operations_tmpl='azure.cli.command_modules.role.custom#{}')
+
     with self.command_group('role definition') as g:
         g.custom_command('list', 'list_role_definitions', 
table_transformer=transform_definition_list)
         g.custom_command('delete', 'delete_role_definition')
@@ -75,41 +78,43 @@
         g.custom_command('create', 'create_role_assignment')
         g.custom_command('list-changelogs', 'list_role_assignment_change_logs')
 
-    with self.command_group('ad app', 
client_factory=get_graph_client_applications, resource_type=PROFILE_TYPE, 
min_api='2017-03-10') as g:
+    with self.command_group('ad app', 
client_factory=get_graph_client_applications, resource_type=PROFILE_TYPE,
+                            exception_handler=graph_err_handler) as g:
         g.custom_command('create', 'create_application')
         g.custom_command('delete', 'delete_application')
         g.custom_command('list', 'list_apps')
-        g.custom_command('show', 'show_application', 
exception_handler=empty_on_404)
-        g.custom_command('update', 'update_application')
+        g.custom_show_command('show', 'show_application')
+        g.generic_update_command('update', setter_name='patch_application', 
setter_type=role_custom,
+                                 getter_name='show_application', 
getter_type=role_custom,
+                                 custom_func_name='update_application', 
custom_func_type=role_custom)
 
-    with self.command_group('ad sp', resource_type=PROFILE_TYPE, 
min_api='2017-03-10') as g:
+    with self.command_group('ad sp', resource_type=PROFILE_TYPE, 
exception_handler=graph_err_handler) as g:
         g.custom_command('create', 'create_service_principal')
         g.custom_command('delete', 'delete_service_principal')
         g.custom_command('list', 'list_sps', 
client_factory=get_graph_client_service_principals)
-        g.custom_command('show', 'show_service_principal', 
client_factory=get_graph_client_service_principals, 
exception_handler=empty_on_404)
+        g.custom_show_command('show', 'show_service_principal', 
client_factory=get_graph_client_service_principals)
 
     # RBAC related
-    with self.command_group('ad sp') as g:
+    with self.command_group('ad sp', exception_handler=graph_err_handler) as g:
         g.custom_command('create-for-rbac', 
'create_service_principal_for_rbac')
-        g.custom_command('reset-credentials', 
'reset_service_principal_credential', deprecate_info='ad sp credential reset')
         g.custom_command('credential reset', 
'reset_service_principal_credential')
         g.custom_command('credential list', 
'list_service_principal_credentials')
         g.custom_command('credential delete', 
'delete_service_principal_credential')
 
-    with self.command_group('ad user', role_users_sdk) as g:
+    with self.command_group('ad user', role_users_sdk, 
exception_handler=graph_err_handler) as g:
         g.command('delete', 'delete')
-        g.command('show', 'get', exception_handler=empty_on_404)
+        g.show_command('show', 'get')
         g.custom_command('list', 'list_users', 
client_factory=get_graph_client_users)
         g.custom_command('create', 'create_user', 
client_factory=get_graph_client_users, 
doc_string_source='azure.graphrbac.models#UserCreateParameters')
 
-    with self.command_group('ad group', role_group_sdk) as g:
+    with self.command_group('ad group', role_group_sdk, 
exception_handler=graph_err_handler) as g:
         g.custom_command('create', 'create_group', 
client_factory=get_graph_client_groups)
         g.command('delete', 'delete')
-        g.command('show', 'get', exception_handler=empty_on_404)
+        g.show_command('show', 'get')
         g.command('get-member-groups', 'get_member_groups')
         g.custom_command('list', 'list_groups', 
client_factory=get_graph_client_groups)
 
-    with self.command_group('ad group member', role_group_sdk) as g:
+    with self.command_group('ad group member', role_group_sdk, 
exception_handler=graph_err_handler) as g:
         g.command('list', 'get_group_members')
         g.command('add', 'add_member')
         g.command('remove', 'remove_member')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/azure-cli-role-2.0.22/azure/cli/command_modules/role/custom.py 
new/azure-cli-role-2.1.4/azure/cli/command_modules/role/custom.py
--- old/azure-cli-role-2.0.22/azure/cli/command_modules/role/custom.py  
2018-04-06 19:33:13.000000000 +0200
+++ new/azure-cli-role-2.1.4/azure/cli/command_modules/role/custom.py   
2018-08-23 01:07:57.000000000 +0200
@@ -16,13 +16,12 @@
 from knack.log import get_logger
 from knack.util import CLIError, todict
 
+from msrest.serialization import TZ_UTC
 from msrestazure.azure_exceptions import CloudError
 from azure.graphrbac.models.graph_error import GraphErrorException
 
 from azure.cli.core.util import get_file_json, shell_safe_json_parse
 
-from azure.mgmt.authorization.models import RoleAssignmentCreateParameters, 
Permission, RoleDefinition
-
 from azure.graphrbac.models import (ApplicationCreateParameters, 
ApplicationUpdateParameters, PasswordCredential,
                                     KeyCredential, UserCreateParameters, 
PasswordProfile,
                                     ServicePrincipalCreateParameters, 
RequiredResourceAccess,
@@ -46,20 +45,47 @@
 
 
 def create_role_definition(cmd, role_definition):
-    return _create_update_role_definition(cmd.cli_ctx, role_definition, 
for_update=False)
+    return _create_update_role_definition(cmd, role_definition, 
for_update=False)
 
 
 def update_role_definition(cmd, role_definition):
-    return _create_update_role_definition(cmd.cli_ctx, role_definition, 
for_update=True)
+    return _create_update_role_definition(cmd, role_definition, 
for_update=True)
+
+
+def _get_role_property(obj, property_name):
+    if isinstance(obj, dict):
+        if 'properties' in obj:
+            return obj['properties'][property_name]
+        return obj[property_name]
+
+    if hasattr(obj, 'properties'):
+        return getattr(obj.properties, property_name)
+    return getattr(obj, property_name)
+
+
+def _set_role_property(obj, property_name, property_value):
+    if isinstance(obj, dict):
+        if 'properties' in obj:
+            obj['properties'][property_name] = property_value
+        else:
+            obj[property_name] = property_value
+    else:
+        if hasattr(obj, 'properties'):
+            setattr(obj.properties, property_name, property_value)
+        else:
+            setattr(obj, property_name, property_value)
 
 
-def _create_update_role_definition(cli_ctx, role_definition, for_update):
-    definitions_client = _auth_client_factory(cli_ctx).role_definitions
+def _create_update_role_definition(cmd, role_definition, for_update):
+    from azure.cli.core.profiles import ResourceType, get_sdk, get_api_version
+    definitions_client = _auth_client_factory(cmd.cli_ctx).role_definitions
     if os.path.exists(role_definition):
         role_definition = get_file_json(role_definition)
     else:
         role_definition = shell_safe_json_parse(role_definition)
 
+    if not isinstance(role_definition, dict):
+        raise CLIError('Invalid role defintion. A valid dictionary JSON 
representation is expected.')
     # to workaround service defects, ensure property names are camel case
     names = [p for p in role_definition if p[:1].isupper()]
     for n in names:
@@ -78,7 +104,7 @@
             raise CLIError('Please provide the unique logic name of an 
existing role')
         role_definition['name'] = matched[0].name
         # ensure correct logical name and guid name. For update we accept both
-        role_name = matched[0].role_name
+        role_name = _get_role_property(matched[0], 'role_name')
         role_id = matched[0].name
     else:
         role_id = _gen_guid()
@@ -86,20 +112,39 @@
     if not for_update and 'assignableScopes' not in role_definition:
         raise CLIError("please provide 'assignableScopes'")
 
+    Permission, RoleDefinition, RoleDefinitionProperties = 
get_sdk(cmd.cli_ctx, ResourceType.MGMT_AUTHORIZATION,
+                                                                   
'Permission', 'RoleDefinition',
+                                                                   
'RoleDefinitionProperties', mod='models',
+                                                                   
operation_group='role_definitions')
+
+    version = getattr(get_api_version(cmd.cli_ctx, 
ResourceType.MGMT_AUTHORIZATION), 'role_definitions')
+    if version == '2015-07-01':
+        permission = Permission(actions=role_definition.get('actions', None),
+                                not_actions=role_definition.get('notActions', 
None))
+
+        properties = RoleDefinitionProperties(role_name=role_name,
+                                              
description=role_definition.get('description', None),
+                                              type=_CUSTOM_RULE,
+                                              
assignable_scopes=role_definition['assignableScopes'],
+                                              permissions=[permission])
+        definition = RoleDefinition(name=role_id, properties=properties)
+        return definitions_client.create_or_update(role_definition_id=role_id,
+                                                   
scope=properties.assignable_scopes[0],
+                                                   properties=properties)
+
     permission = Permission(actions=role_definition.get('actions', None),
                             not_actions=role_definition.get('notActions', 
None),
                             data_actions=role_definition.get('dataActions', 
None),
                             
not_data_actions=role_definition.get('notDataActions', None))
 
-    role_definition = RoleDefinition(role_name=role_name,
-                                     
description=role_definition.get('description', None),
-                                     role_type=_CUSTOM_RULE,
-                                     
assignable_scopes=role_definition['assignableScopes'],
-                                     permissions=[permission])
-
+    definition = RoleDefinition(role_name=role_name,
+                                description=role_definition.get('description', 
None),
+                                role_type=_CUSTOM_RULE,
+                                
assignable_scopes=role_definition['assignableScopes'],
+                                permissions=[permission])
     return definitions_client.create_or_update(role_definition_id=role_id,
-                                               
scope=role_definition.assignable_scopes[0],
-                                               role_definition=role_definition)
+                                               
scope=definition.assignable_scopes[0],
+                                               role_definition=definition)
 
 
 def delete_role_definition(cmd, name, resource_group_name=None, scope=None,
@@ -115,9 +160,9 @@
 def _search_role_definitions(definitions_client, name, scope, 
custom_role_only=False):
     roles = list(definitions_client.list(scope))
     if name:
-        roles = [r for r in roles if r.name == name or r.role_name == name]
+        roles = [r for r in roles if r.name == name or _get_role_property(r, 
'role_name') == name]
     if custom_role_only:
-        roles = [r for r in roles if r.role_type == _CUSTOM_RULE]
+        roles = [r for r in roles if _get_role_property(r, 'role_type') == 
_CUSTOM_RULE]
     return roles
 
 
@@ -131,18 +176,31 @@
 
 def _create_role_assignment(cli_ctx, role, assignee, resource_group_name=None, 
scope=None,
                             resolve_assignee=True):
+    from azure.cli.core.profiles import ResourceType, get_sdk, get_api_version
     factory = _auth_client_factory(cli_ctx, scope)
     assignments_client = factory.role_assignments
     definitions_client = factory.role_definitions
+    RoleAssignmentCreateParameters, RoleAssignmentProperties = 
get_sdk(cli_ctx, ResourceType.MGMT_AUTHORIZATION,
+                                                                       
'RoleAssignmentCreateParameters',
+                                                                       
'RoleAssignmentProperties', mod='models',
+                                                                       
operation_group='role_assignments')
 
     scope = _build_role_scope(resource_group_name, scope,
                               assignments_client.config.subscription_id)
 
     role_id = _resolve_role_id(role, scope, definitions_client)
     object_id = _resolve_object_id(cli_ctx, assignee) if resolve_assignee else 
assignee
-    parameters = RoleAssignmentCreateParameters(role_definition_id=role_id, 
principal_id=object_id)
+    version = getattr(get_api_version(cli_ctx, 
ResourceType.MGMT_AUTHORIZATION), 'role_assignments')
     assignment_name = _gen_guid()
     custom_headers = None
+
+    if version == '2015-07-01':
+        properties = RoleAssignmentProperties(role_definition_id=role_id, 
principal_id=object_id)
+        return assignments_client.create(scope=scope, 
role_assignment_name=assignment_name,
+                                         properties=properties,
+                                         custom_headers=custom_headers)
+
+    parameters = RoleAssignmentCreateParameters(role_definition_id=role_id, 
principal_id=object_id)
     return assignments_client.create(scope=scope, 
role_assignment_name=assignment_name,
                                      parameters=parameters,
                                      custom_headers=custom_headers)
@@ -153,7 +211,7 @@
                           show_all=False, include_groups=False, 
include_classic_administrators=False):
     '''
     :param include_groups: include extra assignments to the groups of which 
the user is a
-    member(transitively). Supported only for a user principal.
+    member(transitively).
     '''
     graph_client = _graph_client_factory(cmd.cli_ctx)
     factory = _auth_client_factory(cmd.cli_ctx, scope)
@@ -184,13 +242,17 @@
     # 2. fill in role names
     role_defs = list(definitions_client.list(
         scope=scope or ('/subscriptions/' + 
definitions_client.config.subscription_id)))
-    role_dics = {i.id: i.role_name for i in role_defs}
+    role_dics = {i.id: _get_role_property(i, 'role_name') for i in role_defs}
     for i in results:
-        if role_dics.get(i['roleDefinitionId']):
-            i['roleDefinitionName'] = role_dics[i['roleDefinitionId']]
+        if not i.get('roleDefinitionName'):
+            if role_dics.get(_get_role_property(i, 'roleDefinitionId')):
+                _set_role_property(i, 'roleDefinitionName', 
role_dics[_get_role_property(i, 'roleDefinitionId')])
+            else:
+                i['roleDefinitionName'] = None  # the role definition might 
have been deleted
 
     # fill in principal names
-    principal_ids = set(i['principalId'] for i in results if i['principalId'])
+    principal_ids = set(_get_role_property(i, 'principalId') for i in results 
if _get_role_property(i, 'principalId'))
+
     if principal_ids:
         try:
             principals = _get_object_stubs(graph_client, principal_ids)
@@ -198,12 +260,15 @@
 
             for i in [r for r in results if not r.get('principalName')]:
                 i['principalName'] = ''
-                if principal_dics.get(i['principalId']):
-                    i['principalName'] = principal_dics[i['principalId']]
+                if principal_dics.get(_get_role_property(i, 'principalId')):
+                    _set_role_property(i, 'principalName', 
principal_dics[_get_role_property(i, 'principalId')])
         except (CloudError, GraphErrorException) as ex:
             # failure on resolving principal due to graph permission should 
not fail the whole thing
             logger.info("Failed to resolve graph object information per error 
'%s'", ex)
 
+    for r in results:
+        if not r.get('additionalProperties'):  # remove the useless 
"additionalProperties"
+            r.pop('additionalProperties', None)
     return results
 
 
@@ -255,7 +320,7 @@
     # pylint: disable=too-many-nested-blocks, too-many-statements
     result = []
     start_events, end_events, offline_events, client = 
_get_assignment_events(cmd.cli_ctx, start_time, end_time)
-    role_defs = {d.id: [d.role_name, d.id.split('/')[-1]] for d in 
list_role_definitions(cmd)}
+    role_defs = {d.id: [_get_role_property(d, 'role_name'), 
d.id.split('/')[-1]] for d in list_role_definitions(cmd)}
 
     for op_id in start_events:
         e = end_events.get(op_id, None)
@@ -341,7 +406,7 @@
 
 def _backfill_assignments_for_co_admins(cli_ctx, auth_client, assignee=None):
     co_admins = auth_client.classic_administrators.list()  # known swagger bug 
on api-version handling
-    co_admins = [x for x in co_admins if x.email_address]
+    co_admins = [x for x in co_admins if _get_role_property(x, 
'email_address')]
     graph_client = _graph_client_factory(cli_ctx)
     if assignee:  # apply assignee filter if applicable
         if _is_guid(assignee):
@@ -352,26 +417,27 @@
                 assignee = _get_displayable_name(result[0]).lower()
             except ValueError:
                 pass
-        co_admins = [x for x in co_admins if assignee == 
x.email_address.lower()]
+        co_admins = [x for x in co_admins if assignee == _get_role_property(x, 
'email_address').lower()]
 
     if not co_admins:
         return []
 
     result, users = [], []
     for i in range(0, len(co_admins), 10):  # graph allows up to 10 query 
filters, so split into chunks here
-        upn_queries = ["userPrincipalName eq '{}'".format(x.email_address) for 
x in co_admins[i:i + 10]]
+        upn_queries = ["userPrincipalName eq 
'{}'".format(_get_role_property(x, 'email_address'))
+                       for x in co_admins[i:i + 10]]
         temp = list(list_users(graph_client.users, query_filter=' or 
'.join(upn_queries)))
         users += temp
     upns = {u.user_principal_name: u.object_id for u in users}
     for admin in co_admins:
         na_text = 'NA(classic admins)'
-        email = admin.email_address
+        email = _get_role_property(admin, 'email_address')
         result.append({
             'id': na_text,
             'name': na_text,
             'principalId': upns.get(email),
             'principalName': email,
-            'roleDefinitionName': admin.role,
+            'roleDefinitionName': _get_role_property(admin, 'role'),
             'roleDefinitionId': 'NA(classic admin role)',
             'scope': '/subscriptions/' + auth_client.config.subscription_id
         })
@@ -433,13 +499,13 @@
     if assignments:
         assignments = [a for a in assignments if (
             not scope or
-            include_inherited and re.match(a.scope, scope, re.I) or
-            a.scope.lower() == scope.lower()
+            include_inherited and re.match(_get_role_property(a, 'scope'), 
scope, re.I) or
+            _get_role_property(a, 'scope').lower() == scope.lower()
         )]
 
         if role:
             role_id = _resolve_role_id(role, scope, definitions_client)
-            assignments = [i for i in assignments if i.role_definition_id == 
role_id]
+            assignments = [i for i in assignments if _get_role_property(i, 
'role_definition_id') == role_id]
 
     return assignments
 
@@ -603,12 +669,11 @@
     return result
 
 
-def update_application(client, identifier, display_name=None, homepage=None,
+def update_application(instance, display_name=None, homepage=None,  # pylint: 
disable=unused-argument
                        identifier_uris=None, password=None, reply_urls=None, 
key_value=None,
                        key_type=None, key_usage=None, start_date=None, 
end_date=None, available_to_other_tenants=None,
                        oauth2_allow_implicit_flow=None, 
required_resource_accesses=None):
-    object_id = _resolve_application(client, identifier)
-
+    from azure.cli.core.commands.arm import make_camel_case, make_snake_case
     password_creds, key_creds, required_accesses = None, None, None
     if any([key_value, key_type, key_usage, start_date, end_date]):
         password_creds, key_creds = _build_application_creds(password, 
key_value, key_type,
@@ -617,16 +682,31 @@
     if required_resource_accesses:
         required_accesses = 
_build_application_accesses(required_resource_accesses)
 
-    app_patch_param = ApplicationUpdateParameters(display_name=display_name,
-                                                  homepage=homepage,
-                                                  
identifier_uris=identifier_uris,
-                                                  reply_urls=reply_urls,
-                                                  key_credentials=key_creds,
-                                                  
password_credentials=password_creds,
-                                                  
available_to_other_tenants=available_to_other_tenants,
-                                                  
required_resource_access=required_accesses,
-                                                  
oauth2_allow_implicit_flow=oauth2_allow_implicit_flow)
-    return client.patch(object_id, app_patch_param)
+    # Workaround until 
https://github.com/Azure/azure-rest-api-specs/issues/3437 is fixed
+    def _get_property(name):
+        try:
+            return getattr(instance, make_snake_case(name))
+        except AttributeError:
+            return instance.additional_properties.get(make_camel_case(name), 
None)
+
+    app_patch_param = ApplicationUpdateParameters(
+        display_name=display_name or _get_property('display_name'),
+        homepage=homepage or _get_property('homepage'),
+        identifier_uris=identifier_uris or _get_property('identifier_uris'),
+        reply_urls=reply_urls or _get_property('reply_urls'),
+        key_credentials=key_creds or _get_property('key_credentials'),
+        password_credentials=password_creds or 
_get_property('password_credentials'),
+        available_to_other_tenants=available_to_other_tenants or 
_get_property('available_to_other_tenants'),
+        required_resource_access=required_accesses or 
_get_property('required_resource_access'),
+        oauth2_allow_implicit_flow=oauth2_allow_implicit_flow or 
_get_property('oauth2_allow_implicit_flow'))
+
+    return app_patch_param
+
+
+def patch_application(cmd, identifier, parameters):
+    graph_client = _graph_client_factory(cmd.cli_ctx)
+    object_id = _resolve_application(graph_client.applications, identifier)
+    return graph_client.applications.patch(object_id, parameters)
 
 
 def _build_application_accesses(required_resource_accesses):
@@ -699,7 +779,7 @@
 
 def _create_service_principal(cli_ctx, identifier, resolve_app=True):
     client = _graph_client_factory(cli_ctx)
-
+    app_id = identifier
     if resolve_app:
         if _is_guid(identifier):
             result = list(client.applications.list(filter="appId eq 
'{}'".format(identifier)))
@@ -707,11 +787,12 @@
             result = list(client.applications.list(
                 filter="identifierUris/any(s:s eq '{}')".format(identifier)))
 
-        if not result:  # assume we get an object id
-            result = [client.applications.get(identifier)]
-        app_id = result[0].app_id
-    else:
-        app_id = identifier
+        try:
+            if not result:  # assume we get an object id
+                result = [client.applications.get(identifier)]
+            app_id = result[0].app_id
+        except GraphErrorException:
+            pass  # fallback to appid (maybe from an external tenant?)
 
     return 
client.service_principals.create(ServicePrincipalCreateParameters(app_id, True))
 
@@ -884,7 +965,6 @@
         scopes=None, role='Contributor',
         show_auth_for_sdk=None, skip_assignment=False, keyvault=None):
     import time
-    import pytz
 
     graph_client = _graph_client_factory(cmd.cli_ctx)
     role_client = _auth_client_factory(cmd.cli_ctx).role_assignments
@@ -904,7 +984,7 @@
         if aad_sps:
             raise CLIError("'{}' already exists.".format(name))
 
-    app_start_date = datetime.datetime.now(pytz.utc)
+    app_start_date = datetime.datetime.now(TZ_UTC)
     app_end_date = app_start_date + relativedelta(years=years or 1)
 
     app_display_name = app_display_name or ('azure-cli-' +
@@ -995,12 +1075,14 @@
 
 def _get_keyvault_client(cli_ctx):
     from azure.cli.core._profile import Profile
-    from azure.keyvault import KeyVaultClient, KeyVaultAuthentication
+    from azure.cli.core.profiles import get_api_version, ResourceType
+    from azure.keyvault import KeyVaultAuthentication, KeyVaultClient
+    version = str(get_api_version(cli_ctx, ResourceType.DATA_KEYVAULT))
 
     def _get_token(server, resource, scope):  # pylint: disable=unused-argument
         return 
Profile(cli_ctx=cli_ctx).get_login_credentials(resource)[0]._token_retriever()  
# pylint: disable=protected-access
 
-    return KeyVaultClient(KeyVaultAuthentication(_get_token))
+    return KeyVaultClient(KeyVaultAuthentication(_get_token), 
api_version=version)
 
 
 def _create_self_signed_cert(start_date, end_date):  # pylint: 
disable=too-many-locals
@@ -1146,7 +1228,6 @@
 
 def reset_service_principal_credential(cmd, name, password=None, 
create_cert=False,
                                        cert=None, years=None, keyvault=None, 
append=False):
-    import pytz
     client = _graph_client_factory(cmd.cli_ctx)
 
     # pylint: disable=no-member
@@ -1164,7 +1245,7 @@
             'app id guid, or app id uri')
     app = show_application(client.applications, aad_sps[0].app_id)
 
-    app_start_date = datetime.datetime.now(pytz.utc)
+    app_start_date = datetime.datetime.now(TZ_UTC)
     app_end_date = app_start_date + relativedelta(years=years or 1)
 
     # build a new password/cert credential and patch it
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/azure-cli-role-2.0.22/azure_cli_role.egg-info/PKG-INFO 
new/azure-cli-role-2.1.4/azure_cli_role.egg-info/PKG-INFO
--- old/azure-cli-role-2.0.22/azure_cli_role.egg-info/PKG-INFO  2018-04-06 
19:33:56.000000000 +0200
+++ new/azure-cli-role-2.1.4/azure_cli_role.egg-info/PKG-INFO   2018-08-23 
01:09:56.000000000 +0200
@@ -1,12 +1,11 @@
 Metadata-Version: 1.1
 Name: azure-cli-role
-Version: 2.0.22
+Version: 2.1.4
 Summary: Microsoft Azure Command-Line Tools Role Command Module
 Home-page: https://github.com/Azure/azure-cli
 Author: Microsoft Corporation
 Author-email: azpy...@microsoft.com
 License: MIT
-Description-Content-Type: UNKNOWN
 Description: Microsoft Azure CLI 'role' Command Module for Role-Based Access 
Control (RBAC)
         
==============================================================================
         
@@ -20,10 +19,55 @@
         
         Release History
         ===============
+        2.1.4
+        ++++++
+        * Minor fixes.
         
-        2.0.22
+        
+        2.1.3
+        ++++++
+        * role assignment: fix a recent regression that principalName is 
missing
+        
+        2.1.2
+        ++++++
+        * support for stack profile 2017-03-09-profile
+        
+        2.1.1
+        +++++
+        * `ad app update`: Fixes issue where generic update parameters would 
not work correctly.
+        
+        2.1.0
+        +++++
+        * BREAKING CHANGE: 'show' commands log error message and fail with 
exit code of 3 upon a missing resource.
+        
+        2.0.27
+        ++++++
+        * Minor fixes.
+        
+        2.0.26
         ++++++
+        * Minor fixes.
         
+        2.0.25
+        ++++++
+        * ad: remove stack traces from graph exceptions before surface to users
+        * ad sp create: do not throw if CLI can't resolve app id
+        
+        2.0.25
+        ++++++
+        * Minor fixes.
+        
+        2.0.24
+        ++++++
+        * ad app update: add generic update support
+        
+        2.0.23
+        ++++++
+        * BREAKING CHANGE: remove deprecated `az ad sp reset-credentials`
+        * Minor fixes.
+        
+        2.0.22
+        ++++++
         * `sdist` is now compatible with wheel 0.31.0
         
         2.0.21
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/azure-cli-role-2.0.22/azure_cli_role.egg-info/requires.txt 
new/azure-cli-role-2.1.4/azure_cli_role.egg-info/requires.txt
--- old/azure-cli-role-2.0.22/azure_cli_role.egg-info/requires.txt      
2018-04-06 19:33:56.000000000 +0200
+++ new/azure-cli-role-2.1.4/azure_cli_role.egg-info/requires.txt       
2018-08-23 01:09:56.000000000 +0200
@@ -1,6 +1,6 @@
 azure-cli-core
-azure-mgmt-authorization==0.40.0
-azure-mgmt-monitor==0.5.0
+azure-mgmt-authorization==0.50.0
+azure-mgmt-monitor==0.5.2
 azure-graphrbac==0.40.0
-azure-keyvault==0.3.7
+azure-keyvault==1.1.0
 pytz
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/azure-cli-role-2.0.22/setup.py 
new/azure-cli-role-2.1.4/setup.py
--- old/azure-cli-role-2.0.22/setup.py  2018-04-06 19:33:14.000000000 +0200
+++ new/azure-cli-role-2.1.4/setup.py   2018-08-23 01:07:57.000000000 +0200
@@ -14,7 +14,8 @@
     logger.warn("Wheel is not available, disabling bdist_wheel hook")
     cmdclass = {}
 
-VERSION = "2.0.22"
+VERSION = "2.1.4"
+
 CLASSIFIERS = [
     'Development Status :: 5 - Production/Stable',
     'Intended Audience :: Developers',
@@ -31,10 +32,10 @@
 
 DEPENDENCIES = [
     'azure-cli-core',
-    'azure-mgmt-authorization==0.40.0',
-    'azure-mgmt-monitor==0.5.0',
+    'azure-mgmt-authorization==0.50.0',
+    'azure-mgmt-monitor==0.5.2',
     'azure-graphrbac==0.40.0',
-    'azure-keyvault==0.3.7',
+    'azure-keyvault==1.1.0',
     'pytz'
 ]
 


Reply via email to