Sphinx-Ansible: use your RST like a Playbook

This Sphinx extension allow you to write Ansible Tasks or Playbook directly in your RST documentation. The extension will ensure everything works fine and use the output in the final documentation.

Sphinx-Ansible helps you address the following scenarios:

  • I want to run my Ansible documentation in a CI.

  • I would like to integrate some task outputs in my documentation.

Installation

Install the sphinx-ansible package and the extension in your conf.py file:

extensions = ["sphinxcontrib.sphinx_ansible"]

New directives

This extensions add the following new extensions:

  • ansible-task: for one single task

  • ansible-tasks: for a list of tasks

  • ansible-playbook: for a full playbook

Configuration keys

The extension exposes the following configuration keys:

  • ansible_roles_path: The key accepts a list of folders.

  • ansible_tmp_dir: Where to write the temporary Playbook. e.g: /tmp/sphinx-ansible.

Contribute

The extension is hosted on Github: https://github.com/ansible-community/sphinx-ansible

examples

Document one plugin

Here for instance, I want to document an Ansible plugin. This is how I will include my example in the RestructuredText file:

.. ansible-task::

   - name: foo bar
     command: ls /tmp/foo/BAR

Sphinx will generate the following output

- name: foo bar
  command: ls /tmp/foo/BAR

Response:

{
    "changed": true,
    "cmd": [
        "ls",
        "/tmp/foo/BAR"
    ],
    "delta": "0:00:00.004692",
    "end": "2021-07-07 11:52:45.380202",
    "rc": 0,
    "start": "2021-07-07 11:52:45.375510",
    "stderr": "",
    "stderr_lines": [],
    "stdout": "index.txt",
    "stdout_lines": [
        "index.txt"
    ]
}

It’s also possible to hide a task with the :hide: parameter:

.. ansible-task::
   :hide:

   - name: This is irrelevant for the final document
     command: ls .

A list of tasks

The following blocks run two tasks

.. ansible-tasks::

   - name: Purge the file
     file:
       path: /tmp/foo/BAR/index.txt
       state: absent
   - name: And the directory
     file:
       path: /tmp/foo/BAR
       state: absent

Sphinx generates this output

- name: Purge the file
  file:
    path: /tmp/foo/BAR/index.txt
    state: absent
- name: And the directory
  file:
    path: /tmp/foo/BAR
    state: absent

Response:

{
    "changed": true,
    "diff": {
        "after": {
            "path": "/tmp/foo/BAR/index.txt",
            "state": "absent"
        },
        "before": {
            "path": "/tmp/foo/BAR/index.txt",
            "state": "file"
        }
    },
    "path": "/tmp/foo/BAR/index.txt",
    "state": "absent"
}
{
    "changed": true,
    "diff": {
        "after": {
            "path": "/tmp/foo/BAR",
            "state": "absent"
        },
        "before": {
            "path": "/tmp/foo/BAR",
            "path_content": {
                "directories": [],
                "files": []
            },
            "state": "directory"
        }
    },
    "path": "/tmp/foo/BAR",
    "state": "absent"
}

A playbook

This is my playbook.

.. ansible-playbook::

   - hosts: localhost
     gather_facts: false
     tasks:
       - name: a first tasks
         debug:
           msg: Some blabla
       - name: run uname
         command: uname -a
         register: result
       - debug: var=result

This is how Sphinx shows up the Playbook

- hosts: localhost
  gather_facts: false
  tasks:
    - name: a first tasks
      debug:
        msg: Some blabla
    - name: run uname
      command: uname -a
      register: result
    - debug: var=result

Response:

[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that
the implicit localhost does not match 'all'

PLAY [localhost] ***************************************************************

TASK [a first tasks] ***********************************************************
ok: [localhost] => {
    "msg": "Some blabla"
}

TASK [run uname] ***************************************************************
changed: [localhost]

TASK [debug] *******************************************************************
ok: [localhost] => {
    "result": {
        "changed": true,
        "cmd": [
            "uname",
            "-a"
        ],
        "delta": "0:00:00.002683",
        "end": "2021-07-07 11:52:47.331037",
        "failed": false,
        "rc": 0,
        "start": "2021-07-07 11:52:47.328354",
        "stderr": "",
        "stderr_lines": [],
        "stdout": "Linux build-14185144-project-653196-sphinx-ansible 5.4.0-1035-aws #37~18.04.1-Ubuntu SMP Wed Jan 6 22:31:04 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux",
        "stdout_lines": [
            "Linux build-14185144-project-653196-sphinx-ansible 5.4.0-1035-aws #37~18.04.1-Ubuntu SMP Wed Jan 6 22:31:04 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux"
        ]
    }
}

PLAY RECAP *********************************************************************
localhost                  : ok=3    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

A single task

This is just a task.

- name: Show up the ansible_distribution of the host
  debug:
    msg: "This documentation was built on a {{ ansible_distribution  }}."

Response:

{
    "changed": false,
    "msg": "This documentation was built on a Ubuntu."
}