Club multiple variable and get one output in ansible - ansible

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

Related

How to run an Ansible task if *any* host has a fact

I'm wrapping my head around something that I'm probably overcomplicating.
I need to check if any of my hosts has ansible_virtualization_type == "openvz"
If this is the case, ALL hosts should execute a specific task.
I'm now trying to set a fact (virt_list) containing a list of hosts with their virtualization_type on localhost:
- name: Set fuse on virtualization OpenVZ
set_fact:
virt_list:
host: "{{item}}"
type: "openvz"
when: hostvars[item].ansible_virtualization_type == "openvz"
with_items: "{{ groups['all'] }}"
delegate_to: localhost
delegate_facts: true
but this doesn't work (both hosts in this play are on openvz):
TASK [roles/testvirt : debug vars ansible_virtualization_type ] ****************************
ok: [host1] => {
"ansible_virtualization_type": "openvz"
}
ok: [host2] => {
"ansible_virtualization_type": "openvz"
}
TASK [roles/testvirt : debug vars virt_list ] **********************************************
ok: [host1] => {
"msg": [
{
"host": "host1",
"type": "openvz"
}
]
}
ok: [host2] => {
"msg": [
{
"host": "host2",
"type": "openvz"
}
]
}
There should be a simpler way, maybe using jinjia2 to combine the lists directly.
Anyone has advices?
Q: "If any of my hosts has ansible_virtualization_type == "openvz" ALL hosts should execute a specific task."
A: For example, given the inventory for testing
shell> cat hosts
host1 ansible_virtualization_type=xen
host2 ansible_virtualization_type=xen
host3 ansible_virtualization_type=openvz
extract the variables
- debug:
msg: "{{ ansible_play_hosts|
map('extract', hostvars, 'ansible_virtualization_type')|
list }}"
run_once: true
gives
msg:
- xen
- xen
- openvz
Test if the type is present
- debug:
msg: OK. ALL hosts should execute a specific task.
when: "'openvz' in vtypes"
vars:
vtypes: "{{ ansible_play_hosts|
map('extract', hostvars, 'ansible_virtualization_type')|
list }}"
run_once: true
gives
msg: OK. ALL hosts should execute a specific task.
If this is working as expected proceed with all hosts
- set_fact:
all_hosts_execute_specific_task: true
when: "'openvz' in vtypes"
vars:
vtypes: "{{ ansible_play_hosts|
map('extract', hostvars, 'ansible_virtualization_type')|
list }}"
run_once: true
- debug:
msg: Execute a specific task.
when: all_hosts_execute_specific_task|default(false)
gives
TASK [set_fact] ************************************************************
ok: [host1]
TASK [debug] ***************************************************************
ok: [host1] =>
msg: Execute a specific task.
ok: [host3] =>
msg: Execute a specific task.
ok: [host2] =>
msg: Execute a specific task.
The task will be skipped if the type is missing.

How can I filter certain element in a string

playbook.yml
---
hosts: local_host
connection: local
gather_facts: False
tasks:
- name: set-details
set_fact:
filter: "{{ lookup('file', 'tmp/task2.yml') | from_json }}"
- set_fact:
result: "{{ filter['msg'] }}"
- debug:
var: result
task2.yml
{
"ansible_loop_var": "item",
"_ansible_no_log": false,
"invocation": {
"module_args": {
"wait_for_task": true,
"policy_package": "Mills07_Simplified",
"version": null,
"wait_for_task_timeout": 30
}
},
"item": "Mills07_Simplified",
"changed": false,
"msg": "Task Verify policy operation with task id 01234567-89ab-cdef-928b-bef7e174fc7a failed. Look at the logs for more details",
"_ansible_item_label": "Mills07_Simplified"
}
debug message
TASK [debug] *****************************************************************************************************************************************************************************
ok: [localhost] => {
"result": "Task Verify policy operation with task id 01234567-89ab-cdef-928b-bef7e174fc7a failed. Look at the logs for more details"
}
When I did the following,
- set_fact:
task_id: "{{ result |
select('regex', my_regex)|
first|
regex_replace(my_regex, my_replace) }}"
vars:
my_regex: '^Task Verify policy operation with task id (.*)$'
my_replace: '\1'
- debug:
var: task_id
I got an error message
fatal: [localhost]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'my_regex' is undefined\n\nThe error appears to be in
Goal: I want to get the task-id "01234567-89ab-cdef-928b-bef7e174fc7a"
How can I get this string 01234567-89ab-cdef-928b-bef7e174fc7a
Since you are looking for a universally unique identifier (or UUID) which has a defined format of 8-4-4-4-12 characters for a total of 36 characters (32 hexadecimal characters and 4 hyphens) source, you can use a simple regex to extract it.
It can be handled with the following regex:
[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}
You can test it there: https://regex101.com/r/4Hs7il/1
So, in a set_fact:
- set_fact:
uuid: >-
{{ filter.msg
| regex_search(
'([0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12})',
'\1',
ignorecase=True
)
| first
}}
As an example:
- hosts: localhost
gather_facts: no
tasks:
- set_fact:
uuid: >-
{{ filter.msg
| regex_search(
'([0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12})',
'\1',
ignorecase=True
)
| first
}}
vars:
filter:
msg: "Task Verify policy operation with task id 01234567-89ab-cdef-928b-bef7e174fc7a failed. Look at the logs for more details"
- debug:
var: uuid
Would yield the recap:
PLAY [localhost] ***************************************************************
TASK [set_fact] ****************************************************************
ok: [localhost]
TASK [debug] *******************************************************************
ok: [localhost] =>
uuid: 01234567-89ab-cdef-928b-bef7e174fc7a
PLAY RECAP *********************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

How to access a programmatically constructed ansible variable?

I have constructed an ansible variable using two other defined ansible variables. The constructed variable is defined in the vars/main.yml and I want to access the defined value in vars/main.yml.
vars/main.yml
---
var1_var2: "some value"
Now, I construct the variable
---
- name: Construct and get the value
hosts: localhost
tasks:
- include_vars: "vars/main.yml"
- set_fact:
variable1: "var1"
variable2: "var2"
- set_fact:
final_variable: "{{ variable1 }}_{{ variable2 }}"
- set_fact:
ultimate_variable: "{{ final_variable }}"
If I run the playbook with -vvv flag, I can see that ultimate_variable sets to var1_var2 while I want to get the value defined in the vars/main.yml
i.e., some value
TASK [set_fact]
ok: [localhost] => {
"ansible_facts": {
"variable1": "var1",
"variable2": "var2"
},
"changed": false,
"failed": false
}
TASK [set_fact] task path: /home/ubuntu/test.yml:78
ok: [localhost] => {
"ansible_facts": {
"final_variable": "var1_var2"
},
"changed": false,
"failed": false
}
TASK [set_fact]
ok: [localhost] => {
"ansible_facts": {
"ultimate_variable": "var1_var2"
},
"changed": false,
"failed": false
}
updated answer:
use the lookup plugin to do the double replacement:
ultimate_variable: "{{ lookup('vars', '{{final_variable}}') }}"
playbook:
- include_vars: "vars/main.yml"
- set_fact:
variable1: "var1"
variable2: "var2"
- set_fact:
final_variable: "{{ variable1 }}_{{ variable2 }}"
- set_fact:
ultimate_variable: "{{ lookup('vars', '{{final_variable}}') }}"
- debug:
var: ultimate_variable
output:
PLAY [localhost] ****************************************************************************************************************************************************************************************************
TASK [include_vars] *************************************************************************************************************************************************************************************************
ok: [localhost]
TASK [set_fact] *****************************************************************************************************************************************************************************************************
ok: [localhost]
TASK [set_fact] *****************************************************************************************************************************************************************************************************
ok: [localhost]
TASK [set_fact] *****************************************************************************************************************************************************************************************************
ok: [localhost]
TASK [debug] ********************************************************************************************************************************************************************************************************
ok: [localhost] => {
"ultimate_variable": "some value"
}
PLAY RECAP **********************************************************************************************************************************************************************************************************
localhost : ok=5 changed=0 unreachable=0 failed=0
hope it helps.
You could also skip the intermediary variable definition:
- include_vars: "vars/main.yml"
- set_fact:
variable1: "var1"
variable2: "var2"
- set_fact:
ultimate_variable: "{{ lookup('vars', variable1 ~ '_' ~ variable2) }}"
- debug:
var: ultimate_variable

set_fact is not persisting

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

Ansible Registered Variable not persisting in task

I am trying to use ansible to check to see if there are any aerospike migrations happening, and then run a task when migrations reach 0. To do that, I am using the ansible shell module to output the total number of migrations to stdout, register that output with ansible, and have ansible test on it.
Ansible seems to be recording the output correctly, but it is constantly displaying the stdout as "Hello World"
Here is my test playbook:
---
- hosts:
- foo
- bar
serial: 1
gather_facts: no
tasks:
- name: check for migrates
shell: "echo 10"
register: as_migrates
- debug: var=as_migrates
- debug: msg = "{{ as_migrates.stdout }}"
- debug: msg = "{{ as_migrates.stdout_lines }}"
- debug: msg = "{{ as_migrates }}"
Here is the output:
PLAY [foo;bar] ******************************************************
TASK: [check for migrates] ****************************************************
changed: [foo-10]
TASK: [debug var=as_migrates] *************************************************
ok: [foo-10] => {
"var": {
"as_migrates": {
"changed": true,
"cmd": "echo 10",
"delta": "0:00:00.001367",
"end": "2016-01-26 23:19:20.586245",
"invocation": {
"module_args": "echo 10",
"module_complex_args": {},
"module_name": "shell"
},
"rc": 0,
"start": "2016-01-26 23:19:20.584878",
"stderr": "",
"stdout": "10",
"stdout_lines": [
"10"
],
"warnings": []
}
}
}
TASK: [debug msg = "{{ as_migrates.stdout }}"] ********************************
ok: [foo-10] => {
"msg": "Hello world!"
}
TASK: [debug msg = "{{ as_migrates.stdout_lines }}"] **************************
ok: [foo-10] => {
"msg": "Hello world!"
}
TASK: [debug msg = "{{ as_migrates }}"] ***************************************
ok: [foo-10] => {
"msg": "Hello world!"
}
My question is: Why is does the debug var clearly show the correct stdout and the as_migrats.stdout display "Hello World"??
I know that "Hello World" is the default message for the message module. So is the register not persisting from one task to another?? I feel like I am missing something obvious. I don't have another variable named "as_migrates" in my ansible environment.
Ansible is "space" sensitive :-) You cannot have a space after msg
Try this:
- debug: msg="{{ as_migrates.stdout }}"
- debug: msg="{{ as_migrates.stdout_lines }}"
- debug: msg="{{ as_migrates }}"

Resources