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