Azure DevOps - AWS CloudFormation and parameters - azure-devops

I have a simple CloudFomration template to create a VPC:
vpc.yaml
---
Parameters:
CidrBlock:
Type: String
Description: The primary IPv4 CIDR block for the VPC
Resources:
VPC:
Type: "AWS::EC2::VPC"
Properties:
CidrBlock: !Ref "CidrBlock"
Tags:
- Key: "Name"
Value: "This is the main VPC"
In my Azure Devops pipleline I want to use AWS Stack create to create a VPC by using this CloudFormation template.
Azure-pipeline.yaml
---
jobs:
- job: Job1
steps:
- task: CloudFormationCreateOrUpdateStack#1
inputs:
awsCredentials: 'My-cred'
regionName: 'ap-southeast-2'
stackName: 'Stack1'
templateSource: 'file'
templateFile: 'vpc.yaml'
templateParametersSource: inline
templateParameters: |
- ParameterKey: CidrBlock
ParameterValue: '10.10.10.0/24'
Obviousely, it'll work fine when I manually provide the value for the CidrBlock parameter when calling vpc.yaml template (like above ^). But what I want to do is using another file to store the parameters and values and pass that when running the vpc template.
In other words, I have a params.yaml file in which I stored the required parameters to run vpc.yaml. How can I use that when running the vpc.yaml template as the parameter files?
params.yaml
---
parameters:
- name: CidrBlock
value: '10.10.10.0/24'
Like how I refer to the template file in azure-pipeline file above, is there a similar way with which I can refer to the params file instead of using templateParametersSource: inline ?

It looks like there is an issue with YAML parameters file with aws-cli:
https://github.com/aws/aws-cli/issues/2275
You can use JSON file:
[
{
"CidrBlock": "10.10.10.0/24",
}
]

Sounds like unlike Azure Bicep or ARM where you can use keys of your own when creating the params files, AWS expect a specific structure where you must always use ParameterKey and ParameterValue as the key.
Here is how the params file should look like in my case:
---
- ParameterKey: CidrBlock
ParameterValue: '10.10.10.0/24'

Related

How to pass variables from variable group between .yaml files with CopyFiles#2?

I have one variable group in ADO library which store different paths and some other variables.
In my main "master" pipeline I use it as below:
variables:
- group: myGroupName
- name: nameOfMyVariable(from variables group) or JustAnyName
- value: $[variables.nameOfMyVariable] or $[variables.JustAnyName]
then in job in the first Stage (for testing, there is only one stage and job for now) I'm trying to using template yaml:
jobs:
- template: my-template.yaml
parameters:
path: $(nameOfMyVariable) or $(JustAnyName)
then in my-template.yaml I have this code:
parameters:
- name: path
type: string
default: ''
jobs:
- job: BuildSomething
steps:
- task: CopyFiles#2
inputs:
Contents: |
${{ parameters.path }}
TargetFolder: '$Build.ArtifactStagingDirectory)'
....
Rest is not that important as it just can't find files to copy and when I try to print parameters.path with echo I get error :
syntax error: invalid arithmetic operator(error token is ".nameOfMyVariable").
I do not know how to fix it so I can access variables from variable group in some of my templates. Do I need to use ##vso[task.setvariables] or something else?
If you want use variable from variable group it is enough to just include this group
variables:
- group: myGroupName
And then use variable by name $(nameOfMyVariable)
In your example it seems you try unnecessary try to declare this variable again in first yaml example.
This example is additionally incorrect because you are addings dash directly before 'value' keyword and it may cause undefined behaviour.
https://learn.microsoft.com/en-us/azure/devops/pipelines/process/variables?view=azure-devops&tabs=yaml%2Cbatch#specify-variables
Just like Kontekst says, when it comes to variable groups, you don't need to declare the variable names and values in your yaml. Once you declare the variable groups in your yaml, you could use the variables from the groups directly.
And if you are using parameters against templates, for your scenario, I suppose that you could declare the parameters in your main yaml, and input the parameter value into your template. (and you don't have to use the variable groups)
My main yaml as below.
trigger:
- none
pool:
vmImage: ubuntu-latest
parameters:
- name: pathmain
displayName: Source Path
type: string
default: README.md
values:
 - azure-pipelines.yml
 - README.md
jobs:
 - job:
   steps:
   - script: echo ${{ parameters.pathmain }}
 - template: test-template.yml
   parameters:
     path: ${{parameters.pathmain}}
My test-template as below.
parameters:
- name: path
displayName: Source Path
type: string
jobs:
- job: BuildSomething
steps:
   - task: CopyFiles#2
     inputs:
       Contents: |
         ${{ parameters.path }}
       TargetFolder: '$Build.ArtifactStagingDirectory'

AzureDevops: Can we pass dynamic value as service connection in yaml

I have a yaml. where I need to pass serviceconnections to a script/template based on an another task which retrieve all required subscriptions.
Question is : Can I pass a dynamic value to a service connection? It is giving me compile time error.
My code below:
trigger: none
pr: none
parameters:
- name: AzureSubscription
type: object
default:
xxx:
Sub: xxx
yyy:
Sub: yyy
jobs:
- job: Updating
condition: succeeded()
pool:
vmImage: "windows-latest"
strategy:
maxParallel: 10
matrix: ${{ parameters.AzureSubscription }}
steps:
- task: AzurePowerShell#5
displayName: Tes
inputs:
azureSubscription: 'zzz'
ScriptType: 'InlineScript'
Inline: |
Write-Output "subcriptionList ---- $(Sub)"
FailOnStandardError: true
azurePowerShellVersion: 'LatestVersion'
pwsh: true
- task: AzurePowerShell#4
displayName: Updating
inputs:
**azureSubscription: ${{ sub }}** # here it is giving me error?
ScriptType: 'FilePath'
ScriptPath: '$(System.DefaultWorkingDirectory)/Foundation/xxxxx.ps1'
azurePowerShellVersion: 'LatestVersion'
So in the 2nd task, I am passing subscription from my parameter.
Error is : Unrecognized value: 'sub'.
Can someone help me?
This is possible with some creativity but not native to the task. Rather using variables and dynamically loading the variable file.
I usually declare the Service Connection name as a variable template file in a separate repository. This allows for reuse across all projects in the org, not required but find it easier that way. Part of the template name would be the environment being deployed to. So a template file might be called azure.dev.yml or azure.uat.yml and look like:
variables:
AzureSubscriptionServiceConnectionName: Azure - Dev
Then a variable defined within the scope of the stage/job would load the template file like below, assuming that a parameter or a local variable would be passed in with the given environmentName.
variables:
- template: /azure.${{ parameters.environmentName }}.yml
Then the stage/job can reference this variable via:
${{ variables.AzureSubscriptionServiceConnectionName }}
Here is some more Microsoft Documentation on YAML Pipeline Variable Scope
You cannot set azureSubcription dynamically. It is known limitation.
#JoeGaggler this feature isn't supported today. Usage of service endpoints (Azure Subscription is one of kind) in release/build definition is controlled by some permissions. At the time of saving a release/build definition service validates that the author (whoever is saving the definition) has appropriate permissions on the endpoint. If we support variable replacements for service endpoint input then service can't validate that the author has required permissions or not and it might become a security issue.

How can I pass a pre-defined pipeline build parameter to a template in Azure DevOps pipelines?

Template:
parameters:
- name: PathPrefix
displayName: 'Path prefix'
type: string
default: ''
steps:
- task: DotNetCoreCLI#2
displayName: 'dotnet restore'
inputs:
command: restore
projects: ${{parameters.PathPrefix}}**/$(Build.DefinitionName).sln
Pipeline:
resources:
repositories:
- repository: devops
name: foo/devops
type: git
ref: master
trigger:
branches:
include:
- refs/heads/*
jobs:
- job: Job_1
displayName: Agent job 1
pool:
vmImage: windows-latest
steps:
- checkout: self
- template: azure/pipelines/pipeline.yaml#devops
parameters:
PathPrefix: $(Build.DefinitionName)
Run error during the restore step:
##[error]No files matched the search pattern.
Even setting verbosityRestore: detailed on the restore step doesn't give me any more information.
If I don't set PathPrefix, it seems to use the default empty string and find the solution file (in some cases). However, if I do set the prefix, which is needed in some repos, it can't find the file. I've tried various ways of referencing the parameter within the template (${{}}, $(), $[] and others) and different ways of specifying it within the pipeline, including hard-coding the path (though I want to use the variable instead), but nothing works.
I thought maybe variables would work instead, so I also tried specifying variables in the pipeline and using them in the template, but that results in the same error. Defining the variable in the template gave me a compilation error for the template (unexpected token 'variable' or something similar).
Look at what you're passing and mentally expand the results.
${{parameters.PathPrefix}}**/$(Build.DefinitionName).sln
If Build.DefinitionName is foo, and you pass that in as PathPrefix, then what you get is:
foo**/foo.sln
It looks like you want an extra forward slash in there, so you get foo/**/foo.sln.

Azure Yaml Pipelines - Dynamic object parameter to template

I would like to trigger a job template with an object as parameter.
Unfortunately, even based on the examples I couldn't find a way to do that.
I would appreciate if someone could guide me how to achieve this.
What I want to achieve, is to replace the ["DEPLOY", "CONFIG"] part with a dynamic variable:
- template: job-template.yaml
parameters:
jobs: ["DEPLOY", "CONFIG"]
This is not possible. YAML is very limited here and you may read more about this here
Yaml variables have always been string: string mappings.
So for instance you can define paramaters as complex type
Template file
parameters:
- name: 'instances'
type: object
default: {}
- name: 'server'
type: string
default: ''
steps:
- ${{ each instance in parameters.instances }}:
- script: echo ${{ parameters.server }}:${{ instance }}
Main file
steps:
- template: template.yaml
parameters:
instances:
- test1
- test2
server: someServer
But you are not able to do it dynamically/programmatically as every output you will create will end up as simple string.
What you can do is to pass as string and then using powershell split that string. But it all depends what you want to run further because you won't be able to simply iterate over yaml structure in that way. All what you can do is to run in in powershell loop and do something, but it can be not enough for you.
It's possible with some logic. see below
- template: job-template.yaml
parameters:
param: ["DEPLOY", "CONFIG"]
and in job-template.yaml file you can define. So every job name will be different
parameters:
param: []
jobs:
- ${{each jobName in parameters.param}}:
- job: ${{jobName}}
steps:
- task: Downl......

How to use Azure DevOps server (TFS) Predefined Variable in My Ansible Playbook?

I want to use Azure DevOps Predefine Variable "$(Build.SourcesDirectory)" in My playbook:
Here is my playbook:
---
- hosts: KBR_MTL361
tasks:
- name: copy file
win_copy:
src: D:\Web.config
dest: $(Build.SourcesDirectory)
I am running this ansible-playbook using Azure DevOps Pipeline:
TFS Pipeline Task
But it is not working
Is there anyone who has any idea how to use the variable in the pipeline?
Just add your variables as additional args in the azure-pipelines.yml like this:
- task: Ansible#0
inputs:
ansibleInterface: 'agentMachine'
playbookPathOnAgentMachine: 'ansible/tfs_playbooks/install_agent.yml'
inventoriesAgentMachine: 'file'
inventoryFileOnAgentMachine: 'hosts.yml'
args: '--extra-vars "build_source_dir=$(Build.SourcesDirectory) AGENT_URL=$(AGENT_URL)"'
Then you can access the variables in your playbook:
---
- hosts: localhost
tasks:
- name: show debug
debug:
msg: "Dir {{ build_source_dir }} agent url {{AGENT_URL}}"
if you look here: https://daniel-krzyczkowski.github.io/Parameters-In-Azure-DevOps-Pipelines there is a certain way to pass Pipeline variables to a powershell script, for instance:
[CmdletBinding()]
param (
$ApiManagementServiceName,
$ApiManagementServiceResourceGroup
)
$apimServiceName = $ApiManagementServiceName
$resourceGroupName = $ApiManagementServiceResourceGroup
Write-Host "Api Management Service Name: $($apimServiceName)"
Write-Host "Api Management Resource Group Name: $($resourceGroupName)"
you are using still powershell you say, so give this a try or try to do something similar that works in your case, for me the above approach works pretty well in standard powershell.