Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Role] az role assignment list/delete: Support --assignee-object-id #30469

Draft
wants to merge 1 commit into
base: dev
Choose a base branch
from

Conversation

jiasli
Copy link
Member

@jiasli jiasli commented Dec 5, 2024

Related command
az role assignment list
az role assignment delete

Description
Close #30436

Testing Guide

az role assignment list --assignee
az role assignment list --assignee-object-id
az role assignment delete --assignee
az role assignment delete --assignee-object-id

Copy link

azure-client-tools-bot-prd bot commented Dec 5, 2024

❌AzureCLI-FullTest
️✔️acr
️✔️2020-09-01-hybrid
️✔️3.12
️✔️3.9
️✔️latest
️✔️3.12
️✔️3.9
️✔️acs
️✔️2020-09-01-hybrid
️✔️3.12
️✔️3.9
️✔️latest
️✔️3.12
️✔️3.9
️✔️advisor
️✔️latest
️✔️3.12
️✔️3.9
️✔️ams
️✔️latest
️✔️3.12
️✔️3.9
️✔️apim
️✔️latest
️✔️3.12
️✔️3.9
️✔️appconfig
️✔️latest
️✔️3.12
️✔️3.9
️✔️appservice
️✔️latest
️✔️3.12
️✔️3.9
️✔️aro
️✔️latest
️✔️3.12
️✔️3.9
️✔️backup
️✔️latest
️✔️3.12
️✔️3.9
️✔️batch
️✔️latest
️✔️3.12
️✔️3.9
️✔️batchai
️✔️latest
️✔️3.12
️✔️3.9
️✔️billing
️✔️latest
️✔️3.12
️✔️3.9
️✔️botservice
️✔️latest
️✔️3.12
️✔️3.9
️✔️cdn
️✔️latest
️✔️3.12
️✔️3.9
️✔️cloud
️✔️latest
️✔️3.12
️✔️3.9
️✔️cognitiveservices
️✔️latest
️✔️3.12
️✔️3.9
️✔️compute_recommender
️✔️latest
️✔️3.12
️✔️3.9
️✔️computefleet
️✔️latest
️✔️3.12
️✔️3.9
️✔️config
️✔️latest
️✔️3.12
️✔️3.9
️✔️configure
️✔️latest
️✔️3.12
️✔️3.9
️✔️consumption
️✔️latest
️✔️3.12
️✔️3.9
️✔️container
️✔️latest
️✔️3.12
️✔️3.9
️✔️containerapp
️✔️latest
️✔️3.12
️✔️3.9
️✔️core
️✔️2018-03-01-hybrid
️✔️3.12
️✔️3.9
️✔️2019-03-01-hybrid
️✔️3.12
️✔️3.9
️✔️2020-09-01-hybrid
️✔️3.12
️✔️3.9
️✔️latest
️✔️3.12
️✔️3.9
️✔️cosmosdb
️✔️latest
️✔️3.12
️✔️3.9
️✔️databoxedge
️✔️2019-03-01-hybrid
️✔️3.12
️✔️3.9
️✔️2020-09-01-hybrid
️✔️3.12
️✔️3.9
️✔️latest
️✔️3.12
️✔️3.9
️✔️dls
️✔️latest
️✔️3.12
️✔️3.9
️✔️dms
️✔️latest
️✔️3.12
️✔️3.9
️✔️eventgrid
️✔️latest
️✔️3.12
️✔️3.9
️✔️eventhubs
️✔️latest
️✔️3.12
️✔️3.9
️✔️feedback
️✔️latest
️✔️3.12
️✔️3.9
️✔️find
️✔️latest
️✔️3.12
️✔️3.9
️✔️hdinsight
️✔️latest
️✔️3.12
️✔️3.9
️✔️identity
️✔️latest
️✔️3.12
️✔️3.9
️✔️iot
️✔️2019-03-01-hybrid
️✔️3.12
️✔️3.9
️✔️2020-09-01-hybrid
️✔️3.12
️✔️3.9
️✔️latest
️✔️3.12
️✔️3.9
️✔️keyvault
️✔️2018-03-01-hybrid
️✔️3.12
️✔️3.9
️✔️2020-09-01-hybrid
️✔️3.12
️✔️3.9
️✔️latest
️✔️3.12
️✔️3.9
️✔️lab
️✔️latest
️✔️3.12
️✔️3.9
️✔️managedservices
️✔️latest
️✔️3.12
️✔️3.9
️✔️maps
️✔️latest
️✔️3.12
️✔️3.9
️✔️marketplaceordering
️✔️latest
️✔️3.12
️✔️3.9
️✔️monitor
️✔️latest
️✔️3.12
️✔️3.9
️✔️mysql
️✔️latest
️✔️3.12
️✔️3.9
️✔️netappfiles
️✔️latest
️✔️3.12
️✔️3.9
️✔️network
️✔️2018-03-01-hybrid
️✔️3.12
️✔️3.9
️✔️latest
️✔️3.12
️✔️3.9
️✔️policyinsights
️✔️latest
️✔️3.12
️✔️3.9
️✔️privatedns
️✔️latest
️✔️3.12
️✔️3.9
️✔️profile
️✔️latest
️✔️3.12
️✔️3.9
️✔️rdbms
️✔️latest
️✔️3.12
️✔️3.9
️✔️redis
️✔️latest
️✔️3.12
️✔️3.9
️✔️relay
️✔️latest
️✔️3.12
️✔️3.9
❌resource
️✔️2018-03-01-hybrid
️✔️3.12
️✔️3.9
️✔️2019-03-01-hybrid
️✔️3.12
️✔️3.9
❌latest
❌3.12
Type Test Case Error Message Line
Failed test_managed_app_def_deployment_mode self = <azure.cli.testsdk.base.ExecutionResult object at 0x7f0ac9840440>
cli_ctx = <azure.cli.core.mock.DummyCli object at 0x7f0ad4f6a1b0>
command = 'role assignment delete --assignee [email protected] --role contributor '
expect_failure = False

    def in_process_execute(self, cli_ctx, command, expect_failure=False):
        from io import StringIO
        from vcr.errors import CannotOverwriteExistingCassetteException
    
        if command.startswith('az '):
            command = command[3:]
    
        stdout_buf = StringIO()
        logging_buf = StringIO()
        try:
            # issue: stderr cannot be redirect in this form, as a result some failure information
            # is lost when command fails.
>           self.exit_code = cli_ctx.invoke(shlex.split(command), out_file=stdout_buf) or 0

src/azure-cli-testsdk/azure/cli/testsdk/base.py:302: 
                                        
env/lib/python3.12/site-packages/knack/cli.py:245: in invoke
    exit_code = self.exception_handler(ex)
src/azure-cli-core/azure/cli/core/init.py:129: in exception_handler
    return handle_exception(ex)
                                        

ex = CLIError('No matched assignments were found to delete'), args = ()
kwargs = {}

    def handle_main_exception(ex, *args, **kwargs):  # pylint: disable=unused-argument
        if isinstance(ex, CannotOverwriteExistingCassetteException):
            # This exception usually caused by a no match HTTP request. This is a product error
            # that is caused by change of SDK invocation.
            raise ex
    
>       raise CliExecutionError(ex)
E       azure.cli.testsdk.exceptions.CliExecutionError: The CLI throws exception CLIError during execution and fails the command.

src/azure-cli-testsdk/azure/cli/testsdk/patches.py:35: CliExecutionError

During handling of the above exception, another exception occurred:

self = <azure.cli.command_modules.resource.tests.latest.test_resource.ManagedAppDefinitionScenarioTest testMethod=test_managed_app_def_deployment_mode>

    @AllowLargeResponse()
    @ResourceGroupPreparer()
    def test_managed_app_def_deployment_mode(self):
        self.kwargs.update({
            'upn': self.create_random_name('testuser', 15) + '@azuresdkteam.onmicrosoft.com',
            'sub': self.get_subscription_id()
        })
        user_principal = self.cmd('ad user create --display-name tester123 --password Test123456789 --user-principal-name {upn}').get_output_in_json()
        time.sleep(15)  # By-design, it takes some time for RBAC system propagated with graph object change
        principal_id = user_principal['id']
        with mock.patch('azure.cli.command_modules.role.custom.gen_guid', side_effect=self.create_guid):
            role_assignment = self.cmd(
                'role assignment create --assignee {upn} --role contributor --scope "/subscriptions/{sub}" ').get_output_in_json()
        from azure.mgmt.core.tools import parse_resource_id
        role_definition_id = parse_resource_id(role_assignment['roleDefinitionId'])['name']
        self.kwargs.update({
            'app_def': self.create_random_name('def', 10),
            'auth': principal_id + ':' + role_definition_id,
            'addn': self.create_random_name('test_appdef', 20),
            'uri': 'https://raw.githubusercontent.com/Azure/azure-managedapp-samples/master/Managed%20Application%20Sample%20Packages/201-managed-storage-account/managedstorage.zip',
        })
        self.cmd('managedapp definition create -n {app_def} -g {rg} --display-name {addn} --description test -a {auth} --package-file-uri {uri} --lock-level None --deployment-mode Incremental', checks=[
            self.check('deploymentPolicy.deploymentMode', 'Incremental')
        ])
        self.cmd('managedapp definition update -n {app_def} -g {rg} --display-name {addn} --description test -a {auth} --package-file-uri {uri} --lock-level None --deployment-mode Complete', checks=[
            self.check('deploymentPolicy.deploymentMode', 'Complete')
        ])
>       self.cmd('role assignment delete --assignee {upn} --role contributor ')

src/azure-cli/azure/cli/command_modules/resource/tests/latest/test_resource.py:4737: 
 
 
                                      
src/azure-cli-testsdk/azure/cli/testsdk/base.py:176: in cmd
    return execute(self.cli_ctx, command, expect_failure=expect_failure).assert_with_checks(checks)
src/azure-cli-testsdk/azure/cli/testsdk/base.py:251: in init
    self.in_process_execute(cli_ctx, command, expect_failure=expect_failure)
src/azure-cli-testsdk/azure/cli/testsdk/base.py:314: in in_process_execute
    raise ex.exception
env/lib/python3.12/site-packages/knack/cli.py:233: in invoke
    cmd_result = self.invocation.execute(args)
src/azure-cli-core/azure/cli/core/commands/init.py:666: in execute
    raise ex
src/azure-cli-core/azure/cli/core/commands/init.py:734: in run_jobs_serially
    results.append(self.run_job(expanded_arg, cmd_copy))
src/azure-cli-core/azure/cli/core/commands/init.py:703: in run_job
    result = cmd_copy(params)
src/azure-cli-core/azure/cli/core/commands/init.py:336: in call
    return self.handler(*args, **kwargs)
src/azure-cli-core/azure/cli/core/commands/command_operation.py:120: in handler
    return op(**command_args)
 
 
 
 
 
                                   

cmd = <azure.cli.core.commands.AzCliCommand object at 0x7f0ac9476270>, ids = []
assignee = '[email protected]'
assignee_object_id = '306974d8-9ac5-4fee-be41-42145bfe0875'
role = 'contributor', resource_group_name = None
scope = '/subscriptions/00000000-0000-0000-0000-000000000000'
include_inherited = False, yes = None

    def delete_role_assignments(cmd, ids=None,
                                assignee=None, assignee_object_id=None,
                                role=None, resource_group_name=None,
                                scope=None, include_inherited=False, yes=None):
        assignee_object_id = _resolve_assignee(cmd.cli_ctx, assignee, assignee_object_id)
    
        factory = _auth_client_factory(cmd.cli_ctx, scope)
        assignments_client = factory.role_assignments
        definitions_client = factory.role_definitions
        ids = ids or []
        if ids:
            # Warn that other arguments are overriden.
            # We can't reuse the logic of azure.cli.core.commands.arm.register_ids_argument, because in that function,
            # ids_metadata is built by checking id_part of each argument.
            # Commands like az&nbsp;vm&nbsp;delete require a resource ID with fixed parts, such as
            # /subscriptions/{}/resourceGroups/{}/providers/Microsoft.Compute/virtualMachines/{}
            # But for az&nbsp;role&nbsp;assignment&nbsp;delete--id can have variable parts:
            # - subscription level:   /subscriptions/{}
            # - resource group level: /subscriptions/{}/resourceGroups/{}
            # - resource level:       /subscriptions/{}/resourceGroups/{}/providers/Microsoft.Compute/virtualMachines/{}
            # so it can't be parsed into pre-defined parts and is passed to SDK as is.
            ids_override_args = ['assignee', 'role', 'resource_group_name', 'scope', 'include_inherited']
            for arg in ids_override_args:
                if locals()[arg]:
                    # This is different with register_ids_argument's --ids handling.
                    # register_ids_argument doesn't show warning if is_default of an argument value is true,
                    # but we do here. I feel being explicit is better than being implicit.
                    logger.warning("option '%s' will be ignored due to use of '--ids'.",
                                   cmd.arguments[arg].type.settings['options_list'][0])
            for i in ids:
                assignments_client.delete_by_id(i)
            return
        if not any([ids, assignee, role, resource_group_name, scope, assignee, yes]):
            from knack.prompting import prompt_y_n
            msg = 'This will delete all role assignments under the subscription. Are you sure?'
            if not prompt_y_n(msg, default="n"):
                return
    
        scope = _build_role_scope(resource_group_name, scope,
                                  assignments_client._config.subscription_id)
        assignments = _search_role_assignments(cmd.cli_ctx, assignments_client, definitions_client,
                                               scope, assignee, role, include_inherited,
                                               include_groups=False)
    
        if assignments:
            for a in assignments:
                assignments_client.delete_by_id(a.id)
        else:
>           raise CLIError('No matched assignments were found to delete')
E           knack.util.CLIError: No matched assignments were found to delete

src/azure-cli/azure/cli/command_modules/role/custom.py:552: CLIError
azure/cli/command_modules/resource/tests/latest/test_resource.py:4709
Failed test_managedappdef self = <azure.cli.testsdk.base.ExecutionResult object at 0x7f0ac95299d0>
cli_ctx = <azure.cli.core.mock.DummyCli object at 0x7f0ad4fe73e0>
command = 'role assignment delete --assignee [email protected] --role contributor '
expect_failure = False

    def in_process_execute(self, cli_ctx, command, expect_failure=False):
        from io import StringIO
        from vcr.errors import CannotOverwriteExistingCassetteException
    
        if command.startswith('az '):
            command = command[3:]
    
        stdout_buf = StringIO()
        logging_buf = StringIO()
        try:
            # issue: stderr cannot be redirect in this form, as a result some failure information
            # is lost when command fails.
>           self.exit_code = cli_ctx.invoke(shlex.split(command), out_file=stdout_buf) or 0

src/azure-cli-testsdk/azure/cli/testsdk/base.py:302: 
                                        
env/lib/python3.12/site-packages/knack/cli.py:245: in invoke
    exit_code = self.exception_handler(ex)
src/azure-cli-core/azure/cli/core/init.py:129: in exception_handler
    return handle_exception(ex)
                                        

ex = CLIError('No matched assignments were found to delete'), args = ()
kwargs = {}

    def handle_main_exception(ex, *args, **kwargs):  # pylint: disable=unused-argument
        if isinstance(ex, CannotOverwriteExistingCassetteException):
            # This exception usually caused by a no match HTTP request. This is a product error
            # that is caused by change of SDK invocation.
            raise ex
    
>       raise CliExecutionError(ex)
E       azure.cli.testsdk.exceptions.CliExecutionError: The CLI throws exception CLIError during execution and fails the command.

src/azure-cli-testsdk/azure/cli/testsdk/patches.py:35: CliExecutionError

During handling of the above exception, another exception occurred:

self = <azure.cli.command_modules.resource.tests.latest.test_resource.ManagedAppDefinitionScenarioTest testMethod=test_managedappdef>
resource_group = 'clitest.rg000001'

    @AllowLargeResponse()
    @ResourceGroupPreparer()
    def test_managedappdef(self, resource_group):
    
        self.kwargs.update({
            'upn': self.create_random_name('testuser', 15) + '@azuresdkteam.onmicrosoft.com',
            'sub': self.get_subscription_id()
        })
    
        user_principal = self.cmd(
            'ad user create --display-name tester123 --password Test123456789 --user-principal-name {upn}').get_output_in_json()
        time.sleep(15)  # By-design, it takes some time for RBAC system propagated with graph object change
        principal_id = user_principal['id']
    
        with mock.patch('azure.cli.command_modules.role.custom.gen_guid', side_effect=self.create_guid):
            role_assignment = self.cmd(
                'role assignment create --assignee {upn} --role contributor --scope "/subscriptions/{sub}" ').get_output_in_json()
        from azure.mgmt.core.tools import parse_resource_id
        role_definition_id = parse_resource_id(role_assignment['roleDefinitionId'])['name']
    
        self.kwargs.update({
            'loc': 'eastus',
            'adn': self.create_random_name('testappdefname', 20),
            'addn': self.create_random_name('test_appdef', 20),
            'ad_desc': 'test_appdef_123',
            'new_ad_desc': 'new_test_appdef_123',
            'uri': 'https://raw.githubusercontent.com/Azure/azure-managedapp-samples/master/Managed%20Application%20Sample%20Packages/201-managed-storage-account/managedstorage.zip',
            'auth': principal_id + ':' + role_definition_id,
            'lock': 'None'
        })
    
        # create a managedapp definition
        self.kwargs['ad_id'] = self.cmd('managedapp definition create -n {adn} --package-file-uri {uri} --display-name {addn} --description {ad_desc} -l {loc} -a {auth} --lock-level {lock} -g {rg}', checks=[
            self.check('name', '{adn}'),
            self.check('displayName', '{addn}'),
            self.check('description', '{ad_desc}'),
            self.check('authorizations[0].principalId', principal_id),
            self.check('authorizations[0].roleDefinitionId', role_definition_id),
            self.check('artifacts[0].name', 'ApplicationResourceTemplate'),
            self.check('artifacts[0].type', 'Template'),
            self.check('artifacts[1].name', 'CreateUiDefinition'),
            self.check('artifacts[1].type', 'Custom')
        ]).get_output_in_json()['id']
    
        # update a managedapp definition
        self.cmd('managedapp definition update -n {adn} --package-file-uri {uri} --display-name {addn} --description {new_ad_desc} -l {loc} -a {auth} --lock-level {lock} -g {rg}', checks=[
            self.check('name', '{adn}'),
            self.check('displayName', '{addn}'),
            self.check('description', '{new_ad_desc}'),
            self.check('authorizations[0].principalId', principal_id),
            self.check('authorizations[0].roleDefinitionId', role_definition_id),
            self.check('artifacts[0].name', 'ApplicationResourceTemplate'),
            self.check('artifacts[0].type', 'Template'),
            self.check('artifacts[1].name', 'CreateUiDefinition'),
            self.check('artifacts[1].type', 'Custom')
        ])
    
        self.cmd('managedapp definition list -g {rg}',
                 checks=self.check('[0].name', '{adn}'))
    
        self.cmd('managedapp definition show --ids {ad_id}', checks=[
            self.check('name', '{adn}'),
            self.check('displayName', '{addn}'),
            self.check('description', '{new_ad_desc}'),
            self.check('authorizations[0].principalId', principal_id),
            self.check('authorizations[0].roleDefinitionId', role_definition_id),
            self.check('artifacts[0].name', 'ApplicationResourceTemplate'),
            self.check('artifacts[0].type', 'Template'),
            self.check('artifacts[1].name', 'CreateUiDefinition'),
            self.check('artifacts[1].type', 'Custom')
        ])
    
        self.cmd('managedapp definition delete -g {rg} -n {adn}')
        self.cmd('managedapp definition list -g {rg}', checks=self.is_empty())
    
>       self.cmd('role assignment delete --assignee {upn} --role contributor ')

src/azure-cli/azure/cli/command_modules/resource/tests/latest/test_resource.py:4641: 
 
 
                                      
src/azure-cli-testsdk/azure/cli/testsdk/base.py:176: in cmd
    return execute(self.cli_ctx, command, expect_failure=expect_failure).assert_with_checks(checks)
src/azure-cli-testsdk/azure/cli/testsdk/base.py:251: in init
    self.in_process_execute(cli_ctx, command, expect_failure=expect_failure)
src/azure-cli-testsdk/azure/cli/testsdk/base.py:314: in in_process_execute
    raise ex.exception
env/lib/python3.12/site-packages/knack/cli.py:233: in invoke
    cmd_result = self.invocation.execute(args)
src/azure-cli-core/azure/cli/core/commands/init.py:666: in execute
    raise ex
src/azure-cli-core/azure/cli/core/commands/init.py:734: in run_jobs_serially
    results.append(self.run_job(expanded_arg, cmd_copy))
src/azure-cli-core/azure/cli/core/commands/init.py:703: in run_job
    result = cmd_copy(params)
src/azure-cli-core/azure/cli/core/commands/init.py:336: in call
    return self.handler(*args, **kwargs)
src/azure-cli-core/azure/cli/core/commands/command_operation.py:120: in handler
    return op(**command_args)
 
 
 
 
 
                                   

cmd = <azure.cli.core.commands.AzCliCommand object at 0x7f0ac94255b0>, ids = []
assignee = '[email protected]'
assignee_object_id = 'e973e93e-4632-4a22-aff4-508790cbc520'
role = 'contributor', resource_group_name = None
scope = '/subscriptions/00000000-0000-0000-0000-000000000000'
include_inherited = False, yes = None

    def delete_role_assignments(cmd, ids=None,
                                assignee=None, assignee_object_id=None,
                                role=None, resource_group_name=None,
                                scope=None, include_inherited=False, yes=None):
        assignee_object_id = _resolve_assignee(cmd.cli_ctx, assignee, assignee_object_id)
    
        factory = _auth_client_factory(cmd.cli_ctx, scope)
        assignments_client = factory.role_assignments
        definitions_client = factory.role_definitions
        ids = ids or []
        if ids:
            # Warn that other arguments are overriden.
            # We can't reuse the logic of azure.cli.core.commands.arm.register_ids_argument, because in that function,
            # ids_metadata is built by checking id_part of each argument.
            # Commands like az&nbsp;vm&nbsp;delete require a resource ID with fixed parts, such as
            # /subscriptions/{}/resourceGroups/{}/providers/Microsoft.Compute/virtualMachines/{}
            # But for az&nbsp;role&nbsp;assignment&nbsp;delete--id can have variable parts:
            # - subscription level:   /subscriptions/{}
            # - resource group level: /subscriptions/{}/resourceGroups/{}
            # - resource level:       /subscriptions/{}/resourceGroups/{}/providers/Microsoft.Compute/virtualMachines/{}
            # so it can't be parsed into pre-defined parts and is passed to SDK as is.
            ids_override_args = ['assignee', 'role', 'resource_group_name', 'scope', 'include_inherited']
            for arg in ids_override_args:
                if locals()[arg]:
                    # This is different with register_ids_argument's --ids handling.
                    # register_ids_argument doesn't show warning if is_default of an argument value is true,
                    # but we do here. I feel being explicit is better than being implicit.
                    logger.warning("option '%s' will be ignored due to use of '--ids'.",
                                   cmd.arguments[arg].type.settings['options_list'][0])
            for i in ids:
                assignments_client.delete_by_id(i)
            return
        if not any([ids, assignee, role, resource_group_name, scope, assignee, yes]):
            from knack.prompting import prompt_y_n
            msg = 'This will delete all role assignments under the subscription. Are you sure?'
            if not prompt_y_n(msg, default="n"):
                return
    
        scope = _build_role_scope(resource_group_name, scope,
                                  assignments_client._config.subscription_id)
        assignments = _search_role_assignments(cmd.cli_ctx, assignments_client, definitions_client,
                                               scope, assignee, role, include_inherited,
                                               include_groups=False)
    
        if assignments:
            for a in assignments:
                assignments_client.delete_by_id(a.id)
        else:
>           raise CLIError('No matched assignments were found to delete')
E           knack.util.CLIError: No matched assignments were found to delete

src/azure-cli/azure/cli/command_modules/role/custom.py:552: CLIError
azure/cli/command_modules/resource/tests/latest/test_resource.py:4565
Failed test_managedappdef_inline The error message is too long, please check the pipeline log for details. azure/cli/command_modules/resource/tests/latest/test_resource.py:4643
Failed test_managedapp The error message is too long, please check the pipeline log for details. azure/cli/command_modules/resource/tests/latest/test_resource.py:4741
❌3.9
Type Test Case Error Message Line
Failed test_managed_app_def_deployment_mode self = <azure.cli.testsdk.base.ExecutionResult object at 0x7f36942d50d0>
cli_ctx = <azure.cli.core.mock.DummyCli object at 0x7f36a014e4c0>
command = 'role assignment delete --assignee [email protected] --role contributor '
expect_failure = False

    def in_process_execute(self, cli_ctx, command, expect_failure=False):
        from io import StringIO
        from vcr.errors import CannotOverwriteExistingCassetteException
    
        if command.startswith('az '):
            command = command[3:]
    
        stdout_buf = StringIO()
        logging_buf = StringIO()
        try:
            # issue: stderr cannot be redirect in this form, as a result some failure information
            # is lost when command fails.
>           self.exit_code = cli_ctx.invoke(shlex.split(command), out_file=stdout_buf) or 0

src/azure-cli-testsdk/azure/cli/testsdk/base.py:302: 
                                        
env/lib/python3.9/site-packages/knack/cli.py:245: in invoke
    exit_code = self.exception_handler(ex)
src/azure-cli-core/azure/cli/core/init.py:129: in exception_handler
    return handle_exception(ex)
                                        

ex = CLIError('No matched assignments were found to delete'), args = ()
kwargs = {}

    def handle_main_exception(ex, *args, **kwargs):  # pylint: disable=unused-argument
        if isinstance(ex, CannotOverwriteExistingCassetteException):
            # This exception usually caused by a no match HTTP request. This is a product error
            # that is caused by change of SDK invocation.
            raise ex
    
>       raise CliExecutionError(ex)
E       azure.cli.testsdk.exceptions.CliExecutionError: The CLI throws exception CLIError during execution and fails the command.

src/azure-cli-testsdk/azure/cli/testsdk/patches.py:35: CliExecutionError

During handling of the above exception, another exception occurred:

self = <azure.cli.command_modules.resource.tests.latest.test_resource.ManagedAppDefinitionScenarioTest testMethod=test_managed_app_def_deployment_mode>

    @AllowLargeResponse()
    @ResourceGroupPreparer()
    def test_managed_app_def_deployment_mode(self):
        self.kwargs.update({
            'upn': self.create_random_name('testuser', 15) + '@azuresdkteam.onmicrosoft.com',
            'sub': self.get_subscription_id()
        })
        user_principal = self.cmd('ad user create --display-name tester123 --password Test123456789 --user-principal-name {upn}').get_output_in_json()
        time.sleep(15)  # By-design, it takes some time for RBAC system propagated with graph object change
        principal_id = user_principal['id']
        with mock.patch('azure.cli.command_modules.role.custom.gen_guid', side_effect=self.create_guid):
            role_assignment = self.cmd(
                'role assignment create --assignee {upn} --role contributor --scope "/subscriptions/{sub}" ').get_output_in_json()
        from azure.mgmt.core.tools import parse_resource_id
        role_definition_id = parse_resource_id(role_assignment['roleDefinitionId'])['name']
        self.kwargs.update({
            'app_def': self.create_random_name('def', 10),
            'auth': principal_id + ':' + role_definition_id,
            'addn': self.create_random_name('test_appdef', 20),
            'uri': 'https://raw.githubusercontent.com/Azure/azure-managedapp-samples/master/Managed%20Application%20Sample%20Packages/201-managed-storage-account/managedstorage.zip',
        })
        self.cmd('managedapp definition create -n {app_def} -g {rg} --display-name {addn} --description test -a {auth} --package-file-uri {uri} --lock-level None --deployment-mode Incremental', checks=[
            self.check('deploymentPolicy.deploymentMode', 'Incremental')
        ])
        self.cmd('managedapp definition update -n {app_def} -g {rg} --display-name {addn} --description test -a {auth} --package-file-uri {uri} --lock-level None --deployment-mode Complete', checks=[
            self.check('deploymentPolicy.deploymentMode', 'Complete')
        ])
>       self.cmd('role assignment delete --assignee {upn} --role contributor ')

src/azure-cli/azure/cli/command_modules/resource/tests/latest/test_resource.py:4737: 
 
 
                                      
src/azure-cli-testsdk/azure/cli/testsdk/base.py:176: in cmd
    return execute(self.cli_ctx, command, expect_failure=expect_failure).assert_with_checks(checks)
src/azure-cli-testsdk/azure/cli/testsdk/base.py:251: in init
    self.in_process_execute(cli_ctx, command, expect_failure=expect_failure)
src/azure-cli-testsdk/azure/cli/testsdk/base.py:314: in in_process_execute
    raise ex.exception
env/lib/python3.9/site-packages/knack/cli.py:233: in invoke
    cmd_result = self.invocation.execute(args)
src/azure-cli-core/azure/cli/core/commands/init.py:666: in execute
    raise ex
src/azure-cli-core/azure/cli/core/commands/init.py:734: in run_jobs_serially
    results.append(self.run_job(expanded_arg, cmd_copy))
src/azure-cli-core/azure/cli/core/commands/init.py:703: in run_job
    result = cmd_copy(params)
src/azure-cli-core/azure/cli/core/commands/init.py:336: in call
    return self.handler(*args, **kwargs)
src/azure-cli-core/azure/cli/core/commands/command_operation.py:120: in handler
    return op(**command_args)
 
 
 
 
 
                                   

cmd = <azure.cli.core.commands.AzCliCommand object at 0x7f3694289250>, ids = []
assignee = '[email protected]'
assignee_object_id = '306974d8-9ac5-4fee-be41-42145bfe0875'
role = 'contributor', resource_group_name = None
scope = '/subscriptions/00000000-0000-0000-0000-000000000000'
include_inherited = False, yes = None

    def delete_role_assignments(cmd, ids=None,
                                assignee=None, assignee_object_id=None,
                                role=None, resource_group_name=None,
                                scope=None, include_inherited=False, yes=None):
        assignee_object_id = _resolve_assignee(cmd.cli_ctx, assignee, assignee_object_id)
    
        factory = _auth_client_factory(cmd.cli_ctx, scope)
        assignments_client = factory.role_assignments
        definitions_client = factory.role_definitions
        ids = ids or []
        if ids:
            # Warn that other arguments are overriden.
            # We can't reuse the logic of azure.cli.core.commands.arm.register_ids_argument, because in that function,
            # ids_metadata is built by checking id_part of each argument.
            # Commands like az&nbsp;vm&nbsp;delete require a resource ID with fixed parts, such as
            # /subscriptions/{}/resourceGroups/{}/providers/Microsoft.Compute/virtualMachines/{}
            # But for az&nbsp;role&nbsp;assignment&nbsp;delete--id can have variable parts:
            # - subscription level:   /subscriptions/{}
            # - resource group level: /subscriptions/{}/resourceGroups/{}
            # - resource level:       /subscriptions/{}/resourceGroups/{}/providers/Microsoft.Compute/virtualMachines/{}
            # so it can't be parsed into pre-defined parts and is passed to SDK as is.
            ids_override_args = ['assignee', 'role', 'resource_group_name', 'scope', 'include_inherited']
            for arg in ids_override_args:
                if locals()[arg]:
                    # This is different with register_ids_argument's --ids handling.
                    # register_ids_argument doesn't show warning if is_default of an argument value is true,
                    # but we do here. I feel being explicit is better than being implicit.
                    logger.warning("option '%s' will be ignored due to use of '--ids'.",
                                   cmd.arguments[arg].type.settings['options_list'][0])
            for i in ids:
                assignments_client.delete_by_id(i)
            return
        if not any([ids, assignee, role, resource_group_name, scope, assignee, yes]):
            from knack.prompting import prompt_y_n
            msg = 'This will delete all role assignments under the subscription. Are you sure?'
            if not prompt_y_n(msg, default="n"):
                return
    
        scope = _build_role_scope(resource_group_name, scope,
                                  assignments_client._config.subscription_id)
        assignments = _search_role_assignments(cmd.cli_ctx, assignments_client, definitions_client,
                                               scope, assignee, role, include_inherited,
                                               include_groups=False)
    
        if assignments:
            for a in assignments:
                assignments_client.delete_by_id(a.id)
        else:
>           raise CLIError('No matched assignments were found to delete')
E           knack.util.CLIError: No matched assignments were found to delete

src/azure-cli/azure/cli/command_modules/role/custom.py:552: CLIError
azure/cli/command_modules/resource/tests/latest/test_resource.py:4709
Failed test_managedappdef self = <azure.cli.testsdk.base.ExecutionResult object at 0x7f36941ee9d0>
cli_ctx = <azure.cli.core.mock.DummyCli object at 0x7f36a01304c0>
command = 'role assignment delete --assignee [email protected] --role contributor '
expect_failure = False

    def in_process_execute(self, cli_ctx, command, expect_failure=False):
        from io import StringIO
        from vcr.errors import CannotOverwriteExistingCassetteException
    
        if command.startswith('az '):
            command = command[3:]
    
        stdout_buf = StringIO()
        logging_buf = StringIO()
        try:
            # issue: stderr cannot be redirect in this form, as a result some failure information
            # is lost when command fails.
>           self.exit_code = cli_ctx.invoke(shlex.split(command), out_file=stdout_buf) or 0

src/azure-cli-testsdk/azure/cli/testsdk/base.py:302: 
                                        
env/lib/python3.9/site-packages/knack/cli.py:245: in invoke
    exit_code = self.exception_handler(ex)
src/azure-cli-core/azure/cli/core/init.py:129: in exception_handler
    return handle_exception(ex)
                                        

ex = CLIError('No matched assignments were found to delete'), args = ()
kwargs = {}

    def handle_main_exception(ex, *args, **kwargs):  # pylint: disable=unused-argument
        if isinstance(ex, CannotOverwriteExistingCassetteException):
            # This exception usually caused by a no match HTTP request. This is a product error
            # that is caused by change of SDK invocation.
            raise ex
    
>       raise CliExecutionError(ex)
E       azure.cli.testsdk.exceptions.CliExecutionError: The CLI throws exception CLIError during execution and fails the command.

src/azure-cli-testsdk/azure/cli/testsdk/patches.py:35: CliExecutionError

During handling of the above exception, another exception occurred:

self = <azure.cli.command_modules.resource.tests.latest.test_resource.ManagedAppDefinitionScenarioTest testMethod=test_managedappdef>
resource_group = 'clitest.rg000001'

    @AllowLargeResponse()
    @ResourceGroupPreparer()
    def test_managedappdef(self, resource_group):
    
        self.kwargs.update({
            'upn': self.create_random_name('testuser', 15) + '@azuresdkteam.onmicrosoft.com',
            'sub': self.get_subscription_id()
        })
    
        user_principal = self.cmd(
            'ad user create --display-name tester123 --password Test123456789 --user-principal-name {upn}').get_output_in_json()
        time.sleep(15)  # By-design, it takes some time for RBAC system propagated with graph object change
        principal_id = user_principal['id']
    
        with mock.patch('azure.cli.command_modules.role.custom.gen_guid', side_effect=self.create_guid):
            role_assignment = self.cmd(
                'role assignment create --assignee {upn} --role contributor --scope "/subscriptions/{sub}" ').get_output_in_json()
        from azure.mgmt.core.tools import parse_resource_id
        role_definition_id = parse_resource_id(role_assignment['roleDefinitionId'])['name']
    
        self.kwargs.update({
            'loc': 'eastus',
            'adn': self.create_random_name('testappdefname', 20),
            'addn': self.create_random_name('test_appdef', 20),
            'ad_desc': 'test_appdef_123',
            'new_ad_desc': 'new_test_appdef_123',
            'uri': 'https://raw.githubusercontent.com/Azure/azure-managedapp-samples/master/Managed%20Application%20Sample%20Packages/201-managed-storage-account/managedstorage.zip',
            'auth': principal_id + ':' + role_definition_id,
            'lock': 'None'
        })
    
        # create a managedapp definition
        self.kwargs['ad_id'] = self.cmd('managedapp definition create -n {adn} --package-file-uri {uri} --display-name {addn} --description {ad_desc} -l {loc} -a {auth} --lock-level {lock} -g {rg}', checks=[
            self.check('name', '{adn}'),
            self.check('displayName', '{addn}'),
            self.check('description', '{ad_desc}'),
            self.check('authorizations[0].principalId', principal_id),
            self.check('authorizations[0].roleDefinitionId', role_definition_id),
            self.check('artifacts[0].name', 'ApplicationResourceTemplate'),
            self.check('artifacts[0].type', 'Template'),
            self.check('artifacts[1].name', 'CreateUiDefinition'),
            self.check('artifacts[1].type', 'Custom')
        ]).get_output_in_json()['id']
    
        # update a managedapp definition
        self.cmd('managedapp definition update -n {adn} --package-file-uri {uri} --display-name {addn} --description {new_ad_desc} -l {loc} -a {auth} --lock-level {lock} -g {rg}', checks=[
            self.check('name', '{adn}'),
            self.check('displayName', '{addn}'),
            self.check('description', '{new_ad_desc}'),
            self.check('authorizations[0].principalId', principal_id),
            self.check('authorizations[0].roleDefinitionId', role_definition_id),
            self.check('artifacts[0].name', 'ApplicationResourceTemplate'),
            self.check('artifacts[0].type', 'Template'),
            self.check('artifacts[1].name', 'CreateUiDefinition'),
            self.check('artifacts[1].type', 'Custom')
        ])
    
        self.cmd('managedapp definition list -g {rg}',
                 checks=self.check('[0].name', '{adn}'))
    
        self.cmd('managedapp definition show --ids {ad_id}', checks=[
            self.check('name', '{adn}'),
            self.check('displayName', '{addn}'),
            self.check('description', '{new_ad_desc}'),
            self.check('authorizations[0].principalId', principal_id),
            self.check('authorizations[0].roleDefinitionId', role_definition_id),
            self.check('artifacts[0].name', 'ApplicationResourceTemplate'),
            self.check('artifacts[0].type', 'Template'),
            self.check('artifacts[1].name', 'CreateUiDefinition'),
            self.check('artifacts[1].type', 'Custom')
        ])
    
        self.cmd('managedapp definition delete -g {rg} -n {adn}')
        self.cmd('managedapp definition list -g {rg}', checks=self.is_empty())
    
>       self.cmd('role assignment delete --assignee {upn} --role contributor ')

src/azure-cli/azure/cli/command_modules/resource/tests/latest/test_resource.py:4641: 
 
 
                                      
src/azure-cli-testsdk/azure/cli/testsdk/base.py:176: in cmd
    return execute(self.cli_ctx, command, expect_failure=expect_failure).assert_with_checks(checks)
src/azure-cli-testsdk/azure/cli/testsdk/base.py:251: in init
    self.in_process_execute(cli_ctx, command, expect_failure=expect_failure)
src/azure-cli-testsdk/azure/cli/testsdk/base.py:314: in in_process_execute
    raise ex.exception
env/lib/python3.9/site-packages/knack/cli.py:233: in invoke
    cmd_result = self.invocation.execute(args)
src/azure-cli-core/azure/cli/core/commands/init.py:666: in execute
    raise ex
src/azure-cli-core/azure/cli/core/commands/init.py:734: in run_jobs_serially
    results.append(self.run_job(expanded_arg, cmd_copy))
src/azure-cli-core/azure/cli/core/commands/init.py:703: in run_job
    result = cmd_copy(params)
src/azure-cli-core/azure/cli/core/commands/init.py:336: in call
    return self.handler(*args, **kwargs)
src/azure-cli-core/azure/cli/core/commands/command_operation.py:120: in handler
    return op(**command_args)
 
 
 
 
 
                                   

cmd = <azure.cli.core.commands.AzCliCommand object at 0x7f36940249a0>, ids = []
assignee = '[email protected]'
assignee_object_id = 'e973e93e-4632-4a22-aff4-508790cbc520'
role = 'contributor', resource_group_name = None
scope = '/subscriptions/00000000-0000-0000-0000-000000000000'
include_inherited = False, yes = None

    def delete_role_assignments(cmd, ids=None,
                                assignee=None, assignee_object_id=None,
                                role=None, resource_group_name=None,
                                scope=None, include_inherited=False, yes=None):
        assignee_object_id = _resolve_assignee(cmd.cli_ctx, assignee, assignee_object_id)
    
        factory = _auth_client_factory(cmd.cli_ctx, scope)
        assignments_client = factory.role_assignments
        definitions_client = factory.role_definitions
        ids = ids or []
        if ids:
            # Warn that other arguments are overriden.
            # We can't reuse the logic of azure.cli.core.commands.arm.register_ids_argument, because in that function,
            # ids_metadata is built by checking id_part of each argument.
            # Commands like az&nbsp;vm&nbsp;delete require a resource ID with fixed parts, such as
            # /subscriptions/{}/resourceGroups/{}/providers/Microsoft.Compute/virtualMachines/{}
            # But for az&nbsp;role&nbsp;assignment&nbsp;delete--id can have variable parts:
            # - subscription level:   /subscriptions/{}
            # - resource group level: /subscriptions/{}/resourceGroups/{}
            # - resource level:       /subscriptions/{}/resourceGroups/{}/providers/Microsoft.Compute/virtualMachines/{}
            # so it can't be parsed into pre-defined parts and is passed to SDK as is.
            ids_override_args = ['assignee', 'role', 'resource_group_name', 'scope', 'include_inherited']
            for arg in ids_override_args:
                if locals()[arg]:
                    # This is different with register_ids_argument's --ids handling.
                    # register_ids_argument doesn't show warning if is_default of an argument value is true,
                    # but we do here. I feel being explicit is better than being implicit.
                    logger.warning("option '%s' will be ignored due to use of '--ids'.",
                                   cmd.arguments[arg].type.settings['options_list'][0])
            for i in ids:
                assignments_client.delete_by_id(i)
            return
        if not any([ids, assignee, role, resource_group_name, scope, assignee, yes]):
            from knack.prompting import prompt_y_n
            msg = 'This will delete all role assignments under the subscription. Are you sure?'
            if not prompt_y_n(msg, default="n"):
                return
    
        scope = _build_role_scope(resource_group_name, scope,
                                  assignments_client._config.subscription_id)
        assignments = _search_role_assignments(cmd.cli_ctx, assignments_client, definitions_client,
                                               scope, assignee, role, include_inherited,
                                               include_groups=False)
    
        if assignments:
            for a in assignments:
                assignments_client.delete_by_id(a.id)
        else:
>           raise CLIError('No matched assignments were found to delete')
E           knack.util.CLIError: No matched assignments were found to delete

src/azure-cli/azure/cli/command_modules/role/custom.py:552: CLIError
azure/cli/command_modules/resource/tests/latest/test_resource.py:4565
Failed test_managedappdef_inline The error message is too long, please check the pipeline log for details. azure/cli/command_modules/resource/tests/latest/test_resource.py:4643
Failed test_managedapp The error message is too long, please check the pipeline log for details. azure/cli/command_modules/resource/tests/latest/test_resource.py:4741
❌role
❌latest
❌3.12
Type Test Case Error Message Line
Failed test_role_assignment_scenario self = <azure.cli.testsdk.base.ExecutionResult object at 0x7fc019411ca0>
cli_ctx = <azure.cli.core.mock.DummyCli object at 0x7fc01bca1a90>
command = 'role assignment delete --assignee [email protected] --role reader -g cli_role_assign000001'
expect_failure = False

    def in_process_execute(self, cli_ctx, command, expect_failure=False):
        from io import StringIO
        from vcr.errors import CannotOverwriteExistingCassetteException
    
        if command.startswith('az '):
            command = command[3:]
    
        stdout_buf = StringIO()
        logging_buf = StringIO()
        try:
            # issue: stderr cannot be redirect in this form, as a result some failure information
            # is lost when command fails.
>           self.exit_code = cli_ctx.invoke(shlex.split(command), out_file=stdout_buf) or 0

src/azure-cli-testsdk/azure/cli/testsdk/base.py:302: 
                                        
env/lib/python3.12/site-packages/knack/cli.py:245: in invoke
    exit_code = self.exception_handler(ex)
src/azure-cli-core/azure/cli/core/init.py:129: in exception_handler
    return handle_exception(ex)
                                        

ex = CLIError('No matched assignments were found to delete'), args = ()
kwargs = {}

    def handle_main_exception(ex, *args, **kwargs):  # pylint: disable=unused-argument
        if isinstance(ex, CannotOverwriteExistingCassetteException):
            # This exception usually caused by a no match HTTP request. This is a product error
            # that is caused by change of SDK invocation.
            raise ex
    
>       raise CliExecutionError(ex)
E       azure.cli.testsdk.exceptions.CliExecutionError: The CLI throws exception CLIError during execution and fails the command.

src/azure-cli-testsdk/azure/cli/testsdk/patches.py:35: CliExecutionError

During handling of the above exception, another exception occurred:

self = <azure.cli.command_modules.role.tests.latest.test_role.RoleAssignmentScenarioTest testMethod=test_role_assignment_scenario>
resource_group = 'cli_role_assign000001'

    @ResourceGroupPreparer(name_prefix='cli_role_assign')
    @AllowLargeResponse()
    def test_role_assignment_scenario(self, resource_group):
        if self.run_under_service_principal():
            return  # this test delete users which are beyond a SP's capacity, so quit...
    
        with mock.patch('azure.cli.command_modules.role.custom.gen_guid', side_effect=self.create_guid):
            user = self.create_random_name('testuser', 15)
            self.kwargs.update({
                'upn': user + TEST_TENANT_DOMAIN,
                'nsg': 'nsg1',
                'role': 'reader',  # Use low-privileged role to make the test secure
                # https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles
                'reader_guid': 'acdd72a7-3385-48ef-bd42-f606fba81ae7'
            })
            self.prepare_scope_kwargs()
    
            # test create role assignment without --scope
            with self.assertRaisesRegex(SystemExit, '2'):
                self.cmd('role assignment create --assignee {upn} --role {role}')
    
            result = self.cmd('ad user create --display-name tester123 --password Test123456789'
                              ' --user-principal-name {upn}').get_output_in_json()
            self.kwargs.update({
                'user_id': result['id']})
    
            group = self.create_random_name('testgroup', 15)
            self.kwargs.update({
                'group': group})
    
            group_result = self.cmd(
                'ad group create --display-name group123 --mail-nickname {group}').get_output_in_json()
            self.kwargs.update({
                'group_id': group_result['id']})
            self.cmd(
                'ad group member add --group {group_id} --member-id {user_id}')
    
            time.sleep(15)  # By-design, it takes some time for RBAC system propagated with graph object change
    
            try:
                self.cmd('network nsg create -n {nsg} -g {rg}')
                result = self.cmd('network nsg show -n {nsg} -g {rg}').get_output_in_json()
                self.kwargs['nsg_id'] = result['id']
    
                # test role assignments on a resource group for the user
                self.cmd('role assignment create --assignee {upn} --role {role} --scope {rg_id}')
                # verify role assignment create is idempotent
                self.cmd('role assignment create --assignee {upn} --role {role} --scope {rg_id}',
                         self.check("principalName", self.kwargs["upn"]))
    
                self.cmd('role assignment list -g {rg}', checks=self.check("length([])", 1))
                self.cmd('role assignment list --assignee {upn} --role {role} -g {rg}', checks=[
                    self.check("length([])", 1),
                    self.check("[0].principalName", self.kwargs["upn"])
                ])
    
                # Create role assignment for the group
                self.cmd('role assignment create --assignee {group_id} --role {role} --scope {rg_id}')
    
                # test include-groups
                self.cmd('role assignment list --assignee {upn} --all --include-groups', checks=[
                    self.check("length([])", 2)
                ])
    
                self.cmd('role assignment delete --assignee {group_id} --role {role} -g {rg}')
>               self.cmd('role assignment delete --assignee {upn} --role {role} -g {rg}')

src/azure-cli/azure/cli/command_modules/role/tests/latest/test_role.py:329: 
 
 
 
                                     
src/azure-cli-testsdk/azure/cli/testsdk/base.py:176: in cmd
    return execute(self.cli_ctx, command, expect_failure=expect_failure).assert_with_checks(checks)
src/azure-cli-testsdk/azure/cli/testsdk/base.py:251: in init
    self.in_process_execute(cli_ctx, command, expect_failure=expect_failure)
src/azure-cli-testsdk/azure/cli/testsdk/base.py:314: in in_process_execute
    raise ex.exception
env/lib/python3.12/site-packages/knack/cli.py:233: in invoke
    cmd_result = self.invocation.execute(args)
src/azure-cli-core/azure/cli/core/commands/init.py:666: in execute
    raise ex
src/azure-cli-core/azure/cli/core/commands/init.py:734: in run_jobs_serially
    results.append(self.run_job(expanded_arg, cmd_copy))
src/azure-cli-core/azure/cli/core/commands/init.py:703: in run_job
    result = cmd_copy(params)
src/azure-cli-core/azure/cli/core/commands/init.py:336: in call
    return self.handler(*args, **kwargs)
src/azure-cli-core/azure/cli/core/commands/command_operation.py:120: in handler
    return op(**command_args)
 
 
 
 
                                   _ 

cmd = <azure.cli.core.commands.AzCliCommand object at 0x7fc0195471d0>, ids = []
assignee = '[email protected]'
assignee_object_id = 'b582d754-5e23-4c28-82e9-0a6cd0390c03', role = 'reader'
resource_group_name = 'cli_role_assign000001'
scope = '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/cli_role_assign000001'
include_inherited = False, yes = None

    def delete_role_assignments(cmd, ids=None,
                                assignee=None, assignee_object_id=None,
                                role=None, resource_group_name=None,
                                scope=None, include_inherited=False, yes=None):
        assignee_object_id = _resolve_assignee(cmd.cli_ctx, assignee, assignee_object_id)
    
        factory = _auth_client_factory(cmd.cli_ctx, scope)
        assignments_client = factory.role_assignments
        definitions_client = factory.role_definitions
        ids = ids or []
        if ids:
            # Warn that other arguments are overriden.
            # We can't reuse the logic of azure.cli.core.commands.arm.register_ids_argument, because in that function,
            # ids_metadata is built by checking id_part of each argument.
            # Commands like az&nbsp;vm&nbsp;delete require a resource ID with fixed parts, such as
            # /subscriptions/{}/resourceGroups/{}/providers/Microsoft.Compute/virtualMachines/{}
            # But for az&nbsp;role&nbsp;assignment&nbsp;delete--id can have variable parts:
            # - subscription level:   /subscriptions/{}
            # - resource group level: /subscriptions/{}/resourceGroups/{}
            # - resource level:       /subscriptions/{}/resourceGroups/{}/providers/Microsoft.Compute/virtualMachines/{}
            # so it can't be parsed into pre-defined parts and is passed to SDK as is.
            ids_override_args = ['assignee', 'role', 'resource_group_name', 'scope', 'include_inherited']
            for arg in ids_override_args:
                if locals()[arg]:
                    # This is different with register_ids_argument's --ids handling.
                    # register_ids_argument doesn't show warning if is_default of an argument value is true,
                    # but we do here. I feel being explicit is better than being implicit.
                    logger.warning("option '%s' will be ignored due to use of '--ids'.",
                                   cmd.arguments[arg].type.settings['options_list'][0])
            for i in ids:
                assignments_client.delete_by_id(i)
            return
        if not any([ids, assignee, role, resource_group_name, scope, assignee, yes]):
            from knack.prompting import prompt_y_n
            msg = 'This will delete all role assignments under the subscription. Are you sure?'
            if not prompt_y_n(msg, default="n"):
                return
    
        scope = _build_role_scope(resource_group_name, scope,
                                  assignments_client._config.subscription_id)
        assignments = _search_role_assignments(cmd.cli_ctx, assignments_client, definitions_client,
                                               scope, assignee, role, include_inherited,
                                               include_groups=False)
    
        if assignments:
            for a in assignments:
                assignments_client.delete_by_id(a.id)
        else:
>           raise CLIError('No matched assignments were found to delete')
E           knack.util.CLIError: No matched assignments were found to delete

src/azure-cli/azure/cli/command_modules/role/custom.py:552: CLIError
azure/cli/command_modules/role/tests/latest/test_role.py:263
Failed test_role_assignment_handle_conflicted_assignments self = <azure.cli.testsdk.base.ExecutionResult object at 0x7fc01b4fc260>
cli_ctx = <azure.cli.core.mock.DummyCli object at 0x7fc01bd3f6e0>
command = 'role assignment delete --assignee [email protected] --role reader --scope /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/cli_role_assign000001'
expect_failure = False

    def in_process_execute(self, cli_ctx, command, expect_failure=False):
        from io import StringIO
        from vcr.errors import CannotOverwriteExistingCassetteException
    
        if command.startswith('az '):
            command = command[3:]
    
        stdout_buf = StringIO()
        logging_buf = StringIO()
        try:
            # issue: stderr cannot be redirect in this form, as a result some failure information
            # is lost when command fails.
>           self.exit_code = cli_ctx.invoke(shlex.split(command), out_file=stdout_buf) or 0

src/azure-cli-testsdk/azure/cli/testsdk/base.py:302: 
                                        
env/lib/python3.12/site-packages/knack/cli.py:245: in invoke
    exit_code = self.exception_handler(ex)
src/azure-cli-core/azure/cli/core/init.py:129: in exception_handler
    return handle_exception(ex)
                                        

ex = CLIError('No matched assignments were found to delete'), args = ()
kwargs = {}

    def handle_main_exception(ex, *args, **kwargs):  # pylint: disable=unused-argument
        if isinstance(ex, CannotOverwriteExistingCassetteException):
            # This exception usually caused by a no match HTTP request. This is a product error
            # that is caused by change of SDK invocation.
            raise ex
    
>       raise CliExecutionError(ex)
E       azure.cli.testsdk.exceptions.CliExecutionError: The CLI throws exception CLIError during execution and fails the command.

src/azure-cli-testsdk/azure/cli/testsdk/patches.py:35: CliExecutionError

During handling of the above exception, another exception occurred:

self = <azure.cli.command_modules.role.tests.latest.test_role.RoleAssignmentWithConfigScenarioTest testMethod=test_role_assignment_handle_conflicted_assignments>
resource_group = 'cli_role_assign000001'

    @ResourceGroupPreparer(name_prefix='cli_role_assign')
    @AllowLargeResponse()
    def test_role_assignment_handle_conflicted_assignments(self, resource_group):
        if self.run_under_service_principal():
            return  # this test delete users which are beyond a SP's capacity, so quit...
    
        with mock.patch('azure.cli.command_modules.role.custom.gen_guid', side_effect=self.create_guid):
            user = self.create_random_name('testuser', 15)
            self.kwargs.update({
                'upn': user + TEST_TENANT_DOMAIN,
                'nsg': 'nsg1'
            })
    
            self.cmd('ad user create --display-name tester123 --password Test123456789 --user-principal-name {upn}')
            time.sleep(15)  # By-design, it takes some time for RBAC system propagated with graph object change
    
            base_dir = os.path.abspath(os.curdir)
    
            try:
                temp_dir = os.path.realpath(self.create_temp_dir())
                os.chdir(temp_dir)
                self.cmd('configure --default group={rg} --scope local')
                local_defaults_config = self.cmd('configure --list-defaults --scope local').get_output_in_json()
    
                self.assertGreaterEqual(len(local_defaults_config), 1)
                actual = set([(x['name'], x['source'], x['value']) for x in local_defaults_config if x['name'] == 'group'])
                # If global config_dir is ~/.azure/dummy_cli_config_dir/0azXbKR9OdJuZPFS/,
                # local config file is  ./0azXbKR9OdJuZPFS/config
                expected = set([('group', os.path.join(temp_dir, os.path.basename(self.cli_ctx.config.config_dir), 'config'), self.kwargs['rg'])])
                self.assertEqual(actual, expected)
    
                # test role assignments on a resource group
                rg_id = self.cmd('group show -n {rg}').get_output_in_json()['id']
                self.cmd('role assignment create --assignee {upn} --role reader --scope ' + rg_id)
                self.cmd('role assignment list --assignee {upn} --role reader --scope ' + rg_id, checks=self.check('length([])', 1))
>               self.cmd('role assignment delete --assignee {upn} --role reader --scope ' + rg_id)

src/azure-cli/azure/cli/command_modules/role/tests/latest/test_role.py:695: 
 
 
                                      
src/azure-cli-testsdk/azure/cli/testsdk/base.py:176: in cmd
    return execute(self.cli_ctx, command, expect_failure=expect_failure).assert_with_checks(checks)
src/azure-cli-testsdk/azure/cli/testsdk/base.py:251: in init
    self.in_process_execute(cli_ctx, command, expect_failure=expect_failure)
src/azure-cli-testsdk/azure/cli/testsdk/base.py:314: in in_process_execute
    raise ex.exception
env/lib/python3.12/site-packages/knack/cli.py:233: in invoke
    cmd_result = self.invocation.execute(args)
src/azure-cli-core/azure/cli/core/commands/init.py:666: in execute
    raise ex
src/azure-cli-core/azure/cli/core/commands/init.py:734: in run_jobs_serially
    results.append(self.run_job(expanded_arg, cmd_copy))
src/azure-cli-core/azure/cli/core/commands/init.py:703: in run_job
    result = cmd_copy(params)
src/azure-cli-core/azure/cli/core/commands/init.py:336: in call
    return self.handler(*args, **kwargs)
src/azure-cli-core/azure/cli/core/commands/command_operation.py:120: in handler
    return op(**command_args)
 
 
 
 
 
                                   

cmd = <azure.cli.core.commands.AzCliCommand object at 0x7fc01ad01100>, ids = []
assignee = '[email protected]'
assignee_object_id = 'a0fd923f-205c-4f76-9ca4-ecb5430cb1c7', role = 'reader'
resource_group_name = None
scope = '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/cli_role_assign000001'
include_inherited = False, yes = None

    def delete_role_assignments(cmd, ids=None,
                                assignee=None, assignee_object_id=None,
                                role=None, resource_group_name=None,
                                scope=None, include_inherited=False, yes=None):
        assignee_object_id = _resolve_assignee(cmd.cli_ctx, assignee, assignee_object_id)
    
        factory = _auth_client_factory(cmd.cli_ctx, scope)
        assignments_client = factory.role_assignments
        definitions_client = factory.role_definitions
        ids = ids or []
        if ids:
            # Warn that other arguments are overriden.
            # We can't reuse the logic of azure.cli.core.commands.arm.register_ids_argument, because in that function,
            # ids_metadata is built by checking id_part of each argument.
            # Commands like az&nbsp;vm&nbsp;delete require a resource ID with fixed parts, such as
            # /subscriptions/{}/resourceGroups/{}/providers/Microsoft.Compute/virtualMachines/{}
            # But for az&nbsp;role&nbsp;assignment&nbsp;delete--id can have variable parts:
            # - subscription level:   /subscriptions/{}
            # - resource group level: /subscriptions/{}/resourceGroups/{}
            # - resource level:       /subscriptions/{}/resourceGroups/{}/providers/Microsoft.Compute/virtualMachines/{}
            # so it can't be parsed into pre-defined parts and is passed to SDK as is.
            ids_override_args = ['assignee', 'role', 'resource_group_name', 'scope', 'include_inherited']
            for arg in ids_override_args:
                if locals()[arg]:
                    # This is different with register_ids_argument's --ids handling.
                    # register_ids_argument doesn't show warning if is_default of an argument value is true,
                    # but we do here. I feel being explicit is better than being implicit.
                    logger.warning("option '%s' will be ignored due to use of '--ids'.",
                                   cmd.arguments[arg].type.settings['options_list'][0])
            for i in ids:
                assignments_client.delete_by_id(i)
            return
        if not any([ids, assignee, role, resource_group_name, scope, assignee, yes]):
            from knack.prompting import prompt_y_n
            msg = 'This will delete all role assignments under the subscription. Are you sure?'
            if not prompt_y_n(msg, default="n"):
                return
    
        scope = _build_role_scope(resource_group_name, scope,
                                  assignments_client._config.subscription_id)
        assignments = _search_role_assignments(cmd.cli_ctx, assignments_client, definitions_client,
                                               scope, assignee, role, include_inherited,
                                               include_groups=False)
    
        if assignments:
            for a in assignments:
                assignments_client.delete_by_id(a.id)
        else:
>           raise CLIError('No matched assignments were found to delete')
E           knack.util.CLIError: No matched assignments were found to delete

src/azure-cli/azure/cli/command_modules/role/custom.py:552: CLIError
azure/cli/command_modules/role/tests/latest/test_role.py:659
❌3.9
Type Test Case Error Message Line
Failed test_role_assignment_scenario self = <azure.cli.testsdk.base.ExecutionResult object at 0x7f7b07df68b0>
cli_ctx = <azure.cli.core.mock.DummyCli object at 0x7f7b092972b0>
command = 'role assignment delete --assignee [email protected] --role reader -g cli_role_assign000001'
expect_failure = False

    def in_process_execute(self, cli_ctx, command, expect_failure=False):
        from io import StringIO
        from vcr.errors import CannotOverwriteExistingCassetteException
    
        if command.startswith('az '):
            command = command[3:]
    
        stdout_buf = StringIO()
        logging_buf = StringIO()
        try:
            # issue: stderr cannot be redirect in this form, as a result some failure information
            # is lost when command fails.
>           self.exit_code = cli_ctx.invoke(shlex.split(command), out_file=stdout_buf) or 0

src/azure-cli-testsdk/azure/cli/testsdk/base.py:302: 
                                        
env/lib/python3.9/site-packages/knack/cli.py:245: in invoke
    exit_code = self.exception_handler(ex)
src/azure-cli-core/azure/cli/core/init.py:129: in exception_handler
    return handle_exception(ex)
                                        

ex = CLIError('No matched assignments were found to delete'), args = ()
kwargs = {}

    def handle_main_exception(ex, *args, **kwargs):  # pylint: disable=unused-argument
        if isinstance(ex, CannotOverwriteExistingCassetteException):
            # This exception usually caused by a no match HTTP request. This is a product error
            # that is caused by change of SDK invocation.
            raise ex
    
>       raise CliExecutionError(ex)
E       azure.cli.testsdk.exceptions.CliExecutionError: The CLI throws exception CLIError during execution and fails the command.

src/azure-cli-testsdk/azure/cli/testsdk/patches.py:35: CliExecutionError

During handling of the above exception, another exception occurred:

self = <azure.cli.command_modules.role.tests.latest.test_role.RoleAssignmentScenarioTest testMethod=test_role_assignment_scenario>
resource_group = 'cli_role_assign000001'

    @ResourceGroupPreparer(name_prefix='cli_role_assign')
    @AllowLargeResponse()
    def test_role_assignment_scenario(self, resource_group):
        if self.run_under_service_principal():
            return  # this test delete users which are beyond a SP's capacity, so quit...
    
        with mock.patch('azure.cli.command_modules.role.custom.gen_guid', side_effect=self.create_guid):
            user = self.create_random_name('testuser', 15)
            self.kwargs.update({
                'upn': user + TEST_TENANT_DOMAIN,
                'nsg': 'nsg1',
                'role': 'reader',  # Use low-privileged role to make the test secure
                # https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles
                'reader_guid': 'acdd72a7-3385-48ef-bd42-f606fba81ae7'
            })
            self.prepare_scope_kwargs()
    
            # test create role assignment without --scope
            with self.assertRaisesRegex(SystemExit, '2'):
                self.cmd('role assignment create --assignee {upn} --role {role}')
    
            result = self.cmd('ad user create --display-name tester123 --password Test123456789'
                              ' --user-principal-name {upn}').get_output_in_json()
            self.kwargs.update({
                'user_id': result['id']})
    
            group = self.create_random_name('testgroup', 15)
            self.kwargs.update({
                'group': group})
    
            group_result = self.cmd(
                'ad group create --display-name group123 --mail-nickname {group}').get_output_in_json()
            self.kwargs.update({
                'group_id': group_result['id']})
            self.cmd(
                'ad group member add --group {group_id} --member-id {user_id}')
    
            time.sleep(15)  # By-design, it takes some time for RBAC system propagated with graph object change
    
            try:
                self.cmd('network nsg create -n {nsg} -g {rg}')
                result = self.cmd('network nsg show -n {nsg} -g {rg}').get_output_in_json()
                self.kwargs['nsg_id'] = result['id']
    
                # test role assignments on a resource group for the user
                self.cmd('role assignment create --assignee {upn} --role {role} --scope {rg_id}')
                # verify role assignment create is idempotent
                self.cmd('role assignment create --assignee {upn} --role {role} --scope {rg_id}',
                         self.check("principalName", self.kwargs["upn"]))
    
                self.cmd('role assignment list -g {rg}', checks=self.check("length([])", 1))
                self.cmd('role assignment list --assignee {upn} --role {role} -g {rg}', checks=[
                    self.check("length([])", 1),
                    self.check("[0].principalName", self.kwargs["upn"])
                ])
    
                # Create role assignment for the group
                self.cmd('role assignment create --assignee {group_id} --role {role} --scope {rg_id}')
    
                # test include-groups
                self.cmd('role assignment list --assignee {upn} --all --include-groups', checks=[
                    self.check("length([])", 2)
                ])
    
                self.cmd('role assignment delete --assignee {group_id} --role {role} -g {rg}')
>               self.cmd('role assignment delete --assignee {upn} --role {role} -g {rg}')

src/azure-cli/azure/cli/command_modules/role/tests/latest/test_role.py:329: 
 
 
 
                                     
src/azure-cli-testsdk/azure/cli/testsdk/base.py:176: in cmd
    return execute(self.cli_ctx, command, expect_failure=expect_failure).assert_with_checks(checks)
src/azure-cli-testsdk/azure/cli/testsdk/base.py:251: in init
    self.in_process_execute(cli_ctx, command, expect_failure=expect_failure)
src/azure-cli-testsdk/azure/cli/testsdk/base.py:314: in in_process_execute
    raise ex.exception
env/lib/python3.9/site-packages/knack/cli.py:233: in invoke
    cmd_result = self.invocation.execute(args)
src/azure-cli-core/azure/cli/core/commands/init.py:666: in execute
    raise ex
src/azure-cli-core/azure/cli/core/commands/init.py:734: in run_jobs_serially
    results.append(self.run_job(expanded_arg, cmd_copy))
src/azure-cli-core/azure/cli/core/commands/init.py:703: in run_job
    result = cmd_copy(params)
src/azure-cli-core/azure/cli/core/commands/init.py:336: in call
    return self.handler(*args, **kwargs)
src/azure-cli-core/azure/cli/core/commands/command_operation.py:120: in handler
    return op(**command_args)
 
 
 
 
                                   _ 

cmd = <azure.cli.core.commands.AzCliCommand object at 0x7f7b07e723d0>, ids = []
assignee = '[email protected]'
assignee_object_id = 'b582d754-5e23-4c28-82e9-0a6cd0390c03', role = 'reader'
resource_group_name = 'cli_role_assign000001'
scope = '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/cli_role_assign000001'
include_inherited = False, yes = None

    def delete_role_assignments(cmd, ids=None,
                                assignee=None, assignee_object_id=None,
                                role=None, resource_group_name=None,
                                scope=None, include_inherited=False, yes=None):
        assignee_object_id = _resolve_assignee(cmd.cli_ctx, assignee, assignee_object_id)
    
        factory = _auth_client_factory(cmd.cli_ctx, scope)
        assignments_client = factory.role_assignments
        definitions_client = factory.role_definitions
        ids = ids or []
        if ids:
            # Warn that other arguments are overriden.
            # We can't reuse the logic of azure.cli.core.commands.arm.register_ids_argument, because in that function,
            # ids_metadata is built by checking id_part of each argument.
            # Commands like az&nbsp;vm&nbsp;delete require a resource ID with fixed parts, such as
            # /subscriptions/{}/resourceGroups/{}/providers/Microsoft.Compute/virtualMachines/{}
            # But for az&nbsp;role&nbsp;assignment&nbsp;delete--id can have variable parts:
            # - subscription level:   /subscriptions/{}
            # - resource group level: /subscriptions/{}/resourceGroups/{}
            # - resource level:       /subscriptions/{}/resourceGroups/{}/providers/Microsoft.Compute/virtualMachines/{}
            # so it can't be parsed into pre-defined parts and is passed to SDK as is.
            ids_override_args = ['assignee', 'role', 'resource_group_name', 'scope', 'include_inherited']
            for arg in ids_override_args:
                if locals()[arg]:
                    # This is different with register_ids_argument's --ids handling.
                    # register_ids_argument doesn't show warning if is_default of an argument value is true,
                    # but we do here. I feel being explicit is better than being implicit.
                    logger.warning("option '%s' will be ignored due to use of '--ids'.",
                                   cmd.arguments[arg].type.settings['options_list'][0])
            for i in ids:
                assignments_client.delete_by_id(i)
            return
        if not any([ids, assignee, role, resource_group_name, scope, assignee, yes]):
            from knack.prompting import prompt_y_n
            msg = 'This will delete all role assignments under the subscription. Are you sure?'
            if not prompt_y_n(msg, default="n"):
                return
    
        scope = _build_role_scope(resource_group_name, scope,
                                  assignments_client._config.subscription_id)
        assignments = _search_role_assignments(cmd.cli_ctx, assignments_client, definitions_client,
                                               scope, assignee, role, include_inherited,
                                               include_groups=False)
    
        if assignments:
            for a in assignments:
                assignments_client.delete_by_id(a.id)
        else:
>           raise CLIError('No matched assignments were found to delete')
E           knack.util.CLIError: No matched assignments were found to delete

src/azure-cli/azure/cli/command_modules/role/custom.py:552: CLIError
azure/cli/command_modules/role/tests/latest/test_role.py:263
Failed test_role_assignment_handle_conflicted_assignments self = <azure.cli.testsdk.base.ExecutionResult object at 0x7f7b07ba0670>
cli_ctx = <azure.cli.core.mock.DummyCli object at 0x7f7b09272d90>
command = 'role assignment delete --assignee [email protected] --role reader --scope /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/cli_role_assign000001'
expect_failure = False

    def in_process_execute(self, cli_ctx, command, expect_failure=False):
        from io import StringIO
        from vcr.errors import CannotOverwriteExistingCassetteException
    
        if command.startswith('az '):
            command = command[3:]
    
        stdout_buf = StringIO()
        logging_buf = StringIO()
        try:
            # issue: stderr cannot be redirect in this form, as a result some failure information
            # is lost when command fails.
>           self.exit_code = cli_ctx.invoke(shlex.split(command), out_file=stdout_buf) or 0

src/azure-cli-testsdk/azure/cli/testsdk/base.py:302: 
                                        
env/lib/python3.9/site-packages/knack/cli.py:245: in invoke
    exit_code = self.exception_handler(ex)
src/azure-cli-core/azure/cli/core/init.py:129: in exception_handler
    return handle_exception(ex)
                                        

ex = CLIError('No matched assignments were found to delete'), args = ()
kwargs = {}

    def handle_main_exception(ex, *args, **kwargs):  # pylint: disable=unused-argument
        if isinstance(ex, CannotOverwriteExistingCassetteException):
            # This exception usually caused by a no match HTTP request. This is a product error
            # that is caused by change of SDK invocation.
            raise ex
    
>       raise CliExecutionError(ex)
E       azure.cli.testsdk.exceptions.CliExecutionError: The CLI throws exception CLIError during execution and fails the command.

src/azure-cli-testsdk/azure/cli/testsdk/patches.py:35: CliExecutionError

During handling of the above exception, another exception occurred:

self = <azure.cli.command_modules.role.tests.latest.test_role.RoleAssignmentWithConfigScenarioTest testMethod=test_role_assignment_handle_conflicted_assignments>
resource_group = 'cli_role_assign000001'

    @ResourceGroupPreparer(name_prefix='cli_role_assign')
    @AllowLargeResponse()
    def test_role_assignment_handle_conflicted_assignments(self, resource_group):
        if self.run_under_service_principal():
            return  # this test delete users which are beyond a SP's capacity, so quit...
    
        with mock.patch('azure.cli.command_modules.role.custom.gen_guid', side_effect=self.create_guid):
            user = self.create_random_name('testuser', 15)
            self.kwargs.update({
                'upn': user + TEST_TENANT_DOMAIN,
                'nsg': 'nsg1'
            })
    
            self.cmd('ad user create --display-name tester123 --password Test123456789 --user-principal-name {upn}')
            time.sleep(15)  # By-design, it takes some time for RBAC system propagated with graph object change
    
            base_dir = os.path.abspath(os.curdir)
    
            try:
                temp_dir = os.path.realpath(self.create_temp_dir())
                os.chdir(temp_dir)
                self.cmd('configure --default group={rg} --scope local')
                local_defaults_config = self.cmd('configure --list-defaults --scope local').get_output_in_json()
    
                self.assertGreaterEqual(len(local_defaults_config), 1)
                actual = set([(x['name'], x['source'], x['value']) for x in local_defaults_config if x['name'] == 'group'])
                # If global config_dir is ~/.azure/dummy_cli_config_dir/0azXbKR9OdJuZPFS/,
                # local config file is  ./0azXbKR9OdJuZPFS/config
                expected = set([('group', os.path.join(temp_dir, os.path.basename(self.cli_ctx.config.config_dir), 'config'), self.kwargs['rg'])])
                self.assertEqual(actual, expected)
    
                # test role assignments on a resource group
                rg_id = self.cmd('group show -n {rg}').get_output_in_json()['id']
                self.cmd('role assignment create --assignee {upn} --role reader --scope ' + rg_id)
                self.cmd('role assignment list --assignee {upn} --role reader --scope ' + rg_id, checks=self.check('length([])', 1))
>               self.cmd('role assignment delete --assignee {upn} --role reader --scope ' + rg_id)

src/azure-cli/azure/cli/command_modules/role/tests/latest/test_role.py:695: 
 
 
                                      
src/azure-cli-testsdk/azure/cli/testsdk/base.py:176: in cmd
    return execute(self.cli_ctx, command, expect_failure=expect_failure).assert_with_checks(checks)
src/azure-cli-testsdk/azure/cli/testsdk/base.py:251: in init
    self.in_process_execute(cli_ctx, command, expect_failure=expect_failure)
src/azure-cli-testsdk/azure/cli/testsdk/base.py:314: in in_process_execute
    raise ex.exception
env/lib/python3.9/site-packages/knack/cli.py:233: in invoke
    cmd_result = self.invocation.execute(args)
src/azure-cli-core/azure/cli/core/commands/init.py:666: in execute
    raise ex
src/azure-cli-core/azure/cli/core/commands/init.py:734: in run_jobs_serially
    results.append(self.run_job(expanded_arg, cmd_copy))
src/azure-cli-core/azure/cli/core/commands/init.py:703: in run_job
    result = cmd_copy(params)
src/azure-cli-core/azure/cli/core/commands/init.py:336: in call
    return self.handler(*args, **kwargs)
src/azure-cli-core/azure/cli/core/commands/command_operation.py:120: in handler
    return op(**command_args)
 
 
 
 
 
                                   

cmd = <azure.cli.core.commands.AzCliCommand object at 0x7f7b07956b50>, ids = []
assignee = '[email protected]'
assignee_object_id = 'a0fd923f-205c-4f76-9ca4-ecb5430cb1c7', role = 'reader'
resource_group_name = None
scope = '/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/cli_role_assign000001'
include_inherited = False, yes = None

    def delete_role_assignments(cmd, ids=None,
                                assignee=None, assignee_object_id=None,
                                role=None, resource_group_name=None,
                                scope=None, include_inherited=False, yes=None):
        assignee_object_id = _resolve_assignee(cmd.cli_ctx, assignee, assignee_object_id)
    
        factory = _auth_client_factory(cmd.cli_ctx, scope)
        assignments_client = factory.role_assignments
        definitions_client = factory.role_definitions
        ids = ids or []
        if ids:
            # Warn that other arguments are overriden.
            # We can't reuse the logic of azure.cli.core.commands.arm.register_ids_argument, because in that function,
            # ids_metadata is built by checking id_part of each argument.
            # Commands like az&nbsp;vm&nbsp;delete require a resource ID with fixed parts, such as
            # /subscriptions/{}/resourceGroups/{}/providers/Microsoft.Compute/virtualMachines/{}
            # But for az&nbsp;role&nbsp;assignment&nbsp;delete--id can have variable parts:
            # - subscription level:   /subscriptions/{}
            # - resource group level: /subscriptions/{}/resourceGroups/{}
            # - resource level:       /subscriptions/{}/resourceGroups/{}/providers/Microsoft.Compute/virtualMachines/{}
            # so it can't be parsed into pre-defined parts and is passed to SDK as is.
            ids_override_args = ['assignee', 'role', 'resource_group_name', 'scope', 'include_inherited']
            for arg in ids_override_args:
                if locals()[arg]:
                    # This is different with register_ids_argument's --ids handling.
                    # register_ids_argument doesn't show warning if is_default of an argument value is true,
                    # but we do here. I feel being explicit is better than being implicit.
                    logger.warning("option '%s' will be ignored due to use of '--ids'.",
                                   cmd.arguments[arg].type.settings['options_list'][0])
            for i in ids:
                assignments_client.delete_by_id(i)
            return
        if not any([ids, assignee, role, resource_group_name, scope, assignee, yes]):
            from knack.prompting import prompt_y_n
            msg = 'This will delete all role assignments under the subscription. Are you sure?'
            if not prompt_y_n(msg, default="n"):
                return
    
        scope = _build_role_scope(resource_group_name, scope,
                                  assignments_client._config.subscription_id)
        assignments = _search_role_assignments(cmd.cli_ctx, assignments_client, definitions_client,
                                               scope, assignee, role, include_inherited,
                                               include_groups=False)
    
        if assignments:
            for a in assignments:
                assignments_client.delete_by_id(a.id)
        else:
>           raise CLIError('No matched assignments were found to delete')
E           knack.util.CLIError: No matched assignments were found to delete

src/azure-cli/azure/cli/command_modules/role/custom.py:552: CLIError
azure/cli/command_modules/role/tests/latest/test_role.py:659
️✔️search
️✔️latest
️✔️3.12
️✔️3.9
️✔️security
️✔️latest
️✔️3.12
️✔️3.9
️✔️servicebus
️✔️latest
️✔️3.12
️✔️3.9
️✔️serviceconnector
️✔️latest
️✔️3.12
️✔️3.9
️✔️servicefabric
️✔️latest
️✔️3.12
️✔️3.9
️✔️signalr
️✔️latest
️✔️3.12
️✔️3.9
️✔️sql
️✔️latest
️✔️3.12
️✔️3.9
️✔️sqlvm
️✔️latest
️✔️3.12
️✔️3.9
️✔️storage
️✔️2018-03-01-hybrid
️✔️3.12
️✔️3.9
️✔️2019-03-01-hybrid
️✔️3.12
️✔️3.9
️✔️2020-09-01-hybrid
️✔️3.12
️✔️3.9
️✔️latest
️✔️3.12
️✔️3.9
️✔️synapse
️✔️latest
️✔️3.12
️✔️3.9
️✔️telemetry
️✔️2018-03-01-hybrid
️✔️3.12
️✔️3.9
️✔️2019-03-01-hybrid
️✔️3.12
️✔️3.9
️✔️2020-09-01-hybrid
️✔️3.12
️✔️3.9
️✔️latest
️✔️3.12
️✔️3.9
️✔️util
️✔️latest
️✔️3.12
️✔️3.9
️✔️vm
️✔️2018-03-01-hybrid
️✔️3.12
️✔️3.9
️✔️2019-03-01-hybrid
️✔️3.12
️✔️3.9
️✔️2020-09-01-hybrid
️✔️3.12
️✔️3.9
️✔️latest
️✔️3.12
️✔️3.9

Copy link

azure-client-tools-bot-prd bot commented Dec 5, 2024

⚠️AzureCLI-BreakingChangeTest
⚠️role
rule cmd_name rule_message suggest_message
⚠️ 1006 - ParaAdd role assignment delete cmd role assignment delete added parameter assignee_object_id
⚠️ 1006 - ParaAdd role assignment list cmd role assignment list added parameter assignee_object_id

@yonzhan
Copy link
Collaborator

yonzhan commented Dec 5, 2024

Thank you for your contribution! We will review the pull request and get back to you soon.

Copy link

github-actions bot commented Dec 5, 2024

⚠️Your changes in this PR will be released on Jan 14, 2025 due to CCOA (extend to Jan 6, 2025)

@jiasli
Copy link
Member Author

jiasli commented Dec 5, 2024

In az role assignment list, --assignee is also used to back fill classic administrators:

if include_classic_administrators:
results += _backfill_assignments_for_co_admins(cmd.cli_ctx, authorization_client, assignee)

Classic administrator support should be dropped: #29470

@jiasli
Copy link
Member Author

jiasli commented Dec 5, 2024

In az role assignment list, even if --assignee-object-id is provided, this command still queries Graph for the assignee information:

if principal_ids:
try:
principals = _get_object_stubs(graph_client, principal_ids)

I feel this behavior should be skipped if --assignee-object-id is provided, or we can introduce another argument such as --no-graph-query.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Auto-Assign Auto assign by bot RBAC az role
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Feature Request] az role assignment list/delete: Support --assignee-object-id
2 participants