Quickstart: Create and deploy a deployment stack with Bicep from template specs

This quickstart describes how to create a deployment stack from a template spec.

Prerequisites

Create a Bicep file

Create a Bicep file to create a storage account and a virtual network.

param resourceGroupLocation string = resourceGroup().location
param storageAccountName string = 'store${uniqueString(resourceGroup().id)}'
param vnetName string = 'vnet${uniqueString(resourceGroup().id)}'

resource storageAccount 'Microsoft.Storage/storageAccounts@2023-04-01' = {
  name: storageAccountName
  location: resourceGroupLocation
  kind: 'StorageV2'
  sku: {
    name: 'Standard_LRS'
  }
}

resource virtualNetwork 'Microsoft.Network/virtualNetworks@2023-11-01' = {
  name: vnetName
  location: resourceGroupLocation
  properties: {
    addressSpace: {
      addressPrefixes: [
        '10.0.0.0/16'
      ]
    }
    subnets: [
      {
        name: 'Subnet-1'
        properties: {
          addressPrefix: '10.0.0.0/24'
        }
      }
      {
        name: 'Subnet-2'
        properties: {
          addressPrefix: '10.0.1.0/24'
        }
      }
    ]
  }
}

Save the Bicep file as main.bicep.

Create template spec

Create a template spec with the following command.

az group create \
  --name 'templateSpecRG' \
  --location 'centralus'

az ts create \
  --name 'stackSpec' \
  --version '1.0' \
  --resource-group 'templateSpecRG' \
  --location 'centralus' \
  --template-file 'main.bicep'

The format of the template spec ID is /subscriptions/<subscription-id>/resourceGroups/templateSpecRG/providers/Microsoft.Resources/templateSpecs/stackSpec/versions/1.0.

Create a deployment stack

Create a deployment stack from the template spec.

az group create \
  --name 'demoRg' \
  --location 'centralus'

id=$(az ts show --name 'stackSpec' --resource-group 'templateSpecRG' --version '1.0' --query 'id')

az stack group create \
  --name demoStack \
  --resource-group 'demoRg' \
  --template-spec $id \
  --action-on-unmanage 'detachAll' \
  --deny-settings-mode 'none'

For more information about action-on-unmanage and deny-setting-mode, see Deployment stacks.

Verify the deployment

To list the deployed deployment stacks at the subscription level:

az stack group show \
  --resource-group 'demoRg' \
  --name 'demoStack'

The output shows two managed resources - one storage account and one virtual network:

{
  "actionOnUnmanage": {
    "managementGroups": "detach",
    "resourceGroups": "detach",
    "resources": "detach"
  },
  "debugSetting": null,
  "deletedResources": [],
  "denySettings": {
    "applyToChildScopes": false,
    "excludedActions": null,
    "excludedPrincipals": null,
    "mode": "none"
  },
  "deploymentId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/demoRg/providers/Microsoft.Resources/deployments/demoStack-240517162aqmf",
  "deploymentScope": null,
  "description": null,
  "detachedResources": [],
  "duration": "PT30.5642429S",
  "error": null,
  "failedResources": [],
  "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/demoRg/providers/Microsoft.Resources/deploymentStacks/demoStack",
  "location": null,
  "name": "demoStack",
  "outputs": null,
  "parameters": {},
  "parametersLink": null,
  "provisioningState": "succeeded",
  "resourceGroup": "demoRg",
  "resources": [
    {
      "denyStatus": "none",
      "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/demoRg/providers/Microsoft.Network/virtualNetworks/vnetthmimleef5fwk",
      "resourceGroup": "demoRg",
      "status": "managed"
    },
    {
      "denyStatus": "none",
      "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/demoRg/providers/Microsoft.Storage/storageAccounts/storethmimleef5fwk",
      "resourceGroup": "demoRg",
      "status": "managed"
    }
  ],
  "systemData": {
    "createdAt": "2024-05-17T16:07:51.172012+00:00",
    "createdBy": "johndoe@contoso.com",
    "createdByType": "User",
    "lastModifiedAt": "2024-05-17T16:07:51.172012+00:00",
    "lastModifiedBy": "johndoe@contoso.com",
    "lastModifiedByType": "User"
  },
  "tags": {},
  "template": null,
  "templateLink": {
    "contentVersion": null,
    "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/templateSpecRG/providers/Microsoft.Resources/templateSpecs/stackSpec/versions/1.0",
    "queryString": null,
    "relativePath": null,
    "resourceGroup": "templateSpecRG",
    "uri": null
  },
  "type": "Microsoft.Resources/deploymentStacks"
}

You can also verify the deployment by list the managed resources in the deployment stack:

az stack group show \
  --name 'demoStack' \
  --resource-group 'demoRg' \
  --output 'json'

The output is similar to:

{
  "actionOnUnmanage": {
    "managementGroups": "detach",
    "resourceGroups": "detach",
    "resources": "detach"
  },
  "debugSetting": null,
  "deletedResources": [],
  "denySettings": {
    "applyToChildScopes": false,
    "excludedActions": null,
    "excludedPrincipals": null,
    "mode": "none"
  },
  "deploymentId": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/demoRg/providers/Microsoft.Resources/deployments/demoStack-240517162aqmf",
  "deploymentScope": null,
  "description": null,
  "detachedResources": [],
  "duration": "PT30.5642429S",
  "error": null,
  "failedResources": [],
  "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/demoRg/providers/Microsoft.Resources/deploymentStacks/demoStack",
  "location": null,
  "name": "demoStack",
  "outputs": null,
  "parameters": {},
  "parametersLink": null,
  "provisioningState": "succeeded",
  "resourceGroup": "demoRg",
  "resources": [
    {
      "denyStatus": "none",
      "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/demoRg/providers/Microsoft.Network/virtualNetworks/vnetthmimleef5fwk",
      "resourceGroup": "demoRg",
      "status": "managed"
    },
    {
      "denyStatus": "none",
      "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/demoRg/providers/Microsoft.Storage/storageAccounts/storethmimleef5fwk",
      "resourceGroup": "demoRg",
      "status": "managed"
    }
  ],
  "systemData": {
    "createdAt": "2024-05-17T16:07:51.172012+00:00",
    "createdBy": "johndoe@contoso.com",
    "createdByType": "User",
    "lastModifiedAt": "2024-05-17T16:07:51.172012+00:00",
    "lastModifiedBy": "johndoe@contoso.com",
    "lastModifiedByType": "User"
  },
  "tags": {},
  "template": null,
  "templateLink": {
    "contentVersion": null,
    "id": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/templateSpecRG/providers/Microsoft.Resources/templateSpecs/stackSpec/versions/1.0",
    "queryString": null,
    "relativePath": null,
    "resourceGroup": "templateSpecRG",
    "uri": null
  },
  "type": "Microsoft.Resources/deploymentStacks"
}

Delete the deployment stack

To delete the deployment stack, and the managed resources:

az stack group delete \
  --name 'demoStack' \
  --resource-group 'demoRg' \
  --action-on-unmanage 'deleteAll' 

To delete the deployment stack, but detach the managed resources. For example:

az stack group delete \
  --name 'demoStack' \
  --resource-group 'demoRg' \
  --action-on-unmanage 'detachAll' 

For more information, see Delete deployment stacks.

Clean up resources

The remove command only remove the managed resources and managed resource groups. You still need to delete the resource group.

az group delete \
  --name 'demoRg'

To delete the template spec and the resource group:

az group delete \
  --name 'templateSpecRG'

Next steps