Skip to content

Commit cd0aac5

Browse files
authored
Stabilize infrastructure deployments by fixing race conditions and making deployment names unique (#461)
### Summary & Motivation Make all Bicep module deployment names unique to avoid concurrent deployments of resources like managed identity container permissions. This resolves issues where deployments failed due to naming conflicts. Fix race condition when assigning user-managed identity permissions to container registry immediately after creation. The fix involves setting the `principalType` to `ServicePrincipal` on Bicep `roleAssignments` resource. Remove `-role-assignment` postfix from Bicep module names to allow for longer resource names, as deployment names in Bicep cannot be longer than 64 characters. Ensure `deploy-cluster.sh` reliably checks for failed deployments even when `az CLI` outputs warnings. This ensures JSON results are parsed correctly by stripping any prefixed warning messages. Rename Application Insights smart detection resource from `Application Insights smart detection` to `staging-application-insights-smart-detection`. Fix information message about setting up SSL certificate to use domain name instead of `account-management`. ### Checklist - [x] I have added a Label to the pull-request - [x] I have added tests, and done manual regression tests - [x] I have updated the documentation, if necessary
2 parents bb3a657 + 1b4679a commit cd0aac5

11 files changed

+41
-37
lines changed

cloud-infrastructure/cluster/deploy-cluster.sh

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,9 @@ then
7676
RED='\033[0;31m'
7777
RESET='\033[0m' # Reset formatting
7878

79+
cleaned_output=$(echo "$output" | sed '/^WARNING/d')
7980
# Check for the specific error message indicating that DNS Records are missing
80-
if [[ $output == *"InvalidCustomHostNameValidation"* ]] || [[ $output == *"FailedCnameValidation"* ]] || [[ $output == *"-certificate' under resource group '$RESOURCE_GROUP_NAME' was not found"* ]]; then
81+
if [[ $cleaned_output == *"InvalidCustomHostNameValidation"* ]] || [[ $cleaned_output == *"FailedCnameValidation"* ]] || [[ $cleaned_output == *"-certificate' under resource group '$RESOURCE_GROUP_NAME' was not found"* ]]; then
8182
# Get details about the container apps environment. Although the creation of the container app fails, the verification ID on the container apps environment is consistent across all container apps.
8283
env_details=$(az containerapp env show --name "$LOCATION_PREFIX-container-apps-environment" --resource-group "$RESOURCE_GROUP_NAME")
8384

@@ -90,27 +91,28 @@ then
9091
echo -e "${RED}- A TXT record with the name 'asuid.$DOMAIN_NAME' and the value '$custom_domain_verification_id'.${RESET}"
9192
echo -e "${RED}- A CNAME record with the Host name '$DOMAIN_NAME' that points to address 'app-gateway.$default_domain'.${RESET}"
9293
exit 1
93-
elif [[ $output == "ERROR:"* ]]; then
94+
elif [[ $cleaned_output == *"ERROR:"* && $cleaned_output == *'"status": "Failed"'* ]]; then
9495
echo -e "${RED}$output${RESET}"
9596
exit 1
9697
fi
9798

9899
# If the domain was not configured during the first run and we didn't receive any warnings about missing DNS entries, we trigger the deployment again to complete the binding of the SSL Certificate to the domain.
99100
if [[ "$IS_DOMAIN_CONFIGURED" == "false" ]] && [[ "$DOMAIN_NAME" != "" ]]; then
100-
echo "Running deployment again to finalize setting up SSL certificate for account-management"
101+
echo "Running deployment again to finalize setting up SSL certificate for $DOMAIN_NAME"
101102
IS_DOMAIN_CONFIGURED=$(is_domain_configured "app-gateway" "$RESOURCE_GROUP_NAME")
102103
DEPLOYMENT_PARAMETERS="-l $LOCATION -n $CURRENT_DATE-$RESOURCE_GROUP_NAME --output json -f ./main-cluster.bicep -p environment=$ENVIRONMENT locationPrefix=$LOCATION_PREFIX resourceGroupName=$RESOURCE_GROUP_NAME clusterUniqueName=$CLUSTER_UNIQUE_NAME useMssqlElasticPool=$USE_MSSQL_ELASTIC_POOL containerRegistryName=$CONTAINER_REGISTRY_NAME domainName=$DOMAIN_NAME isDomainConfigured=$IS_DOMAIN_CONFIGURED sqlAdminObjectId=$ACTIVE_DIRECTORY_SQL_ADMIN_OBJECT_ID appGatewayVersion=$APP_GATEWAY_VERSION accountManagementVersion=$ACTIVE_ACCOUNT_MANAGEMENT_VERSION backOfficeVersion=$ACTIVE_BACK_OFFICE_VERSION applicationInsightsConnectionString=$APPLICATIONINSIGHTS_CONNECTION_STRING"
103104

104105
. ../deploy.sh
105106

106-
if [[ $output == "ERROR:"* ]]; then
107+
cleaned_output=$(echo "$output" | sed '/^WARNING/d')
108+
if [[ $cleaned_output == "ERROR:"* ]]; then
107109
echo -e "${RED}$output"
108110
exit 1
109111
fi
110112
fi
111113

112114
# Extract the ID of the Managed Identities, which can be used to grant access to SQL Database
113-
ACCOUNT_MANAGEMENT_IDENTITY_CLIENT_ID=$(echo "$output" | jq -r '.properties.outputs.accountManagementIdentityClientId.value')
115+
ACCOUNT_MANAGEMENT_IDENTITY_CLIENT_ID=$(echo "$cleaned_output" | jq -r '.properties.outputs.accountManagementIdentityClientId.value')
114116
if [[ -n "$GITHUB_OUTPUT" ]]; then
115117
echo "ACCOUNT_MANAGEMENT_IDENTITY_CLIENT_ID=$ACCOUNT_MANAGEMENT_IDENTITY_CLIENT_ID" >> $GITHUB_OUTPUT
116118
else

cloud-infrastructure/cluster/main-cluster.bicep

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ var subnetId = resourceId(
4343

4444
module diagnosticStorageAccount '../modules/storage-account.bicep' = {
4545
scope: clusterResourceGroup
46-
name: 'diagnostic-storage-account'
46+
name: '${clusterUniqueName}-diagnostic-storage-account'
4747
params: {
4848
location: location
4949
name: diagnosticStorageAccountName
@@ -54,7 +54,7 @@ module diagnosticStorageAccount '../modules/storage-account.bicep' = {
5454

5555
module virtualNetwork '../modules/virtual-network.bicep' = {
5656
scope: clusterResourceGroup
57-
name: 'virtual-network'
57+
name: '${clusterUniqueName}-virtual-network'
5858
params: {
5959
location: location
6060
name: virtualNetworkName
@@ -64,7 +64,7 @@ module virtualNetwork '../modules/virtual-network.bicep' = {
6464

6565
module containerAppsEnvironment '../modules/container-apps-environment.bicep' = {
6666
scope: clusterResourceGroup
67-
name: 'container-apps-environment'
67+
name: '${clusterUniqueName}-container-apps-environment'
6868
params: {
6969
location: location
7070
name: '${locationPrefix}-container-apps-environment'
@@ -76,7 +76,7 @@ module containerAppsEnvironment '../modules/container-apps-environment.bicep' =
7676

7777
module microsoftSqlServer '../modules/microsoft-sql-server.bicep' = {
7878
scope: clusterResourceGroup
79-
name: 'microsoft-sql-server'
79+
name: '${clusterUniqueName}-microsoft-sql-server'
8080
params: {
8181
location: location
8282
name: clusterUniqueName
@@ -90,7 +90,7 @@ module microsoftSqlServer '../modules/microsoft-sql-server.bicep' = {
9090

9191
module microsoftSqlDerverDiagnosticConfiguration '../modules/microsoft-sql-server-diagnostic.bicep' = {
9292
scope: clusterResourceGroup
93-
name: 'microsoft-sql-server-diagnostic'
93+
name: '${clusterUniqueName}-microsoft-sql-server-diagnostic'
9494
params: {
9595
diagnosticStorageAccountName: diagnosticStorageAccountName
9696
microsoftSqlServerName: clusterUniqueName
@@ -103,7 +103,7 @@ module microsoftSqlDerverDiagnosticConfiguration '../modules/microsoft-sql-serve
103103
module microsoftSqlServerElasticPool '../modules/microsoft-sql-server-elastic-pool.bicep' =
104104
if (useMssqlElasticPool) {
105105
scope: clusterResourceGroup
106-
name: 'microsoft-sql-server-elastic-pool'
106+
name: '${clusterUniqueName}-microsoft-sql-server-elastic-pool'
107107
params: {
108108
location: location
109109
name: '${locationPrefix}-microsoft-sql-server-elastic-pool'
@@ -118,7 +118,7 @@ module microsoftSqlServerElasticPool '../modules/microsoft-sql-server-elastic-po
118118

119119
module communicationService '../modules/communication-services.bicep' = {
120120
scope: clusterResourceGroup
121-
name: 'communication-services'
121+
name: '${clusterUniqueName}-communication-services'
122122
params: {
123123
name: clusterUniqueName
124124
tags: tags
@@ -130,7 +130,7 @@ module communicationService '../modules/communication-services.bicep' = {
130130

131131
module keyVault '../modules/key-vault.bicep' = {
132132
scope: clusterResourceGroup
133-
name: 'key-vault'
133+
name: '${clusterUniqueName}-key-vault'
134134
params: {
135135
location: location
136136
name: clusterUniqueName
@@ -153,7 +153,7 @@ var cdnUrl = publicUrl
153153

154154
var accountManagementIdentityName = 'account-management-${resourceGroupName}'
155155
module accountManagementIdentity '../modules/user-assigned-managed-identity.bicep' = {
156-
name: 'account-management-managed-identity'
156+
name: '${clusterUniqueName}-account-management-managed-identity'
157157
scope: clusterResourceGroup
158158
params: {
159159
name: accountManagementIdentityName
@@ -165,7 +165,7 @@ module accountManagementIdentity '../modules/user-assigned-managed-identity.bice
165165
}
166166

167167
module accountManagementDatabase '../modules/microsoft-sql-database.bicep' = {
168-
name: 'account-management-database'
168+
name: '${clusterUniqueName}-account-management-database'
169169
scope: clusterResourceGroup
170170
params: {
171171
sqlServerName: clusterUniqueName
@@ -179,7 +179,7 @@ module accountManagementDatabase '../modules/microsoft-sql-database.bicep' = {
179179
var accountManagementStorageAccountName = '${clusterUniqueName}acctmgmt'
180180
module accountManagementStorageAccount '../modules/storage-account.bicep' = {
181181
scope: clusterResourceGroup
182-
name: 'account-management-storage-account'
182+
name: '${clusterUniqueName}-account-management-storage-account'
183183
params: {
184184
location: location
185185
name: accountManagementStorageAccountName
@@ -232,7 +232,7 @@ var accountManagementEnvironmentVariables = [
232232
]
233233

234234
module accountManagementWorkers '../modules/container-app.bicep' = {
235-
name: 'account-management-workers-container-app'
235+
name: '${clusterUniqueName}-account-management-workers-container-app'
236236
scope: clusterResourceGroup
237237
params: {
238238
name: 'account-management-workers'
@@ -256,7 +256,7 @@ module accountManagementWorkers '../modules/container-app.bicep' = {
256256
}
257257

258258
module accountManagementApi '../modules/container-app.bicep' = {
259-
name: 'account-management-api-container-app'
259+
name: '${clusterUniqueName}-account-management-api-container-app'
260260
scope: clusterResourceGroup
261261
params: {
262262
name: 'account-management-api'
@@ -284,7 +284,7 @@ module accountManagementApi '../modules/container-app.bicep' = {
284284

285285
var backOfficeIdentityName = 'back-office-${resourceGroupName}'
286286
module backOfficeIdentity '../modules/user-assigned-managed-identity.bicep' = {
287-
name: 'back-office-managed-identity'
287+
name: '${clusterUniqueName}-back-office-managed-identity'
288288
scope: clusterResourceGroup
289289
params: {
290290
name: backOfficeIdentityName
@@ -296,7 +296,7 @@ module backOfficeIdentity '../modules/user-assigned-managed-identity.bicep' = {
296296
}
297297

298298
module backOfficeDatabase '../modules/microsoft-sql-database.bicep' = {
299-
name: 'back-office-database'
299+
name: '${clusterUniqueName}-back-office-database'
300300
scope: clusterResourceGroup
301301
params: {
302302
sqlServerName: clusterUniqueName
@@ -310,7 +310,7 @@ module backOfficeDatabase '../modules/microsoft-sql-database.bicep' = {
310310
var backOfficeStorageAccountName = '${clusterUniqueName}backoffice'
311311
module backOfficeStorageAccount '../modules/storage-account.bicep' = {
312312
scope: clusterResourceGroup
313-
name: 'back-office-storage-account'
313+
name: '${clusterUniqueName}-back-office-storage-account'
314314
params: {
315315
location: location
316316
name: backOfficeStorageAccountName
@@ -357,7 +357,7 @@ var backOfficeEnvironmentVariables = [
357357
]
358358

359359
module backOfficeWorkers '../modules/container-app.bicep' = {
360-
name: 'back-office-workers-container-app'
360+
name: '${clusterUniqueName}-back-office-workers-container-app'
361361
scope: clusterResourceGroup
362362
params: {
363363
name: 'back-office-workers'
@@ -381,7 +381,7 @@ module backOfficeWorkers '../modules/container-app.bicep' = {
381381
}
382382

383383
module backOfficeApi '../modules/container-app.bicep' = {
384-
name: 'back-office-api-container-app'
384+
name: '${clusterUniqueName}-back-office-api-container-app'
385385
scope: clusterResourceGroup
386386
params: {
387387
name: 'back-office-api'
@@ -408,7 +408,7 @@ module backOfficeApi '../modules/container-app.bicep' = {
408408

409409
var appGatewayIdentityName = 'app-gateway-${resourceGroupName}'
410410
module mainAppIdentity '../modules/user-assigned-managed-identity.bicep' = {
411-
name: 'app-gateway-managed-identity'
411+
name: '${clusterUniqueName}-app-gateway-managed-identity'
412412
scope: clusterResourceGroup
413413
params: {
414414
name: appGatewayIdentityName
@@ -421,7 +421,7 @@ module mainAppIdentity '../modules/user-assigned-managed-identity.bicep' = {
421421

422422
var appGatewayContainerAppName = 'app-gateway'
423423
module appGateway '../modules/container-app.bicep' = {
424-
name: 'app-gateway-container-app'
424+
name: '${clusterUniqueName}-app-gateway-container-app'
425425
scope: clusterResourceGroup
426426
params: {
427427
name: appGatewayContainerAppName
@@ -474,7 +474,7 @@ module appGateway '../modules/container-app.bicep' = {
474474

475475
module appGatwayAccountManagementStorageBlobDataReaderRoleAssignment '../modules/role-assignments-storage-blob-data-reader.bicep' = {
476476
scope: clusterResourceGroup
477-
name: '${appGatewayContainerAppName}-blob-reader-role-assignment'
477+
name: '${clusterUniqueName}-${appGatewayContainerAppName}-blob-reader'
478478
params: {
479479
storageAccountName: accountManagementStorageAccountName
480480
userAssignedIdentityName: appGatewayIdentityName

cloud-infrastructure/environment/deploy-environment.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ DEPLOYMENT_PARAMETERS="-l $LOCATION -n "$CURRENT_DATE-$ENVIRONMENT" --output tab
77
cd "$(dirname "${BASH_SOURCE[0]}")"
88
. ../deploy.sh
99

10-
if [[ $output == "ERROR:"* ]]; then
10+
cleaned_output=$(echo "$output" | sed '/^WARNING/d')
11+
if [[ $cleaned_output == "ERROR:"* ]]; then
1112
echo -e "${RED}$output"
1213
exit 1
1314
fi

cloud-infrastructure/environment/main-environment.bicep

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ resource monitorResourceGroup 'Microsoft.Resources/resourceGroups@2023-07-01' =
1313
}
1414

1515
module logAnalyticsWorkspace '../modules/log-analytics-workspace.bicep' = {
16-
name: 'log-analytics-workspace'
16+
name: '${resourceGroupName}-log-analytics-workspace'
1717
scope: resourceGroup(monitorResourceGroup.name)
1818
params: {
1919
name: '${environment}-log-analytics-workspace'
@@ -23,7 +23,7 @@ module logAnalyticsWorkspace '../modules/log-analytics-workspace.bicep' = {
2323
}
2424

2525
module applicationInsights '../modules/application-insights.bicep' = {
26-
name: 'application-insights'
26+
name: '${resourceGroupName}-application-insights'
2727
scope: resourceGroup(monitorResourceGroup.name)
2828
params: {
2929
name: '${environment}-application-insights'

cloud-infrastructure/modules/application-insights.bicep

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ resource applicationInsights 'Microsoft.Insights/components@2020-02-02' = {
2525
}
2626

2727
resource applicationInsightsSmartDetection 'Microsoft.Insights/actionGroups@2023-01-01' = {
28-
name: 'Application Insights Smart Detection'
28+
name: '${name}-smart-detection'
2929
location: 'Global'
3030
tags: tags
3131
properties: {

cloud-infrastructure/modules/container-app.bicep

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ resource containerAppsEnvironment 'Microsoft.App/managedEnvironments@2023-05-02-
3434

3535
module newManagedCertificate './managed-certificate.bicep' =
3636
if (isCustomDomainSet) {
37-
name: certificateName
37+
name: '${resourceGroupName}-${name}-managed-certificate'
3838
scope: resourceGroup(resourceGroupName)
3939
dependsOn: [containerApp]
4040
params: {

cloud-infrastructure/modules/microsoft-sql-server-diagnostic.bicep

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ param dianosticStorageAccountSubscriptionId string
55
param dianosticStorageAccountBlobEndpoint string
66

77
module diagnosticStorageBlobDataContributorRoleAssignment 'role-assignments-storage-blob-data-contributor.bicep' = if (principalId != '') {
8-
name: '${microsoftSqlServerName}-sql-server-blob-contributer-role-assignment'
8+
name: '${microsoftSqlServerName}-sql-server-blob-contributer'
99
params: {
1010
storageAccountName: diagnosticStorageAccountName
1111
principalId: principalId

cloud-infrastructure/modules/storage-account.bicep

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ resource blobContainers 'Microsoft.Storage/storageAccounts/blobServices/containe
5555
}]
5656

5757
module storageBlobDataContributorRoleAssignment 'role-assignments-storage-blob-data-contributor.bicep' = if (userAssignedIdentityName != '') {
58-
name: '${name}-blob-contributer-role-assignment'
58+
name: '${name}-blob-contributer'
5959
params: {
6060
storageAccountName: name
6161
userAssignedIdentityName: userAssignedIdentityName

cloud-infrastructure/modules/user-assigned-managed-identity.bicep

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,14 @@ resource userAssignedIdentity 'Microsoft.ManagedIdentity/userAssignedIdentities@
1212

1313
var containerRegistryResourceGroupName = 'shared'
1414
module containerRegistryPermission './role-assignments-container-registry-acr-pull.bicep' = {
15-
name: 'container-registry-permission'
15+
name: '${name}-permission'
1616
scope: resourceGroup(subscription().subscriptionId, containerRegistryResourceGroupName)
1717
params: {
1818
containerRegistryName: containerRegistryName
1919
principalId: userAssignedIdentity.properties.principalId
2020
}
2121
}
2222

23-
2423
resource keyVault 'Microsoft.KeyVault/vaults@2021-10-01' existing = {
2524
name: keyVaultName
2625
}
@@ -31,6 +30,7 @@ resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
3130
scope: keyVault
3231
properties: {
3332
roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', keyVaultSecretsUserRoleDefinitionId)
33+
principalType: 'ServicePrincipal'
3434
principalId: userAssignedIdentity.properties.principalId
3535
}
3636
}

cloud-infrastructure/shared/deploy-shared.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ DEPLOYMENT_PARAMETERS="-l $LOCATION -n "$CURRENT_DATE-$RESOURCE_GROUP_NAME" --ou
2020
cd "$(dirname "${BASH_SOURCE[0]}")"
2121
. ../deploy.sh
2222

23-
if [[ $output == "ERROR:"* ]]; then
23+
cleaned_output=$(echo "$output" | sed '/^WARNING/d')
24+
if [[ $cleaned_output == "ERROR:"* ]]; then
2425
echo -e "${RED}$output"
2526
exit 1
2627
fi

cloud-infrastructure/shared/main-shared.bicep

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ resource sharedResourceGroup 'Microsoft.Resources/resourceGroups@2023-07-01' = {
1414
}
1515

1616
module containerRegistry '../modules/container-registry.bicep' = {
17-
name: 'container-registry'
17+
name: '${resourceGroupName}-${containerRegistryName}-container-registry'
1818
scope: resourceGroup(sharedResourceGroup.name)
1919
params: {
2020
name: containerRegistryName

0 commit comments

Comments
 (0)