Is it possible to combine with_dict with with_items? - ansible

I have an output of a playbook and I want to debug a message based on a condition of the output. I need the key and value pairs of the item to match a when statement then I will print out the actual data.
ok: [pynet-sw5] => {
"loop_iterate": {
"changed": false,
"msg": "All items completed",
"results": [
{
"_ansible_ignore_errors": null,
"_ansible_item_label": "1.1.1.1",
"_ansible_item_result": true,
"_ansible_no_log": false,
"_ansible_parsed": true,
"changed": false,
"failed": false,
"invocation": {
"module_args": {
"count": null,
"destination": "1.1.1.1",
"dev_os": "eos",
"hostname": "arista5.twb-tech.com",
"optional_args": null,
"password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
"ping_timeout": null,
"provider": {
"dev_os": "eos",
"hostname": "arista5.twb-tech.com",
"password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
"timeout": 60,
"username": "xxx"
},
"size": null,
"source": null,
"timeout": 60,
"ttl": null,
"username": "pyclass",
"vrf": null
}
},
"item": "1.1.1.1",
"results": {
"success": {
"packet_loss": 0,
"probes_sent": 5,
When I put the below statement it returns with item is not defined error.
- debug:
msg: "{{item[1].item}} is pingable from {{ansible_host}} with {{item[1].results.success.packet_loss}} out of 5 packets"
when: "item[0].key == 'packet_loss'"
with_sublements:
- "{{loop_iterate.results.results.success}}"
- "{{loop_iterate.results}}"
so is there a way of combining with_dict with with_items ? I want to use
- "{{loop_iterate.results.results.success}}" as with_dict iteration while using - "{{loop_iterate.results}}" as with_items

Related

Getting a value out of registered variable in Ansible

So, I'm provisioning an EC2 instance using the ec2 module. At the end I'm using register: ec2info, so, I can later reference values inside, such as instance ID and Public DNS.
- name: Print the results
debug:
var: ec2info
Gets me
TASK [Print the results] ***********************************************************************************************************************
ok: [localhost] => {
"ec2info": {
"changed": true,
"deprecations": [
{
"collection_name": "amazon.aws",
"msg": "The 'ec2' module has been deprecated and replaced by the 'ec2_instance' module'",
"version": "4.0.0"
}
],
"failed": false,
"instance_ids": [
"i-0e9de15eb82eda3ad"
],
"instances": [
{
"ami_launch_index": "0",
"architecture": "x86_64",
"block_device_mapping": {
"/dev/sda1": {
"delete_on_termination": true,
"status": "attached",
"volume_id": "vol-066bb2dd4d14bdcac"
}
},
"dns_name": "ec2-35-173-126-60.compute-1.amazonaws.com",
"ebs_optimized": false,
"groups": {
"sg-0a732c6cbeb3f1025": "launch-wizard-39"
},
"hypervisor": "xen",
"id": "i-0e9de15eb82eda3ad",
"image_id": "ami-06644055bed38ebd9",
"instance_type": "t2.micro",
"kernel": null,
"key_name": "daro.io",
"launch_time": "2022-02-01T02:05:22.000Z",
"placement": "us-east-1c",
"private_dns_name": "ip-172-31-90-87.ec2.internal",
"private_ip": "172.31.90.87",
"public_dns_name": "ec2-35-173-126-60.compute-1.amazonaws.com",
"public_ip": "35.173.126.60",
"ramdisk": null,
"region": "us-east-1",
"root_device_name": "/dev/sda1",
"root_device_type": "ebs",
"state": "running",
"state_code": 16,
"tags": {
"Name": "new_demo_template"
},
"tenancy": "default",
"virtualization_type": "hvm"
}
],
"tagged_instances": []
}
}
I would like to get the value of Public DNS I have tried
- name: Print the results
debug:
var: ec2info.instances.public_dns_name
## AND
var: ec2info.instances['public_dns_name']
## AND
var: '{{ec2info.instances.public_dns_name}}'
If you could also point out to the part of the documentation that covers this?
So, I figured it out
var: ec2info.instances[0].public_dns_name

How to print only the non empty list results in Ansible

I would like to print only the non empty list(pog_test) in the output(JSON). The below Register output is a result of another previous task. I have even tried using a when condition, but no luck. Is it possible to handle this in the previous task itself(have mentioned the task below) rather than creating a separate task to filter the non empty lists.
Register Output
{
"changed": false,
"msg": "All items completed",
"results": [
{
"ansible_facts": {
"pog_test": []
},
"ansible_loop_var": "item",
"changed": false,
"failed": false,
"item": {
"dhcpBootOptionsEnabled": false,
"dhcpHandling": "Run a DHCP server",
"dhcpLeaseTime": "1 day",
"po_id": "4654646"
}
},
{
"ansible_facts": {
"pog_test": [
{
"id": "782500435255624287",
"name": "PG-L-DE-MCC-COOLING_DMZ",
"networkIds": [],
"networkObjectIds": [
"12345678"
]
}
]
},
"ansible_loop_var": "item",
"changed": false,
"failed": false,
"item": {
"dhcpBootOptionsEnabled": false,
"dhcpHandling": "Run a DHCP server",
"dhcpLeaseTime": "1 day",
"po_id": "12345678"
}
}
],
"skipped": false
}
Task
- name: Check if the POG exists for all PO.
set_fact:
pog_test: "{{ pog | json_query(pogquery) }}"
vars:
pogquery: "[].pog[?contains(networkObjectIds, '{{ item.po_id }}')][]"
with_items: "{{ comborgpoidcool }}"
register: pogcheck
pog
[
{
"OrgId": "5555",
"OrgName": "abcd",
"pog": [
{
"id": "9546413",
"name": "test123",
"networkIds": [
"654654654"
],
"networkObjectIds": [
"12345678"
]
}
]
},
{
"OrgId": "9876546",
"OrgName": "Tdsqfsf",
"pog": []
},
{
"OrgId": "98798756",
"OrgName": "qdqsdqdqsd",
"pog": []
}
]
comborgpoidcool
[
{
"dhcpBootOptionsEnabled": false,
"dhcpHandling": "Run a DHCP server",
"dhcpLeaseTime": "1 day",
"dhcpOptions": [],
"po_id": "4654646"
},
{
"dhcpBootOptionsEnabled": false,
"dhcpHandling": "Run a DHCP server",
"dhcpLeaseTime": "1 day",
"po_id": "12345678"
}
]
Expected Output
{
"changed": false,
"msg": "All items completed",
"results": [
{
"ansible_facts": {
"pog_test": [
{
"id": "782500435255624287",
"name": "PG-L-DE-MCC-COOLING_DMZ",
"networkIds": [],
"networkObjectIds": [
"12345678"
]
}
]
},
"ansible_loop_var": "item",
"changed": false,
"failed": false,
"item": {
"dhcpBootOptionsEnabled": false,
"dhcpHandling": "Run a DHCP server",
"dhcpLeaseTime": "1 day",
"po_id": "12345678"
}
}
],
"skipped": false
}
My initial approach was to get all the details in the pog json file which contains some value inside "pog" array . But now I have used another approach to filter the pog array whose length == 0( code as below).
when: (item.ansible_facts.pog_match | length == 0 )

Anlible. How do I add a condition to a loop operation?

How can I get from this data only the value ("subclientName": "test") where "count" = 1
"subclientName": "start9pm" should not be in the selection
{
"countbackupsetName": {
"results": [
{
"actions": {
"xpath": "//subClientProperties[subClientEntity[#subclientName=\"test\"]]/vmContent/children",
"namespaces": {},
"state": "present"
},
"changed": false,
"count": 2,
"msg": "found 2 nodes",
"invocation": {
"module_args": {
"path": "/var/lib/awx/projects/commv/parse/get_subclient2.xml",
"xpath": "//subClientProperties[subClientEntity[#subclientName=\"test\"]]/vmContent/children",
"count": true,
"namespaces": {},
"state": "present",
"print_match": false,
"pretty_print": false,
"input_type": "yaml",
"backup": false,
"strip_cdata_tags": false,
"insertbefore": false,
"insertafter": false,
"xmlstring": null,
"value": null,
"attribute": null,
"add_children": null,
"set_children": null,
"content": null
}
},
"failed": false,
"item": {
"appName": "Virtual Server",
"backupsetName": "backupset-test",
"clientName": "name05-vcagent",
"displayName": "name05-VCAgent",
"instanceName": "VC01",
"subclientName": "test"
},
"ansible_loop_var": "item"
},
{
"actions": {
"xpath": "//subClientProperties[subClientEntity[#subclientName=\"start9pm\"]]/vmContent/children",
"namespaces": {},
"state": "present"
},
"changed": false,
"count": 2,
"msg": "found 2 nodes",
"invocation": {
"module_args": {
"path": "/var/lib/awx/projects/commv/parse/get_subclient2.xml",
"xpath": "//subClientProperties[subClientEntity[#subclientName=\"start9pm\"]]/vmContent/children",
"count": true,
"namespaces": {},
"state": "present",
"print_match": false,
"pretty_print": false,
"input_type": "yaml",
"backup": false,
"strip_cdata_tags": false,
"insertbefore": false,
"insertafter": false,
"xmlstring": null,
"value": null,
"attribute": null,
"add_children": null,
"set_children": null,
"content": null
}
},
"failed": false,
"item": {
"appName": "Virtual Server",
"backupsetName": "Test01",
"clientName": "name05-vcagent",
"displayName": "name05-VCAgent",
"instanceName": "VC01",
"subclientName": "start9pm"
},
"ansible_loop_var": "item"
}
],
"msg": "All items completed",
"changed": false
},
"_ansible_verbose_always": true,
"_ansible_no_log": false,
"changed": false
}
This is how I managed to select everything, without the condition operation:
- debug:
msg: "{{ item.subclientName }}"
loop: "{{ countbackupsetName.results|map(attribute='item')|list }}"
result:
{
"msg": "test",
"_ansible_verbose_always": true,
"_ansible_no_log": false,
"changed": false,
"item": {
"appName": "Virtual Server",
"backupsetName": "backupset-test",
"clientName": "name05-vcagent",
"displayName": "name05-VCAgent",
"instanceName": "VC01",
"subclientName": "test"
},
"ansible_loop_var": "item",
"_ansible_item_label": {
"appName": "Virtual Server",
"backupsetName": "backupset-test",
"clientName": "name05-vcagent",
"displayName": "name05-VCAgent",
"instanceName": "VC01",
"subclientName": "test"
}
}
This is how I get to the data I need, but the number of lines is always different.
I also don't need lines where count ":" 2 "
code:
- name: Show value in countbackupsetName.results.0.count
debug:
var: countbackupsetName.results.0.count
- debug:
var: countbackupsetName.results.0.item.subclientName
- name: Show value in countbackupsetName.results.1.count
debug:
var: countbackupsetName.results.1.count
- debug:
var: countbackupsetName.results.1.item.subclientName
result:
TASK [Show value in countbackupsetName.results.0.count] ************************
ok: [localhost] => {
"countbackupsetName.results.0.count": "1"
}
TASK [debug] *******************************************************************
ok: [localhost] => {
"countbackupsetName.results.0.item.subclientName": "test"
}
TASK [Show value in countbackupsetName.results.1.count] ************************
ok: [localhost] => {
"countbackupsetName.results.1.count": "2"
}
code:
- name: debug jinja
debug:
msg: |
[
{% for p in countbackupsetName.results %}
{% for o in countbackupsetName.results[p].item %}
{
"count": "{{ countbackupsetName.results[p].count }}",
"key": "{{ o }}",
"value": "{{ countbackupsetName.results[p].item[o] }}"
},
{% endfor %}
{% endfor %}
]
result:
line 112, column 9, but may\nbe elsewhere in the file depending on the exact syntax problem.
Not sure I've got properly what is desired output. But idea should be the same regardless: loop through results checking for condition and printing matching items. Here you go:
- hosts: localhost
become: false
tasks:
- set_fact:
data: {
"countbackupsetName": {
"results": [
{
"actions": {
"xpath": "//subClientProperties[subClientEntity[#subclientName=\"test\"]]/vmContent/children",
"namespaces": {},
"state": "present"
},
"changed": false,
"count": 2,
"msg": "found 2 nodes",
"invocation": {
"module_args": {
"path": "/var/lib/awx/projects/commv/parse/get_subclient2.xml",
"xpath": "//subClientProperties[subClientEntity[#subclientName=\"test\"]]/vmContent/children",
"count": true,
"namespaces": {},
"state": "present",
"print_match": false,
"pretty_print": false,
"input_type": "yaml",
"backup": false,
"strip_cdata_tags": false,
"insertbefore": false,
"insertafter": false,
"xmlstring": null,
"value": null,
"attribute": null,
"add_children": null,
"set_children": null,
"content": null
}
},
"failed": false,
"item": {
"appName": "Virtual Server",
"backupsetName": "backupset-test",
"clientName": "name05-vcagent",
"displayName": "name05-VCAgent",
"instanceName": "VC01",
"subclientName": "test"
},
"ansible_loop_var": "item"
},
{
"actions": {
"xpath": "//subClientProperties[subClientEntity[#subclientName=\"start9pm\"]]/vmContent/children",
"namespaces": {},
"state": "present"
},
"changed": false,
"count": 2,
"msg": "found 2 nodes",
"invocation": {
"module_args": {
"path": "/var/lib/awx/projects/commv/parse/get_subclient2.xml",
"xpath": "//subClientProperties[subClientEntity[#subclientName=\"start9pm\"]]/vmContent/children",
"count": true,
"namespaces": {},
"state": "present",
"print_match": false,
"pretty_print": false,
"input_type": "yaml",
"backup": false,
"strip_cdata_tags": false,
"insertbefore": false,
"insertafter": false,
"xmlstring": null,
"value": null,
"attribute": null,
"add_children": null,
"set_children": null,
"content": null
}
},
"failed": false,
"item": {
"appName": "Virtual Server",
"backupsetName": "Test01",
"clientName": "name05-vcagent",
"displayName": "name05-VCAgent",
"instanceName": "VC01",
"subclientName": "start9pm"
},
"ansible_loop_var": "item"
}
],
"msg": "All items completed",
"changed": false
},
"_ansible_verbose_always": true,
"_ansible_no_log": false,
"changed": false
}
- debug:
var: result
# check for condition in result
when: result['item']['subclientName'] == "test"
# iterate over result list
loop: "{{ data['countbackupsetName']['results'] }}"
# set loop_var to not confuse ansible's "item" var with "item" key in data
loop_control:
loop_var: result
Was able to solve the problem using json_query!
code:
- set_fact:
add_filter: "{{ countbackupsetName|json_query(query2) }}"
vars:
query2: "results[?count==`1`].item.subclientName"
- name: debug json_query(query2)
debug:
var: add_filter
result:
TASK [debug json_query(query2)] ************************************************
ok: [localhost] => {
"add_filter": [
"test"
]
}
code:
- set_fact:
add_filter: "{{ count_add_hostname.results|json_query(_query) }}"
vars:
_query: "[].{subclientName: '[?count==`1`]'.item.subclientName,
backupsetName: '[?count==`1`]'.item.backupsetName}"
- name: debug json_query(add_filter)
debug:
var: add_filter
I try to execute in a loop
result:
TASK [debug json_query(add_filter) var=add_filter] *****************************
ok: [localhost] => {
"add_filter": [
{
"backupsetName": null,
"subclientName": null
},
{
"backupsetName": null,
"subclientName": null
},
{
"backupsetName": null,
"subclientName": null
}
]
}
is the empty result related to a conflict in the loop item and the dictionary name item ...

Combining json register results in ansible

I have searched for an answer to the following question. I could find some related answers but unfortunatly doesn't solve my issue.
i have this json out put from debugging a register in a win_find task:
- name: find docs older than 15 days
win_find:
paths: '{{ main_dir }}\{{ item }}\docs'
age: 15d
loop: '{{ all_folders}}'
register: register_files
- debug:
var: register_files
this is the debug output (i have removed some attributes to make the code shorter and easier to explain):
"register_files": {
"changed": false,
"msg": "All items completed",
"results": [
{
"_ansible_item_label": "folder_1",
"changed": false,
"examined": 378,
"files": [
{
"attributes": "Archive",
"checksum": "0351d8fffad7a16a5c21136ac5a77b33931237ad",
"creationtime": 1568633779.2339206,
},
{
"attributes": "Archive",
"checksum": "d25dd0915fe825790c8c3a27acdf6f5b34f6686b",
"creationtime": 1568633767.7103796,
"item": folder_1",
"matched": 302
},
"_ansible_item_label": "folder_2",
"changed": false,
"examined": 266,
"files": [
{
"attributes": "Archive",
"checksum": "0351d8fffad7a16a5c21136ac5a77b33931237ad",
"creationtime": 1568633779.2339206,
},
{
"attributes": "Archive",
"checksum": "d25dd0915fe825790c8c3a27acdf6f5b34f6686b",
"creationtime": 1568633767.7103796,
"item": folder_2",
"matched": 125
Because the code lookup two different folders i am getting the results back as two different dict lists. how can i combine those into one so i can get those results:
"files": [
{
"attributes": "Archive",
"checksum": "0351d8fffad7a16a5c21136ac5a77b33931237ad",
"creationtime": 1568633779.2339206,
},
{
"attributes": "Archive",
"checksum": "d25dd0915fe825790c8c3a27acdf6f5b34f6686b",
"creationtime": 1568633767.7103796,
{
"attributes": "Archive",
"checksum": "0351d8fffad7a16a5c21136ac5a77b33931237ad",
"creationtime": 1568633779.2339206,
},
{
"attributes": "Archive",
"checksum": "d25dd0915fe825790c8c3a27acdf6f5b34f6686b",
"creationtime": 1568633767.7103796,
Is this what you're looking for?
my_files: "{{ register_files.results|json_query('[].files')|flatten }}"
(not tested)
One easy way to get the result you want is to use the json_query filter with the correct jmespath expression
- name: Get file info
debug:
msg: "{{ register_files | json_query('results[].files[]') | list }}"
This was tested against the following data structure taken from your example and fixed to end up with a correct json.
"register_files": {
"changed": false,
"msg": "All items completed",
"results": [
{
"_ansible_item_label": "folder_1",
"changed": false,
"examined": 378,
"files": [
{
"attributes": "Archive",
"checksum": "0351d8fffad7a16a5c21136ac5a77b33931237ad",
"creationtime": 1568633779.2339206
},
{
"attributes": "Archive",
"checksum": "d25dd0915fe825790c8c3a27acdf6f5b34f6686b",
"creationtime": 1568633767.7103796
}
],
"item": folder_1",
"matched": 302
},
{
"_ansible_item_label": "folder_2",
"changed": false,
"examined": 266,
"files": [
{
"attributes": "Archive",
"checksum": "0351d8fffad7a16a5c21136ac5a77b33931237ad",
"creationtime": 1568633779.2339206
},
{
"attributes": "Archive",
"checksum": "d25dd0915fe825790c8c3a27acdf6f5b34f6686b",
"creationtime": 1568633767.7103796
}
],
"item": folder_2",
"matched": 125
}
]
}
Please make sure you check your MCVE in your future questions.

How to access information in ansible yum list result?

could you help me accessing some information in the result of the yum list module?
This is my task:
- name: check if lgto networker is installed
yum:
list: "{{ (item | basename | splitext)[0] }}"
state: present
register: yum_result
with_fileglob:
- "lgt*.rpm"
When i debug my registered var yum_result i got this output:
ok: [XX.XX.XX.XXX] => {
"yum_result": [
{
"_ansible_ignore_errors": null,
"_ansible_item_result": true,
"_ansible_no_log": false,
"_ansible_parsed": true,
"changed": false,
"failed": false,
"invocation": {
"module_args": {
"allow_downgrade": false,
"conf_file": null,
"disable_gpg_check": false,
"disablerepo": null,
"enablerepo": null,
"exclude": null,
"install_repoquery": true,
"installroot": "/",
"list": "lgtoclnt-8.2.4.9-1.x86_64",
"name": null,
"security": false,
"skip_broken": false,
"state": "installed",
"update_cache": false,
"validate_certs": true
}
},
"item": "/data/playbooks/roles/backup_networker/files/lgtoclnt-8.2.4.9-1.x86_64.rpm",
"results": [
{
"arch": "x86_64",
"envra": "0:lgtoclnt-8.2.4.9-1.x86_64",
"epoch": "0",
"name": "lgtoclnt",
"release": "1",
"repo": "installed",
"version": "8.2.4.9",
"yumstate": "installed"
}
]
}
How can i access the information in the last results block?
"arch": "x86_64",
"envra": "0:lgtoclnt-8.2.4.9-1.x86_64",
"epoch": "0",
"name": "lgtoclnt",
"release": "1",
"repo": "installed",
"version": "8.2.4.9",
"yumstate": "installed"
I've tried something like yum_result.results.yumstate or yum_result[2].yumstate, but nothing works.
You can access the result with
yum_result.results[0].yumstate
Use:
yum_result to access registered dictionary
yum_result.results to access the list of registered iterations
yum_result.results[-1] to access result of last iteration
yum_result.results[-1].yumstate to access it's yumstate status

Resources