I'm creating a bash script to provision multiple Azure resources via the Azure CLI. So far so good, however I'm having a problem tagging resources.
My goal is to store multiple tags in a variable and provide that variable to the --tags option of several az
commands in the script. The problem however is that a space in the value will be interpreted as a new key.
If we take for example the command az group update
(which will update a resource group) the docs state the following about the --tags option:
--tags
Space-separated tags in 'key[=value]' format. Use "" to clear existing tags.
When a value (or key) contains spaces it must be enclosed in quotes. So when we provide the key-value pairs directly to the command including a value with spaces, like in the following example, the result will be as expected:
az group update --tags owner="FirstName LastName" application=coolapp --name resource-group-name
The result will be that two tags have been added to the resource group:
{
"id": "/subscriptions/1e42c44c-bc55-4b8a-b35e-de1dfbcfe481/resourceGroups/resource-group-name",
"location": "westeurope",
"managedBy": null,
"name": "resource-group-name",
"properties": {
"provisioningState": "Succeeded"
},
"tags": {
"application": "coolapp",
"owner": "FirstName LastName"
}
}
However, when we store the same value we used in the previous step in a variable the problem occurs.
tag='owner="FirstName LastName" application=coolapp'
I use echo $tag
to validate that the variable contains exactly the same value as we provided in the previous example to the --tags option:
owner="FirstName LastName" application=coolapp
But when we provide this tag variable to the tags option of the command as shown in the next line:
az group update --tags $tag --name resource-group-name
The result will be three tags instead of the expected two:
{
"id": "/subscriptions/1e42c44c-bc55-4b8a-b35e-de1dfbcfe481/resourceGroups/resource-group-name",
"location": "westeurope",
"managedBy": null,
"name": "resource-group-name",
"properties": {
"provisioningState": "Succeeded"
},
"tags": {
"LastName\"": "",
"application": "coolapp",
"owner": "\"FirstName"
}
}
I've already tried defining the variable in the following ways, but no luck so far:
tag="owner=FirstName LastName application=coolapp"
tag=owner="Firstname Lastname" application=cool-name
tag='`owner="Firstname Lastname" application=cool-name`'
I even tried defining the variable as an array and providing it to the command as shown on the next line, but also that didn't provide the correct result:
tag=(owner="Firstname Lastname" application=cool-name)
az group update --tags ${tag[*]}--name resource-group-name
I also tried putting quotes around the variable in the command, as was suggested by @socowi, but this leads to the following incorrect result of one tag instead of two:
az group update --tags "$tag" --name resource-group-name
{
"id": "/subscriptions/1e42c44c-bc55-4b8a-b35e-de1dfbcfe481/resourceGroups/resource-group-name",
"location": "westeurope",
"managedBy": null,
"name": "resource-group-name",
"properties": {
"provisioningState": "Succeeded"
},
"tags": {
"owner": "Firstname Lastname application=cool-name"
}
}
Does anybody know how to solve this?
Define your tags as
tags=("owner=Firstname Lastname" "application=cool-name")
then use
--tags "${tags[@]}"
I've found the following works. It requires a resource group already be created.
I used the following template:
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"resourceName": {
"type": "string",
"metadata": {
"description": "Specifies the name of the resource"
}
},
"location": {
"type": "string",
"defaultValue": "[resourceGroup().location]",
"metadata": {
"description": "Location for the resources."
}
},
"resourceTags": {
"type": "object",
"defaultValue": {
"Cost Center": "Admin"
}
}
},
"resources": [
{
"apiVersion": "2019-06-01",
"kind": "StorageV2",
"location": "[parameters('location')]",
"name": "[parameters('resourceName')]",
"properties": {
"supportsHttpsTrafficOnly": true
},
"sku": {
"name": "Standard_LRS"
},
"type": "Microsoft.Storage/storageAccounts",
"tags": "[parameters('resourceTags')]"
}
]
}
In the Azure CLI using Bash, you can pass in the tag as a JSON object. In the following example, a template file with a location requires two parameters, resourceName
and the tags which is an ARM object named resourceTags
:
az deployment group create --name addstorage --resource-group myResourceGroup \
--template-file $templateFile \
--parameters resourceName=abcdef45216 resourceTags='{"owner":"bruce","Cost Cen":"2345-324"}'
If you want to pass it as an environment variable, use:
tags='{"owner":"bruce","Cost Center":"2345-324"}'
az deployment group create --name addstorage --resource-group myResourceGroup \
--template-file $templateFile \
--parameters resourceName=abcdef4556 resourceTags="$tags"
The $tags
must be in double quotes. (You are passing in a JSON object string)
The JSON string also works when you are passing in the tags into Azure DevOps pipeline. See https://github.com/MicrosoftDocs/azure-devops-docs/issues/9051
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With