Ansible time Conversion - date

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 }}"

Related

Azure DevOps YAML: compare two variables

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

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

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:

Convert Ansible variable from Unicode to ASCII

I'm getting the output of a command on the remote system and storing it in a variable. It is then used to fill in a file template which gets placed on the system.
- name: Retrieve Initiator Name
command: /usr/sbin/iscsi-iname
register: iscsiname
- name: Setup InitiatorName File
template: src=initiatorname.iscsi.template dest=/etc/iscsi/initiatorname.iscsi
The initiatorname.iscsi.template file contains:
InitiatorName={{ iscsiname.stdout_lines }}
When I run it however, I get a file with the following:
InitiatorName=[u'iqn.2005-03.org.open-iscsi:2bb08ec8f94']
What I want:
InitiatorName=iqn.2005-03.org.open-iscsi:2bb08ec8f94
What am I doing wrong?
I realize I could write this to the file with an "echo "InitiatorName=$(/usr/sbin/iscsi-iname)" > /etc/iscsi/initiatorname.iscsi" but that seems like an un-Ansible way of doing it.
Thanks in advance.
FWIW, if you really do have an array:
[u'string1', u'string2', u'string3']
And you want your template/whatever result to be NOT:
ABC=[u'string1', u'string2', u'string3']
But you prefer:
ABC=["string1", "string2", "string3"]
Then, this will do the trick:
ABC=["{{ iscsiname.stdout_lines | list | join("\", \"") }}"]
(extra backslashes due to my code being in a string originally.)
Use a filter to avoid unicode strings:
InitiatorName = {{ iscsiname.stdout_lines | to_yaml }}
Ansible Playbook Filters
To avoid the 80 symbol limit of PyYAML, just use the to_json filter instead:
InitiatorName = {{ iscsiname.stdout_lines | to_yaml }}
In my case, I'd like to create a python array from a comma seperated list. So a,b,c should become ["a", "b", "c"]. But without the 'u' prefix because I need string comparisations (without special chars) from WebSpher. Since they seems not to have the same encoding, comparisation fails. For this reason, I can't simply use var.split(',').
Since the strings contains no special chars, I just use to_json in combination with map(trim). This fixes the problem that a, b would become "a", " b".
restartApps = {{ apps.split(',') | map('trim') | list | to_json }}
Since JSON also knows arrays, I get the same result than python would generate, but without the u prefix.