I have a situation where I'm writing a playbook for changing attributes of virtual machine, and the input I get comes from an automation that outputs the following, which is then passed in extra_vars
:
{
"vmvars": {
"v_ads1as_operating_system": "Linux",
"v_mdjx2d_vm_name": "myvm123",
"v_srsj4d_mount_point": "tmp"
}
}
As you can see, the key in vmvars
, the string v_<something>
is not consistent and can be anything. The remaining string of the key for e.g. _operating_system
remains the same.
I know the key should be unique. Well it is unique, sadly some of it is random.
Now in order to get the values I've tried the following, however none of them seem to work.
---
- hosts: localhost
tasks:
- name: Get os_type from input
set_fact:
os_type: "{{ vmvars[item] | json_query(['*operating_system']) }}"
loop: "{{ vmvars.keys() | list }}"
More queries that I've tried.
- set_fact:
os_type: "{{ vmvars[item] | json_query(vmvars['*operating_system']) }}"
- set_fact:
os_type: "{{ vmvars[item] | json_query([?contains(item,'operating_system')]) }}"
You will have two issues using JMESPath and
json_query
in this use case:Reference: https://github.com/jmespath/jmespath.jep/issues/23
keys()
— will destroy the value and the way to get the value of dynamic keys — via an object projection.*
— will destroy the key.This said, you can use the filter
dict2items
in order to make, from a dictionary likea normalised list:
The resulting list is easier to filter, since you can now apply filter on values and not on keys, which tend to be more complex.
So, with that list, you can use the filter
selectattr
to target the key containing_operating_system
and get its value.Given the task:
Ansible would yield:
Note: the above output was generated running the playbook with the option
-v
, which, amongst other useful information, shows the result of aset_fact
task.You could also use a regex, with the
match
filter provided by Ansible, as your first intend was:Giving the same result as above.