I am searching for job templates via the Ansible Tower API & would like to create a dictionary (?) of key/value pairs from the returned 'name' & 'id' fields that are stored in the registered results json entry.
- name: Search for job templates
uri:
url: "{{ tower_url }}/api/v2/job_templates?search={{ item.name }}"
method: GET
user: admin
password: "{{ tower_admin_password }}"
force_basic_auth: yes
validate_certs: no
register: get_job_templates
loop: "{{ job_template_search }}"
This searches for a job template and returns the following output - I have removed a bunch of output that isn't required for troubleshooting;
"get_job_templates": {
"changed": false,
"msg": "All items completed",
"results": [
{
"_ansible_ignore_errors": null,
"_ansible_item_label": {
"name": "example_template"
},
"_ansible_item_result": true,
"_ansible_no_log": false,
"_ansible_parsed": true,
"allow": "GET, POST, HEAD, OPTIONS",
"cache_control": "no-cache, no-store, must-revalidate",
"changed": false,
"connection": "close",
"content_language": "en",
"content_length": "3264",
"content_type": "application/json",
"failed": false,
"invocation": {
"module_args": {
"headers": {
"Authorization": "Basic "
},
"status_code": [
200
],
"timeout": 30,
"unsafe_writes": null,
"url": "",
"url_password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
"url_username": "admin",
"use_proxy": true,
"user": "admin",
"validate_certs": false
}
},
"item": {
"name": "example_template"
},
"json": {
"count": 1,
"next": null,
"previous": null,
"results": [
{
"become_enabled": false,
"created": "2019-06-03T13:08:54.586346Z",
"credential": null,
"custom_virtualenv": null,
"description": "",
"diff_mode": false,
"extra_vars": "",
"force_handlers": false,
"forks": 0,
"host_config_key": "",
"id": 10,
"inventory": 88,
"name": "example_template",
}
]
},
}
]
}
}
I have attempted to extract the name and ID from the results using a few different methods, all similar to this one.
- set_fact:
job_template_ids: "{{ job_template_ids | default({}) | combine( { item.name: item.id } ) }}"
loop: "{{ get_job_templates.results.json }}"
Along with this I have tried to map the attributes using the solution provided here with no success: Ansible loop over JSON output from URI Call
I believe I am missing something fundamental about how Ansible works with registered variables that are defined like this. Frustratingly, if I simply do a GET on all job templates, users, orgs etc this code works with a slight change to the loop item ( get_job_templates.json.results ) to produce the name:id key/value pairs, but the layout of the registered variable differs slightly when it comes to searching a specific list of templates (and possibly other objects). Cheers!
Edit: After posting this I tried something else that works for a single job template search, but not multiple for some reason.
This code returns the expected output and the job template can then be called in future code with the template name which will return the template ID.
- set_fact:
job_template_ids: "{{ get_job_templates.results | map(attribute='json') | list | join }}"
- set_fact:
job_template_ids: "{{ job_template_ids | default({}) | combine( { item.name: item.id } ) }}"
loop: "{{ job_template_ids.results }}"
If I add a list of templates to search for in the initial task, it stops working, returning the following error when setting fact on the second set_fact in the above code.
fatal: [localhost]: FAILED! => {"msg": "'ansible.utils.unsafe_proxy.AnsibleUnsafeText object' has no attribute 'results'"}
Progress is progress though I suppose!
The tasks below
- set_fact:
job_template_ids: "{{ dict(
get_job_templates.results|json_query('[].json.results[].[name,id]')) }}"
- debug:
var: job_template_ids
give:
"job_template_ids": {
"example_template": 10
}