diff --git a/src/azure-cli/azure/cli/command_modules/resource/_utils.py b/src/azure-cli/azure/cli/command_modules/resource/_utils.py index 9d875bf8992..bb73bca6ce4 100644 --- a/src/azure-cli/azure/cli/command_modules/resource/_utils.py +++ b/src/azure-cli/azure/cli/command_modules/resource/_utils.py @@ -76,3 +76,34 @@ def split_resource_id(resource_id): return subscription_scope, relative_resource_id return "/", relative_resource_id + + +def _build_preflight_error_message(preflight_error): + err_messages = [f'{preflight_error.code} - {preflight_error.message}'] + for detail in preflight_error.details or []: + err_messages.append(_build_preflight_error_message(detail)) + return '\n'.join(err_messages) + + +def _build_http_response_error_message(http_error): + error_txt = http_error.response.internal_response.text + + import json + error_info = json.loads(error_txt)['error'] + error_details = error_info.pop('details') if 'details' in error_info else [] + err_messages = [f'{error_info}'] + + for detail in error_details: + err_messages.append(_build_error_details(detail)) + + return '\n\n'.join(err_messages) + + +def _build_error_details(error_detail): + nested_error_details = error_detail.pop('details') if 'details' in error_detail else [] + err_messages = [f'Inner Errors: \n{error_detail}'] + + for detail in nested_error_details: + err_messages.append(_build_error_details(detail)) + + return '\n\n'.join(err_messages) diff --git a/src/azure-cli/azure/cli/command_modules/resource/custom.py b/src/azure-cli/azure/cli/command_modules/resource/custom.py index 7883c30d06a..ecca48388d0 100644 --- a/src/azure-cli/azure/cli/command_modules/resource/custom.py +++ b/src/azure-cli/azure/cli/command_modules/resource/custom.py @@ -58,6 +58,8 @@ supports_bicep_publish ) +from ._utils import _build_preflight_error_message, _build_http_response_error_message + logger = get_logger(__name__) RPAAS_APIS = {'microsoft.datadog': '/subscriptions/{subscriptionId}/providers/Microsoft.Datadog/agreements/default?api-version=2020-02-01-preview', @@ -369,8 +371,9 @@ def _deploy_arm_template_core_unmodified(cmd, resource_group_name, template_file if cmd.supported_api_version(min_api='2019-10-01', resource_type=ResourceType.MGMT_RESOURCE_RESOURCES): try: validation_poller = deployment_client.begin_validate(resource_group_name, deployment_name, deployment) - except HttpResponseError as cx: - raise_subdivision_deployment_error(cx.response.internal_response.text, cx.error.code if cx.error else None) + except HttpResponseError as err: + err_message = _build_http_response_error_message(err) + raise_subdivision_deployment_error(err_message, err.error.code if err.error else None) validation_result = LongRunningOperation(cmd.cli_ctx)(validation_poller) else: validation_result = deployment_client.validate(resource_group_name, deployment_name, deployment) @@ -489,8 +492,9 @@ def _deploy_arm_template_at_subscription_scope(cmd, if cmd.supported_api_version(min_api='2019-10-01', resource_type=ResourceType.MGMT_RESOURCE_RESOURCES): try: validation_poller = mgmt_client.begin_validate_at_subscription_scope(deployment_name, deployment) - except HttpResponseError as cx: - raise_subdivision_deployment_error(cx.response.internal_response.text, cx.error.code if cx.error else None) + except HttpResponseError as err: + err_message = _build_http_response_error_message(err) + raise_subdivision_deployment_error(err_message, err.error.code if err.error else None) validation_result = LongRunningOperation(cmd.cli_ctx)(validation_poller) else: validation_result = mgmt_client.validate_at_subscription_scope(deployment_name, deployment) @@ -579,8 +583,9 @@ def _deploy_arm_template_at_resource_group(cmd, if cmd.supported_api_version(min_api='2019-10-01', resource_type=ResourceType.MGMT_RESOURCE_RESOURCES): try: validation_poller = mgmt_client.begin_validate(resource_group_name, deployment_name, deployment) - except HttpResponseError as cx: - raise_subdivision_deployment_error(cx.response.internal_response.text, cx.error.code if cx.error else None) + except HttpResponseError as err: + err_message = _build_http_response_error_message(err) + raise_subdivision_deployment_error(err_message, err.error.code if err.error else None) validation_result = LongRunningOperation(cmd.cli_ctx)(validation_poller) else: validation_result = mgmt_client.validate(resource_group_name, deployment_name, deployment) @@ -667,8 +672,9 @@ def _deploy_arm_template_at_management_group(cmd, try: validation_poller = mgmt_client.begin_validate_at_management_group_scope(management_group_id, deployment_name, deployment) - except HttpResponseError as cx: - raise_subdivision_deployment_error(cx.response.internal_response.text, cx.error.code if cx.error else None) + except HttpResponseError as err: + err_message = _build_http_response_error_message(err) + raise_subdivision_deployment_error(err_message, err.error.code if err.error else None) validation_result = LongRunningOperation(cmd.cli_ctx)(validation_poller) else: validation_result = mgmt_client.validate_at_management_group_scope(management_group_id, deployment_name, @@ -750,8 +756,9 @@ def _deploy_arm_template_at_tenant_scope(cmd, try: validation_poller = mgmt_client.begin_validate_at_tenant_scope(deployment_name=deployment_name, parameters=deployment) - except HttpResponseError as cx: - raise_subdivision_deployment_error(cx.response.internal_response.text, cx.error.code if cx.error else None) + except HttpResponseError as err: + err_message = _build_http_response_error_message(err) + raise_subdivision_deployment_error(err_message, err.error.code if err.error else None) validation_result = LongRunningOperation(cmd.cli_ctx)(validation_poller) else: validation_result = mgmt_client.validate_at_tenant_scope(deployment_name=deployment_name, @@ -929,13 +936,6 @@ def _what_if_deploy_arm_template_core(cli_ctx, what_if_poller, no_pretty_print, return what_if_result -def _build_preflight_error_message(preflight_error): - err_messages = [f'{preflight_error.code} - {preflight_error.message}'] - for detail in preflight_error.details or []: - err_messages.append(_build_preflight_error_message(detail)) - return '\n'.join(err_messages) - - def _prepare_template_uri_with_query_string(template_uri, input_query_string): from urllib.parse import urlencode, parse_qs, urlsplit, urlunsplit