I am using ansible 2.0.1 on RHEL 7 hosts. Somehow following roles when called through playbook skips the Get the yellow major version.
Attaching output below. Looks like there is something wrong with the when condition.
- set_fact: is_yos="true"
- name: Fetch yellow version
shell: /bin/gawk '{ for(col = 1; col <= NF; col++) if ($col ~ /[0-9.]+/) { print $col; } }' /etc/yellow-release
register: yel_ver_str
failed_when: false
changed_when: false
- set_fact:
is_yos: "false"
when: yel_ver_str.rc != 0
- debug: var=yel_ver_str
- debug: var=is_yos
- name: Get yellow major version.
shell: echo {{ yel_ver_str.stdout }} | awk -F. '{print $1}'
register: yel_major_ver
when: is_yos == "true"
delegate_to: localhost
changed_when: false
Output
ansible-playbook -i hosts test.yml -c local
PLAY ***************************************************************************
TASK [setup] *******************************************************************
ok: [172.31.83.23]
TASK [test : set_fact] *********************************************************
ok: [172.31.83.23]
TASK [test : Fetch yellow version] *********************************************
ok: [172.31.83.23]
TASK [test : set_fact] *********************************************************
skipping: [172.31.83.23]
TASK [test : debug] ************************************************************
ok: [172.31.83.23] => {
"yel_ver_str": {
"changed": false,
"cmd": "/bin/gawk '{ for(col = 1; col <= NF; col++) if ($col ~ /[0-9.]+/) { print $col; } }' /etc/yellow-release",
"delta": "0:00:00.004225",
"end": "2016-04-22 13:37:29.517570",
"failed": false,
"failed_when_result": false,
"rc": 0,
"start": "2016-04-22 13:37:29.513345",
"stderr": "",
"stdout": "7.2.0",
"stdout_lines": [
"7.2.0"
],
"warnings": []
}
}
TASK [test : debug] ************************************************************
ok: [172.31.83.23] => {
"is_yos": true
}
TASK [test : Get yellow major version.] ****************************************
skipping: [172.31.83.23]
PLAY RECAP *********************************************************************
172.31.83.23 : ok=5 changed=0 unreachable=0 failed=0
Look at this output from your debug task:
TASK [test : debug] ************************************************************
ok: [172.31.83.23] => {
"is_yos": true
}
The is_yos fact is a boolean variable (true is a boolean value, while "true" would be a string value). So when you test:
when: is_yos == "true"
The check is false, because you are comparing a boolean to a string. Instead use:
when: is_yos
Related
I want to run a task only if at the previous task it contains a specific output.
E.g. I am checking if the status is "running". If yes, then run a command
My playbook:
- name: 'Backup'
hosts: localhost
tasks:
-
name: 'CHeck_Status'
shell: tool ha status |grep -i Status
register: service_status
-
debug:
var: service_status.stdout_lines
-
name: 'Run ls'
shell: ls -ltr
when: service_status.stdout_lines == "Status*running"
register: output
-
debug:
var: output
The output of the command is
PLAY [Backup] ******************************************************************************************************************************************************
TASK [Gathering Facts] *****************************************************************************************************************************************************
ok: [localhost]
TASK [CHeck_Status] *****************************************************************************************************************************************************
changed: [localhos]
TASK [debug] ***************************************************************************************************************************************************************
ok: [localhost] => {
"service_status.stdout_lines": [
"Status: running",
"Status: running"
]
}
TASK [Run ls] **************************************************************************************************************************************************************
skipping: [localhost]
TASK [debug] ***************************************************************************************************************************************************************
ok: [localhost] => {
"output": {
"changed": false,
"skip_reason": "Conditional result was False",
"skipped": true
}
}
PLAY RECAP *****************************************************************************************************************************************************************
localhost : ok=4 changed=1 unreachable=0 failed=0
it always fails. Any help on how can I do the conditional for when?
Also if I try this conditional I get the below error:
The offending line appears to be:
shell: ls -ltr
when: service_status.stdout_lines == "'Status: running'"
^ here
Thank you
Test the item 'Status: running' is in the list, e.g.
- name: Run ls
shell: ls -ltr
register: output
when: "'Status: running' in service_status.stdout_lines"
Club multiple variable and get one output in ansible
I will be using combined variable many other parts of the code and Is there a way to do it.
name:
hosts: dummy
gather_facts: True
tasks:
block:
Capture package-Infra agent version
v1
- name: Get package-Integration agent version ostype1.4
shell: command1
register: NRAV1
when: ansible_distribution == "ostype" and ansible_distribution_version == "v1"
- name: Debug
debug:
msg: "{{ NRAV1 }}"
v2
- name: Get package-Integration agent version ostype2.2
shell: command2
register: NRAV2
when: ansible_distribution == "ostype" and ansible_distribution_version == "v2"
- name: Debug
debug:
msg: "{{ NRAV2 }}"
v3
- name: Get package-Integration agent version ostype2.3
shell: command3
register: NRAV3
when: ansible_distribution == "ostype" and ansible_distribution_version == "v3"
- name: Debug
debug:
msg: "{{ NRAV3 }}"
- name: Result
debug:
msg: "{{ NRAV1.stdout | NRAV2.stdout | NRAV2.stdout }}"
#Output:
TASK [setup] *******************************************************************
ok: [dummy]
TASK [Get package-Integration agent version ostype1.4] *************************
skipping: [dummy]
TASK [Debug] *******************************************************************
ok: [dummy] => {
"msg": {
"changed": false,
"skip_reason": "Conditional check failed",
"skipped": true
}
}
TASK [Get package-Integration agent version ostype2.2] *************************
changed: [dummy]
TASK [Debug] *******************************************************************
ok: [dummy] => {
"msg": {
"changed": true,
"cmd": "rpm -qa --last | grep package-infra | awk '{print $1}' | cut -d'-' -f 3,4 | cut -d'.' -f 1,2,3,4,5",
"delta": "0:00:00.524132",
"end": "2021-03-07 12:06:33.150778",
"rc": 0,
"start": "2021-03-07 12:06:32.626646",
"stderr": "",
"stdout": "1.15.1-1.ostype2.2",
"stdout_lines": [
"1.15.1-1.ostype2.2"
],
"warnings": [
"Consider using yum module rather than running rpm"
]
}
}
TASK [Get package-Integration agent version ostype2.3] *************************
skipping: [dummy]
TASK [Debug] *******************************************************************
ok: [dummy] => {
"msg": {
"changed": false,
"skip_reason": "Conditional check failed",
"skipped": true
}
}
TASK [Result] *******************************************************************
fatal: [dummy]: FAILED! => {"failed": true, "msg": "ERROR! template error while templating string: no filter named 'NRAV3.stdout'"}
PLAY RECAP *********************************************************************
dummy : ok=5 changed=1 unreachable=0 failed=1
#My expected result would be >> NRAV2.stdout >> "1.15.1-1.ostype2.2"
Ansible is unable to parse below line -
msg: "{{ NRAV1.stdout | NRAV2.stdout | NRAV3.stdout }}"
You need to replace it with something like this -
msg: "{{ NRAV1.stdout }} | {{ NRAV2.stdout }} | {{ NRAV3.stdout }}"
I have two identical tasks in the same playbook:
when: var == "true"
when: var == "false"
Both tasks are using register: result, but first one fails and second one succeeds.
I tried using block: and not just when: and the behaviour is the same.
bug-when.yml
---
- hosts: localhost
tasks:
- name: when true
debug:
msg: "this is true"
register: result
when: var == "true"
- name: when false
debug:
msg: "this is false"
register: result
when: var == "false"
- name: print result
debug:
msg: "{{ result }}"
Example running it:
ansible-playbook bug-when.yml -e var=true
PLAY [localhost] ***************************************************************
TASK [setup] *******************************************************************
Thursday 09 May 2019 18:51:35 +0000 (0:00:02.018) 0:00:02.018 **********
ok: [localhost]
TASK [when true] ***************************************************************
Thursday 09 May 2019 18:51:35 +0000 (0:00:00.437) 0:00:02.456 **********
ok: [localhost] => {
"msg": "this is true"
}
TASK [when false] **************************************************************
Thursday 09 May 2019 18:51:35 +0000 (0:00:00.027) 0:00:02.483 **********
skipping: [localhost]
TASK [print result] ************************************************************
Thursday 09 May 2019 18:51:36 +0000 (0:00:00.023) 0:00:02.506 **********
ok: [localhost] => {
"msg": {
"changed": false,
"skip_reason": "Conditional check failed",
"skipped": true
}
}
PLAY RECAP *********************************************************************
localhost : ok=3 changed=0 unreachable=0 failed=0
Second example running it:
ansible-playbook bug-when.yml -e var=false
PLAY [localhost] ***************************************************************
TASK [setup] *******************************************************************
Thursday 09 May 2019 18:52:01 +0000 (0:00:02.019) 0:00:02.019 **********
ok: [localhost]
TASK [when true] ***************************************************************
Thursday 09 May 2019 18:52:01 +0000 (0:00:00.453) 0:00:02.472 **********
skipping: [localhost]
TASK [when false] **************************************************************
Thursday 09 May 2019 18:52:01 +0000 (0:00:00.024) 0:00:02.497 **********
ok: [localhost] => {
"msg": "this is false"
}
TASK [print result] ************************************************************
Thursday 09 May 2019 18:52:02 +0000 (0:00:00.028) 0:00:02.525 **********
ok: [localhost] => {
"msg": {
"changed": false,
"msg": "this is false"
}
}
PLAY RECAP *********************************************************************
localhost : ok=3 changed=0 unreachable=0 failed=0
To expand upon what #b.enoit.be said:
When you have a task like this:
- name: some task
debug:
msg: this is an example
when: false
register: result
This will update result even if the task is skipped. This is what permits you, in a subsequent task, to see if this task was skipped or not:
- name: check if task was skipped
debug:
msg: previous task was skipped
when: result is skipped
Consider registering a different variable in each task, and then:
- name: when true
debug:
msg: "this is true"
register: result1
when: var == "true"
- name: when false
debug:
msg: "this is false"
register: result2
when: var == "false"
- name: print result
debug:
msg: "{{ result1.msg if result2 is skipped else result2.msg }}"
The behaviour you see here happens because the tasks are always registered, mostly because you can self reference a task register in itself, and this behaviour would fail if the tasks was not always registering itself.
So what you need to do is to have two different register handle and act upon the result and skipped attributes of them to display your message properly.
Here is the playbook:
---
- hosts: localhost
tasks:
- name: when true
debug:
msg: "this is true"
register: result_is_true
when: var == "true"
- name: when false
debug:
msg: "this is false"
register: result_is_false
when: var == "false"
- name: print result
debug:
msg: "{{ result_is_true if result_is_false is skipped else result_is_false }}"
Here is the run when var is true
$ ansible-playbook so.yml -e var=true
PLAY [localhost] *******************************************************************************************************************************************************************************************
TASK [Gathering Facts] *************************************************************************************************************************************************************************************
ok: [host1]
TASK [when true] *******************************************************************************************************************************************************************************************
ok: [host1] => {
"msg": "this is true"
}
TASK [when false] ******************************************************************************************************************************************************************************************
skipping: [host1]
TASK [print result] ****************************************************************************************************************************************************************************************
ok: [host1] => {
"msg": {
"changed": false,
"failed": false,
"msg": "this is true"
}
}
PLAY RECAP *************************************************************************************************************************************************************************************************
host1 : ok=3 changed=0 unreachable=0 failed=0
And here is the result when var is false
$ ansible-playbook so.yml -e var=false
PLAY [localhost] *******************************************************************************************************************************************************************************************
TASK [Gathering Facts] *************************************************************************************************************************************************************************************
ok: [host1]
TASK [when true] *******************************************************************************************************************************************************************************************
skipping: [host1]
TASK [when false] ******************************************************************************************************************************************************************************************
ok: [host1] => {
"msg": "this is false"
}
TASK [print result] ****************************************************************************************************************************************************************************************
ok: [host1] => {
"msg": {
"changed": false,
"failed": false,
"msg": "this is false"
}
}
PLAY RECAP *************************************************************************************************************************************************************************************************
host1 : ok=3 changed=0 unreachable=0 failed=0
Needless to say: I would guess you simplified your issue for a MCVE, but your play can actually be as simple as
---
- hosts: localhost
tasks:
- name: print result
debug:
msg: "{{ 'this is true' if var == true else 'this is false' }}"
Which runs:
$ ansible-playbook so.yml -e var=false
PLAY [localhost] ***********************************************************************************************************************************************************************************
TASK [Gathering Facts] *****************************************************************************************************************************************************************************
ok: [host1]
TASK [print result] ********************************************************************************************************************************************************************************
ok: [host1] => {
"msg": "this is false"
}
PLAY RECAP *****************************************************************************************************************************************************************************************
host1 : ok=2 changed=0 unreachable=0 failed=0
$ ansible-playbook so.yml -e var=true
PLAY [localhost] ***********************************************************************************************************************************************************************************
TASK [Gathering Facts] *****************************************************************************************************************************************************************************
ok: [host1]
TASK [print result] ********************************************************************************************************************************************************************************
ok: [host1] => {
"msg": "this is true"
}
PLAY RECAP *****************************************************************************************************************************************************************************************
host1 : ok=2 changed=0 unreachable=0 failed=0
And for reference here is a jinja inline if-expression question: https://stackoverflow.com/a/14215034/2123530
Let's consider following output of some command (it is debug of stdout_lines):
- command: "some command"
register: output
- debug:
msg: "{{ output.stdout_lines }}"
"msg": [
"X",
"Y",
"Z",
" 1 some_word1",
" 1 some_word2",
" 1 some_word3",
" 1 some_word4"
]
The output is registered in variable output using command task. Now, I need to parse it into a list of the form: [some_word1,some_word2,some_word3,some_word4].
Please keep in mind that output can contain more or less (even 0) than 4 words.
When it comes to "X","Y","Z" they are constant (always three lines) so I can skip it using:
- debug:
msg: "{{ output.stdout_lines[3:] }}"
However, I don't know how to deal with leading spaces and digit.
Could you give me some clues, please?
Knowing a string is "just" a list of char in python, if your output is always
/[[:space:]]+[[:digit:]] (.*)/
and never
/[[:space:]]+[[:digit:]]+ (.*)/
e.g. 1 some_word1 or 9 some_word9 but not 10 some_word10
Then you could apply the trim filter and just reuse your same list index trick, ending with this jinja expression:
---
- hosts: local
vars:
"msg": [
"X",
"Y",
"Z",
" 1 some_word1",
" 1 some_word2",
" 1 some_word3",
" 1 some_word4"
]
tasks:
- debug:
msg: "{{ (item | trim())[2:] }}" # after trimming the item, we just ignore the first two char as you did for your three first output lines
with_items: "{{ msg[3:] }}"
This outputs:
/data/playbooks # ansible-playbook so.yml
PLAY [local] *******************************************************************
TASK [Gathering Facts] *********************************************************
ok: [host1]
TASK [debug] *******************************************************************
ok: [host1] => (item= 1 some_word1) => {
"msg": "some_word1"
}
ok: [host1] => (item= 1 some_word2) => {
"msg": "some_word2"
}
ok: [host1] => (item= 1 some_word3) => {
"msg": "some_word3"
}
ok: [host1] => (item= 1 some_word4) => {
"msg": "some_word4"
}
PLAY RECAP *********************************************************************
host1 : ok=2 changed=0 unreachable=0 failed=0
Now if you have the second form, or if you want to make it more the bash way, then you could change your command to a shell – because shell accepts piping when command does not – and pipe your output to awk:
---
- hosts: local
tasks:
- shell: printf "X\nY\nZ\n 1 some_word1\n 1 some_word2\n 1 some_word3\n 1 some_word4" | awk '{print $2}'
register: output
- debug:
msg: "{{ output.stdout_lines[3:] }}"
This outputs:
/data/playbooks # ansible-playbook so.yml
PLAY [local] *******************************************************************
TASK [Gathering Facts] *********************************************************
ok: [host1]
TASK [shell] *******************************************************************
changed: [host1]
TASK [debug] *******************************************************************
ok: [host1] => {
"msg": [
"some_word1",
"some_word2",
"some_word3",
"some_word4"
]
}
PLAY RECAP *********************************************************************
host1 : ok=3 changed=1 unreachable=0 failed=0
I have my playbook as below:
---
- hosts: myser
tasks:
- name: Checking.
win_command: mycommand
register: win_command_result
- set_fact:
myvar={{win_command_result.stdout | regex_search('\\d+')}}
register: myvar_result
- debug:
var: myvar_result.ansible_facts.ple
- name: Checking Condition
win_command: ipconfig
register: ipconfig
when: myvar_result.ansible_facts.ple < 5000
- debug:
var: ipconfig
And below is output.
I am getting two different values per server but the task Checking Condition gets skipped. Based on the value, for one server it should skip and for another it should execute.
PLAY [myser]
*******************************************************
TASK [Gathering Facts]
**************************************************
ok: [ser1]
ok: [ser2]
TASK [Checking]
****************************
changed: [ser1]
changed: [ser2]
TASK [set_fact]
*********************************************************
ok: [ser1]
ok: [ser2]
TASK [debug]
************************************************************
ok: [ser1] => {
"myvar_result.ansible_facts.ple": "232"
}
ok: [ser2] => {
"myvar_result.ansible_facts.ple": "378416"
}
TASK [Checking Condition]
**********************************************
skipping: [ser1]
skipping: [ser2]
TASK [debug]
************************************************************
ok: [ser1] => {
"ipconfig": {
"changed": false,
"skip_reason": "Conditional result was False",
"skipped": true
}
}
ok: [ser2] => {
"ipconfig": {
"changed": false,
"skip_reason": "Conditional result was False",
"skipped": true
}
}
PLAY RECAP
**************************************************************
ser2 : ok=5 changed=1 unreachable=0 failed=0
ser1 : ok=5 changed=1 unreachable=0 failed=0
I want to use myvar_result.ansible_facts.ple in when condition. So idea here is if myvar_result.ansible_facts.ple crosses value of 5000 then execute "checking name"
Am I missing something here? How to get it work?
It is working properly, but you are comparing a string with an integer.
As you can see in your output:
"myvar_result.ansible_facts.ple": "232"
"myvar_result.ansible_facts.ple": "378416"
your values are strings (as is any command result passed in stdout, as well as the output of the regex_search filter).
Cast them to integer before doing the comparison in the conditional:
- name: Checking Condition
win_command: ipconfig
register: ipconfig
when: myvar_result.ansible_facts.ple|int < 5000