Azure Pipelines, Bicep, DevOps, IaC

Passing Parameters to Bicep from Azure Pipelines

In previous posts I’ve used various techniques to supply parameters to Bicep from Azure Pipelines YAML and overriding values in a parameters JSON file so I thought I would collate them in one post.

Technique #1

Using multiple template files to handle complex types and standard types separately and create a variable for each parameter that can then be used for File Transform of a parameters JSON file.

parameters:
- name: tags
  displayName: 'Tags'
  type: object
  default:
     Environment: "prod"
     Resource: "AKS"
     Project: "Demo"
 - name: clusterName
    displayName: 'Name of the AKS Cluster'
    type: string
    default: 'demo'
  - name: nodeVmSize
    displayName: 'VM Size for the Nodes'
    type: string
    default: 'Standard_D2s_V3'
    values:
      - 'Standard_D2s_V3'
      - 'Standard_DS2_v2'
      - 'Standard_D4s_V3'
      - 'Standard_DS3_v2'
      - 'Standard_DS4_v2'
      - 'Standard_D8s_v3'
  - name: nodeCount
    displayName: 'The number of nodes'
    type: number
    default: 3

- template: objectparameters.yml
  parameters:
    tags: ${{ parameters.tags }}
- template: parameters.yml
  parameters:
    clusterName: ${{ parameters.clusterName }}
    nodeVmSize: ${{ parameters.nodeVmSize }}
    nodeCount: ${{ parameters.nodeCount }}
- task: FileTransform@2
  displayName: "Transform Parameters"
  inputs:
    folderPath: '$(System.DefaultWorkingDirectory)'
    xmlTransformationRules: ''
    jsonTargetFiles: 'deploy.parameters.json'

objectParameters.yml

parameters:
  - name: tags
    type: object 
steps:
- ${{ each item in parameters }}:
  - bash: |
      value='${{ convertToJson(item.value) }}'
      echo '##vso[task.setvariable variable=parameters.${{ item.key }}.value]'$value
    displayName: "Create Variable ${{ item.key }}"

parameters.yml

parameters:
  - name: clusterName
    type: string
  - name: nodeVmSize
    type: string
  - name: nodeCount
    type: number
 
steps:
- ${{ each item in parameters }}: 
    - bash: |
        echo '##vso[task.setvariable variable=parameters.${{ item.key }}.value]${{ item.value }}'
      displayName: "Create Variable ${{ item.key }}"

Technique #2

Using a PowerShell step to read all parameters and create a variable for each parameter that can then be used for File Transform of a parameters JSON file.

parameters:
- name: tags
  displayName: 'Tags'
  type: object
  default:
     Environment: "prod"
     Resource: "AKS"
     Project: "Demo"
 - name: clusterName
    displayName: 'Name of the AKS Cluster'
    type: string
    default: 'demo'
  - name: nodeVmSize
    displayName: 'VM Size for the Nodes'
    type: string
    default: 'Standard_D2s_V3'
    values:
      - 'Standard_D2s_V3'
      - 'Standard_DS2_v2'
      - 'Standard_D4s_V3'
      - 'Standard_DS3_v2'
      - 'Standard_DS4_v2'
      - 'Standard_D8s_v3'
  - name: nodeCount
    displayName: 'The number of nodes'
    type: number
    default: 3

- ${{ each item in parameters }}:  
   - pwsh: | 
       $obj = '${{ convertToJson(item.value) }}' | ConvertFrom-Json 
       $value = ($obj | ConvertTo-Json -Compress) 
       if($obj.GetType().Name -eq "String") { 
         $value = $obj 
       }  
       Write-Host "##vso[task.setvariable variable=parameters.${{ item.key }}.value;]$value"
     displayName: "Create Variable ${{ item.key }}"

- task: FileTransform@2
  displayName: "Transform Parameters"
  inputs:
    folderPath: '$(System.DefaultWorkingDirectory)'
    xmlTransformationRules: ''
    jsonTargetFiles: 'deploy.parameters.json'

example of the PowerShell step with optional part to ignore unwanted parameters using notIn.

- ${{ each item in parameters }}:  
  - ${{ if notIn(item.key, 'myunwantedparameter') }}:
    - pwsh: | 
        $obj = '${{ convertToJson(item.value) }}' | ConvertFrom-Json 
        $value = ($obj | ConvertTo-Json -Compress) 
        if($obj.GetType().Name -eq "String") { 
          $value = $obj 
        }  
        Write-Host "##vso[task.setvariable variable=parameters.${{ item.key }}.value;]$value"
      displayName: "Create Variable ${{ item.key }}"

Technique #3

Use a template file and PowerShell to create the parameters JSON file as a whole with all the parameters. Note: Probably best used from a template file with the

createParametersFile.yml

parameters: 
- name: paramsJson 
  type: string 
- name: parameterFilePath
  type: string
  default: main.parameters.json
steps: 
- pwsh: | 
    $obj = '${{ parameters.paramsJson }}' | ConvertFrom-Json -AsHashtable 
    $header = [ordered]@{ 
      schema = "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#" 
      contentVersion = "1.0.0.0" 
      parameters = @{} 
    } 
    $valueObject = New-Object -TypeName PsObject 
    foreach ($item in $obj.GetEnumerator()) 
    {   
       $value = @{ 
         value = $item.Value 
       } 
       Add-Member -InputObject $valueObject -MemberType NoteProperty -Name $item.Name -Value $value 
    } 
    $header.parameters = $valueObject 
    Set-Content ${{ parameters.parameterFilePath }} ($header | ConvertTo-Json -Depth 10)   

Call the template:

parameters:
- name: tags
  displayName: 'Tags'
  type: object
  default:
     Environment: "prod"
     Resource: "AKS"
     Project: "Demo"
 - name: clusterName
    displayName: 'Name of the AKS Cluster'
    type: string
    default: 'demo'
  - name: nodeVmSize
    displayName: 'VM Size for the Nodes'
    type: string
    default: 'Standard_D2s_V3'
    values:
      - 'Standard_D2s_V3'
      - 'Standard_DS2_v2'
      - 'Standard_D4s_V3'
      - 'Standard_DS3_v2'
      - 'Standard_DS4_v2'
      - 'Standard_D8s_v3'
  - name: nodeCount
    displayName: 'The number of nodes'
    type: number
    default: 3

- template: createParametersFile.yml
  parameters:
     paramsJson: '${{ convertToJson(parameters) }}'

2 thoughts on “Passing Parameters to Bicep from Azure Pipelines

Comments are closed.