Search code examples
arraysazureazure-devopsazure-rm-templateazure-pipelines-yaml

Azure DevOps AzureResourceManagerTemplateDeployment@3 task overrideParameters array


This should be easy :)

Can anyone assist with the syntax required for the AzureResourceManagerTemplateDeployment@3 task to assign a value in overrideParameters where the ARM template parameters file is expecting an array?

Example:

The ARM template parameters file expects an array:

"my-ssis-ir_publicIPs": {
            "type": "array",
            "defaultValue": [
                "/subscriptions/XXXXX/resourceGroups/my-rg/providers/Microsoft.Network/publicIPAddresses/my-01-ssisir-pip",
                "/subscriptions/XXXXX/resourceGroups/my-rg/providers/Microsoft.Network/publicIPAddresses/my-02-ssisir-pip"
            ]
        },

AzureResourceManagerTemplateDeployment@3 code task - showing the attempt to use override parameters to provide override values for my-ssis-ir_publicIPs with hard-coded values representing two public ips as an array:

- task: AzureResourceManagerTemplateDeployment@3
  displayName: 'ARM Template deployment: Resource Group scope'
  inputs:
    azureResourceManagerConnection: ${{ parameters.azureResourceManagerConnection }}
    subscriptionId: ${{ parameters.subscriptionId }}
    resourceGroupName: ${{ parameters.resourceGroupName }}
    location: '${{ parameters.location }}'
    csmFile: '$(Build.SourcesDirectory)/${{parameters.squadName}}/$(Build.Repository.Name)/${{parameters.buildId}}/ARMTemplateForFactory.json'
    csmParametersFile: '$(Build.SourcesDirectory)/${{parameters.squadName}}/$(Build.Repository.Name)/${{parameters.buildId}}/ARMTemplateParametersForFactory.json'
    overrideParameters:
          -my-ssis-ir_publicIPs ['/subscriptions/XXXXX/resourceGroups/my-rg/providers/Microsoft.Network/publicIPAddresses/my-01-ssisir-pip','/subscriptions/XXXXX/resourceGroups/my-rg/providers/Microsoft.Network/publicIPAddresses/my-02-ssisir-pip']

Most of my efforts result in errors indicating that a string is being passed into the parameter, where an Array is expected.

I have tried a number of options such as - setting parameters in the yml file

parameters:
 - name: my-ssis-ir_publicIPs
   type: object
   default:
    - '/subscriptions/XXXXX/resourceGroups/my-rg/providers/Microsoft.Network/publicIPAddresses/my-01-ssisir-pip'
    - '/subscriptions/XXXXX/resourceGroups/my-rg/providers/Microsoft.Network/publicIPAddresses/my-02-ssisir-pip'

And then have tried to assign the parameter:

overrideParameters:
              -my-ssis-ir_publicIPs ${{ convertToJson(parameters.my-ssis-ir_publicIPs) }}

Obviously, I will need to be using parameters, passed into the YAML file, but am first trying to get this to work by learning the syntax at the point the override is being applied.


Solution

  • The way it works, is you have arm template JSON and arm template parameters JSON.

    So you have a parameter to overrideParameters that will pass it to arm template parameters.

    so let's take an example, here we have managementgroup.json:

    {
      "$schema": "https://schema.management.azure.com/schemas/2019-08-01/managementGroupDeploymentTemplate.json#",
      "contentVersion": "1.0.0.0",
      "parameters": {
        "NameId": {
          "type": "string"
        },
        "DisplayName": {
          "type": "string"
        },
        "ParentId": {
          "type": "string"
        },
        "Location": {
          "type": "string"
        }
      },
      "resources": [
        {
          "name": "[parameters('NameId')]",
          "type": "Microsoft.Management/managementGroups",
          "apiVersion": "2021-04-01",
          "scope": "/",
          "location": "[parameters('Location')]",
          "properties": {
            "details": {
              "parent": {
                "id": "[tenantResourceId('Microsoft.Management/managementGroups', parameters('ParentId'))]"
              }
            },
            "displayName": "[parameters('DisplayName')]"
          }
        }
      ],
      "outputs": {
        "output": {
          "type": "string",
          "value": "[parameters('NameId')]"
        }
      }
    }
    

    And here we have managementgroup.parameters.json that takes 3 parameters:

    {
      "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
      "contentVersion": "1.0.0.0",
      "parameters": {
        "NameId": {
          "value": {}
        },
        "DisplayName": {
          "value": {}
        },
        "ParentId": {
          "value": {}
        },
        "Location": {
          "value": "westeurope"
        }
      }
    }
    

    Now lets as you can see we pass parameters to AzureResourceManagerTemplateDeployment:

      - task: AzureResourceManagerTemplateDeployment@3
        displayName: "Creating/Updating ${{ parameters.DisplayName }}"
        inputs:
          deploymentScope: "Management Group"
          azureResourceManagerConnection: ${{ parameters.ServiceConnection }}
          location: "West Europe"
          csmFile: "${{ parameters.ArmBasePath }}/managementgroup.json"
          csmParametersFile: "${{ parameters.ArmBasePath }}/managementgroup.parameters.json"
          overrideParameters: "-NameId ${{ parameters.NameId }} -DisplayName ${{ parameters.DisplayName }} -ParentId ${{ parameters.ParentId }}"
          deploymentMode: "Incremental"
          deploymentOutputs: armOutputs
    

    In this case I pass parameters from yaml.

    parameters:
      - name: ParentId
        type: string
      - name: NameId
        type: string
      - name: DisplayName
        type: string
      - name: ServiceConnection
        type: string
      - name: ArmBasePath
        type: string
    

    Now if you need to run this multiple times, for instance, 2 calls one for network 1 and a second call for network 2, you just create a template and call it as many times as possible. I use this example to create multiple management groups. I provided this example, you can change it to fit it your question.