Reputation: 353
I have a playbook that sets the variable "certData" which is an array of dictionaries. This is what "certData" looks like:
ok: [localhost] => {
"msg": [
{
"cn": "node1.corp.com",
"expires": "2020-11-05T15:20:18+00:00",
"id": 705,
"serial": "111"
},
{
"cn": "node2.corp.com",
"expires": "2020-11-05T15:20:28+00:00",
"id": 728,
"serial": "222"
},
{
"cn": "node3.corp.com",
"expires": "2020-10-28T19:37:29+00:00",
"id": 670,
"serial": "333"
},
{
"cn": "node4.corp.com",
"expires": "2021-04-04T09:55:08+00:00",
"id": 1163,
"serial": "444"
},
{
"cn": "node5.corp.com",
"expires": "2020-11-05T15:20:22+00:00",
"id": 715,
"serial": "555"
}
]
}
I have a play that is taking the data from "certData" and saving it a file called cert_expiring.json like this:
- name: Testing jinja
lineinfile:
dest: "./cert_expiring.json"
line: |-
{
"devices": [{
"items": {
{%- for i in certData -%}
{{ "" if loop.first else "," }}
"{{ i.id }}": "{{ i.cn }}"
{%- endfor %}
}
}]
}
state: present
create: yes
The playbook runs successfully but gives this warning:
[WARNING]: The value {'devices': [{'items': {'705': 'node1.corp.com', '715': 'node5.corp.com', '670': 'node3.corp.com', '728': 'node2.corp.com', '1163':
'node4.corp.com'}}]} (type dict) in a string field was converted to u"{'devices': [{'items': {'705': 'node1.corp.com', '715': 'node5.corp.com', '670':
'node3.corp.com', '728': 'node2.corp.com', '1163': 'node4.corp.com'}}]}" (type string). If this does not look like what you expect, quote the entire value to ensure it does not
change.
The data from the warning is exactly how it gets printed to the "cert_expiring.json" file with single quotes.
certs_expiring.json:
{'devices': [{'items': {'705': 'node1.corp.com', '715': 'node5.corp.com', '670': 'node3.corp.com', '728': 'node2.corp.com', '1163': 'node4.corp.com'}}]}
But, when I load the contents of the "cert_expiring.json" back into a variable (expired_certs2) and print it, it prints properly:
- name: Store file contents into variable
include_vars:
file: cert_expiring.json
name: expired_certs2
- name: Print expired_certs2 variable.
debug:
msg: "{{ expired_certs2 | json_query('devices[*].items') }}"
TASK [Print expired_certs2 variable.] **********************************************************************************************************************************************************************
ok: [localhost] => {
"msg": [
{
"1163": "DUKEISEC12.corp.cox.com",
"670": "sage.stg.cox.com",
"705": "btnrssmoloch01.corp.cox.com",
"715": "elmwssmoloch01.corp.cox.com",
"728": "rnkessmoloch01.corp.cox.com"
}
]
}
I tried single quoting the Jinja code like this but it doesn't help:
- name: Testing jinja
lineinfile:
dest: "./cert_expiring.json"
line: |-
'{
"devices": [{
"items": {
{%- for i in certData -%}
{{ "" if loop.first else "," }}
"{{ i.id }}": "{{ i.cn }}"
{%- endfor %}
}
}]
}'
state: present
create: yes
Also, tried using double quotes with no luck.
How can I get the data to print to the "cert_expiring.json" file in proper json format?
Upvotes: 1
Views: 377
Reputation: 68034
Q: "How can I get the data to print to the "cert_expiring.json" file in proper JSON format?"
A: Use filter to_json, e.g.
- include_vars:
file: cert_expiring.json
name: expired_certs2
- debug:
msg: "{{ expired_certs2 | to_json }}"
gives
msg: '{"devices": [{"item": {"705": "node1.corp.com", "728": "node2.corp.com", "670": "node3.corp.com", "1163": "node4.corp.com", "715": "node5.corp.com"}}]}'
The query
- debug:
msg: "{{ expired_certs2.devices | json_query('[].item') | to_json }}"
gives
msg: '[{"705": "node1.corp.com", "728": "node2.corp.com", "670": "node3.corp.com", "1163": "node4.corp.com", "715": "node5.corp.com"}]'
It's possible to simplify the content, e.g.
- set_fact:
devices: "{{ devices | default([]) +
[{'item': certData | items2dict(key_name='id', value_name='cn')}] }}"
- copy:
dest: cert_expiring.json
content: >
{"devices": {{ devices | to_json }} }
gives
shell> cat cert_expiring.json
{"devices": [{"item": {"705": "node1.corp.com", "728": "node2.corp.com", "670": "node3.corp.com", "1163": "node4.corp.com", "715": "node5.corp.com"}}] }
Upvotes: 2