In this article, we are going to see how to read the JSON file in ansible-playbook
JSON is the most famous data representation it is widely used to store and transmit data. When you are working in Ansible automation, you might get a requirement to work with JSON files and read JSON files into Ansible playbook and process the data and store the data as a variables.
In general, JSON data can be processed easily with json_query
module of ansible and you can read more about it in our previous article
Our primary objective of this article is to talk about how to process the JSON FILE and read the JSON file into ansible playbook and process it.
in the previous article, we have talked about how to directly use the JSON output of a website or URL and use it for further processing. but now we are going to use the file as our source of data in this article.
we are going to take some sample JSON file which contains elements and sub elements in both array and single line formats, to understand this better.
Sample JSON file for our testing
This is the JSON file we are going to be using this article. the file name is config.json
it was ideally designed for weblogic ansible installation setup but this can serve as a viable example in here.
{
"domain":{
"name": "mwidomain",
"prod_mode": "prod",
"user": "weblogic",
"password": "weblogic1",
"admin": {
"servername": "AdminServer",
"listenport": "8001"
},
"machines": [
{
"refname": "Machine1",
"name": "MWINODE01"
},
{
"refname": "Machine2",
"name": "MWINODE02"
}
],
"clusters": [
{
"refname": "Cluster1",
"name": "App1Cluster",
"machine": "Box1"
},
{
"refname": "Cluster2",
"name": "App2Cluster",
"machine": "Box2"
}
],
"servers": [
{
"name": "ms1",
"port": 9001,
"machine": "Box1",
"clusterrefname": "Cluster1"
},
{
"name": "ms2",
"port": 9002,
"machine": "Box2",
"clusterrefname": "Cluster2"
},
{
"name": "ms3",
"port": 9003,
"machine": "Box1",
"clusterrefname": "Cluster1"
},
{
"name": "ms4",
"port": 9004,
"machine": "Box2",
"clusterrefname": "Cluster2"
}
]
}
}
How to read JSON file into ansible playbook
To read JSON file into the ansible playbook, ansible has given us a filter named from_json
but, of course, we need to use it along with few more commands and module like shell to read the json file.
here is the quick ansible playbook example that reads JSON file
---
- name: ReadJsonfile
hosts: localhost
tasks:
- name: Display the JSON file content
shell: cat config.json
register: result
- name: save the Json data to a Variable as a Fact
set_fact:
jsondata: "{{ result.stdout | from_json }}"
Let us see how this playbook works.
- The First task or play is to display the json file using the normal Shell command
cat
at this same tasks we are saving this output into a ansible register variable namedresult
- The Second task or play is to read the register variable of the previous task named
result
and convert that into a properjson
data, this is done usingfrom_json
filter and then we store it into a new ansible fact variable namedjsondata
- Now we have our JSON file content stored in
jsondata
variable after being formatted as proper JSON, which can be easily parsed now using ansible json query module.
As simple as that we have now learnt how to read JSON data into ansible playbook using from_json
and shell module.
How to use the JSON data in your playbook as a variable
So now we have processed the JSON file and imported it into our playbook but here comes the next part of the equation. So how are we going to use this JSON data in our playbook or store it as a variable?
Refer the following ansible playbook, A continuation of our previous read json playbook, in this ansible playbook we are taking out the necessary elements/keys and using in our playbook by setting it as ansible fact.
once the values are stored as ansible fact. it can be referred from anywhere in the playbook or ansible role using jinja 2 syntax {{ }}
---
- name: ReadJsonfile
hosts: localhost
tasks:
- name: Display the JSON file content
shell: cat config.json
register: result
- name: save the Json data to a Variable as a Fact
set_fact:
jsondata: "{{ result.stdout | from_json }}"
- name: setDomainName
set_fact:
domain_name: "{{ jsondata | json_query(jmesquery) }}"
vars:
jmesquery: 'domain.name'
- name: setDomainUsername
set_fact:
domain_username: "{{ jsondata | json_query(jmesquery) }}"
vars:
jmesquery: 'domain.user'
- name: setDomainPassword
set_fact:
domain_password: "{{ jsondata | json_query(jmesquery) }}"
vars:
jmesquery: 'domain.password'
- name: setadmin_Listenport
set_fact:
admin_ListenPort: "{{ jsondata | json_query(jmesquery) }}"
vars:
jmesquery: 'domain.admin.listenport'
- name: Debug the values
debug: msg=" Admin Listen Port => {{ admin_ListenPort }}, DomainName => {{ domain_name }}, DomainUserName => {{ domain_username }} , Domain Password => {{ domain_password }}"
Explanation of this playbook.
- Other than the previously explained two tasks/plays of
shell
andfrom_json
we have more tasks added withset_fact
in this playbook
set_fact
is used to create a new ansible variable at a run time of the playbook. we can also call it as run time variables or dynamic variables.
- To filter out the required key or element from an otherwise big JSON data set. we are here using ansible
jmes_query
which has been covered in detail here
- vars is used to set a limited variable for every task/play. it was primarily used to create a variable named
jmesquery
which contains the actual jmesquery
- The Last play or task in this playbook is to display the created facts/variables using set_fact.
Execution result of this playbook
Here is the output of the playbook.
Complex JSON JMES Queries and Ansible Playbook
Sometimes we would want to create a list from the JSON data like a Dictionary or array. Or let's say we want to find all the server names and their ports from the JSON we have taken for example.
here is the playbook that creates a dictionary of data by processing the JSON file.
It simply creates a list or dictionary of servers and their port numbers.
---
- name: ReadJsonfile
hosts: localhost
tasks:
- name: Display the JSON file content
shell: cat config.json
register: result
- name: save the Json data to a Variable as a Fact
set_fact:
jsondata: "{{ result.stdout | from_json }}"
- name: Server Names
set_fact:
servernames: "{{ jsondata | json_query(jmesquery) }}"
vars:
jmesquery: '*.servers[*].name'
- name: Server Names and Ports
set_fact:
serverinfo: "{{ jsondata | json_query(jmesquery) }}"
vars:
jmesquery: '*.servers[*].[name, port]'
- name: Print all server names
debug:
msg: "{{ item}}"
with_items:
- "{{ servernames }}"
- name: Print all server names
debug:
msg: "{{ item }}"
with_items:
- "{{ serverinfo }}"
Explanation
- With the help of
jmespath
queries, we are filtering out the Server names and Server Names with Port number like the same way we did in the previous playbook examples. - Now we are printing all the server names using the loop iteration
with_items
Result of the playbook
Conclusion
I hope this article was helpful to understand how to read and process JSON file with Ansible. Feel free to ask in comments if you have any questions.
Cheers
Sarav
Follow me on Linkedin My Profile Follow DevopsJunction onFacebook orTwitter For more practical videos and tutorials. Subscribe to our channel
Signup for Exclusive "Subscriber-only" Content