Azure DevOps YAML: compare two variables - azure-devops

To determine which parameter value (my_param) I want to pass to a template (my-template.yml), I would like to compare two variables (var1 and var2) in my YAML pipeline.
- template: my-template.yml
parameters:
${{ if eq(variables.var1, variables.var2) }}:
my_param: 'abc'
${{ else }}:
my_param: 'xyz'
I tested this with different values for var1 and var2 (defined in a DevOps variable group/library). No matter what I put as variable values (whether or not they are equal), the "else" case is always triggered even if both variables have the same value. What am I missing?

Based on my test, there is no direct way to compare two variables in library->variable group.
So I suggest you set another variable 'compare' to previously compare the values of the two variables in the variable group.
Example:
In variablegroup 'MyVarGroup', I have var1 'SomeNumber' and var2 'samplevariable'. I now set var3 'compare', if var1=var2, I set var3 value '0', otherwise other different number.
You could also set it as true if the two variables are the same and false if they are different.
Here are my sample:
mytemplate.yml:
parameters:
name: my_param
type: string
steps:
- task: PowerShell#2
inputs:
targetType: 'inline'
script: echo "${{ parameters.my_param }}"][1]][1]
azure-pipelines.yml:
trigger:
- master
variables:
- group: MyVarGroup
- name: para
value: $[replace(replace('True',eq(variables['compare'], '0'), 'abc'),'True','xyz')]
steps:
- task: PowerShell#2
inputs:
targetType: 'inline'
script: |
echo "$(SomeNumber)"
echo "$(samplevariable)"
echo "$(compare)"
echo "$(para)"
- template: mytemplate.yml
parameters:
my_param: $(para)
If var3 compare is '0',then I will get 'abc' in the template output.
[![enter image description here][1]][1]
Otherwise, I will get 'xyz'
[![enter image description here][2]][2]
I hope it could do some help.
[1]: https://i.stack.imgur.com/1uYU6.png
[2]: https://i.stack.imgur.com/yeRy4.png

Related

Check if a values.yaml property has any entries in it when you don't know the names?

I have a helm chart template that looks like this:
volumes:
- name: secrets
projected:
sources:
{{- range $secretKey := .Values.secrets }}
- secret:
name: {{ $secretKey | kebabcase }}-secret
{{- end }}
This works perfectly, except for when .Values.secrets has no entries in it. Then it gives this error:
error validating data: ValidationError(Deployment.spec.template.spec.volumes[0].projected): missing required field "sources" in io.k8s.api.core.v1.ProjectedVolumeSource
Basically, it is complaining that sources does not have any values.
But I can't find a way to check to only do this section when .Values.secrets has entries. My values.yaml file is filled automatically and sometimes does not have any values for the secrets.
But because it is filled automatically, I don't know the names of the values in it. As such I cannot just do a test for one of the entries (like most examples do).
How can I check if .Values.secrets has any values?
You only need to add a conditional judgment above, and no object is generated when there is no value.
According to the helm document, when the object is empty, the if statement judges to return false.
A pipeline is evaluated as false if the value is:
a boolean false
a numeric zero
an empty string
a nil (empty or null)
an empty collection (map, slice, tuple, dict, array)
volumes:
{{- if .Values.secrets }}
- name: secrets
projected:
sources:
{{- range $secretKey := .Values.secrets }}
- secret:
name: {{ $secretKey | kebabcase }}-secret
{{- end }}
{{- end }}
case 1:
values.yaml
secrets:
output:
volumes:
case 2:
values.yaml
secrets:
- "aaa"
- "bbb"
output:
volumes:
- name: secrets
projected:
sources:
- secret:
name: aaa-secret
- secret:
name: bbb-secret

Find a string which has leading space and add line exactly below to add line

I have a file like below.
# Start OF Java_Out_Of_Memory
- displayName: "Java_Out_Of_Memory"
logDirectory: "/opt/xyz"
logName: "TextLog_*"
searchStrings:
- displayName: "Out_Of_Memory"
pattern: "java.lang.OutOfMemoryError"
matchExactString: false
caseSensitive: false
# End OF Java_Out_Of_Memory
I wanted to add line exactly below of caseSensitive: false with printMatchesString: false...
# Start OF Java_Out_Of_Memory
- displayName: "Java_Out_Of_Memory"
logDirectory: "/opt/xyz"
logName: "TextLog_*"
searchStrings:
#displayName Should be unique across the patterns including the case.
- displayName: "Out_Of_Memory"
pattern: "java.lang.OutOfMemoryError"
matchExactString: false
caseSensitive: false
printMatchedString: false
# End OF Java_Out_Of_Memory
I don't know how many lead space of matched string... Leading space may vary depends on file to file.
I tried this
sed -i '/^[^#]*caseSensitive:*/a \\ printMatchedString: false'
So my requirement is to add a line exactly below and even consider lead space
NOTE:- I have multi configuration like above and I need add PrinitMatched string on every configuration
Try this:
sed -E '/^[^#]*caseSensitive:/ {p; s/^([[:blank:]]*)[^[:blank:]].*$/\1printMatchesString: false/;}' myfile.txt
Explanation:
/^[^#]*caseSensitive:/ - on lines matching "caseSensitive:" (not preceded by "#"
{ - do the following block of commands
p - print the current line (in its original form)
s/^([[:blank:]]*)[^[:blank:]].*$/\1printMatchesString: false/ - parse the line as a bunch of blanks (in parens, so it's a capture group) and then whatever's left, and replace it with the blanks (\1 recalls the capture group) and "printMatchesString: false". Note that the result will be printed automatically.
} - marks the end of the group of commands

Azure DevOps pipelines : backslashes in parameters - do they need to be escaped and how?

I'm using a pipeline template and have a few string runtime parameters that will be file systems paths and they contain backslashes, I was echoing them out to test the template pipeline and have tried all possible approaches
no quotes
single quotes
double quotes escaping backslashes with another backslash
Echoing out all these different strings never displays backslashes and it doesn't seem to me to be a log display issue (accessing the raw log I never see a single backslash however I pass the paths).
This is my simple pipeline template to test what I'm doing
parameters:
- name: string1
type: string
default: C:\APPS\XYZ\
- name: string2
type: string
default: 'C:\APPS\XYZ\'
- name: string3
type: string
default: "C:\\APPS\\XYZ\\"
jobs:
- job: JOB
displayName: JOB
steps:
- checkout: none
- script: |
echo 1 ${{ parameters.string1 }}
echo 2 ${{ parameters.string2 }}
echo 3 ${{ parameters.string3 }}
In the end the disappearance of the backslashes was only in echoing out values. I don't fully understand why this is happening but clearly the backslash is a special character and gets interpreted. By putting the strings to be printed inside single quotes this does not occur and the parameter values get printed out correctly.
This is the correct code
parameters:
- name: string1
type: string
# no quotes
default: C:\APPS\XYZ\
- name: string2
type: string
# single quotes
default: 'C:\APPS\XYZ\'
- name: string3
type: string
# double quotes
default: "C:\\APPS\\XYZ\\"
steps:
- checkout: none
- script: |
echo '1 ${{ parameters.string1 }}'
echo '2 ${{ parameters.string2 }}'
echo '3 ${{ parameters.string3 }}'
First of all, you have a mistake in the second value - the single quote at the start is missing.
Second, you don't need quotes in paramaters value. If you set double quotes the rules for text are changed.
http://blogs.perl.org/users/tinita/2018/03/strings-in-yaml---to-quote-or-not-to-quote.html

how Access Variable in Azure script btw Powershell in Dev Ops Pipeline

In my yaml file I defined some variables which should contain the value of the month ($MinorVersion) or year ($MajorVersion), by setting the value to '$(Month)' and/or '$(Year:yy)'. When I print them in the task script or task powershell it only displays '$(Month)' and/or '$(Year:yy)' . The expected output of the variable $(MajorVersion) is of course the current month and year 09 and 20.
Can someone tell me how I can access the variable $MinorVersion in the task script / powershell to get the actual value of it? That's the files content:
trigger:
- master
pool:
vmImage: 'windows-latest'
#import variable group resize-group, local variables are name/value pairs
variables:
- group: resize-group
- name: buildConfiguration
value: 'Release'
- name: appxPackageDir
value: '$(build.artifactStagingDirectory)\AppxPackages\\'
- name: MajorVersion
value: '$(Year:yy)'
- name: MinorVersion
value: '$(Month)'
- name: PatchVersion
value: 45
- name: RevVersion
value: '$(BuildID)'
- name: Packageappxmanifest
value: Package.appxmanifest
- name: PackageVersion
value: '$(MajorVersion).$(MinorVersion).$(PatchVersion).$(RevVersion)'
name: $(BuildDefinitionName)_$(MajorVersion).$(MinorVersion).$(PatchVersion)$(RevVersion)
steps:
- checkout: self
submodules: true
- script: |
echo %MinorVersion%
echo %variables.MinorVersion%
echo $($[variables.MinorVersion])
echo ${{ variables.MinorVersion }} # outputs initialValue
echo $(Month)
echo $(MajorVersion)
echo $(MinorVersion)
echo $(RevVersion)
echo $(PackageVersion)
echo $(Year:yyyy).$(Month).$(DayOfMonth)$(Rev:.r)
- powershell: |
Write-Host $env:MinorVersion
Write-Host $env:variables.MinorVersion%
Write-Host "$env:MY_MAPPED_PACKAGEVERSION"
Write-Host "$env:MY_MAPPED_REVVERSION"
Output only displays the unevaluated content of the variables:
Can someone tell me how I can access the variable $MinorVersion in the
task script / powershell to get the actual value of it?
Az devops doesn't have such System variables or Predefined variables like $(Year:yy) and $(Month). The available predefined variables are defined here, we can't expand $(Year:yy) and $(Month) cause they're not predefined. As for value: '$(BuildID)', the correct format of BuildID is $(Build.BuildID) instead of $(BuildID).
The $(Date:yyyyMMdd) and $(Rev:.r) are something that only valid for Build Number(name for yaml pipeline), related document here. So normal variables can't expand the value of them, only the name element can recognize them. You should use:
name: $(BuildDefinitionName)_$(Date:yyyyMMdd)$(Rev:.r)
Instead of wrong format:
name: $(BuildDefinitionName)_$(MajorVersion).$(MinorVersion).xxx
Workaround to get/define variables with value of Date time:
Though the variables of Date time are not predefined, we can put one PowerShell step at the start of steps to define those variables manually. You can check link1 and link2 for more details.
So if you want to define data-related variables, you can check set variables in scripts:
- task: PowerShell#2
inputs:
targetType: 'inline'
script: |
$year=$(Get-Date -Format 'yyyy')
Write-Host "##vso[task.setvariable variable=MajorVersion]$year"
$month=$(Get-Date -Format 'MM')
Write-Host "##vso[task.setvariable variable=MinorVersion]$month"
$day=$(Get-Date -Format 'dd')
Write-Host "##vso[task.setvariable variable=DayOfMonth]$day"
- powershell: |
Write-Host $(MajorVersion)
Write-Host $(MinorVersion)
Write-Host $(DayOfMonth)
Output of second PS task:

Ansible time Conversion

I am comparing the last access time of a file with a file_date variable.
Vars:
file_date: '2013-12-12 14:35:02'
Playbook:
- name: set fact
set_fact:
time: "{{ (file_date|to_datetime).strftime('%s') }}"
Output shows as below:
ok: <server> {
"ansible_facts": {
"time": "1386876902"
},
"changed": false
}
But the last access time from win_stat output is
"lastwritetime": 1386858902.
There is slight difference because of the timezone. I need to subtract some value from time or change the timezone. Kindly advice how this can be done.
I would save that lastwritetime from win_stat to a register, and then use set_fact to perform the math operation on it.
- set_fact:
math_time: "{{ register_name.lastwritetime - 18000 }}"
Based on your output this should work, seeing as there are no quotes around the number. But if its getting returned as a string, just use a jinja filter to recast it as an integer and it should still work.
- set_fact:
math_time: "{{ register_name.lastwritetime|int - 18000 }}"