Part one: Ansible URI module and Jinja2 templating

This article about the Ansible URI module. I have recently spend a lot of time around automation for AVI software defined load balancers and wanted to share some useful information about how to use Ansible to interacting with REST API’s. Please check out my other articles around AVI Networks.

Let’s start with the playbook:

- hosts: controller
  gather_facts: false
    - { role: "config" }

The config role needs the following folders:

├── defaults    # Useful for default variables
├── tasks       # Includes Ansible tasks using the URI module
├── templates   # Jinja2 json templates
└── vars        # Variables to load json j2 templates

I will use defaults just as an example for variables which I use in the task and the json template.

Here’s the content of defaults/main.yml:

username: admin
password: demo
api_version: 17.2.11

Next the Json Jinja2 template, the example below is the system configuration from AVI load balancers but this can be any json content you want to push to a REST API, templates/systemconfiguration_json.j2:

  "dns_configuration": {
    {% if dns_domain is defined %}
    "search_domain": "{{ dns_domain }}"
    {% endif %}
    {% if dns_servers is defined %}
    {% for item in dns_servers %}
    "server_list": [
         "type": "V4",
         "addr": "{{ item }}"
      {% if not loop.last %}
      {% endif %}
      {% endfor %}
      {% endif %}
  "ntp_configuration": {
    {% if ntp_servers is defined %}
    {% for item in ntp_servers %}
    "ntp_servers": [
        "server": {
          "type": "DNS",
          "addr": "{{ item }}"
      {% if not loop.last %}
      {% endif %}
      {% endfor %}
      {% endif %}  
  "portal_configuration": {
    "password_strength_check": true,
    "use_uuid_from_input": false,
    "redirect_to_https": true,
    "enable_clickjacking_protection": true,
    "enable_https": true,
    "disable_remote_cli_shell": false,
    "http_port": 80,
    "enable_http": true,
    "allow_basic_authentication": true,

After we have specified the default variables and created the j2 template, let’s continue and see how we load the json template into a single variables in vars/main.yml:

systemconfiguration_json: "{{ lookup('template', 'systemconfiguration_json.j2') }}"

The step is the task itself using the Ansible URI module, tasks/main.yml:

- block:
  - name: Config | Systemconfiguration | Configure DNS, NTP and Portal settings
      url: "https://{{ ansible_host }}/api/systemconfiguration"
      method: PUT
      user: "{{ username }}"
      password: "{{ password }}"
      return_content: yes
      body: "{{ systemconfiguration_json }}"
      force_basic_auth: yes
      validate_certs: false
      status_code: 200, 201
      timeout: 180
        X-Avi-Version: "{{ api_version }}"
  when: '( inventory_hostname == group["controller"][0] )'

I like to use blocks in my Ansible tasks because you can group your tasks and use a single WHEN statement when you have multiple similar tasks.

I hope you find this article useful and please try it out and let me now in the comments below if you have questions.

NetBox Open Source DCIM and IPAM tool

I wanted to share some information about an open source tool I have found some time ago which helps you to keep track of your infrastructure assets and configuration items. The name is NetBox which is an DCIM (Datacenter infrastructure management) and IPAM (IP address management) tool. NetBox was started by the network engineering team from DigitalOcean, specifically to address the needs of network and infrastructure engineers.

We all know that documentation is something no one wants to do, and no one has time for. What makes NetBox interesting is that not only does it focus on infrastructure documentation with a clean web console, it also comes with a API to push changes via the API , or use NetBox as dynamic inventory for Ansible.

Here a few screenshots showing the look and feel from NetBox:

The rack overview:

The IPAM module:

Here is an example how to add a device via the REST API, very useful if you use ZTP (zero touch provisioning) and add your switches or servers automatically to NetBox or in your automation scripts when you deploy configurations:

[email protected]:~$ curl -X POST -H "Authorization: Token fde02a67ca0c248bf5695bbf5cd56975add33655" -H "Content-Type: application/json" -H "Accept: application/json; indent=4" http://localhost:80/api/dcim/devices/ --data '{ "nae": "server-9", "display_name": "server-9", "device_type": 5, "device_role": 8 , "site": 1 }'
    "id": 21,
    "name": "server-9",
    "device_type": 5,
    "device_role": 8,
    "tenant": null,
    "platform": null,
    "serial": "",
    "asset_tag": null,
    "site": 1,
    "rack": null,
    "position": null,
    "face": null,
    "status": 1,
    "primary_ip4": null,
    "primary_ip6": null,
    "cluster": null,
    "virtual_chassis": null,
    "vc_position": null,
    "vc_priority": null,
    "comments": "",
    "created": "2018-04-16",
    "last_updated": "2018-04-16T14:40:47.787862Z"
[email protected]:~$

In the web console you see the device I have just added via the REST API:

On the main NetBox Github repository page you find links for a Ansible Role or Vagrant environment.

I am personally very interested in using NetBox as dynamic inventory with Ansible. I will write a separate article about this in the coming weeks.

Please share your feedback and leave a comment.