Quickstart: Create and deploy template spec
Article 04/01/2024
8 contributors
Feedback
In this article
This quickstart shows you how to package an Azure Resource Manager template (ARM template) into a template spec . Then, you deploy that template spec. Your template spec contains an ARM template that deploys a storage account.
Prerequisites
An Azure account with an active subscription. Create an account .
Create template
You create a template spec from a local template. Copy the following template and save it locally to a file named azuredeploy.json . This quickstart assumes you've saved to a path c:\Templates\azuredeploy.json but you can use any path.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"metadata": {
"_generator": {
"name": "bicep",
"version": "0.13.1.58284",
"templateHash": "13120038605368246703"
}
},
"parameters": {
"storageAccountType": {
"type": "string",
"defaultValue": "Standard_LRS",
"allowedValues": [
"Standard_LRS",
"Standard_GRS",
"Premium_LRS"
],
"metadata": {
"description": "Storage Account type"
}
},
"location": {
"type": "string",
"defaultValue": "[resourceGroup().location]",
"metadata": {
"description": "The storage account location."
}
},
"storageAccountName": {
"type": "string",
"defaultValue": "[format('store{0}', uniqueString(resourceGroup().id))]",
"metadata": {
"description": "The name of the storage account"
}
}
},
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2022-09-01",
"name": "[parameters('storageAccountName')]",
"location": "[parameters('location')]",
"sku": {
"name": "[parameters('storageAccountType')]"
},
"kind": "StorageV2",
"properties": {}
}
],
"outputs": {
"storageAccountName": {
"type": "string",
"value": "[parameters('storageAccountName')]"
},
"storageAccountId": {
"type": "string",
"value": "[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName'))]"
}
}
}
Create template spec
The template spec is a resource type named Microsoft.Resources/templateSpecs
. To create a template spec, use PowerShell, Azure CLI, the portal, or an ARM template.
Create a new resource group to contain the template spec.
New-AzResourceGroup `
-Name templateSpecRG `
-Location chinanorth2
Create the template spec in that resource group. Give the new template spec the name storageSpec .
New-AzTemplateSpec `
-Name storageSpec `
-Version "1.0" `
-ResourceGroupName templateSpecRG `
-Location chinanorth2 `
-TemplateFile "c:\Templates\azuredeploy.json"
Create a new resource group to contain the template spec.
az group create \
--name templateSpecRG \
--location chinanorth2
Create the template spec in that resource group. Give the new template spec the name storageSpec .
az ts create \
--name storageSpec \
--version "1.0" \
--resource-group templateSpecRG \
--location "chinanorth2" \
--template-file "c:\Templates\azuredeploy.json"
Sign in to the Azure portal .
Search for template specs . Select Template specs from the available options.
Select Import template .
Select the folder icon.
Navigate to the local template you saved and select it. Select Open .
Select Import .
Provide the following values:
Name : enter a name for the template spec. For example, storageSpec
Subscription : select an Azure subscription used for creating the template spec.
Resource Group : select Create new , and then enter a new resource group name. For example, templateSpecRG .
Location : select a location for the resource group. For example, China North 2 .
Version : enter a version for the template spec. Use 1.0 .
Select Review + Create .
Select Create .
Note
Instead of using an ARM template, we recommend that you use PowerShell or CLI to create your template spec. Those tools automatically convert linked templates to artifacts connected to your main template. When you use an ARM template to create the template spec, you must manually add those linked templates as artifacts, which can be complicated.
When you use an ARM template to create the template spec, the template is embedded in the resource definition. There are some changes you need to make to your local template. Copy the following template and save it locally as azuredeploy.json .
Note
In the embedded template, all template expressions must be escaped with a second left bracket. Use "[[
instead of "[
. JSON arrays still use a single left bracket.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {},
"functions": [],
"variables": {},
"resources": [
{
"type": "Microsoft.Resources/templateSpecs",
"apiVersion": "2021-05-01",
"name": "storageSpec",
"location": "chinanorth2",
"properties": {
"displayName": "Storage template spec"
},
"tags": {},
"resources": [
{
"type": "versions",
"apiVersion": "2021-05-01",
"name": "1.0",
"location": "chinanorth2",
"dependsOn": [ "storageSpec" ],
"properties": {
"mainTemplate": {
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"storageAccountType": {
"type": "string",
"defaultValue": "Standard_LRS",
"allowedValues": [
"Standard_LRS",
"Standard_GRS",
"Premium_LRS"
],
"metadata": {
"description": "Storage Account type"
}
},
"location": {
"type": "string",
"defaultValue": "[[resourceGroup().location]",
"metadata": {
"description": "Location for all resources."
}
}
},
"variables": {
"storageAccountName": "[[concat('store', uniquestring(resourceGroup().id))]"
},
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2022-09-01",
"name": "[[variables('storageAccountName')]",
"location": "[[parameters('location')]",
"sku": {
"name": "[[parameters('storageAccountType')]"
},
"kind": "StorageV2",
"properties": {}
}
],
"outputs": {
"storageAccountName": {
"type": "string",
"value": "[[variables('storageAccountName')]"
}
}
}
},
"tags": {}
}
]
}
],
"outputs": {}
}
Use Azure CLI or PowerShell to create a new resource group.
New-AzResourceGroup `
-Name templateSpecRG `
-Location chinanorth2
az group create \
--name templateSpecRG \
--location chinanorth2
Deploy your template with Azure CLI or PowerShell.
New-AzResourceGroupDeployment `
-ResourceGroupName templateSpecRG `
-TemplateFile "c:\Templates\azuredeploy.json"
az deployment group create \
--resource-group templateSpecRG \
--template-file "c:\Templates\azuredeploy.json"
Deploy template spec
To deploy a template spec, use the same deployment commands as you would use to deploy a template. Pass in the resource ID of the template spec to deploy.
Create a resource group to contain the new storage account.
New-AzResourceGroup `
-Name storageRG `
-Location chinanorth2
Get the resource ID of the template spec.
$id = (Get-AzTemplateSpec -ResourceGroupName templateSpecRG -Name storageSpec -Version "1.0").Versions.Id
Deploy the template spec.
New-AzResourceGroupDeployment `
-TemplateSpecId $id `
-ResourceGroupName storageRG
You provide parameters exactly as you would for an ARM template. Redeploy the template spec with a parameter for the storage account type.
New-AzResourceGroupDeployment `
-TemplateSpecId $id `
-ResourceGroupName storageRG `
-storageAccountType Standard_GRS
Create a resource group to contain the new storage account.
az group create \
--name storageRG \
--location chinanorth2
Get the resource ID of the template spec.
id=$(az ts show --name storageSpec --resource-group templateSpecRG --version "1.0" --query "id")
Note
There is a known issue with getting a template spec ID and assigning it to a variable in Windows PowerShell.
Deploy the template spec.
az deployment group create \
--resource-group storageRG \
--template-spec $id
You provide parameters exactly as you would for an ARM template. Redeploy the template spec with a parameter for the storage account type.
az deployment group create \
--resource-group storageRG \
--template-spec $id \
--parameters storageAccountType='Standard_GRS'
Select the template spec you created.
Select Deploy .
Provide the following values:
Subscription : select an Azure subscription for creating the resource.
Resource group : select Create new and then enter storageRG .
Storage Account Type : select Standard_GRS .
Select Review + create .
Select Create .
Copy the following template and save it locally to a file named storage.json .
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {},
"functions": [],
"variables": {},
"resources": [
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2021-04-01",
"name": "demo",
"properties": {
"templateLink": {
"id": "[resourceId('templateSpecRG', 'Microsoft.Resources/templateSpecs/versions', 'storageSpec', '1.0')]"
},
"parameters": {
},
"mode": "Incremental"
}
}
],
"outputs": {}
}
Use Azure CLI or PowerShell to create a new resource group for the storage account.
New-AzResourceGroup `
-Name storageRG `
-Location chinanorth2
az group create \
--name storageRG \
--location chinanorth2
Deploy your template with Azure CLI or PowerShell.
New-AzResourceGroupDeployment `
-ResourceGroupName storageRG `
-TemplateFile "c:\Templates\storage.json"
az deployment group create \
--resource-group storageRG \
--template-file "c:\Templates\storage.json"
Grant access
If you want to let other users in your organization deploy your template spec, you need to grant them read access. You can assign the Reader role to a Microsoft Entra group for the resource group that contains template specs you want to share. For more information, see Tutorial: Grant a group access to Azure resources using Azure PowerShell .
Update template
Let's suppose you've identified a change you want to make to the template in your template spec. The following template is similar to your earlier template except it adds a prefix for the storage account name. Copy the following template and update your azuredeploy.json file.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"storageAccountType": {
"type": "string",
"defaultValue": "Standard_LRS",
"allowedValues": [
"Standard_LRS",
"Standard_GRS",
"Premium_LRS"
],
"metadata": {
"description": "Storage Account type"
}
},
"location": {
"type": "string",
"defaultValue": "[resourceGroup().location]",
"metadata": {
"description": "Location for all resources."
}
},
"namePrefix": {
"type": "string",
"maxLength": 11,
"defaultValue": "store",
"metadata": {
"description": "Prefix for storage account name"
}
}
},
"variables": {
"storageAccountName": "[concat(parameters('namePrefix'), uniquestring(resourceGroup().id))]"
},
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2021-04-01",
"name": "[variables('storageAccountName')]",
"location": "[parameters('location')]",
"sku": {
"name": "[parameters('storageAccountType')]"
},
"kind": "StorageV2",
"properties": {}
}
],
"outputs": {
"storageAccountName": {
"type": "string",
"value": "[variables('storageAccountName')]"
}
}
}
Update template spec version
Rather than creating a new template spec for the revised template, add a new version named 2.0
to the existing template spec. Users can choose either version to deploy.
Create a new version for the template spec.
New-AzTemplateSpec `
-Name storageSpec `
-Version "2.0" `
-ResourceGroupName templateSpecRG `
-Location chinanorth2 `
-TemplateFile "c:\Templates\azuredeploy.json"
To deploy the new version, get the resource ID for the 2.0
version.
$id = (Get-AzTemplateSpec -ResourceGroupName templateSpecRG -Name storageSpec -Version "2.0").Versions.Id
Deploy that version. Provide a prefix for the storage account name.
New-AzResourceGroupDeployment `
-TemplateSpecId $id `
-ResourceGroupName storageRG `
-namePrefix "demoaccount"
Create a new version for the template spec.
az ts create \
--name storageSpec \
--version "2.0" \
--resource-group templateSpecRG \
--location "chinanorth2" \
--template-file "c:\Templates\azuredeploy.json"
To deploy the new version, get the resource ID for the 2.0
version.
id=$(az ts show --name storageSpec --resource-group templateSpecRG --version "2.0" --query "id")
Deploy that version. Provide a prefix for the storage account name.
az deployment group create \
--resource-group storageRG \
--template-spec $id \
--parameters namePrefix='demoaccount'
In your template spec, select Create new version .
Name the new version 2.0
and optionally add notes. Select Edit template .
Replace the contents of the template with your updated template. Select Review + Save .
Select Save changes .
To deploy the new version, select Versions
For the version you want to deploy, select the three dots and Deploy .
Fill in the fields as you did when deploying the earlier version.
Select Review + create .
Select Create .
Again, you must make some changes to your local template to make it work with template specs. Copy the following template and save it locally as azuredeploy.json.
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {},
"functions": [],
"variables": {},
"resources": [
{
"type": "Microsoft.Resources/templateSpecs",
"apiVersion": "2021-05-01",
"name": "storageSpec",
"location": "chinanorth2",
"properties": {
"displayName": "Storage template spec"
},
"tags": {},
"resources": [
{
"type": "versions",
"apiVersion": "2021-05-01",
"name": "2.0",
"location": "chinanorth2",
"dependsOn": [ "storageSpec" ],
"properties": {
"mainTemplate": {
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"storageAccountType": {
"type": "string",
"defaultValue": "Standard_LRS",
"allowedValues": [
"Standard_LRS",
"Standard_GRS",
"Premium_LRS"
],
"metadata": {
"description": "Storage Account type"
}
},
"location": {
"type": "string",
"defaultValue": "[[resourceGroup().location]",
"metadata": {
"description": "Location for all resources."
}
},
"namePrefix": {
"type": "string",
"maxLength": 11,
"defaultValue": "store",
"metadata": {
"description": "Prefix for storage account name"
}
}
},
"variables": {
"storageAccountName": "[[concat(parameters('namePrefix'), uniquestring(resourceGroup().id))]"
},
"resources": [
{
"type": "Microsoft.Storage/storageAccounts",
"apiVersion": "2021-04-01",
"name": "[[variables('storageAccountName')]",
"location": "[[parameters('location')]",
"sku": {
"name": "[[parameters('storageAccountType')]"
},
"kind": "StorageV2",
"properties": {}
}
],
"outputs": {
"storageAccountName": {
"type": "string",
"value": "[[variables('storageAccountName')]"
}
}
}
},
"tags": {}
}
]
}
],
"outputs": {}
}
To add the new version to your template spec, deploy your template with Azure CLI or PowerShell.
New-AzResourceGroupDeployment `
-ResourceGroupName templateSpecRG `
-TemplateFile "c:\Templates\azuredeploy.json"
az deployment group create \
--resource-group templateSpecRG \
--template-file "c:\Templates\azuredeploy.json"
Copy the following template and save it locally to a file named storage.json .
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {},
"functions": [],
"variables": {},
"resources": [
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2021-04-01",
"name": "demo",
"properties": {
"templateLink": {
"id": "[resourceId('templateSpecRG', 'Microsoft.Resources/templateSpecs/versions', 'storageSpec', '2.0')]"
},
"parameters": {
},
"mode": "Incremental"
}
}
],
"outputs": {}
}
Deploy your template with Azure CLI or PowerShell.
New-AzResourceGroupDeployment `
-ResourceGroupName storageRG `
-TemplateFile "c:\Templates\storage.json"
az deployment group create \
--resource-group storageRG \
--template-file "c:\Templates\storage.json"
Clean up resources
To clean up the resource you deployed in this quickstart, delete both resource groups that you created.
From the Azure portal, select Resource group from the left menu.
Enter the resource group name (templateSpecRG and storageRG) in the Filter by name field.
Select the resource group name.
Select Delete resource group from the top menu.
Next steps
To learn about creating a template spec that includes linked templates, see Create a template spec of a linked template .