Azure pipeline iteration for ARM template Parameters - azure-devops

I have a bicep file as below to create role assignment to resourceGroup scope using azure devops pipeline.
main.bicep
targetScope = 'resourceGroup'
#description('Principal type of the assignee.')
#allowed([
'Device'
'ForeignGroup'
'Group'
'ServicePrincipal'
'User'
])
param principalType string
#description('the id for the role defintion, to define what permission should be assigned')
param RoleDefinitionId string
#description('the id of the principal that would get the permission')
param principalId string
#description('the role deffinition is collected')
resource roleDefinition 'Microsoft.Authorization/roleDefinitions#2018-01-01-preview' existing = {
scope: subscription()
name: RoleDefinitionId
}
resource RoleAssignment 'Microsoft.Authorization/roleAssignments#2020-10-01-preview' = {
name: guid(resourceGroup().id, RoleDefinitionId, principalId)
properties: {
roleDefinitionId: roleDefinition.id
principalId: principalId
principalType: principalType
}
}
This is my pipeline where I want to build the bicep and pass multiple principle iD as array.but its failing
pipeline.yaml.
parameters:
- name: roleList
type: object
stages:
- stage: BuilD_Roles_ARM_Artifact
displayName: 'Build_ARM_Template'
jobs:
- ${{ each role in parameters.roleList }}:
- job: BuilD_ARM_Artifact_${{ role.environment }}_${{ role.rolesname }}
displayName: '${{ role.rolesname }}'
variables:
- name: subscription
${{ if or(eq(role.environment, 'development'), eq(role.environment, 'staging')) }}:
value: 'mynonprod'
${{ if eq(role.environment, 'production')}}:
value: "myprod"
${{ if eq(role.environment, 'dr')}}:
value: "mydr"
workspace:
clean: all
pool:
${{ if eq(role.environment, 'development')}}:
name: devpool
${{ if eq(role.environment, 'staging')}}:
name: stagepool
${{ if eq(role.environment, 'production')}}:
name: az-prod-spoke
${{ if eq(role.environment, 'dr')}}:
name: drpool
steps:
- bash: |
resourceGroup=${{ role.resourceGroup }}
echo "##vso[task.setvariable variable=resourceGroup]$resourceGroup"
principalType=${{ role.principalType }}
echo "##vso[task.setvariable variable=principalType]$principalType"
principalid=${{ role.principalid }}
echo "##vso[task.setvariable variable=principalid]$principalid"
roleDefinitionId=${{ role.roleDefinitionId }}
echo "##vso[task.setvariable variable=roleDefinitionId]$roleDefinitionId"
- bash: az bicep build --file template/main.bicep
displayName: 'Compile Bicep to ARM'
- task: qetza.replacetokens.replacetokens-task.replacetokens#3
inputs:
rootDirectory: '$(System.DefaultWorkingDirectory)/'
targetFiles: '$(System.DefaultWorkingDirectory)/template/parameters.json'
encoding: 'auto'
writeBOM: true
actionOnMissing: 'warn'
keepToken: false
tokenPrefix: '#{'
tokenSuffix: '}#'
useLegacyPattern: false
enableTelemetry: true
- task: AzureCLI#2
displayName: "validate the templates"
inputs:
azureSubscription: ${{ variables.subscription }}
scriptType: 'bash'
scriptLocation: 'inlineScript'
inlineScript: 'az group deployment validate --resource-group $(resourceGroup) --template-file $(System.DefaultWorkingDirectory)/template/main.json --parameters $(System.DefaultWorkingDirectory)/template/parameters.json'
- task: AzureCLI#2
displayName: "verify the change result"
inputs:
azureSubscription: ${{ variables.subscription }}
scriptType: 'bash'
scriptLocation: 'inlineScript'
inlineScript: 'az deployment group what-if --resource-group $(resourceGroup) --template-file $(System.DefaultWorkingDirectory)/template/main.json --parameters $(System.DefaultWorkingDirectory)/template/parameters.json'
- task: PublishBuildArtifacts#1
inputs:
PathtoPublish: '$(System.DefaultWorkingDirectory)/template/'
ArtifactName: 'arm-source-${{ role.environment }}-${{ role.rolesname }}'
publishLocation: 'Container'
name: "Publish_arm_code"
displayName: "Publish arm code as build artifact"
- stage: Create_RoleAssignment
displayName: 'Create RoleAssignment'
jobs:
- ${{ each role in parameters.roleList }}:
- deployment: deploy_role_${{ role.environment }}_${{ role.rolesname }}
displayName: '${{ role.rolesname }}'
variables:
- name: resourceGroup
value: ${{ role.resourceGroup }}
- name: subscription
${{ if or(eq(role.environment, 'development'), eq(role.environment, 'staging')) }}:
value: 'mynonprod'
${{ if eq(role.environment, 'production')}}:
value: "myprod"
${{ if eq(role.environment, 'dr')}}:
value: "mydr"
${{ if eq(variables.subscription, 'mynonprod') }}:
environment: NON-PROD-RBAC
${{ if eq(variables.subscription, 'myprod') }}:
environment: PROD-RBAC
${{ if eq(variables.subscription, 'mydr') }}:
environment: DR-RBAC
pool:
${{ if eq(variables.subscription, 'mynonprod') }}:
name: devpool
${{ if eq(variables.subscription, 'mytest') }}:
name: stagepool
${{ if eq(variables.subscription, 'myprod') }}:
name: az-prod-spoke
${{ if eq(variables.subscription, 'mydr') }}:
name: drpool
strategy:
runOnce:
deploy:
steps:
- download: none
- task: DownloadBuildArtifacts#0
inputs:
artifactName: 'arm-source-${{ role.environment }}-${{ role.rolesname }}'
downloadPath: $(System.ArtifactsDirectory)
- task: CopyFiles#2
inputs:
sourceFolder: $(System.ArtifactsDirectory)/arm-source-${{ role.environment }}-${{ role.rolesname }}
contents: '**'
targetFolder: $(System.DefaultWorkingDirectory)/arm-source-${{ role.environment }}-${{ role.rolesname }}
cleanTargetFolder: true
- task: AzureCLI#2
displayName: "Create the change result"
inputs:
azureSubscription: ${{ variables.subscription }}
scriptType: 'bash'
scriptLocation: 'inlineScript'
inlineScript: 'az deployment group create --resource-group $(resourceGroup) --template-file $(System.DefaultWorkingDirectory)/arm-source-${{ role.environment }}-${{ role.rolesname }}/main.json --parameters $(System.DefaultWorkingDirectory)/arm-source-${{ role.environment }}-${{ role.rolesname }}/parameters.json'
and this is my pipeline input file
name: $(Build.SourceBranchName)-$(Build.BuildId)
trigger: none
stages:
- template: azure-pipeline.yaml
parameters:
roleList:
- rolesname: rolename1
environment: development
scope: resourcegroup
principalType: Group
principalid: xxxxxxxxxxx,yyyyyyyy, zzzzzzzzz
roleDefinitionId: acdxxxxxxxxxxxxxxxxxxxxx # reader id
resourceGroup: myrg-1
- rolesname: rolename2
environment: development
scope: resourcegroup
principalType: Group
principalid: aaaaaaaa,bbbbbbbbbb,cccccccccc
roleDefinitionId: acdxxxxxxxxxxxxxxxxxxxxx # reader id
resourceGroup: myrg-2
- rolesname: rolename3
environment: development
scope: resourcegroup
principalType: Group
principalid:
roleDefinitionId: acdxxxxxxxxxxxxxxxxxxxxx # reader id
resourceGroup: myrg-3
so here first I am building the bicep to ARM file and replacing the variables with the pipelines variables over a loop, Which is creating mutiple ARM templates together.
So I am looking for 2 things.
I would be able to pass list of PrincipleIDs over the input, for each roleassignment. The above template syntax is failing if I add multiple PrincipleIDs
looking for a way to iterate through all the roles paramaters i9f any changes added and have a single ARM template with the inputs. So that it will produce a single ARM build artifact for only the modification to roleassignment items.
Adding the modified files
New bicep file
targetScope = 'resourceGroup'
#description('Principal type of the assignee.')
#allowed([
'Device'
'ForeignGroup'
'Group'
'ServicePrincipal'
'User'
])
param principalType string
#description('the id for the role defintion, to define what permission should be assigned')
param RoleDefinitionId string
#description('the id of the principal that would get the permission')
param principalId string
#description('the role deffinition is collected')
resource roleDefinition 'Microsoft.Authorization/roleDefinitions#2018-01-01-preview' existing = {
scope: subscription()
name: RoleDefinitionId
}
resource RoleAssignment 'Microsoft.Authorization/roleAssignments#2020-10-01-preview' = [for id in split(principalId, ','): {
name: guid(resourceGroup().id, RoleDefinitionId, principalId)
properties: {
roleDefinitionId: roleDefinition.id
principalId: principalId
principalType: principalType
}
}]
parameters file
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"principalType": {
"value": "#{principalType}#"
},
"RoleDefinitionId": {
"value": "#{RoleDefinitionId}#"
},
"principalId": {
"value": "#{principalId}#"
}
}
}
pipeline file.
- rolesname: readerall
environment: development
scope: resourcegroup
principalType: Group
principalid: aaaaaaaaaaaaaa,bbbbbbbbbbbbbbbbb,ccccccccccccccccccccc,ddddddddddddddddddddd
roleDefinitionId: acddxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
resourceGroup: aks-rg
- rolesname: reader_apimrg_all
environment: development
scope: resourcegroup
principalType: Group
principalid: aaaaaaaaaaaaaa,bbbbbbbbbbbbbbbbb,ccccccccccccccccccccc,ddddddddddddddddddddd
roleDefinitionId: acddxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
resourceGroup: apim-rg
- rolesname: reader_lawrg_all
environment: development
scope: resourcegroup
principalType: Group
principalid: aaaaaaaaaaaaaa,bbbbbbbbbbbbbbbbb,ccccccccccccccccccccc,ddddddddddddddddddddd
roleDefinitionId: acddxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
resourceGroup: la-rg

Here the principal ids are passed as string:
principalid: xxxxxxxxxxx,yyyyyyyy,zzzzzzzzz
In the bicep file, you could split the string to create multiple role assignments:
resource roleAssignments 'Microsoft.Authorization/roleAssignments#2020-10-01-preview' = [for id in split(principalId, ','): {
name: guid(resourceGroup().id, RoleDefinitionId, id)
properties: {
roleDefinitionId: roleDefinition.id
principalId: id
principalType: principalType
}
}]
Regarding your second question, it sounds quite complex. You probably would need to have a preparation task that will iterate and check which role assignments already exist and then create a complex object to pass to the bicep file. Because the ARM API is idempotent, not sure why are you trying only to deploy the new changes ?

Related

Not able to set variable based on parameters in YAML

I'm trying to build a new yaml file that reads keyvault secrets based on the parameters at the runtime and declared variables with the condition as per the parameters, but this isn't working.
- name: azure_subscription
displayName: " Select subscription "
type: string
default: "service-connection-dev"
values:
- 'service-connection-dev'
- 'service-connection-sit'
- 'service-connection-tes'
- 'service-connection-prd'
variables:
- ${{ if eq('${{ parameters.azure_subscription }}', 'service-connection-sit') }}:
name: key_vault
value: 'core-kv-sit'
- ${{ if eq('${{ parameters.azure_subscription }}', 'service-connection-dev') }}:
name: key_vault
value: 'core-kv-dev'
stages:
- stage: Validate
${{ if eq(parameters.azure_subscription, 'service-connection-dev') }}:
pool:
name: agent-pool-win-dev
${{ if eq(parameters.azure_subscription, 'service-connection-sit') }}:
pool:
name: agent-pool-win-sit
jobs:
- job: Validate
steps:
- task: AzureKeyVault#2
inputs:
KeyVaultName: "${{variables.key_vault}}"
SecretsFilter: "*"
RunAsPreJob: false
azureSubscription: ${{ parameters.azure_subscription }}
I've tried using variables inside jobs, but that is also not working. Can someone please help?
Also, I'll have to declare 2 more variables as per the parameters input, Is it possible ?
Thanks in advance
- ${{ if eq('${{ parameters.azure_subscription }}', 'service-connection-sit') }}:
You're using a literal value of "${{ parameters.azure_subscription }}" for the left side of the comparison. The comparison should just be parameters.azure_subscription.
So: - ${{ if eq(parameters.azure_subscription, 'service-connection-sit') }}:

How to convert string variable to object and pass it to another pipeline?

I have two Azure Devops pipelines: 'Starter' and 'Processing'. 'Starter' triggers 'Processing' and passes some parameters to it.
Starter:
trigger: none
pool:
vmImage: 'windows-2019'
stages:
- stage: A
jobs:
- template: Processing.yml
parameters:
products: $(Products)
creds: $(Creds)
Processing:
parameters:
- name: products
type: object
default: []
- name: creds
default: ''
jobs:
- ${{ each product in parameters.products }}:
- task: PowerShell#2
displayName: Importing ${{ product }} solution
inputs:
targetType: 'inline'
script: |
#Code
Key detail here is opportunity to loop through 'products' variable (each product in parameters.products), which must be setted in 'Starter' variables:
In other words, starting my pipeline I must pass list of products as 'string' and then loop through this list in second pipeline. 'Is it generally possible? Maybe products should be another type? I tried some work around but didn't get appropriate solution:
- job: Prepare_Products_Array
steps:
- task: PowerShell#2
inputs:
targetType: 'inline'
script: |
# Write your PowerShell commands here.
$productsArray = []
$productsArray = $(Products)
$productsArray = $productsArray.Split(',')
Write-Host ("##vso[task.setvariable variable=productsArray;]$productsArray")
- template: Processing.yml
parameters:
products: $env:productsArray
Exception:
From your yaml sample, you are defining the variable in YAML Pipeline UI and using parameters in YAML Template.
In this case, the variables defined on the UI will be assigned at runtime, but the parameters and expressions in the YAML template will be expanded at compile time.
Therefore, YAML UI variables cannot be passed to the Pipeline YAML Template.
And it will show the error:
Expected a...... Actual value $(Product)
This means that the pipeline variable not expanded at compile time.
I am afraid that there is no such method can pass the UI Pipeline variable to YAML Template.
Here are the workarounds:
Method 1 : You can use parameters in Starter yaml to pass the Object type parameters to YAML template.
Starter:
trigger: none
parameters:
- name: products
type: object
default: []
- name: creds
default: ''
pool:
vmImage: 'windows-2019'
stages:
- stage: A
jobs:
- template: Processing.yml
parameters:
products: ${{ parameters.products }}
creds: ${{ parameters.creds }}
Processing:
parameters:
- name: products
type: object
default: []
- name: creds
default: ''
jobs:
- job: test
steps:
- ${{ each product in parameters.products }}:
- task: PowerShell#2
displayName: Importing ${{ product }} solution
inputs:
targetType: 'inline'
script: |
echo ${{ product }}
Result: You can input the value when you run the pipeline.
Method2: You need to define the variable in Starter pipeline and change the products parameters as String type. Then you can use the expression - ${{ each product in split(parameters.products, ',')}}: to split the string.
Starter:
pool:
vmImage: 'windows-2019'
variables:
products: '1,2,3'
creds: test
stages:
- stage: A
jobs:
- template: Processing.yml
parameters:
products: ${{ variables.products }}
creds: ${{ variables.creds }}
Processing:
parameters:
- name: products
type: string
default: ''
- name: creds
default: ''
jobs:
- job: test
steps:
- ${{ each product in split(parameters.products, ',')}}:
- task: PowerShell#2
displayName: Importing ${{ product }} solution
inputs:
targetType: 'inline'
script: |
echo ${{ product }}

Conditional dependson for multiple stage YAML

I have a YAML pipeline which contains some template files.
Within my pipeline, there are 4 stages that run in parallel to apply DSC. I then have a destroy task which i would like to run, only when all 4 tasks have ran successfully. When i try to add a depends on with a list:
dependsOn:
- Stage_A
- Stage_B
- Stage_C
- Stage_D
The error I get is:
The 'dependsOn' parameter is not a valid String.
My template YAML looks like:
...
stages:
...
- template: Apply-DSC.yml
parameters:
azureSub: '[sub]'
AutoAccountResourceGroup: 'rg'
AutoAccountName: 'aa'
environment: 'b1'
stageDependsOn: 'b1_apply'
- template: Destroy-Pipeline.yml
parameters:
azureSub: '[sub]'
terraformStorageAccountResourceGroup: 'rg'
terraformStorageAccountName: '[]'
terraformStorageContainerName: '[]'
terraformStorageRemoteStateKey: '[].tfstate'
environment: 'b1'
terraformEnvironmentFileName: 'B01'
dependsOn: 'Stage_A'
I have 4 stages within my Apply-DSC.yml
Stage_A
Stage_B
Stage_C
Stage_D
Question is, is this possible for my destroy stage to await a successful deployment of Stages A-D when using these stage templates?
Thanks.
Edit: Adding Destroy-Pipeline.yml
# Run & upload Terraform plan
parameters:
- name: azureSub
type: string
- name: terraformStorageAccountResourceGroup
type: string
- name: terraformStorageAccountName
type: string
- name: terraformStorageContainerName
type: string
- name: terraformStorageRemoteStateKey
type: string
- name: environment
type: string
- name: terraformEnvironmentFileName
type: string
- name: dependsOn
type: string
stages:
- stage: Destroy_${{ parameters.environment }}
dependsOn: ${{ parameters.dependsOn }}
jobs:
- deployment: '${{ parameters.environment }}_Destroy'
displayName: '${{ parameters.environment }} Destroy'
environment: '${{ parameters.environment }} destroy'
pool:
vmImage: windows-latest
strategy:
runOnce:
deploy:
steps:
- download: current
artifact: 'drop'
name: 'Download_Terraform_code'
displayName: 'Download Terraform code'
- task: ms-devlabs.custom-terraform-tasks.custom-terraform-installer-task.TerraformInstaller#0
inputs:
terraformVersion: '$(TerraformVersion)'
displayName: 'Install Terraform'
- task: TerraformCLI#0
inputs:
command: 'init'
workingDirectory: '$(Pipeline.Workspace)/Drop'
backendType: 'azurerm'
backendServiceArm: '${{ parameters.azureSub }}'
backendAzureRmResourceGroupName: '${{ parameters.terraformStorageAccountResourceGroup }}'
backendAzureRmStorageAccountName: '${{ parameters.terraformStorageAccountName }}'
backendAzureRmContainerName: '${{ parameters.terraformStorageContainerName }}'
backendAzureRmKey: '${{ parameters.terraformStorageRemoteStateKey }}'
allowTelemetryCollection: false
displayName: 'Terraform Init'
- task: PowerShell#2
inputs:
targetType: 'inline'
script: |
terraform workspace select $(WorkspaceEnvironment)
workingDirectory: '$(Pipeline.Workspace)/Drop'
displayName: 'Select Workspace'
- task: TerraformCLI#0
inputs:
command: 'plan'
environmentServiceName: '${{ parameters.azureSub }}'
commandOptions: '-destroy -var-file="./environments/${{ parameters.terraformEnvironmentFileName }}.tfvars" -input=false'
allowTelemetryCollection: false
workingDirectory: '$(Pipeline.Workspace)/Drop'
displayName: 'Plan Destroy'
- task: TerraformCLI#0
inputs:
command: 'destroy'
workingDirectory: '$(Pipeline.Workspace)/Drop'
environmentServiceName: '${{ parameters.azureSub }}'
commandOptions: '-var-file="./environments/${{ parameters.terraformEnvironmentFileName }}.tfvars" -input=false '
allowTelemetryCollection: false
displayName: 'Run Destroy'
I changed the type from string to object
parameters:
- name: dependsOn
type: object
default: []
Then within my template block i added the object like:
- template: Destroy-Pipeline.yml
parameters:
...
dependsOn: ['Stage_A', 'Stage_B' ...]

set and refer to variables in yaml

I have the following yml code that sets and refers to some variables as follows:
<one.yml>
- task: AzurePowerShell#4
displayName: 'Copy functions templates'
inputs:
azureSubscription: ${{parameters.serviceConnection}}
ScriptPath: ${{ parameters.root }}/Scripts/ReleaseManagement/CopyChildTemplatesToContainer.ps1
ScriptArguments: '-resourceGroupName ''${{ parameters.solutionAbbreviation}}-data-${{ parameters.environmentAbbreviation}}''
name: copyFunctionsTemplates
- powershell: |
Write-Host "##vso[task.setvariable variable=data_containerSASToken;isOutput=true]$(copyFunctionsTemplates.containerSASToken)"
Write-Host "##vso[task.setvariable variable=data_containerEndPoint;isOutput=true]$(copyFunctionsTemplates.containerEndPoint)"
displayName: 'set data output variables'
name: dataVariables
<two.yml>
stages:
- deployment: ${{ parameters.stageName }}_DeployResources
displayName: ${{ parameters.stageName }}_DeployResources
- stage: ${{ parameters.stageName }}
dependsOn: ${{ parameters.dependsOn }}
condition: ${{ parameters.condition }}
jobs:
- deployment: ${{ parameters.stageName }}_DeployResources
displayName: ${{ parameters.stageName }}_DeployResources
steps:
- template: one.yml
jobs:
- job: ${{ parameters.stageName }}_DeployFunctions
dependsOn: ${{ parameters.stageName }}_DeployResources
variables:
data_containerEndPoint: $[ dependencies.DeployResources.outputs['DeployResources.dataVariables.data_containerEndPoint'] ]
data_containerSASToken: $[ dependencies.DeployResources.outputs['DeployResources.dataVariables.data_containerSASToken'] ]
steps:
- ${{ each func in parameters.functionApps }}:
- template: three.yml
<three.yml>
steps:
- task: AzureResourceGroupDeployment#2
displayName: 'deploy ${{ parameters.name }} data resources'
inputs:
azureSubscription: ${{parameters.serviceConnection}}
resourceGroupName: ${{parameters.solutionAbbreviation}}-data-${{parameters.environmentAbbreviation}}
location: ${{parameters.location}}
csmFile: ${{ parameters.root }}/functions_arm_templates/${{ parameters.name }}/Infrastructure/data/template.json
csmParametersFile: ${{ parameters.root }}/functions_arm_templates/${{ parameters.name }}/Infrastructure/data/parameters/parameters.${{parameters.environmentAbbreviation}}.json
overrideParameters: -environmentAbbreviation "${{parameters.environmentAbbreviation}}"
-tenantId "${{parameters.tenantId}}"
-solutionAbbreviation "${{parameters.solutionAbbreviation}}"
-containerBaseUrl "$(data_containerEndPoint)functions/${{ parameters.name }}/Infrastructure/data/"
-containerSasToken "$(data_containerSASToken)"
deploymentMode: 'Incremental'
On enabling the debug mode while running pipeline, I see values printed for data_containerSASToken and data_containerEndPoint from the task 'Copy functions templates' however I see empty values from the task 'deploy data resources'. What am I missing?
Your problem may be in when you retrieve the output from the previous job:
data_containerEndPoint: $[ dependencies.DeployResources.outputs['DeployResources.dataVariables.data_containerEndPoint'] ]
That's looking for a prior job called DeployResources, but the prior job is actually called {{ parameters.stageName }}_DeployResources.

Parameterized variable names as task input in Azure Pipelines

I've been trying to make a YAML template that first uses the AzureKeyVault#1 task to get the value ofsome Azure KeyVault secrets, and then uses these secrets for the sqlUsername and sqlPassword in asqlAzureDacpacDeployment#1 task.
I want to make the names of the KeyVault secrets a parameter, so that this template can be used for many different situations.
I've successfully used this technique before, with an AzureKeyVault#1 task and then an AzurePowerShell#4 task, where the secret gets injected as an environment variable for the PowerShell script.
This is a dressed down version of the working template:
parameters:
- name: subscription
type: string
- name: keyVaultSecretName
type: string
- name: keyVault
type: string
jobs:
- job: Run_PowerShell_With_Secret
pool:
name: Azure Pipelines
vmImage: windows-latest
steps:
- task: AzureKeyVault#1
inputs:
azureSubscription: ${{ parameters.subscription }}
keyVaultName: ${{ parameters.keyVault }}
secretsFilter: ${{ parameters.keyVaultSecretName }}
- task: AzurePowerShell#4
inputs:
azureSubscription: ${{ parameters.subscription }}
ScriptPath: 'some_script.ps1'
azurePowerShellVersion: LatestVersion
env:
SECRETVALUE: $(${{ parameters.keyVaultSecretName }})
And here is the template where I can't get the same technique to work:
parameters:
- name: subscription
type: string
- name: keyVault
type: string
- name: sqlServerName
type: string
- name: sqlDatabaseName
type: string
- name: sqlServerAdminSecretName
type: string
- name: sqlServerPasswordSecretName
type: string
- name: dacpacName
type: string
- name: artifactName
type: string
jobs:
- job: Deploy_SQL_Database
pool:
name: Azure Pipelines
vmImage: windows-latest
steps:
- task: DownloadPipelineArtifact#2
inputs:
artifact: ${{ parameters.artifactName }}_artifacts
- task: AzureKeyVault#1
inputs:
azureSubscription: ${{ parameters.subscription }}
keyVaultName: ${{ parameters.keyVault }}
secretsFilter: '${{ parameters.sqlServerAdminSecretName }}, ${{ parameters.sqlServerPasswordSecretName }}'
- task: sqlAzureDacpacDeployment#1
inputs:
azureSubscription: ${{ parameters.subscription }}
ServerName: ${{ parameters.sqlServerName }}.database.windows.net
DatabaseName: ${{ parameters.sqlDatabaseName }}
sqlUsername: $(${{ parameters.sqlServerAdminSecretName }})
sqlPassword: $(${{ parameters.sqlServerPasswordSecretName }})
DacpacFile: $(Pipeline.Workspace)\${{ parameters.dacpacName }}.dacpac
I can get the template to work if I hardcode the secret names:
parameters:
- name: subscriptionName
type: string
- name: keyVault
type: string
- name: sqlServerName
type: string
- name: sqlDatabaseName
type: string
- name: dacpacName
type: string
- name: artifactName
type: string
jobs:
- job: Deploy_${{ parameters.sqlDatabaseName }}_Database
pool:
name: Azure Pipelines
vmImage: windows-latest
steps:
- checkout: none
- task: AzureKeyVault#1
inputs:
azureSubscription: ${{ parameters.subscriptionName }}
keyVaultName: ${{ parameters.keyVault }}
secretsFilter: 'SQLServerAdmin, SQLServerPassword'
- task: DownloadPipelineArtifact#2
inputs:
artifact: ${{ parameters.artifactName }}_artifacts
- task: sqlAzureDacpacDeployment#1
inputs:
azureSubscription: ${{ parameters.subscriptionName }}
ServerName: ${{ parameters.sqlServerName }}.database.windows.net
DatabaseName: ${{ parameters.sqlDatabaseName }}
sqlUsername: $(sqlServerAdmin)
sqlPassword: $(sqlServerPassword)
DacpacFile: $(Pipeline.Workspace)\${{ parameters.dacpacName }}.dacpac
Although this works for us for now, I find this sub-optimal. Is there any way I can make these parameterized variable names work?