Azure / arm-deploy

ARM action to deploy an Azure Resource Manager (ARM) template to all the deployment scopes
MIT License
82 stars 36 forks source link

Cannot use array parameter #214

Open vRune4 opened 3 months ago

vRune4 commented 3 months ago

(Similar to other open issues, but maybe I can describe this a little better)

- name: šŸš€ Deploy to development environment (subscription scope)
  uses: azure/arm-deploy@v2
  with:
    scope: subscription
    subscriptionId: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
    failOnStdErr: false # https://github.com/Azure/arm-deploy/issues/126
    region: Norway East
    template: ./main.bicep
    parameters: >
      ipList=${{vars.IPLIST}}

If I try: gh variable set IPLIST --env dev --body '{[ ["Somewhere", "xx.yy.zz.xx"], ["Somewhere else", "xx.yy.zz.xx"] ]}'

What is logged: ipList={[ ["Somewhere", "xx.yy.zz.xx"], ["Somewhere else", "xx.yy.zz.xx"] ]}

Error: ERROR: Failed to parse string as JSON: {[ Error detail: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)

This should work: gh variable set IPLIST --env dev --body '[ ["Somewhere", "xx.yy.zz.xx"], ["Somewhere else", "xx.yy.zz.xx"] ]'

ipList=[ ["Somewhere", "xx.yy.zz.xx"], ["Somewhere else", "xx.yy.zz.xx"] ]

Error: ERROR: Failed to parse string as JSON: [ Error detail: Expecting value: line 1 column 2 (char 1)

Try with a surrounding quote: gh variable set IPLIST --env dev --body '''[ ["Somewhere", "xx.yy.zz.xx"], ["Somewhere else", "xx.yy.zz.xx"] ]'''

ipList='[ ["Somewhere", "xx.yy.zz.xx"], ["Somewhere else", "xx.yy.zz.xx"] ]'

Error: ERROR: Failed to parse string as JSON: '[ Error detail: Expecting value: line 1 column 1 (char 0)

The json parameter files look promising. Try putting that into a string: gh variable set IPLIST --env dev --body '{"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", "contentVersion": "1.0.0.0", "parameters": {"iplist": { "value": [["", ""] ]}}}'

What follows is what is passed on to the action. Notice that $schema is still inside double quotes: ipList={"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", "contentVersion": "1.0.0.0", "parameters": {"iplist": { "value": [["", ""] ]}}}

Error: ERROR: Failed to parse string as JSON: {$schema: Error detail: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)

Escape the quotes? ipList={\"$schema\": \"https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#\", \"contentVersion\": \"1.0.0.0\", \"parameters\": {\"iplist\": { \"value\": [[\"\", \"\"] ]}}}

Error: ERROR: Failed to parse string as JSON: {\$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", "contentVersion": "1.0.0.0", "parameters": {"iplist": { "value": [["", ""] ]}}} -o json Error detail: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)

So now it is randomly dropping characters from the input. The parser needs work.

The "json parameter file as a string" approach is just desperation on my part. I am definitively barking up the wrong tree. A workaround would be to have separate json parameter files for each environment, but cannot use that approach with secrets.

anthony-c-martin commented 2 months ago

To understand this better, in your GitHub workflow, this section:

    parameters: >
      ipList=${{vars.IPLIST}}

This is essentially going to be directly added to the underlying AzCli command:

az deployment ... --parameters ipList=${{vars.IPLIST}}

The ${{ ... }} syntax in GitHub workflows will dump out the exact value of the expression, without any understanding of escaping. So in your first example, where you have:

gh variable set IPLIST --env dev --body '{[ ["Somewhere", "xx.yy.zz.xx"], ["Somewhere else", "xx.yy.zz.xx"]  ]}'

The value of IPLIST is going to be (note that the outer ' will be stripped because they were used to pass the arg to the gh command):

{[ ["Somewhere", "xx.yy.zz.xx"], ["Somewhere else", "xx.yy.zz.xx"]  ]}

So the result is that the underlying AzCli command is going to be something like:

az deployment ... --parameters ipList={[ ["Somewhere", "xx.yy.zz.xx"], ["Somewhere else", "xx.yy.zz.xx"]  ]}

Because there are no quotes around the parameter, it's going to be interpreted as:

--parameters ipList={[
anthony-c-martin commented 2 months ago

Here is what I would try based on my above understanding:

Setting:

gh variable set IPLIST --env dev --body "[ ['Somewhere', 'xx.yy.zz.xx'], ['Somewhere else', 'xx.yy.zz.xx']  ]"

Using:

    parameters: >
      ipList="${{vars.IPLIST}}"

The double quotes in the "set" command will be consumed, so the underlying variable will not contain them. This means I need to explicitly add them back in the "using" block, to ensure the full JSON string is interpreted as the parameter value.

I picked single quotes for the inner JSON because AzCli understands them, and it avoids having to worry about escaping.

vRune4 commented 2 months ago
gh variable set IPLIST --env dev --body "[ ['Somewhere', 'xx.yy.zz.xx'], ['Somewhere else', 'xx.yy.zz.xx']  ]"

Using:

    parameters: >
      ipList="${{vars.IPLIST}}"

Works a treat. Thank you!