Azure-cli: Consider alternative method to handle multiple tags when creating resources

Created on 10 Oct 2019  路  8Comments  路  Source: Azure/azure-cli

While the current way to generate tags does not pose any difficulties in a bash shell, it is very cumbersome when calling it from an Azure DevOps Pipeline in an Azure-Cli task when you want to use tags that are generated from different variables.

Example:

  • Create Azure-CLI task in Azure DevOps with an inline shell script:
tag1=foo
tag2=bar
tags="'project=$tag1' 'costcenter=$tag2'"
az group create -l westus -n MyResourceGroup --tags "$tags"

Resulting good command (shell):

az group create -l westus -n MyResourceGroup --tags 'project=foo' 'costcenter=bar'

Resulting bad command (pipeline):

az group create -l westus -n MyResourceGroup --tags ''\''project=foo'''\'' ''\''costcenter=bar'\''

Headache:

The way how ' gets escaped in an Azure DevOps Pipeline.

Describe the solution you'd like

Easier way to state multiple tags

Alternative Method 1

tags="tag1=foo,tag2=bar"
az group create -l westus -n MyResourceGroup --tags "$tags"

Alternative Method 2

az group create -l westus -n MyResourceGroup --tag tag1:foo --tag tag2:bar
ARM OKR3.4 Candidate

Most helpful comment

@rrottmann Hi, the reason that the spaces in tags affect parsing is that word splitting in Bash is \ Pass parameters as above, there is no difference between the space of tags and word splitting when them are passed to az command, so spaces in tags are treated as word splitting. Such as:

tag="this is an awesome project"
+ tag='this is an awesome project'

tags="description=$tag"
+ tags='description=this is an awesome project'

az group create -l westus -n githubissue --tags $tags --debug
+ az group create -l westus -n githubissue --tags description=this is an awesome project --debug

Command arguments: ['group', 'create', '-l', 'westus', '-n', 'githubissue', '--tags', 'description=this', 'is', 'an', 'awesome', 'project', '--debug']

For this qustion, you can refer to the solution provided in https://github.com/Azure/azure-cli/issues/13170#issuecomment-629007240 from jiasli

  • We need a syntactical whitespace (1) to separate tags and a literal whitespace within the value (2)
    "a=b" "c=a dog"
         ^^   ^   ^
         13   2   3
  • So we need syntactical double quotes (3) to quote the literal whitespace (2)
  • However, double quotes are treated as "literal" within a Bash variable ('"c=a' 'dog"')
  • As shown in the tutorial, we need extra eval to parse double quotes

For your example, it can be written as:

tag1=foo
tag2=bar-baz
tag3="this is an awesome project"
tags='"project=$tag1" "costcenter=$tag2" "description=$tag3"'
eval az group create -l westus -n githubissue --tags $tags --debug

By the way, we will support JSON format input for tags in the future, so as to facilitate customers input when the tags contain spaces in scripts.

All 8 comments

Hi@rrottmann, thanks for your suggestion! We will consider it and if there is any update, I will let you know. Thanks!

add to S170

@rrottmann Hi, the single quotation mark in tags="'project=$tag1' 'costcenter=$tag2'" is unnecessary, please use tags="project=$tag1 costcenter=$tag2" to have a try?

Please see https://github.com/Azure/azure-cli/issues/13170#issuecomment-629007240 for a similar issue. I provided very detailed explanation there.

The command you are receiving from pipeline doesn't seem to be valid:

$ echo ''\''project=foo'''\'' ''\''costcenter=bar'\''
> 

Note that the quotes are not correctly paired. It is parsed as

''
\'
'project=foo'
''
\'
' '
'\'
'costcenter=bar'
\'
'     <<< missing pairing quote

This is the correct output from Bash:

$ set -vx

$ tag1=foo
tag1=foo
+ tag1=foo

$ tag2=bar
tag2=bar
+ tag2=bar

$ tags="'project=$tag1' 'costcenter=$tag2'"
tags="'project=$tag1' 'costcenter=$tag2'"
+ tags=''\''project=foo'\'' '\''costcenter=bar'\'''

$ az "$tags" --debug
az "$tags" --debug
+ az ''\''project=foo'\'' '\''costcenter=bar'\''' --debug
Command arguments: ["'project=foo' 'costcenter=bar'", '--debug']
                 1.  ^           ^ ^              ^
                 2.               ^

Of course this is not the desired format, because

  1. Bash doesn't parse single quotes ' in variables, so they are preserved and sent to az as "literal"
  2. Double quotes around $tags like "$tags" stops Bash from doing field splitting, so space is preserved and sent to az as "literal"

To solve it,

  1. If your tags don't contain space (just don't do that as it introduces much more complexity), do not quote them with either single or double quotes
  2. Do not quote $tags which double quotes so that Bash can do field splitting

Please try this format instead:

$ tags="project=$tag1 costcenter=$tag2"
tags="project=$tag1 costcenter=$tag2"
+ tags='project=foo costcenter=bar'

$ az $tags --debug
az $tags --debug
+ az project=foo costcenter=bar --debug
Command arguments: ['project=foo', 'costcenter=bar', '--debug']

Thanks for your pointers! Really helpful and much appreciated.

I've verified this and it works as long as the tags variable gets first composed in a separate bash line and does not contain spaces.

The following works:

tag1=foo
tag2=bar-baz
tags="project=$tag1 costcenter=$tag2"
az group create -l westus -n githubissue --tags $tags --debug
```` 

And this does not work:

```bash
tag1=foo
tag2=bar-baz
az group create -l westus -n githubissue --tags "project=$tag1 costcenter=$tag2" --debug
```` 
A tag with name `project` and value `foo costcenter=bar-baz` gets created.

And obviously spaces will not work as you have already mentioned:

```bash
tag1=foo
tag2=bar-baz
tag3="this is an awesome project"
tags="project=$tag1 costcenter=$tag2 description=$tag3"
az group create -l westus -n githubissue --tags $tags --debug
```` 

2020-05-22T18:41:45.8121725Z "id": "/subscriptions/2b45e*/resourceGroups/githubissue",
2020-05-22T18:41:45.8122041Z "location": "westus",
2020-05-22T18:41:45.8122244Z "managedBy": null,
2020-05-22T18:41:45.8122462Z "name": "githubissue",
2020-05-22T18:41:45.8122668Z "properties": {
2020-05-22T18:41:45.8122906Z "provisioningState": "Succeeded"
2020-05-22T18:41:45.8123106Z },
2020-05-22T18:41:45.8123271Z "tags": {
2020-05-22T18:41:45.8123441Z "an": "",
2020-05-22T18:41:45.8123621Z "awesome": "",
2020-05-22T18:41:45.8123992Z "costcenter": "bar-baz",
2020-05-22T18:41:45.8124219Z "description": "this",
2020-05-22T18:41:45.8124430Z "is": "",
2020-05-22T18:41:45.8124608Z "project": ""
2020-05-22T18:41:45.8124789Z },
2020-05-22T18:41:45.8124993Z "type": "Microsoft.Resources/resourceGroups"
```

One of the usecases in our deployment is also to provide a tag that contains a sentence with a short project description.

@rrottmann Hi, the reason that the spaces in tags affect parsing is that word splitting in Bash is \ Pass parameters as above, there is no difference between the space of tags and word splitting when them are passed to az command, so spaces in tags are treated as word splitting. Such as:

tag="this is an awesome project"
+ tag='this is an awesome project'

tags="description=$tag"
+ tags='description=this is an awesome project'

az group create -l westus -n githubissue --tags $tags --debug
+ az group create -l westus -n githubissue --tags description=this is an awesome project --debug

Command arguments: ['group', 'create', '-l', 'westus', '-n', 'githubissue', '--tags', 'description=this', 'is', 'an', 'awesome', 'project', '--debug']

For this qustion, you can refer to the solution provided in https://github.com/Azure/azure-cli/issues/13170#issuecomment-629007240 from jiasli

  • We need a syntactical whitespace (1) to separate tags and a literal whitespace within the value (2)
    "a=b" "c=a dog"
         ^^   ^   ^
         13   2   3
  • So we need syntactical double quotes (3) to quote the literal whitespace (2)
  • However, double quotes are treated as "literal" within a Bash variable ('"c=a' 'dog"')
  • As shown in the tutorial, we need extra eval to parse double quotes

For your example, it can be written as:

tag1=foo
tag2=bar-baz
tag3="this is an awesome project"
tags='"project=$tag1" "costcenter=$tag2" "description=$tag3"'
eval az group create -l westus -n githubissue --tags $tags --debug

By the way, we will support JSON format input for tags in the future, so as to facilitate customers input when the tags contain spaces in scripts.

@rrottmann Do you have any other questions?

@zhoxing-ms No, I'm good. Looking forward to the JSON format input. Thanks!

Was this page helpful?
0 / 5 - 0 ratings