Debug of output in ansible fails with error - ansible

I am using following playbook
---
- name: ""
hosts: nexus
tasks:
- name: ""
debug:
var="{{ vlans | map(attribute='vlan_id') | join(',') }}"
and the output is:
ok: [nx01] => {
"10,20,100,30": "(10, 20, 100, 30)"
}
What is the type of my output ?
I tried
---
- name: ""
hosts: nexus
tasks:
- name: ""
debug:
var="{{ vlans | map(attribute='vlan_id') | join(',') | type_debug }} "
but get an error
ok: [nx02] => {
"str ": "VARIABLE IS NOT DEFINED!"
}

try this:
- name: Create a string with vlans
debug:
msg:
"{{ vlans | map(attribute = 'vlan_id') | join(',') }}"
- name: Create a string with vlans | type_debug
debug:
msg:
"{{ vlans | map(attribute = 'vlan_id') | join(',') | type_debug }}"
output:
TASK [Create a string with vlans] **************************************
ok: [localhost] => {
"msg": "10,20,100,30"
}
TASK [Create a string with vlans | type_debug] *************************
ok: [localhost] => {
"msg": "str"
}
The same example with list:
- name: Create a list with vlans
debug:
msg:
"{{ vlans | map(attribute = 'vlan_id') | list | default([]) }}"
- name: Create a string with vlans | type_debug
debug:
msg:
"{{ vlans | map(attribute = 'vlan_id') | list | default([]) | type_debug }}"
And the Output:
TASK [Create a list with vlans] ***************************************
ok: [localhost] => {
"msg": [
10,
20,
100,
30
]
}
TASK [Create a string with vlans | type_debug] ************************
ok: [localhost] => {
"msg": "list"
}
And if you need to set a variable:
- name: Set variable
set_fact:
mystrvar: "{{ vlans | map(attribute = 'vlan_id') | join(',') }}"
mylistvar: "{{ vlans | map(attribute = 'vlan_id') | list | default([]) }}"
- name: Debug mystrvar
debug:
var: mystrvar
- name: Debug mystrvar
debug:
var: mystrvar | type_debug
- name: Debug mylistvar
debug:
var: mylistvar
- name: Debug mylistvar
debug:
var: mylistvar | type_debug
The output:
TASK [Set variable] *******************************************************
ok: [localhost]
TASK [Debug mystrvar] *****************************************************
ok: [localhost] => {
"mystrvar": "10,20,100,30"
}
TASK [Debug mystrvar] *****************************************************
ok: [localhost] => {
"mystrvar | type_debug": "str"
}
TASK [Debug mylistvar] ****************************************************
ok: [localhost] => {
"mylistvar": [
10,
20,
100,
30
]
}
TASK [Debug mylistvar] ****************************************************
ok: [localhost] => {
"mylistvar | type_debug": "list"
}

Related

Ansible sum register value

How to get the sum of two hosts with Jinja2 filtering ansible
host1 and host 2
---
- name: Count Check
hosts: MYGROUP
gather_facts: true
user: sv_admin
tasks:
- name: count check
shell: cat /etc/hosts | wc -l
register: command_result
- debug:
var: command_result.stdout
- set_fact:
total_result: "{{ command_result.stdout | map('int') | sum(start=0) }}"
- debug:
msg: "Total count: {{ total_result }}"
Playbook Output
TASK [debug] *****************************************************************
ok: [Host-01] => {
"msg": "Total count: 134"
}
ok: [Host-02] => {
"msg": "Total count: 133"
}
Use extract and sum. For example, the playbook below
shell> cat playbook.yml
- hosts: test_01:test_03
gather_facts: false
tasks:
- shell: cat /etc/hosts | wc -l
register: command_result
- debug:
var: command_result.stdout
- set_fact:
total_result: "{{ ansible_play_hosts_all|
map('extract', hostvars, ['command_result', 'stdout'])|
map('int')|
sum }}"
run_once: true
- debug:
var: total_result
gives (abridged)
shell> ansible-playbook playbook.yml
PLAY [test_01:test_03] ****
TASK [shell] ****
changed: [test_01]
changed: [test_03]
TASK [debug] ****
ok: [test_01] => {
"command_result.stdout": " 62"
}
ok: [test_03] => {
"command_result.stdout": " 31"
}
TASK [set_fact] ****
ok: [test_01]
TASK [debug] ****
ok: [test_03] => {
"total_result": "93"
}
ok: [test_01] => {
"total_result": "93"
}
See serial
See the difference between ansible_play_hosts and ansible_play_hosts_all
You can use custom stats to do that: https://docs.ansible.com/ansible/latest/modules/set_stats_module.html
So for your case it would look like
---
- name: Count Check
hosts: MYGROUP
gather_facts: true
user: sv_admin
tasks:
- name: count check
shell: cat /etc/hosts | wc -l
register: command_result
- debug:
var: command_result.stdout
- set_fact:
host_result: "{{ command_result.stdout }}"
- debug:
msg: "Count for this host: {{ host_result }}"
- set_stats:
data: "{{ { 'total_count': host_result | int } }}"
Then if you run it with ANSIBLE_SHOW_CUSTOM_STATS=yes it will show you the result at the end:
$ ANSIBLE_SHOW_CUSTOM_STATS=yes ansible-playbook -i inventory pb.yml
... (usual output)
CUSTOM STATS: *************************************************************
RUN: { "total_count": 267}
The set_stats task adds results together from all the hosts by default, which is what you are looking for. You need to make sure the values are integers though, because if they are strings it will just concatenate them and you will end up with something like RUN: { "total_count": "134133"}. That's why I have put the data: bit the way I have - if you try to create the dictionary in regular yaml, like
data:
total_count: "{{ host_result | int }}"
you will see that the value is still a string (due to the way yaml/jinja works) and it won't work properly.

How to select mandatory character when generating random password with ansible?

I create a random password with Ansible. 4 characters in length.
- hosts: localhost
vars:
pwd_alias: "{{ lookup('password', '/dev/null length=4 chars=ascii_letters,digits,hexdigits,punctuation' ) }}"
user: root
tasks:
- debug:
msg: Sifre= {{pwd_alias}}
- debug:
msg: Sifre= {{pwd_alias}}
- debug:
msg: Sifre= {{pwd_alias}}
- debug:
msg: Sifre= {{pwd_alias}}
I want it to be password example. I want the output to look like this example.
TASK [debug]
ok: [localhost] => {
"msg": "Sifre= Z/bO"
}
TASK [debug]
ok: [localhost] => {
"msg": "Sifre= a_4G"
}
TASK [debug]
ok: [localhost] => {
"msg": "Sifre= 9a&0"
}
TASK [debug]
ok: [localhost] => {
"msg": "Sifre= d.2C"
}
ascii_letters = 1
hexdigits = 1
digits = 1
punctuation = 1
I want him to generate a random password like this. But what the system produces sometimes changes. Sometimes there are no digits, sometimes there is no punctuation. I want these 4 features to be absolutely.

ansible version = 2.7.10
This is how the outputs are
TASK [debug]
ok: [localhost] => {
"msg": "Sifre= Z/bh"
}
TASK [debug]
ok: [localhost] => {
"msg": "Sifre= a_-G"
}
TASK [debug]
ok: [localhost] => {
"msg": "Sifre= 9ad0"
}
TASK [debug]
ok: [localhost] => {
"msg": "Sifre= d.aC"
}
How do I get each character? Thank you so much
Generate the passwords in a separate file. Get random character from each set and create pwd_alias_list. Then shuffle and join the list.
$ cat generate-password-4.yml
- set_fact:
pwd_alias_list: []
- set_fact:
pwd_alias_list: "{{ pwd_alias_list + [
lookup('password', '/dev/null length=1 chars=' ~ item) ]
}}"
loop:
- ascii_letters
- digits
- hexdigits
- punctuation
- set_fact:
pwd_alias: "{{ pwd_alias_list|shuffle|join('') }}"
The tasks below
tasks:
- include_tasks: generate-password-4.yml
- debug:
var: pwd_alias
- include_tasks: generate-password-4.yml
- debug:
var: pwd_alias
- include_tasks: generate-password-4.yml
- debug:
var: pwd_alias
- include_tasks: generate-password-4.yml
- debug:
var: pwd_alias
give
"pwd_alias": "ld(9"
"pwd_alias": "2R`9"
"pwd_alias": "O5(0"
"pwd_alias": "2>z5"
It's possible to make the generation of the password more flexible and create a list of the characters' sets my_char_specs and number of the repetitions my_repeat
$ cat generate-password.yml
- set_fact:
pwd_alias_list: []
- set_fact:
pwd_alias_list: "{{ pwd_alias_list + [
lookup('password', '/dev/null length=1 chars=' ~ item.0) ]
}}"
with_nested:
- "{{ my_char_specs }}"
- "{{ range(0, my_repeat)|list }}"
- set_fact:
pwd_alias: "{{ pwd_alias_list|shuffle|join('') }}"
The task below repeat the random choice from four sets four times
vars:
my_char_specs:
- ascii_letters
- digits
- hexdigits
- punctuation
my_repeat: 4
tasks:
- include_tasks: generate-password.yml
- debug:
var: pwd_alias
and gives
"pwd_alias": "8=3[9BD(7?3bJ5y3"
This solution works, you need to generate each type chars separately then concatenate them :
- hosts: localhost
vars:
pwd_alias_digit1: "{{ lookup('password', '/dev/null length=1 chars=ascii_letters' ) }}"
pwd_alias_digit2: "{{ lookup('password', '/dev/null length=1 chars=digits' ) }}"
pwd_alias_digit3: "{{ lookup('password', '/dev/null length=1 chars=hexdigits' ) }}"
pwd_alias_digit4: "{{ lookup('password', '/dev/null length=1 chars=punctuation' ) }}"
pwd_alias: "{{ pwd_alias_digit1 + pwd_alias_digit2 + pwd_alias_digit3 + pwd_alias_digit4 }}"
user: root
tasks:
- debug:
msg: Sifre= {{pwd_alias}}
- debug:
msg: Sifre= {{pwd_alias}}
- debug:
msg: Sifre= {{pwd_alias}}
- debug:
msg: Sifre= {{pwd_alias}}
Another way is to create your own password lookup plugin : my_password. It's easier to create a new plugin and use it simple in a playbook. It's better and the playbook will remain readable.

How to use comparison operators with dictionary values?

I am trying to write a task that stores the dictionary values in variable based on the condition .
I'm new to this technology. Please anyone help on the below request.
I tried with the below code. Please check below.
- set_fact:
v1: "{{ v1|default([]) + item.keys() if item.values() == false else 1 }}"
loop: "{{ dv }}"
'dv' is a dictionary.
[{1A:True},{2A:True},{3A:False},{4A:False}]
Actually, here I'm trying to store false values in v1 by using comparison operators only.
Expected output:
v1 should contain following list:
[3A,4A]
Ansible Version: 2.5.15
Below works for me:
---
- hosts: localhost
vars:
dv:
1A: 'True'
2A: 'False'
3A: 'True'
4A: 'False'
tasks:
- name: debug
debug:
msg: "{{ item.value }}"
loop: "{{ dv | dict2items }}"
- set_fact:
v1: "{{ v1| default([]) + item.key if (item.value in 'False') else('') }}"
loop: "{{ dv | dict2items }}"
- debug:
var: v1
output -->
TASK [set_fact] *********************************************************************************************************
ok: [localhost] => (item={'key': u'1A', 'value': u'True'})
ok: [localhost] => (item={'key': u'3A', 'value': u'True'})
ok: [localhost] => (item={'key': u'2A', 'value': u'False'})
ok: [localhost] => (item={'key': u'4A', 'value': u'False'})
TASK [debug] ************************************************************************************************************
ok: [localhost] => {
"v1": "2A4A"
}
You can try the below code.
- hosts: localhost
connection: local
vars:
dv: [{1A:True},{2A:True},{3A:False},{4A:False}]
v2: []
v1: []
tasks:
- set_fact:
v1: "{{ v1|default([]) }} + [ {{ v1.append((item.keys()|first).split(':')[0]) if (item.keys()|first).split(':')[1] == 'False' else v2.append('1') }} ]"
with_items: "{{ dv }}"
- debug:
msg: "{{ v1 }}"
Here v2 is a variable declared to direct if the conditions are not met.
Output of the a above code is a below:
ok: [localhost] => {
"msg": [
"3A",
"4A"
]
}

ansible-playbook with_flattened migration to loop

I am trying to migrate my old playbooks that uses with_flattened to loop.
I tried to follow ansible user guide but failed to do so.
This is my host_var:
- hosts: example.com
vars:
- configureddisks:
- xvdb
- xvdc
- btrfsdisks:
- xvdf
- xvdg
My original task and its output is as follow:
# Task
- debug:
msg: "{{ item }}"
with_flattened:
- "{{ configureddisks | select('defined') | list }}"
- "{{ btrfsdisks | select('defined') | list }}"
# ansible-playbook output
TASK [devices : debug] **********************************************************************************************************************************************************************************************************************
ok: [example.com] => (item=xvdb) => {
"msg": "xvdb"
}
ok: [example.com] => (item=xvdc) => {
"msg": "xvdc"
}
ok: [example.com] => (item=xvdf) => {
"msg": "xvdf"
}
ok: [example.com] => (item=xvdg) => {
"msg": "xvdg"
}
My new task and its output is as follow:
# Task
- debug:
msg: "{{ item }}"
loop:
- "{{ configureddisks | select('defined') | list | flatten }}"
- "{{ btrfsdisks | select('defined') | list | flatten }}"
# ansible-playbook output
ok: [example.com] => (item=[u'xvdb', u'xvdc']) => {
"msg": [
"xvdb",
"xvdc"
]
}
ok: [example.com] => (item=[u'xvdf', u'xvdg']) => {
"msg": [
"xvdf",
"xvdg"
]
}
How should I write the new task using loop so that it has the same outputs as the old task?
You are misuing the flatten filter. When you write this:
loop:
- "{{ configureddisks | select('defined') | list | flatten }}"
- "{{ btrfsdisks | select('defined') | list | flatten }}"
The flatten filter has no effect: you are providing as input (twice) a list that is already flattened. You would need to apply the filter to the generated list, but rather than doing that, you can rewrite your expression so that no flattening is necessary:
- debug:
msg: "{{ item }}"
loop: "{{ (configureddisks + btrfsdisks) | select('defined') | list }}"
If you really wanted to go the "build a list of lists and flatten it" route, that might look something like:
- debug:
msg: "{{ item }}"
loop: >-
{{
(
(configureddisks | select('defined') | list) +
(btrfsdisks | select('defined') | list)
)|flatten
}}
Note that I've spread that across multiple lines for legibility, but you could just as easily write it all on one line:
loop: "{{ ((configureddisks | select('defined') | list) + (btrfsdisks | select('defined') | list))|flatten }}"

Splitting Ansible output into 2 different strings

I have the following on my playbook:
- name: Debug
debug:
msg: "{{ item.stdout }}"
with_items:
- "{{ tapip.results }}"
- "{{ hostname.results }}"
Which returns me this:
TASK [Debug] ***************************************************************************************************************************************************************************************************
ok: [localhost] => (item=None) => {
"msg": "192.168.0.104"
}
ok: [localhost] => (item=None) => {
"msg": "hostname1"
}
I would like to break the hostname and ip into 2 different strings. What is the best way to achieve this?
btw, I have also tried the following:
- name: Debug
debug:
msg: "{{ item.stdout.0 }} {{ item.stdout.1 }}"
with_items:
- "{{ tapip.results }}"
- "{{ hostname.results }}"
Which returns this:
TASK [Debug] ***************************************************************************************************************************************************************************************************
ok: [localhost] => (item=None) => {
"msg": "1"
}
ok: [localhost] => (item=None) => {
"msg": "h"
}
Any ideas would be appreciated
Try this
name: Debug
debug:
msg: "{{ item.stdout }}"
with_items:
tapip.results
hostname.results
name: Debug
debug:
msg: "{{ item.stdout }}"
with_items:
tapip.results
hostname.results

Resources