Skip to content

Commit 87094cd

Browse files
authored
[ARM] az deployment: Fix bicep template size inflation with differential template handling (#31990)
1 parent 008f1c2 commit 87094cd

File tree

4 files changed

+1439
-20
lines changed

4 files changed

+1439
-20
lines changed

src/azure-cli/azure/cli/command_modules/resource/custom.py

Lines changed: 50 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -384,13 +384,11 @@ def _deploy_arm_template_core_unmodified(cmd, resource_group_name, template_file
384384
if template_uri:
385385
template_link = TemplateLink(uri=template_uri)
386386
template_obj = _remove_comments_from_json(_urlretrieve(template_uri).decode('utf-8'), file_path=template_uri)
387+
template_for_deployment = None # Use template_link for URI-based deployments
387388
else:
388-
template_content = (
389-
run_bicep_command(cmd.cli_ctx, ["build", "--stdout", template_file])
390-
if is_bicep_file(template_file)
391-
else read_file_content(template_file)
392-
)
393-
template_obj = _remove_comments_from_json(template_content, file_path=template_file)
389+
# This function is resource-group-specific, so we hardcode 'resourceGroup' deployment scope
390+
template_content, template_obj = _process_template_file(cmd, template_file, 'resourceGroup')
391+
template_for_deployment = _get_template_for_deployment(template_uri, None, template_file, template_content, template_obj, None)
394392

395393
if rollback_on_error == '':
396394
on_error_deployment = OnErrorDeployment(type='LastSuccessful')
@@ -403,7 +401,7 @@ def _deploy_arm_template_core_unmodified(cmd, resource_group_name, template_file
403401

404402
parameters = json.loads(json.dumps(parameters))
405403

406-
properties = DeploymentProperties(template=template_content, template_link=template_link,
404+
properties = DeploymentProperties(template=template_for_deployment, template_link=template_link,
407405
parameters=parameters, mode=mode, on_error_deployment=on_error_deployment)
408406

409407
smc = get_mgmt_service_client(cmd.cli_ctx, ResourceType.MGMT_RESOURCE_DEPLOYMENTS,
@@ -476,6 +474,7 @@ def on_request(self, request):
476474
# Because the service cannot deserialize the template element: "template": "{\r\n \"$schema\": \"...\",\r\n \"contentVersion\": \"...\",\r\n \"parameters\": {...}}"
477475
partial_request = json.dumps(modified_data)
478476
json_data = partial_request[:-2] + ", template:" + template + r"}}"
477+
479478
http_request.data = json_data.encode('utf-8')
480479

481480
# This caused a very difficult-to-debug issue, because AzCLI's debug logs are written before this transformation.
@@ -1118,6 +1117,46 @@ def _load_template_spec_template(cmd, template_spec):
11181117
return template_obj
11191118

11201119

1120+
def _get_template_for_deployment(template_uri, template_spec, template_file, template_content, template_obj, parameters):
1121+
"""Determine what to use for template deployment based on the source"""
1122+
if template_uri or template_spec:
1123+
# For URI and template spec deployments, use None (template_link will be used)
1124+
return None
1125+
1126+
if _is_bicepparam_file_provided(parameters):
1127+
# For bicepparam files, use the content
1128+
return template_content
1129+
1130+
if template_file and is_bicep_file(template_file):
1131+
# For bicep files, convert the parsed object back to compact JSON string
1132+
# This avoids the size inflation issue while maintaining compatibility
1133+
# with the Azure SDK which expects string content
1134+
return json.dumps(template_obj, separators=(',', ':'))
1135+
1136+
# For ARM template files, use string content
1137+
return template_content
1138+
1139+
1140+
def _process_template_file(cmd, template_file, deployment_scope):
1141+
"""Process template file and return template_content and template_obj"""
1142+
if is_bicep_file(template_file):
1143+
# Get compiled JSON from bicep
1144+
template_content = run_bicep_command(cmd.cli_ctx, ["build", "--stdout", template_file])
1145+
# For bicep files, parse JSON directly to avoid Azure SDK size inflation.
1146+
# Bicep compilation outputs clean JSON without comments, so it's safe to
1147+
# parse directly. This prevents the 4MB template size limit issue caused
1148+
# by Azure SDK string escaping when using template content as string.
1149+
template_obj = json.loads(template_content)
1150+
template_schema = template_obj.get('$schema', '')
1151+
validate_bicep_target_scope(template_schema, deployment_scope)
1152+
else:
1153+
# For ARM template files, read content and process comments
1154+
template_content = read_file_content(template_file)
1155+
template_obj = _remove_comments_from_json(template_content, file_path=template_file)
1156+
1157+
return template_content, template_obj
1158+
1159+
11211160
def _prepare_deployment_properties_unmodified(cmd, deployment_scope, template_file=None, template_uri=None, parameters=None,
11221161
mode=None, rollback_on_error=None, no_prompt=False, template_spec=None, query_string=None,
11231162
validation_level=None):
@@ -1164,17 +1203,7 @@ def _prepare_deployment_properties_unmodified(cmd, deployment_scope, template_fi
11641203
template_schema = template_obj.get('$schema', '')
11651204
validate_bicep_target_scope(template_schema, deployment_scope)
11661205
else:
1167-
template_content = (
1168-
run_bicep_command(cmd.cli_ctx, ["build", "--stdout", template_file])
1169-
if is_bicep_file(template_file)
1170-
else read_file_content(template_file)
1171-
)
1172-
1173-
template_obj = _remove_comments_from_json(template_content, file_path=template_file)
1174-
1175-
if is_bicep_file(template_file):
1176-
template_schema = template_obj.get('$schema', '')
1177-
validate_bicep_target_scope(template_schema, deployment_scope)
1206+
template_content, template_obj = _process_template_file(cmd, template_file, deployment_scope)
11781207

11791208
if rollback_on_error == '':
11801209
on_error_deployment = OnErrorDeployment(type='LastSuccessful')
@@ -1190,7 +1219,9 @@ def _prepare_deployment_properties_unmodified(cmd, deployment_scope, template_fi
11901219
parameters = _get_missing_parameters(parameters, template_obj, _prompt_for_parameters, no_prompt)
11911220
parameters = json.loads(json.dumps(parameters))
11921221

1193-
properties = DeploymentProperties(template=template_content, template_link=template_link,
1222+
template_for_deployment = _get_template_for_deployment(template_uri, template_spec, template_file, template_content, template_obj, parameters)
1223+
1224+
properties = DeploymentProperties(template=template_for_deployment, template_link=template_link,
11941225
parameters=parameters, mode=mode, on_error_deployment=on_error_deployment,
11951226
validation_level=validation_level)
11961227
return properties

0 commit comments

Comments
 (0)