Ansible - Looping and Debug/Register - ansible

I have the following task.
However, it doesn't output the output for each ping that is produced, and I only get a 1 x output. When there should be x 5.
Task
tasks:
- name: "Check Connectivity (ping)"
nxos_ping:
provider: "{{ nxos_ssh }}"
source: "{{ hostvars[inventory_hostname]['lo0_ipaddr'] }}"
vrf: default
dest: "192.168.1.{{item}}"
with_sequence: start=1 end=5
register: out
- debug:
msg:
- "command: {{ out['results'][0]['commands'][0] }}"
Example
TASK [Check Connectivity (ping)] ***************************************************************************************************
ok: [spine-nxos-1] => (item=1)
ok: [spine-nxos-2] => (item=1)
ok: [spine-nxos-2] => (item=2)
ok: [spine-nxos-1] => (item=2)
ok: [spine-nxos-1] => (item=3)
ok: [spine-nxos-2] => (item=3)
ok: [spine-nxos-1] => (item=4)
ok: [spine-nxos-2] => (item=4)
ok: [spine-nxos-1] => (item=5)
ok: [spine-nxos-2] => (item=5)
TASK [debug] ***********************************************************************************************************************
ok: [spine-nxos-1] => {
"msg": [
"command: ping 192.168.1.1 count 5 source 192.168.1.1 vrf default"
]
}
ok: [spine-nxos-2] => {
"msg": [
"command: ping 192.168.1.1 count 5 source 192.168.1.2 vrf default"
]
}

Your code is working correct, as you only print out the first element of the registered output. If you want to see all your commands you should replace the last line of your playbook with:
- "command {{ out | json_query('results[*].commands[*]') }}"
or loop through your output corresponding to your sequence:
debug:
msg:
- "command {{ out.results[item|int].commands[0]}}"
with_sequence: start=0 end=2

Related

Ansible set_fact array not appending

I'm trying to look for all drives that have certain properties and append those drives to an array under set_facts.
When I print the contents of the array I only see the last drive in the system that matched the search. I can't figure out why it's not appending all the drives that match the criteria.
---
- hosts: worker1
gather_facts: yes
tasks:
- name: Initialize an empty list for our strings
set_fact:
disks: []
run_once: True
- name: Print disk result
set_fact:
disks: "{{ disks + [item.key] }}"
when:
- not item.value.partitions
- not item.value.holders
- not item.value.links.ids
- item.key | search ("vd")
with_dict: "{{ ansible_devices }}"
- name: debug
debug:
msg: "{{disks}}"
Output
ok: [worker1] => {
"msg": [
"vdd"
]
}
it should contain "vdb", "vdc", "vdd", and "vde"
FYI when I replace the
set_fact:
disks: "{{ disks + [item.key] }}"
with
debug:
msg: "{{ item.key }}"
output
ok: [worker1] => (item=None) => {
"msg": "vdc"
}
ok: [worker1] => (item=None) => {
"msg": "vdb"
}
ok: [worker1] => (item=None) => {
"msg": "vde"
}
skipping: [worker1] => (item=None)
skipping: [worker1] => (item=None)
ok: [vmaas-worker1] => (item=None) => {
"msg": "vdd"
}
skipping: [worker1] => (item=None)
skipping: [worker1] => (item=None)
I do see the correct drives listed, hence why I'm baffled it doesn't append to the array.

for each host need to print only one item

I have a list of descriptions that will be added one per host. I would like to print one item per host and it is becoming harder than I expected. The same item is being printed per each host.
tasks:
- name: items in list
debug:
msg: "{{ item }}"
with_items:
- ['a', 'b']
THIS IS WHAT I GET:
TASK [items in list] *****************************************************************************************************************************************************************************************************************************
ok: [Host1] => (item=a) => {
"msg": "a"
}
ok: [Host2] => (item=a) => {
"msg": "a"
}
ok: [Host1] => (item=b) => {
"msg": "b"
}
ok: [Host2] => (item=b) => {
"msg": "b"
}
THIS IS WHAT I WANT:
TASK [items in list] *****************************************************************************************************************************************************************************************************************************
ok: [Host1] => (item=a) => {
"msg": "a"
}
ok: [Host2] => (item=b) => {
"msg": "b"
}
There are many options. For example,
Create lists for the hosts
- name: items in list
debug:
msg: "{{ item }}"
loop: "{{ _list[inventory_hostname] }}"
vars:
_list:
host1: ['a']
host2: ['b']
gives
ok: [host1] => (item=['a']) =>
msg: a
ok: [host2] => (item=['b']) =>
msg: b
Calculate the index of the host in the group, e.g.
- name: items in list
debug:
msg: "{{ _list[_idx|int] }}"
vars:
_list: ['a', 'b']
_idx: "{{ groups.all.index(inventory_hostname) }}"
gives
ok: [host2] =>
msg: b
ok: [host1] =>
msg: a
Run the task once and iterate the sequence, e.g.
- name: items in list
debug:
msg: "{{ _list[item|int] }}"
with_sequence: start=0 end="{{ groups.all|length -1 }}"
vars:
_list: ['a', 'b']
run_once: true
delegate_to: localhost
gives
ok: [host1 -> localhost] => (item=0) =>
msg: a
ok: [host1 -> localhost] => (item=1) =>
msg: b

Migration between with_items to loop

I'm trying to migrate some code from with_items to loop.
I have this playbook.yml. Seems they are the same but just changed the with_items to loop
- debug:
msg: "{{ item }}"
loop:
- "{{ lookup('pipe','echo -e \"pro.json\npre.json\ndev.json\"').split('\n') }}"
- debug:
msg: "{{ item }}"
with_items:
- "{{ lookup('pipe','echo -e \"pro.json\npre.json\ndev.json\"').split('\n') }}"
This is the output.
TASK [loop: debug] **********************************************************************************************************************************************************************************
ok: [server] => (item=[u'pro.json', u'pre.json', u'dev.json']) => {
"msg": [
"pro.json",
"pre.json",
"dev.json"
]
}
TASK [with_items : debug] **********************************************************************************************************************************************************************************
Ok: [server] => (item=pro.json) => {
"msg": "pro.json"
}
ok: [server] => (item=pre.json) => {
"msg": "pre.json"
}
ok: [server] => (item=dev.json) => {
"msg": "dev.json"
}
As you see loop keeps the output in a kind of chain and with_items split it in three outputs.
I need change the ouput of loop, to look like the with_items. What I want is create a loop that give me a list, depend on the list this loop will be looping.
The with_items result will loop three or as many as the pipe command does but loop only will one
EDIT:
I have tried the with sequence solution for loop and seems this is posible but I cannot change my code to work like.
https://docs.ansible.com/ansible/latest/user_guide/playbooks_loops.html?highlight=loop#with-sequence
TASK [: with_sequence] **************************************************************************************************************************************************************************
ok: [server] => (item=testuser00) => {
"msg": "testuser00"
}
ok: [server] => (item=testuser02) => {
"msg": "testuser02"
}
ok: [server] => (item=testuser04) => {
"msg": "testuser04"
}
TASK [: with_sequence -> loop] ******************************************************************************************************************************************************************
ok: [server] => (item=0) => {
"msg": "testuser00"
}
ok: [server] => (item=2) => {
"msg": "testuser02"
}
ok: [server] => (item=4) => {
"msg": "testuser04"
}
Pass the list directly and not as a listitem containing the list to loop
- debug:
msg: "{{ item }}"
loop: "{{ lookup('pipe','echo -e \"pro.json\npre.json\ndev.json\"').split('\n') }}"
For more infos see https://docs.ansible.com/ansible/latest/user_guide/playbooks_loops.html

ansible find first undefined value in list

I have a list in ansible and I want to find the first "unused" item in that list.
Example list:
item001
item002
item004
item005
item100
item101
The prefix numbers in the items could be up to 999
In the example above the result should be item003.
Here is an example playbook of what I want
---
- name: Test
connection: local
hosts: localhost
vars:
my_list: []
list1:
- item107
- item002
- item004
- item001
- item007
- item101
- item604
tasks:
- name: Initialize a dummy list
set_fact:
my_list: "{{ my_list|sort }} + [ '{{ item }}' ]"
with_sequence: start=1 end=19 format=item%.3d
- name: print first unused value in my_list
debug:
msg: "{{ (my_list | difference(list1))[0] }}"
output:
PLAY [Test] *******************************************************************************************************************************************************************************************************
TASK [Gathering Facts] ********************************************************************************************************************************************************************************************
ok: [localhost]
TASK [Initialize a dummy list] ************************************************************************************************************************************************************************************
ok: [localhost] => (item=item001)
ok: [localhost] => (item=item002)
ok: [localhost] => (item=item003)
ok: [localhost] => (item=item004)
ok: [localhost] => (item=item005)
ok: [localhost] => (item=item006)
ok: [localhost] => (item=item007)
ok: [localhost] => (item=item008)
ok: [localhost] => (item=item009)
ok: [localhost] => (item=item010)
ok: [localhost] => (item=item011)
ok: [localhost] => (item=item012)
ok: [localhost] => (item=item013)
ok: [localhost] => (item=item014)
ok: [localhost] => (item=item015)
ok: [localhost] => (item=item016)
ok: [localhost] => (item=item017)
ok: [localhost] => (item=item018)
ok: [localhost] => (item=item019)
TASK [print first unused value in my_list] ************************************************************************************************************************************************************************
ok: [localhost] => {
"msg": "item003"
}
PLAY RECAP ********************************************************************************************************************************************************************************************************
localhost : ok=3 changed=0 unreachable=0 failed=0
But if I change with_sequence: start=1 end=19 to with_sequence: start=1 end=999 the tasks takes very long time and also prints 999 lines in the output I really would love to not see.
This actually worked better, didn't print any large output and was much quicker:
- name: Initialize a dummy list
set_fact:
my_list: "{{ lookup('sequence', 'start=1 count=999 format=item%.3d', wantlist=True) }}"

Create VLAN number based on the current last VLAN number

I would like to create new VLAN based on the last number of existing VLANS. For example my last VLAN number on the eos is 100 so I would like to run my playbook and create VLAN 101. However when I run my playbook it looks like set_fact iteration is not in order and playbook created for me VLAN 15 instead VLAN 101.
Even I am using sort filter it looks like asnible is not doing iteration in order. Does anyone know how to do it?
My playbook
- name: CHECK VLAN
hosts: eos
connection: local
tasks:
- name: CHECK FOR VLAN NUMBERS
eos_command:
commands: show vlan | json
provider: "{{ cli }}"
ignore_errors: yes
register: sh_vlan_output
- debug: var=sh_vlan_output.stdout[0].vlans.keys()
- name: SET VLAN NUMBER
set_fact:
vlan_index: "{{ item | int +1 }}"
with_items:
- "{{ sh_vlan_output.stdout[0].vlans.keys() | sort }}"
- debug: var=vlan_index
- name: CREATE VLAN
eos_config:
lines:
- vlan {{ vlan_index }}
provider: "{{ cli }}"
authorize: yes
PLAY [CHECK VLAN] **************************************************************
TASK [setup] *******************************************************************
ok: [eos-1]
TASK [CHECK FOR VLAN NUMBERS] **************************************************
ok: [eos-1]
TASK [debug] *******************************************************************
ok: [eos-1] => {
"sh_vlan_output.stdout[0].vlans.keys()": [
"11",
"10",
"13",
"12",
"14",
"1",
"100"
]
}
TASK [SET VLAN NUMBER] *********************************************************
ok: [eos-1] => (item=10)
ok: [eos-1] => (item=1)
ok: [eos-1] => (item=100)
ok: [eos-1] => (item=11)
ok: [eos-1] => (item=12)
ok: [eos-1] => (item=13)
ok: [eos-1] => (item=14)
TASK [debug] *******************************************************************
ok: [eos-1] => {
"vlan_index": "15"
}
TASK [CREATE VLAN] *************************************************************
changed: [eos-1]
PLAY RECAP *********************************************************************
eos-1
You can get max + 1 with the following jinja expression:
{{ sh_vlan_output.stdout[0].vlans.keys() | map('int') | max + 1 }}

Resources