Ansible set_fact output - ansible

I need the string or destination path as the output and use it in other task but the output displayed is dfifferent.
Here is the register output
ok: [localhost] => {
"msg": {
"changed": true,
"msg": "All items completed",
"results": [
{
"ansible_loop_var": "item",
"changed": true,
"checksum": "b045e5836bbd01d9c6dd2b7426afb5d1c8957b30",
"dest": "/home/ec2-user/bb/Data-1.1.tar.gz",
"failed": false,
"invocation": {
"module_args": {
"_original_basename": null,
"attributes": null,
"backup": false,
"checksum": null,
"content": null,
"delimiter": null,
"dest": "/home/ec2-user/bb/Data-1.1.tar.gz",
"directory_mode": null,
"follow": false,
"force": true,
"group": null,
"local_follow": null,
"mode": null,
"owner": null,
"regexp": null,
"remote_src": true,
"selevel": null,
"serole": null,
"setype": null,
"seuser": null,
"src": "/home/ec2-user/aa/Data-1.1.tar.gz",
"unsafe_writes": null,
"validate": null
}
},
"item": "/home/ec2-user/aa/Data-1.1.tar.gz",
"md5sum": "df9309334454cc3ceac9a6ac8fea8989",
"src": "/home/ec2-user/aa/Data-1.1.tar.gz"
I used the below the task to display the destination path
- set_fact:
filefact: "{{ output.results | map(attribute='item') | string }}"
- debug:
msg: "{{ filefact }}"
The output displayed is
ok: [localhost] => {
"msg": "<generator object do_map at 0x7f59539f01e0>"

i'd write :
- set_fact:
filefact: "{{ filefact | default([]) + [output.results.item] }}"
- debug:
msg: "{{ filefact }}"
the right syntax , following your output should be:
- set_fact:
filefact: "{{ filefact | default([]) + [output.results[0].item] }}"
or
- set_fact:
filefact: "{{ filefact | default([]) + [item.item] }}"
loop: "{{ output.results }}"

Related

Ansible vmware_guest module with_items how to loop the debug msg output

I'm trying to deploy some virtual machines which seems to be working fine, and I can get the output to a debug screen, but what I would like is to be able to filter the output a bit and show hostname and IP address really. But I'm not sure how to loop the output! I've tried:
- debug:
msg: {{ item.instance.ipv4 }}
with_items: _result.results
Here is my playbook:
---
- name: Clone VMs
hosts: localhost
gather_facts: false
vars_files:
- vars.yml
- secrets.yml
tasks:
- name: Clone multiple VMs from template
local_action:
module: vmware_guest
hostname: "{{ vcenter_hostname }}"
username: "{{ username }}"
password: "{{ password }}"
validate_certs: no
folder: "{{ folder }}"
template: "{{ item.template }}"
name: "{{ item.name }}"
esxi_hostname: "{{ esxi_hostname }}"
datacenter: "{{ datacenter }}"
state: "{{ state }}"
# customization_spec: "{{ customization_spec }}"
with_items: "{{ servers }}"
register: _result
- name: Output
debug:
msg: "{{ _result.results }}"
#with_items: _result.results.msg
In my vars I have the following (amongst other things)
servers:
- { name: centos8_01, template: centos8 }
- { name: centos7_01, template: centos7-minimal }
The output in the debug currently is:
ok: [localhost] => {
"msg": [
{
"ansible_loop_var": "item",
"changed": false,
"failed": false,
"instance": {
"annotation": "",
"current_snapshot": null,
"customvalues": {},
"guest_consolidation_needed": false,
"guest_question": null,
"guest_tools_status": "guestToolsRunning",
"guest_tools_version": "10346",
"hw_cluster": "Cluster",
"hw_cores_per_socket": 1,
"hw_datastores": [
"SSD"
],
"hw_esxi_host": "******",
"hw_eth0": {
"addresstype": "assigned",
"ipaddresses": [],
"label": "Network adapter 1",
"macaddress": "00:50:56:a3:4b:ba",
"macaddress_dash": "00-50-56-a3-4b-ba",
"portgroup_key": null,
"portgroup_portkey": null,
"summary": "10.0.0.0"
},
"hw_files": [
"[SSD] centos8_01/centos8_01.vmx",
"[SSD] centos8_01/centos8_01.nvram",
"[SSD] centos8_01/centos8_01.vmsd",
"[SSD] centos8_01/centos8_01.vmdk"
],
"hw_folder": "/Learn/vm/L2L",
"hw_guest_full_name": "CentOS 8 (64-bit)",
"hw_guest_ha_state": null,
"hw_guest_id": "centos8_64Guest",
"hw_interfaces": [
"eth0"
],
"hw_is_template": false,
"hw_memtotal_mb": 4096,
"hw_name": "centos8_01",
"hw_power_status": "poweredOn",
"hw_processor_count": 2,
"hw_product_uuid": "4223465f-32ce-38ab-0d0e-a92f187b7d4d",
"hw_version": "vmx-14",
"instance_uuid": "5023b456-cda0-1fa6-c0a5-67d57ede5707",
"ipv4": null,
"ipv6": null,
"module_hw": true,
"moid": "vm-12173",
"snapshots": [],
"vimref": "vim.VirtualMachine:vm-12173",
"vnc": {}
},
"invocation": {
"module_args": {
"annotation": null,
"cdrom": [],
"cluster": null,
"convert": null,
"customization": {},
"customization_spec": null,
"customvalues": [],
"datacenter": "******",
"datastore": null,
"disk": [],
"esxi_hostname": "******",
"folder": "L2L",
"force": false,
"guest_id": null,
"hardware": {},
"hostname": "******",
"is_template": false,
"linked_clone": false,
"name": "centos8_01",
"name_match": "first",
"networks": [],
"password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
"port": 443,
"proxy_host": null,
"proxy_port": null,
"resource_pool": null,
"snapshot_src": null,
"state": "poweredon",
"state_change_timeout": 0,
"template": "centos8",
"use_instance_uuid": false,
"username": "******#vsphere.local",
"uuid": null,
"validate_certs": false,
"vapp_properties": [],
"wait_for_customization": false,
"wait_for_ip_address": false
}
},
"item": {
"name": "centos8_01",
"template": "centos8"
}
},
{
"ansible_loop_var": "item",
"changed": false,
"failed": false,
"instance": {
"annotation": "",
"current_snapshot": null,
"customvalues": {},
"guest_consolidation_needed": false,
"guest_question": null,
"guest_tools_status": "guestToolsRunning",
"guest_tools_version": "10309",
"hw_cluster": "Corby",
"hw_cores_per_socket": 1,
"hw_datastores": [
"SSD"
],
"hw_esxi_host": "******",
"hw_eth0": {
"addresstype": "assigned",
"ipaddresses": [
"10.0.0.137",
"fe80::e1b4:c7c5:8268:4e7b"
],
"label": "Network adapter 1",
"macaddress": "00:50:56:a3:f8:9f",
"macaddress_dash": "00-50-56-a3-f8-9f",
"portgroup_key": null,
"portgroup_portkey": null,
"summary": "VM Network"
},
"hw_files": [
"[SSD] centos7_01/centos7_01.vmx",
"[SSD] centos7_01/centos7_01.nvram",
"[SSD] centos7_01/centos7_01.vmsd",
"[SSD] centos7_01/centos7_01_2.vmdk"
],
"hw_folder": "/Learn/vm/L2L",
"hw_guest_full_name": "CentOS 6 (64-bit)",
"hw_guest_ha_state": null,
"hw_guest_id": "centos6_64Guest",
"hw_interfaces": [
"eth0"
],
"hw_is_template": false,
"hw_memtotal_mb": 2048,
"hw_name": "centos7_01",
"hw_power_status": "poweredOn",
"hw_processor_count": 1,
"hw_product_uuid": "4223d5ef-9363-03d4-8aea-7b1822b21e36",
"hw_version": "vmx-14",
"instance_uuid": "5023eea9-85ac-1c18-48bb-e0b63339c9fa",
"ipv4": "10.0.0.137",
"ipv6": null,
"module_hw": true,
"moid": "vm-12174",
"snapshots": [],
"vimref": "vim.VirtualMachine:vm-12174",
"vnc": {}
},
"invocation": {
"module_args": {
"annotation": null,
"cdrom": [],
"cluster": null,
"convert": null,
"customization": {},
"customization_spec": null,
"customvalues": [],
"datacenter": "******",
"datastore": null,
"disk": [],
"esxi_hostname": "******",
"folder": "******",
"force": false,
"guest_id": null,
"hardware": {},
"hostname": "******",
"is_template": false,
"linked_clone": false,
"name": "centos7_01",
"name_match": "first",
"networks": [],
"password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
"port": 443,
"proxy_host": null,
"proxy_port": null,
"resource_pool": null,
"snapshot_src": null,
"state": "poweredon",
"state_change_timeout": 0,
"template": "centos7-minimal",
"use_instance_uuid": false,
"username": "******",
"uuid": null,
"validate_certs": false,
"vapp_properties": [],
"wait_for_customization": false,
"wait_for_ip_address": false
}
},
"item": {
"name": "centos7_01",
"template": "centos7-minimal"
}
}
]
}
There are multiple ways to do this.
A loop is one of them:
- debug:
msg:
hostname: "{{ item.invocation.module_args.hostname }}"
ip: "{{ item.instance.ipv4 }}"
loop: "{{ _result.results }}"
loop_control:
label: "item.invocation.module_args.hostname"
This would yield:
ok: [localhost] => (item=item.invocation.module_args.hostname) =>
msg:
hostname: '******'
ip: ''
ok: [localhost] => (item=item.invocation.module_args.hostname) =>
msg:
hostname: '******'
ip: 10.0.0.137
Another solution is to use JMESPath and the json_query filter:
- debug:
var: >-
_result.results
| json_query('[].{
hostname: invocation.module_args.hostname, ip: instance.ipv4
}')
This would yield:
ok: [localhost] =>
? |-
_result.results | json_query('[].{
hostname: invocation.module_args.hostname, ip: instance.ipv4
}')
: - hostname: '******'
ip: null
- hostname: '******'
ip: 10.0.0.137

Ansible: loop our shell command(Linux user group search) result and display the groups

Ansible: loop our shell command(Linux user group search) result and display the groups
Task to check if group exist
- name: "Checking if group doesn't exist"
shell: "grep -i {{ item.group }} /etc/group"
register: presence
loop: "{{ UserAddList.add_users }}"
ignore_errors: true
no_log: true
Json input file:
UserAddList is a json file
{
"add_users": [
{
"name": "test1_123",
"group": "test1_123",
"additional_groups":
[
"test2",
"group1"
],
"password" : "test1_newcdsaf",
"sudo_entry": "ALL=(ALL) NOPASSWD: ALL",
"comment": "test1"
}
],
"delete_users": [
]
}
Task to display the groups doesn't exist
- name: The following groups does't' exist
debug:
msg:
"{{ item._ansible_item_label.group }}"
loop: "{{ presence.results }}"
output:
(item={
'_ansible_parsed': True,
'stderr_lines': [
],
u'changed': True,
u'stdout': u'',
'_ansible_item_result': True,
u'msg': u'non-zero return code',
u'delta': u'0:00:00.008175',
'stdout_lines': [
],
'_ansible_item_label': {
u'comment': u'test1',
u'password': u'test1_newcdsaf',
u'group': u'test1_123',
u'name': u'test1_123',
u'sudo_entry': u'ALL=(ALL) NOPASSWD: ALL',
u'additional_groups': [
u'test2',
u'group1'
]
},
u'end': u'2019-12-10 14:23:15.725676',
'_ansible_no_log': True,
'item': {
u'comment': u'test1',
u'password': u'test1_newcdsaf',
u'group': u'test1_123',
u'name': u'test1_123',
u'sudo_entry': u'ALL=(ALL) NOPASSWD: ALL',
u'additional_groups': [
u'test2',
u'group1'
]
},
u'cmd': u'grep -i test1_123 /etc/group',
u'failed': True,
u'stderr': u'',
u'rc': 1,
u'invocation': {
u'module_args': {
u'warn': True,
u'executable': None,
u'_uses_shell': True,
u'_raw_params': u'grep -i test1_123 /etc/group',
u'removes': None,
u'argv': None,
u'creates': None,
u'chdir': None,
u'stdin': None
}
},
u'start': u'2019-12-10 14:23:15.717501'
})=>{
"changed": false,
"item": {
"changed": true,
"cmd": "grep -i test1_123 /etc/group",
"delta": "0:00:00.008175",
"end": "2019-12-10 14:23:15.725676",
"failed": true,
"invocation": {
"module_args": {
"_raw_params": "grep -i test1_123 /etc/group",
"_uses_shell": true,
"argv": null,
"chdir": null,
"creates": null,
"executable": null,
"removes": null,
"stdin": null,
"warn": true
}
},
"item": {
"additional_groups": [
"test2",
"group1"
],
"comment": "test1",
"group": "test1_123",
"name": "test1_123",
"password": "test1_newcdsaf",
"sudo_entry": "ALL=(ALL) NOPASSWD: ALL"
},
"msg": "non-zero return code",
"rc": 1,
"start": "2019-12-10 14:23:15.717501",
"stderr": "",
"stderr_lines": [
],
"stdout": "",
"stdout_lines": [
]
},
"msg": "test1_123"
}
I don't want to display the whole output, I just want to display the groups information.
The debug is printing all the input data as well.
Please any suggestions
The debug is printing all the input data as well.
It's actually not the debug: task that is printing your data, ansible is showing you what it is looping over. However, you are using loop: over the top-level presence.results list, and .results contains not only the output you care about, but also the invocation parameters, success or failure, and the actual returned data that you care about
There are two ways of fixing that problem: tell ansible that you only want it to show something smaller in the loop label, or change the loop: to actually only loop over the deleted users
In the first way, loop_control: will do that (it even cites your exact circumstance in the docs saying When looping over complex data structures, the console output of your task can be enormous. To limit the displayed output, use the label directive with loop_control):
- name: The following groups does't' exist
debug:
msg:
"{{ item._ansible_item_label.group }}"
loop: "{{ presence.results }}"
loop_control:
label: "{{ item.item.name }}"
In the second way, just select out the group you care about and msg: it:
- name: The following groups does't' exist
debug:
msg:
"{{ item }}"
loop: "{{ presence.results | map(attribute='item') | map(attribute='group') | list }}"

Debug not working with_items in ansible play

Need some help in debug the specific value from register task.
- debug:
msg: "{{ item.stdout }}"
with_items: path_result.results
This is not working
{
"changed": false,
"path_result": {
"msg": "All items completed",
"changed": true,
"results": [
{
"_ansible_parsed": true,
"stderr_lines": [],
"_ansible_item_result": true,
"end": "2019-04-10 14:55:18.726270",
"_ansible_no_log": false,
"_ansible_delegated_vars": {
"ansible_delegated_host": "**.***.***.***",
"ansible_host": "**.***.***.***"
},
"cmd": "cat /tmp/abc.conf | grep apple",
"rc": 0,
"stdout": "fruit=apple",
"item": "**.***.***.***",
"delta": "0:00:00.021499",
"stderr": "",
"changed": true,
"invocation": {
"module_args": {
"creates": null,
"executable": null,
"_uses_shell": true,
"_raw_params": "cat /tmp/abc.conf | grep apple",
"removes": null,
"warn": true,
"chdir": null,
"stdin": null
}
},
"stdout_lines": [
"fruit=apple"
],
"start": "2019-04-10 14:55:18.704771",
"_ansible_ignore_errors": null,
"failed": false
}
]
},
"_ansible_verbose_always": true,
"_ansible_no_log": false
}
I would like to debug this particular output:
"stdout": "fruit=apple"
It looks like you have registered the result of a play with: register: path_result. That variable ALSO has path_result inside it. Here's what I think you have:
- command: cat /tmp/abc.conf | grep apple
register: path_result
- debug:
msg: "{{ item.stdout }}"
with_items: "{{ path_result.results }}"
Here's what I think you need:
- command: cat /tmp/abc.conf | grep apple
register: path_result
- debug:
msg: "{{ item.stdout }}"
with_items: "{{ path_result.path_result.results }}"
Notice the added .path_result part in with_items.

Locate string/integer not in list

Im pulling a list of VLANs from our IPAM via an API and I want to be able to locate an unused "vlanId" that isnt in the list. I was expecting that I could use with_items for the JSON content and then use the random function with an until loop and occasionally it will initially generate a number that doesnt exist in the list. Mostly it just gets stuck and doesnt generate a new random number when the one generated already exists.
Playbook:
- uri:
url: "#"
validate_certs: no
headers:
token: "{{ token }}"
method: GET
force_basic_auth: yes
return_content: yes
register: ipam
- set_fact:
value: "{{ 4094 | random(start=1) }}"
until: value not in item.vlanId
with_items: "{{ ipam.json.data }}"
retries: 4093
- debug: msg="{{ value }}"
Relevant Output:
ok: [localhost] => (item={u'domainId': u'3', u'description': u'#', u'editDate': None, u'Customer ID': None, u'number': u'2241', u'vlanId': u'548', u'name': u'2241', u'Customer Name': None, u'custom_fields': None, u'Engineer': None}) => {
"ansible_facts": {
"value": "2727"
},
"ansible_facts_cacheable": false,
"attempts": 1,
"changed": false,
"item": {
"Customer ID": null,
"Customer Name": null,
"Engineer": null,
"custom_fields": null,
"description": "#",
"domainId": "3",
"editDate": null,
"name": "2241",
"number": "2241",
"vlanId": "548"
}
}
ok: [localhost] => (item={u'domainId': u'3', u'description': u'#', u'editDate': None, u'Customer ID': None, u'number': u'2242', u'vlanId': u'549', u'name': u'2242', u'Customer Name': None, u'custom_fields': None, u'Engineer': None}) => {
"ansible_facts": {
"value": "1955"
},
"ansible_facts_cacheable": false,
"attempts": 1,
"changed": false,
"item": {
"Customer ID": null,
"Customer Name": null,
"Engineer": null,
"custom_fields": null,
"description": "#",
"domainId": "3",
"editDate": null,
"name": "2242",
"number": "2242",
"vlanId": "549"
}
}
FAILED - RETRYING: set_fact (4000 retries left).Result was: {
"ansible_facts": {
"value": "50"
},
"ansible_facts_cacheable": false,
"attempts": 1,
"changed": false,
"retries": 4001
}
FAILED - RETRYING: set_fact (3999 retries left).Result was: {
"ansible_facts": {
"value": "50"
},
"ansible_facts_cacheable": false,
"attempts": 2,
"changed": false,
"retries": 4001
}
FAILED - RETRYING: set_fact (3998 retries left).Result was: {
"ansible_facts": {
"value": "50"
},
"ansible_facts_cacheable": false,
"attempts": 3,
"changed": false,
"retries": 4001
Im currently using ansible 2.4.2.0
If this is something that cant/shouldnt be done in Ansible, any guidance would be appreciated.
Here's what you want:
- debug:
msg: "{{ range(1, 4095) | difference(vlanIds) | random }}"
vars:
vlanIds: "{{ ipam.json.data | map(attribute='vlanId') | list }}"
Explanation:
map(attribute=... - create a list of vlan IDs,
range - generate a sequence from 1 to 4094,
difference - select all the elements from the above. that are not on the vlanIds list,
random - select a random element from the above.
For strings (as the title suggests) replace range with a list of possible strings.

ansible V2 -> "skip_reason": "Conditional check failed" with_items

I am getting some errors while doing the following:
group_vars:
tomcat_servers:
- name: tomcat_1
shutdown_port: 8005
connector_port: 8080
ajp_port: 8009
- name: tomcat_2
shutdown_port: 8105
connector_port: 8180
ajp_port: 8109
main code:
- name: "Check if tomcat is already installed"
stat: path={{ tomcat_server_dir }}/{{ item.name }}/RELEASE-NOTES
register: status
with_items: "{{ tomcat_servers }}"
- debug: var=status
- name: "Copy tomcat into folder if it is not installed"
command: /bin/tar -zxvf /tmp/{{ tomcat_catalina_base }} -C {{ tomcat_server_dir }}/{{ item.name }} --strip 2
when: not status.results[0].stat.exists
with_items:
- "{{ tomcat_servers }}"
- "{{ status.results }}"
Debug result:
ok: [VM1] => {
"status": {
"changed": false,
"msg": "All items completed",
"results": [
{
"_ansible_item_result": true,
"_ansible_no_log": false,
"changed": false,
"invocation": {
"module_args": {
"checksum_algorithm": "sha1",
"follow": false,
"get_checksum": true,
"get_md5": true,
"mime": false,
"path": "/opt/tomcat_3/RELEASE-NOTES"
},
"module_name": "stat"
},
"item": {
"ajp_port": 8009,
"connector_port": 8080,
"name": "tomcat_1",
"shutdown_port": 8005
},
"stat": {
"exists": false
},
{
"_ansible_item_result": true,
"_ansible_no_log": false,
"changed": false,
"invocation": {
"module_args": {
"checksum_algorithm": "sha1",
"follow": false,
"get_checksum": true,
"get_md5": true,
"mime": false,
"path": "/opt/tomcat_3/RELEASE-NOTES"
},
"module_name": "stat"
},
"item": {
"ajp_port": 8109,
"connector_port": 8180,
"name": "tomcat_2",
"shutdown_port": 8105
},
"stat": {
"exists": false
}
}
]
}
}
Now unfortunally I seem to get the error
"skip_reason": "Conditional check failed", "skipped": true
I have been around the "have you googled it" many times but cannot seem to find the solution here. Google ansible check if file exists with_items and you will probably see the same results.
Any one got an idea how to get this working?
Correct second loop:
---
- hosts: localhost
vars:
results:
- item:
ajp_port: 8009
connector_port: 8080
name: tomcat_1
shutdown_port: 8005
stat:
exists: false
- item:
ajp_port: 8109
connector_port: 8180
name: tomcat_2
shutdown_port: 8105
stat:
exists: false
- item:
name: tomcat_exist
stat:
exists: true
tasks:
- debug:
msg: "name: {{ item.item.name }}, exists: {{ item.stat.exists }}"
when: not item.stat.exists
with_items: "{{ results }}"
So in your setup you need to loop over status.results and refer to item.item.name and item.stat.exists.

Resources