I have a bicep template that specifies a SQL Server resource. I’ve already deployed this template (in Incremental mode) and the SQL Server resource exists.
When I now run az deployment group what-if --mode Complete
, the report states
that the SQL Server resource will be deleted.
I’ve checked that the compiled ARM template generated by az bicep build
still includes the
resource, and it does.
The SQL Server resource is specified in a bicep module used by a main bicep template. If I move the resource into the main bicep template and run what-if
, the report does not say the SQL Server will be deleted. I see the same behavior with the databases in modules/database.bicep
.
The main azuredeploy.bicep
contains:
var sqlServerName = 'mySqlServer'
var storageAccountName = 'myStorageAccount'
resource storageAccount 'Microsoft.Storage/storageAccounts@2021-09-01' = {
name: storageAccountName
location: resourceGroup().location
kind: 'StorageV2'
sku: {
name: 'Standard_LRS'
}
}
module sqlServer 'modules/sql-server.bicep' = {
name: 'sqlserver'
params: {
sqlServerName: sqlServerName
storageAccountKey: storageAccount.listKeys().keys[0].value
}
}
And modules/sql-server.bicep
contains:
param sqlServerName string
@secure()
param storageAccountKey string
resource sqlServer 'Microsoft.Sql/servers@2022-02-01-preview' = {
name: sqlServerName
location: resourceGroup.location()
}
resource sqlServerAuditSettings 'Microsoft.Sql/servers/auditingSettings@2022-02-01-preview' = {
name: 'default'
parent: sqlServer
properties: {
state: 'Enabled'
storageAccountAccessKey: storageAccountKey
}
}
What could possibly be going on here? I understand that bicep modules are not purely organizational and actually create separate resource deployments, but it’s not clear to me that should affect Complete deployments, particularly if I just created that resource.
2
Answers
I was able to resolve this. There is a long-standing issue with the "what-if" tool (GitHub issue here) itself that causes it to prune sub-deployments if they are passed parameters which reference other resources. In my case, I was passing in
storageAccountKey
as a secure parameter (which ARM requires it to be), which gets compiled to[listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('storageAccountName')), '2021-09-01').keys[0].value]
.My workaround is to instead reference the storage account as an existing resource inside the module, and get the key from there:
It looks like the issue is tied to how Azure handles deployments in Complete mode when using Bicep modules. When you use Complete mode, Azure compares the current state of the resource group with the template and removes resources that are not explicitly defined in the current deployment scope. Since Bicep modules create their own deployment scopes, the SQL Server resource defined in
modules/sql-server.bicep
is treated as part of a separate deployment.In your case, the
sqlServer
resource in the module might not be recognized as part of the main template’s Complete deployment because the module’s deployment scope isn’t explicitly linked to the main template. When you move the resource directly into the main template, it becomes part of the main deployment scope, which resolves the issue.To fix this without moving the resource into the main template, you can ensure that the deployment in Complete mode references all the resources in the module. This can be done by adding a reference to the module’s deployment output in the main template or by rethinking how you structure your modules and deployments.
The core of the problem lies in how Complete mode evaluates resources across different scopes. If Azure doesn’t see a resource in the current deployment scope, it assumes that resource should be deleted, even if it exists in a module. You could consider using Incremental mode unless you have a specific reason for requiring Complete mode.