There are multiple Infrastructure as Code
languages (Terraform, Pulumi, Bicep, ARM).
Depending on the language used, there is a specific way of holding the state of resources from a deployment:
The state has always been a weakness of Bicep and ARM. The lifecycle of the resources where difficult to track, you could implement workarounds with what-if operations always an additional step to take before a deployment.
Microsoft recently announced a public preview of ARM Deployment Stacks to tackle this. To me this was the missing element in order to use Bicep or ARM templates.
Official documentation can be found over here
Bicep or ARM template files can be submitted to a Deployment Stack, the Deployment Stacks basically define the resources that are managed by the stack.
Deployment Stacks can be created at the following scopes:
Creating/Update Deployment Stacks PowerShell & CLI commands:
Note: You can Block Unwanted Changes by setting a
DenySettingsMode
on the Deployment Stack (None, DenyDelete, DenyWriteAndDelete)
Delete Deployment Stacks PowerShell & CLI commands:
Note: A Cleanup can be done after removal of a Deployment Stack (Resources or/and Resource Groups), this is optional flag by default Resources or/and Resource Groups are detached from a Deployment Stack. Possible
flags
for Deployment Stack deletion: (DeleteAll, DeleteResourceGroups ,DeleteResources).
In this example, the template will deploy:
The Deployment Stack will be scoped at subscription level.
bicepdemo1.bicep
targetScope = 'subscription'
// **Parameters**
// Generic Parameters - Used in multiple modules
param parLocation string
param parLocationAbbrevation string
param parEnvironment string
param parPurpose string
resource resResourceGroup 'Microsoft.Resources/resourceGroups@2022-09-01' = {
name: 'rg-${parLocationAbbrevation}-${parEnvironment}-${parPurpose}'
location: parLocation
}
// module dynamic windows function app
module modFunctionAppWindowsConsumption '../../modules/functionAppWindowsConsumption/functionAppWindowsConsumption.bicep' = {
name: 'deploy-fun-${parLocationAbbrevation}-${parEnvironment}-${parPurpose}'
scope: resourceGroup(resResourceGroup.name)
params: {
functionAppName: 'fun-${parLocationAbbrevation}-${parEnvironment}-${parPurpose}'
functionWorkerRuntime: 'dotnet'
location: parLocation
storageAccountName: 'st${parLocationAbbrevation}${parEnvironment}${parPurpose}'
storageAccountType: 'Standard_LRS'
applicationInsightsName: 'appi-${parLocationAbbrevation}-${parEnvironment}-${parPurpose}'
hostingPlanName: 'asp-${parLocationAbbrevation}-${parEnvironment}-${parPurpose}'
}
}
tst-bicepdemo1.bicepparam
using '../bicepdemo1.bicep'
param parLocation = 'westeurope'
param parLocationAbbrevation = 'weu'
param parEnvironment = 'tst'
param parPurpose = 'bicepdemo1'
New-Deploymentstack.ps1
$inputObject = @{
Name = "stack-weu-tst-bicepdemo1"
TemplateFile = "infra-as-code/bicep/orchestration/bicepdemo1/bicepdemo1.bicep"
TemplateParameterFile = "infra-as-code/bicep/orchestration/bicepdemo1/parameters/tst-bicepdemo1.bicepparam"
DenySettingsMode = "DenyWriteAndDelete"
Location = "westeurope"
}
New-AzSubscriptionDeploymentStack @inputObject -Force
Ar subscription level, the Deployment Stack will become visible:
In the deployed Deployment Stack, the details will be displayed:
Note: The
Deny status
for all Resource Groups and Resources of the Deployment Stack are set todenyWriteAndDelete
, the Deployment Stack will block all write and delete actions on the Resource Group or Resources controlled by the Deployment Stack.
Deny assignments:
In an attemnt of deleting a storage account controlled by the Deployment Stack, will result as a deny
because of the deny assignment
created by Deployment Stack:
To update a Deployment Stack (update controlled Resource Group, Resources or update DenySettingsMode), you can use the following script.
Note: In this example the
DenySettingMode
is set toNone
Set-Deploymentstack.ps1
$inputObject = @{
Name = "stack-weu-tst-bicepdemo1"
TemplateFile = "infra-as-code/bicep/orchestration/bicepdemo1/bicepdemo1.bicep"
TemplateParameterFile = "infra-as-code/bicep/orchestration/bicepdemo1/parameters/tst-bicepdemo1.bicepparam"
DenySettingsMode = "None"
Location = "westeurope"
}
Set-AzSubscriptionDeploymentStack @inputObject -Force
The Deny status
for the resources were updated:
Also visible in the Deny assignments
blade:
To delete a Deployment Stack and delete the resource groups and resources you can use the following script.
Remove-Deploymentstack.ps1
Remove-AzSubscriptionDeploymentStack `
-name "stack-weu-tst-bicepdemo1" `
-DeleteAll `
-Force
Note: The removal of Deployment Stacks support the following options:
Detach: Detach resources and resource groups (Default)
DeleteAll: Delete both the resources and the resource groups
DeleteResourceGroups: Delete the resource groups only
DeleteResources: Delete resources only