Parsing Command Output in Ansible with JC

Ansible is a popular automation framework that allows you to configure any number of remote hosts in a declarative and idempotent way. A common use-case is to run a shell command on the remote host, return the STDOUT output, loop through it and parse it.

Starting in Ansible 2.9 with the community.general collection, it is possible to use jc (https://github.com/kellyjonbrazil/jc) as a filter to automatically parse the command output for you so you can easily use the output as an object.

For more information on the motivations for creating jc, see my blog post.

Installation

To use the jc filter plugin, you just need to install jc and the community.general collection on the Ansible controller. Ansible version 2.9 or higher is required to install the community.general collection.

Installing jc:

$ pip3 install jc

Installing the community.general Ansible collection:

$ ansible-galaxy collection install community.general

Now we are ready to use the jc filter plugin!

Syntax

To use the jc filter plugin you just need to pipe the command output to the plugin and specify the parser as an argument. For example, this is how you would parse the output of ps on the remote host:

  tasks:
  - shell: ps aux
    register: result
  - set_fact:
      myvar: "{{ result.stdout | community.general.jc('ps') }}"

This will generate a myvar object that includes the exact same information you would have received by running jc ps aux on the remote host. Now you can use object notation to pull out the information you are interested in.

A Simple Example

Let’s put it all together with a very simple example. In this example we will run the date command on the remote host and print the timezone as a debug message:

- name: Get Timezone
  hosts: ubuntu
  tasks:
  - shell: date
    register: result
  - set_fact:
      myvar: "{{ result.stdout | community.general.jc('date') }}"
  - debug:
      msg: "The timezone is: {{ myvar.timezone }}"

Instead of parsing the STDOUT text manually, we used the timezone attribute of the myvar object that jc gave us. Let’s see this in action:

$ ansible-playbook get-timezone.yml 

PLAY [Get Timezone] *****************************************************************************

TASK [Gathering Facts] **************************************************************************
ok: [192.168.1.239]

TASK [shell] ************************************************************************************
changed: [192.168.1.239]

TASK [set_fact] *********************************************************************************
ok: [192.168.1.239]

TASK [debug] ************************************************************************************
ok: [192.168.1.239] => {
    "msg": "The timezone is: UTC"
}

PLAY RECAP **************************************************************************************
192.168.1.239              : ok=4    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

Simple – no more need to grep/awk/sed your way through the output to get what you are looking for!

For a complete list of jc parsers available and their associated schemas, see the parser documentation.

Happy parsing!

Published by kellyjonbrazil

I'm a cybersecurity and cloud computing nerd.

2 thoughts on “Parsing Command Output in Ansible with JC

Leave a Reply

RSS
Follow by Email
LinkedIn
LinkedIn
Share
%d bloggers like this: