Parsing JSON in Ansible

Introduction

Ansible is a simple to use infrastructure automation tool and is used for automating infrastructure, platform and deployments. Playbooks and roles are defined for set of tasks and are executed to bring the state of resources to desired state. One of things often needed for orchestrating a non trivial deployment/platform creation is interacting with multiple systems and extracting and combining information. These systems often expose a REST API with JSON data. In this short tutorial we will look at a way to process JSON outputs from REST APIs in Ansible playbooks.

We will use Github public API which is free to use but limited at certain hit rate. Overall here is what we will do:

  • Hit the users endpoint of the API which will give a list of random users.
  • From the list of users, we will match the user with ID 3 and get the name corresponding to that ID.
  • We will use ID to form next URL and get email of the user from user details API endpoint.

So let’s get started, you can check code used for this exercise here. Once you check out the code, you can simply run ‘ansible-playbook api.yml‘ from within project directory assuming you have Ansible installed. The first step is hitting the root endpoint of API to get a list of users:

- name: Running API
  uri:
    url: https://api.github.com/users
    method: GET
    return_content: yes
  register: user_list

- name: App Details
  debug: var=user_list

The above block will get the list of users which gets stored in user_list variable using uri module of Ansible. You can also see the content of the list as we are printing it out in next block. You will notice the the content of user_list.json has the list of many users.

"user_list": {
"_content_encoding": "gzip",
"access_control_allow_origin": "*",
"date": "Wed, 10 Aug 2016 15:15:54 GMT",
"etag": "W/\"37cd21f64c9bddd3c1b4178f043300ac\"",
"json": [
{
"gravatar_id": "",
"html_url": "https://github.com/mojombo",
"id": 1,
"login": "mojombo",
"organizations_url": "https://api.github.com/users/mojombo/orgs",
"received_events_url": "https://api.github.com/users/mojombo/received_events",
"starred_url": "https://api.github.com/users/mojombo/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/mojombo/subscriptions",
"type": "User",
"url": "https://api.github.com/users/mojombo"
},

Ansible looping constructs

What we want to do with above data is retrieve the url for an user whose “id” is 3 and then the URL of user will give email address of user in turn. You can use looping constructs in Ansible along with conditionals to iterate through the JSON and filter desired data. But the code will be lot of boilerplate and not cleanest approach possible. We want a cleaner way to extract the data from JSON while also reducing the boilerplate code and possibly separate that logic into a separate block/file. One of ways to achieve that is to use Jinja templates. Let’s first call a jinja template and we expect the output of jinja template rendering to be the URL of user with ID 3.

- set_fact:
  user_url: "{{ lookup('template', './app.yml.j2') }}"

Now let’s code the jinja template which will iterate over the JSON and conditionally check for user with ID 3. The file named app.yml.j2 has code below:

{%- for item in user_list.json -%}
  {%- if item.id == 3 -%}
    {{ item.url }}
  {%- endif -%}
{%- endfor -%}

We used the “-“ in every block to ensure trimming of white spaces which are not needed. This will set the user_url variable to the URL of the user. We can make another HTTP request to retrieve details of user and filter email of the user:

- name: Using username
  uri:
    url: "{{ user_url }}"
    method: GET
    return_content: yes
  register: user_details

- name: User Email
  debug: var=user_details.json.email

And finally we get desired output:

AnsibleOutput

Ansible is a powerful tool for automation and orchestration and a templating engine such as Jinja can make it all the more useful and clear for certain tasks.

Vishal Biyani

Vishal Biyani has worked across the whole spectrum of SDLC from developing code to deploying code and supporting customer. Vishal's roles have spanned from being a consultant to Fortune 500 companies to hands on platform building for Internet scale companies. Vishal is a DevOps practitioner, likes to work in Agile environments with a focus on Test Driven Development. Vishal's interests span continuous delivery, Kubernetes, containers and security. Before founding InfraCloud he worked in companies like HCL and AudienceScience building multiple Cloud and DevOps solutions.

You may also like...

Enjoy this blog? Please spread the word :)