My Top 5 Ansible Tips and Tricks

My Top 5 Ansible Tips and Tricks

Introduction

In this article I will share my top 5 Ansible tips and tricks, that I hope will save you time when automating your networks with Ansible.

List Tasks

Ansible provides a rather handy little option to print each of your tasks for your plays via the option --list-tasks. Certainly a time saver, rather than having to write grep statements each time.

Below shows an example:

$ ansible-playbook playbooks/create_bf_snapshot.yml --list-tasks
playbook: playbooks/create_bf_snapshot.yml

  play #1 (localhost): Create Batfish Snapshot Directory        TAGS: []
    tasks:
      Create Snapshot Directory /       TAGS: []
      Create Snapshot Directory /configs        TAGS: []
      Create Snapshot Directory /hosts  TAGS: []
      Create Snapshot Directory /iptables       TAGS: []

  play #2 (linux): Create Batfish Snapshot Files for Hosts      TAGS: []
    tasks:
      Generate (via J2) and Save Host IP JSON   TAGS: []
      Collect IPTable Config    TAGS: []
      Save IPTable Config to Snapshot   TAGS: []

  play #3 (netdev): Create Batfish Snapshot Files for Net Devices       TAGS: []
    tasks:
      Collect ASA Network Device Configs        TAGS: []
      Collect JunOS Network Device Configs      TAGS: []
      Save ASA Network Device Configs to Snapshot       TAGS: []
      Save JunOS Network Device Configs to Snapshot     TAGS: []

Start at Task

A useful little option when needing to debug your tasks and playbooks is --start-at-task. This simply allows you to start the execution of your playbook at a given task. Below shows the syntax:

ansible-playbook push-config.yml --start-at-task="Clear ACLs"

Graph Inventory

The ansible-inventory option --graph allows you to, you guessed it - graph your inventory. Extremely handy when you have a large inventory and/or lots of groups.

Below shows an example:

$ ansible-inventory -i inventory/hosts --graph
@all:
  |--@linux:
  |  |--db
  |  |--websrv
  |--@netdev:
  |  |--@asa:
  |  |  |--fw1-asa
  |  |  |--fw2-asa
  |  |--@junos:
  |--@ungrouped:

List Inventory

Another inventory option is --list. This option displays the various variables and also group hierarchies from within your inventory. Again, extremely useful for large and complex inventory sets.

$ ansible-inventory -i inventory/hosts --list
{
    "_meta": {
        "hostvars": {
            "db": {
                "ansible_become_password": "cisco",
                "ansible_become_user": "root",
                "ansible_connection": "ssh",
                "ansible_host": "172.29.132.201",
                "ansible_ssh_pass": "cisco",
                "ansible_user": "cisco"
            },
            "fw1-asa": {
                "ansible_become": "yes",
                "ansible_become_method": "enable",
                "ansible_become_password": "cisco",
                "ansible_connection": "network_cli",
                "ansible_host": "172.29.132.100",
                "ansible_network_os": "asa",
                "ansible_ssh_pass": "cisco",
                "ansible_user": "cisco"
            },
            "fw2-asa": {
                "ansible_become": "yes",
                "ansible_become_method": "enable",
                "ansible_become_password": "cisco",
                "ansible_connection": "network_cli",
                "ansible_host": "172.29.132.200",
                "ansible_network_os": "asa",
                "ansible_ssh_pass": "cisco",
                "ansible_user": "cisco"
            },
            "websrv": {
                "ansible_become_password": "cisco",
                "ansible_become_user": "root",
                "ansible_connection": "ssh",
                "ansible_host": "172.29.132.101",
                "ansible_ssh_pass": "cisco",
                "ansible_user": "cisco"
            }
        }
    },
    "all": {
        "children": [
            "linux",
            "netdev",
            "ungrouped"
        ]
    },
    "asa": {
        "hosts": [
            "fw1-asa",
            "fw2-asa"
        ]
    },
    "linux": {
        "hosts": [
            "db",
            "websrv"
        ]
    },
    "netdev": {
        "children": [
            "asa",
            "junos"
        ]
    }
}

Pretty-Print Play Errors

By default when an Ansible play fails the result is a blob of text, like so, containing the error details:

TASK [Upload Configuration to Device] *************************************************************************************************
fatal: [fw1]: FAILED! => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": true, "cmd": "scp -o \"StrictHostKeyChecking no\" './data/snapshots/snapshot/configs/fw1.cfg' \"cisco\"@\"172.29.132.100\":\"disk0:configuration.txt\"", "delta": "0:00:21.205542", "end": "2019-12-12 20:09:05.637109", "msg": "non-zero return code", "rc": 1, "start": "2019-12-12 20:08:44.431567", "stdout": "ssh: connect to host 172.29.132.100 port 22: Resource temporarily unavailable\r\r\nlost connection", "stdout_lines": ["ssh: connect to host 172.29.132.100 port 22: Resource temporarily unavailable", "", "lost connection"]}
fatal: [fw2]: FAILED! => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": true, "cmd": "scp -o \"StrictHostKeyChecking no\" './data/snapshots/snapshot/configs/fw2.cfg' \"cisco\"@\"172.29.132.200\":\"disk0:configuration.txt\"", "delta": "0:00:21.208292", "end": "2019-12-12 20:09:05.639666", "msg": "non-zero return code", "rc": 1, "start": "2019-12-12 20:08:44.431374", "stdout": "ssh: connect to host 172.29.132.200 port 22: Resource temporarily unavailable\r\r\nlost connection", "stdout_lines": ["ssh: connect to host 172.29.132.200 port 22: Resource temporarily unavailable", "", "lost connection"]}

In order to get Ansible to print this in a more readable format, a callback plugin can be enabled. To enable add the following to your ansible.cfg.

[DEFAULTS]
stdout_callback = debug

Your output will now be displayed like so:

TASK [Upload Configuration to Device] *************************************************************************************************

fatal: [fw2]: FAILED! => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": true,
    "cmd": "scp -o \"StrictHostKeyChecking no\" './data/snapshots/snapshot/configs/fw2.cfg' \"cisco\"@\"172.29.132.200\":\"disk0:configuration.txt\"",
    "delta": "0:00:21.218448",
    "end": "2019-12-12 20:18:47.709376",
    "rc": 1,
    "start": "2019-12-12 20:18:26.490928"
}

STDOUT:
ssh: connect to host 172.29.132.200 port 22: Resource temporarily unavailable
lost connection

MSG:
non-zero return code

fatal: [fw1]: FAILED! => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": true,
    "cmd": "scp -o \"StrictHostKeyChecking no\" './data/snapshots/snapshot/configs/fw1.cfg' \"cisco\"@\"172.29.132.100\":\"disk0:configuration.txt\"",
    "delta": "0:00:21.222286",
    "end": "2019-12-12 20:18:47.711059",
    "rc": 1,
    "start": "2019-12-12 20:18:26.488773"
}

STDOUT:
ssh: connect to host 172.29.132.100 port 22: Resource temporarily unavailable lost connection

MSG:
non-zero return code

Subscribe to our newsletter and stay updated.

Don't miss anything. Get all the latest posts delivered straight to your inbox.
Great! Check your inbox and click the link to confirm your subscription.
Error! Please enter a valid email address!