--- EDIT ---
Partial-Solution: Messed around with the JMESPath syntax and was able to successfully get a match for the first test case (without the optional variable) using:
jmesquery: "{{ datacenter }}{{ subcategory }}.{{ refine_hosts }}.[*][].[*][][]"
I am writing an Ansible Playbook that takes a list of hosts from a network server, parses the JSON list, and finds hostnames that matches the user's input when they deploy the playbook as a Jenkin's Job through it's API.
The issue I am encountering is that I am unable to successfully query the JSON host list. Currently, I am only trying to run the following test case:
datacenter: a
subcategory: bc
refine_hosts: QA
However, the final version of this playbook should be able to take in values for datacenter
, subcategory
, and refine_hosts
with an optional input value of host_type
. An example test case including the optional input value would be the following:
datacenter: a
subcategory: bc
refine_hosts: QA
host_type: WEBSITE
In my playbook, I am using JMESPath within the following task:
- name: Build HOSTS list
set_fact:
hosts_list: "{{ jsondata | json_query(jmesquery) }}"
vars:
jmesquery: '%%datacenter%%-%%subcategory%%.%%refine_hosts%%.[*][*][][]'
The JSON host list is structured in the following manner (I am unable to edit the structure of the host list, but it will always follow the following structure nonetheless):
{
"a-bc":{
"all":{
"webServer":[
],
"archive":[
"someHostAlias-123.privateDomain.com"
],
"central":[
"someHostAlias-456.privateDomain.com"
]
},
"QA":{
"xyz":{
"INBOUND_HTTP":[
"someHostAlias-789.privateDomain.com"
],
"WEBSITE":[
"someHostAlias-1011.privateDomain.com"
]
}
}
}
}
I have been using the following websites for this issue:
I apologize if the query seems obvious, this is my first attempt at an Ansible Playbook. All help/feedback is greatly appreciated.
One of the issue of your query is that you are confusing [*]
— a list projection — that selects all the elements of a list with .*
— an object projection — that selects all the properties of a dictionary.
So, one solution in JMESPath, would be to do:
jmesquery: >-
"{{ datacenter }}-{{ subcategory }}".{{ refine_hosts }}.*.
{{ host_type if host_type | default('') != '' else '*' }}[] | []
Given the playbook:
- hosts: localhost
gather_facts: no
tasks:
- debug:
msg: "{{ jsondata | json_query(jmesquery) }}"
loop: "{{ fake_user_input }}"
loop_control:
label: "{{ jmesquery }}"
vars:
jmesquery: >-
"{{ datacenter }}-{{ subcategory }}".{{ refine_hosts }}.*.
{{ host_type if host_type | default('') != '' else '*' }}[] | []
datacenter: "{{ item.datacenter }}"
subcategory: "{{ item.subcategory }}"
refine_hosts: "{{ item.refine_hosts }}"
host_type: "{{ item.host_type | default('') }}"
fake_user_input:
- datacenter: a
subcategory: bc
refine_hosts: QA
host_type: WEBSITE
- datacenter: a
subcategory: bc
refine_hosts: QA
jsondata:
a-bc:
all:
webServer: []
archive:
- someHostAlias-123.privateDomain.com
central:
- someHostAlias-456.privateDomain.com
QA:
xyz:
INBOUND_HTTP:
- someHostAlias-789.privateDomain.com
WEBSITE:
- someHostAlias-1011.privateDomain.com
This yields:
ok: [localhost] => (item="a-bc".QA.*. WEBSITE[] | []) =>
msg:
- someHostAlias-1011.privateDomain.com
ok: [localhost] => (item="a-bc".QA.*. *[] | []) =>
msg:
- someHostAlias-789.privateDomain.com
- someHostAlias-1011.privateDomain.com