How to add multiply variables with YAML conditional insertion - yaml

I read this document https://learn.microsoft.com/zh-cn/azure/devops/pipelines/process/expressions?view=azure-devops#conditional-insertion
but not like what demoed in the document, I need add three variables with same condition as below:
name: arm_temp
resources:
repositories:
- repository: self
type: git
variables:
- ${{ if in(lower(coalesce(variables['ENV'], variables['Build.SourceBranchName'])), 'release', 'prod') }}:
- newEnv: 'Prod'
- account: '$(ACCOUNT)'
- password: '$(PASSWORD)'
- ${{ if eq(lower(coalesce(variables['ENV'], variables['Build.SourceBranchName'])), 'qa') }}:
- newEnv: 'QA'
- account: '$(ACCOUNT)'
- password: '$(PASSWORD)'
- resGroupName: ${{ format('RESGROUP-{0}', variables['newEnv']) }}
ACCOUNT, PASSWORD and ENV are variables defined in azure build pipeline
but I always get error before run the build pipeline.
and error notification is about line under the if conditiona.

From your Yaml sample, it seems that the Yaml format has some issues.
You could refer to the following YAML Sample:
variables:
${{ if in(lower(coalesce(variables['ENV'], variables['Build.SourceBranchName'])), 'release', 'prod') }}:
newEnv: 'Prod'
account: $(myaccount)
password: $(mypassword)
${{ if eq(lower(coalesce(variables['ENV'], variables['Build.SourceBranchName'])), 'qa') }}:
newEnv: 'QA'
account: $(myaccount)
password: $(mypassword)
resGroupName: ${{ format('RESGROUP-{0}', variables['newEnv']) }}
pool:
vmimage: windows-latest
steps:
- script: |
echo $(newEnv)
echo $(account)
echo $(password)
Variable:
Result:
Note: You need to change the variable name $(ACCOUNT) $(PASSWORD). They cannot have the same name as the variable defined in yaml($(account), $(password)). Or the variable couldn't pass successfully.

Related

Can I have a GitHub Actions Workflow without any Jobs inside?

When translating existing Azure DevOps YAML pipelines to GitHub Actions YAML, I noticed some of my Azure pipelines were just templates calling other YAML files.
trigger:
- master
resources:
repositories:
- repository: templates
type: git
name: 'Cloud Integration\PipelineTemplates'
name: $(Build.SourceBranchName)_$(Build.Reason)_$(rev:r)
variables:
- group: var-lc-integration-emailservice
- name: logicapp_workflows
value: false
- name: base_resources
value: false
- name: functionapp_resources
value: false
- name: functionapp
value: false
- name: ia_resources
value: false
- name: ia_configs
value: false
- name: apim_resources
value: true
stages:
- template: yml-templates\master.yml#templates
parameters:
logicapp_workflows: ${{ variables.logicapp_workflows }}
base_resources: ${{ variables.base_resources }}
functionapp_resources: ${{ variables.functionapp_resources }}
functionapp: ${{ variables.functionapp }}
ia_resources: ${{ variables.ia_resources }}
ia_configs: ${{ variables.ia_configs }}
apim_resources: ${{ variables.apim_resources }}
While writing a GitHub workflow for the above Azure pipeline, Can we have a "dummy job" or no job at all within a workflow to solve this issue?
IIUC yes, see reusing GitHub Actions workflows.
It allows you to call another workflow from your repository and provide inputs/secrets as necessary.

How can i read json key-value using inline script in git actions and pass them outside the bash tas a variable

How can i read json key-value using inline script in git actions and pass them outside the bash tas a variable, below is the file to create a resource group and parse the json from the repo and pass the vaues as variable to the parameter
on: [push]
name: sp_keyvault
jobs:
build-and-deploy:
runs-on: ubuntu-latest
env:
ResourceGroupName: sp_keyvault-rg
ResourceGroupLocation: "eastus"
steps:
- uses: actions/checkout#master
- uses: azure/login#v1
with:
creds: ${{ secrets.Azure_cred }}
- uses: Azure/CLI#v1
with:
inlineScript: |
#!/bin/bash
if $(az group exists --name ${{ env.ResourceGroupName }}) ; then
echo "Azure resource group already exists, skipping creation..."
else
az group create --name ${{ env.ResourceGroupName }} --location ${{ env.ResourceGroupLocation }}
echo "Azure resource group created"
fi
inlineScript: |
#!/bin/bash
#need to access json from the repo and pass it to parameter variable
- uses: azure/arm-deploy#v1
with:
resourceGroupName: ${{ env.ResourceGroupName }}
template: ./sp_repo-main/KeyVaultSetup.json
parameters: "need variable from bash script"

Syntax errors declaring conditional variables inside YAML jobs

Trying to edit a function YAML file to include some conditional variables, but whatever I try the file won't seem to run in the pipeline.
The desired variable is an array, which I've tried declaring like this:
jobs:
- deployment: Databases
displayName: Deploy Databases in ${{ parameters.stage }}
environment: '${{ parameters.stage }}.${{ parameters.serverName }}'
timeoutInMinutes: 2880
variables:
${{ if eq(parameters.MyParam, True) }}:
MyArray: [ 'Bar' ]
${{ if ne(parameters.MyParam, True) }}:
MyArray: [ 'Foo' ]
stages: [ YAML continues ]
But when trying to run the pipeline, I get the error:
A sequence was not expected
I've tried declaring it as a simple string variable instead, but that just gives a different error:
variables:
${{ if eq(parameters.MyParam, True) }}:
MyArray: 'Bar'
${{ if ne(parameters.MyParam, True) }}:
MyArray: 'Foo'
Expected a sequence or mapping. Actual value '$(MyArray)'
Trying this syntax:
variables:
${{ if eq(parameters.MyParam, True) }}:
- name: MyArray
value: 'Foo'
${{ if ne(parameters.MyParam, True) }}:
- name: MyArray
value: 'Bar'
Yields the error:
[path] (Line: 9, Col: 5): Expected a mapping
[path]: Object reference not set to an instance of an object.
Trying this:
variables:
- name: MyArray
${{ if eq(parameters.myParam, True) }}:
value: 'Foo'
${{ if ne(parameters.myParam, True) }}:
value: 'Bar'
Gets me the same errors as my initial attempts.
I've also tried simply declaring a variable without the conditional and that also gives the same original errors. What am I doing wrong here?

How to access value from a Object using a dynamic key in Yaml

I have a yaml configuration as follows:
parameters:
group: '$(group)'
acl:
certificateFile: AclCertificates.p12
provisioningProfileFile: AmericashDisProfile.mobileprovision
keystore: 'acl.jks'
sail:
certificateFile: AclCertificates.p12
provisioningProfileFile: AmericashDisProfile.mobileprovision
keystore: 'acl.jks'
steps:
- bash: |
echo ${{ parameters[$(group)]['certificateFile'] }}
I want to access the object value using the dynamic key. Here group: '$(group)' is a dynamic value which is coming from another var file.
I have tried a way of access the object value like ${{ parameters[$(group)]['certificateFile'] }} But its not working. I'm not able to figure out that how should i pass the parameter group in the echo ${{ parameters[$(group)]['certificateFile'] }} in order to get specific object's value.
For example, you have a YAML pipeline A:
parameters:
- name: test
type: object
default:
- name: Name1
path: Path1
- name: Name2
path: Path2
variables:
sth: ${{ join(';',parameters.test.*.name) }}
And then you can use YAML pipeline B to get the object value:
variables:
- template: azure-pipelines-2.yml # Template reference
steps:
- task: CmdLine#2
inputs:
script: 'echo "${{variables.sth}}"'

How to use an each expression to concatenate a bash script in Azure Pipelines

I have a few places, where I need to define a set of K8s secrets during deployment at various stages, so I want to extract the recurring script into a template:
parameters:
- name: secretName
type: string
default: ""
- name: secrets
type: object
default:
Foo: Bar
steps:
- task: Bash#3
displayName: Create generic secret ${{ parameters.secretName }}
inputs:
targetType: inline
script: |
echo "Creating generic secret ${{ parameters.secretName }}"
microk8s kubectl delete secret ${{ parameters.secretName }}
microk8s kubectl create secret generic ${{ parameters.secretName }} ${{ each secret in parameters.secrets }}: --from-literal=${{ secretKey }}="${{ secret.value }}"
I want to call it like this multiple times, to create all neccessary secrets for the deployment to each stage
- job: CreateSecrets
pool:
name: $(poolName)
steps:
- template: "Templates/template-create-secret.yml"
parameters:
secretName: "testSecret"
secrets:
username: $(staging-user)
password: $(staging-password)
foo: $(bar)
And it should simply execute a scriptn similar to this one:
kubectl create secret generic secretName \
-- from-literal=username=user1 \
-- from-literal=password=pass1 \
-- ...etc
With my current approach I am receiving the error:
/Code/BuildScripts/Templates/template-create-secret.yml (Line: 18,
Col: 15): The directive 'each' is not allowed in this context.
Directives are not supported for expressions that are embedded within
a string. Directives are only supported when the entire value is an
expression.
How is it possible to iterate over a parameter of type object and use its key and value to build a string for bash? The alternative would be to simply use a single key-value-pair per secret and create multiple secrets, which I'd like to avoid
If you concatenate the command arguments into a variable you can use that in a future step/ task. This example will concatenate all secrets within the key vaults indicated in the keyVaultSecretSources parameter into one command. It shouldn't be too hard to adjust so you can specify which secrets you'd like to include/ exclude:
- name: environment
type: string
- name: namespace
type: string
- name: releaseName
type: string
# contains an array of Azure key vault names
- name: keyVaultSecretSources
type: object
stages:
- stage: MountSecrets${{ parameters.releaseName }}
pool: [Your k8s Pool]
displayName: Mount Key Vault Secrets ${{ parameters.releaseName }}
# Then key vault arguments will be concatenated into the stage variable secretArgs
variables:
secretArgs: ""
jobs:
- deployment: [Your Job Deployment Name]
displayName: [Your Job Display Name]
strategy:
runOnce:
deploy:
steps:
# skip artifacts download for this stage
- download: none
- ${{ each keyVault in parameters.keyVaultSecretSources }}:
# 1. obtain all secrets from keyVault.name key vault
# 2. remove all Json formatting, left with each secret name on one line
# 3. assign to local variable secretNameArray as an array
# 4. loop through secretNameArray and assign the secret to local variable kvs
# 5. construct the argument --from-literal and append to local variable mountCommand
# 6. append mountCommand to the stage variable secretArgs
- task: AzureCLI#2
displayName: 'Concatenate Keyvault Secrets'
inputs:
azureSubscription: [Your subscription]
scriptType: 'bash'
failOnStandardError: true
scriptLocation: 'inlineScript'
inlineScript: |
secretNameArray=($(az keyvault secret list --vault-name ${{ keyVault.name }} --query "[].name" | tr -d '[:space:][]"' | sed -r 's/,+/ /g'));
for i in "${secretNameArray[#]}"; do kvs="$(az keyvault secret show --vault-name ${{ keyVault.name }} --name "$i" --query "value" -o tsv)"; mountCommand="$mountCommand --from-literal=$(echo -e "$i" | sed -r 's/-/_/g')='$kvs'"; done;
echo "##vso[task.setvariable variable=secretArgs;issecret=true]$(secretArgs)$mountCommand"
- task: Kubernetes#1
displayName: 'Kubectl Login'
inputs:
kubernetesServiceEndpoint: [Your Service Connection Name]
command: login
namespace: ${{ parameters.namespace }}
- task: AzureCLI#2
displayName: 'Delete Secrets'
inputs:
azureSubscription: [Your subscription]
scriptType: 'bash'
failOnStandardError: false
scriptLocation: 'inlineScript'
inlineScript: |
kubectl delete secret ${{ parameters.releaseName }}-keyvault -n '${{ parameters.namespace}}'
exit 0
- task: AzureCLI#2
displayName: 'Mount Secrets'
inputs:
azureSubscription: [Your subscription]
scriptType: 'bash'
failOnStandardError: false
scriptLocation: 'inlineScript'
inlineScript: |
kubectl create secret generic ${{ parameters.releaseName }}-keyvault$(secretArgs) -n '${{ parameters.namespace}}'
exit 0
- task: Kubernetes#1
displayName: 'Kubectl Logout'
inputs:
command: logout
According the doc: Parameter data types, we can know that we need to use the 'each' key words before the script and here is the doc to help you know more about the Runtime parameters. Here is the demo script:
parameters:
- name: listOfStrings
type: object
default:
- one
- two
steps:
- ${{ each value in parameters.listOfStrings }}:
- script: echo ${{ value }}

Resources