Ansible
Troubleshooting
This section we’ll talk about printing messages to screen and setting the verbose level:
-v
-vv
-vvv
-vvvv { connection level }
The verbose levels are used when executing an ansible playbook.
ansible-playbook -i inventory someplaybook.yaml -vvv
Debug and verbose will truly become your best allies as you build playbooks. You can use debug to print registered variables
to screen or even print messages. Below I’ll cover using the msg:
function and in a very Pythonic way,
concatenating stings into our messages with +
and quotes.
Strategies
linear
default; One task after another
free
complete each task as fast as possilbe, do not wait
debug
Run debug after failure of any task
---
- name:
hosts:
gather_facts: false
strategy: free
[defaults]
strategy = free
External Vars
Let’s create a new playbook called ext.yml
and use the contents below
vim ext.yml
---
- hosts: all
gather_facts: false
connection: local
tasks:
- name: Show external variables
ansible.builtin.debug:
msg: "{{ \"This is var1: \" + var1 + \" 'and also' \" + \"This is var2: \" + var2 }}"
Now we’ll run this play against the localhost. A couple of items to watch when running playbooks against the localhost
The hosts:
line should have the value of all
connection
should have the value of localansible-playbook -i "localhost," ext.yml -e "var1='is var one' var2='is var two'"
Example of connection directive missing from YAML file, you must add the -c
connection switch to the cli command
ansible-playbook -i "localhost," -c local ext.yml -e "var1='is var one' var2='is var two'"
Fig 1
Limit
One way to reduce the all awesome power of automation (to kill everything) is to limit what hosts your playbooks run on. This can be accomplished with limit
or tags
.
The example below we run a play on only host1
@ line 1 ,but @ line 2 we run the playbook against all hosts except host1
1 ansible-playbook -i inventory someplay.yml --limit "host1"
2 ansible-playbook -i inventory someplay.yml --limit "all:!host1"
Loops
My most commonly used looping methods. In nearly all cases with_items is fine to use but you should start using loop.
loop
with_items
---
- hosts: all
gather_facts: false
connection: local
tasks:
- name: A loop
ansible.builtin.debug:
msg: "{{ item }}"
loop:
- one
- two
- three
---
- hosts: all
gather_facts: false
connection: local
tasks:
- name: A loop
ansible.builtin.debug:
msg: "{{ item }}"
with_items:
- one
- two
- three
Conditionals
There are too many to cover and that’s why we have the internet. Ansible Docs
- My most used:
ignore_errors
until/retries/delay
status_code
when
fail_when
This play will download the vault_play.png if it does not exist within the specified directory (the path
directive), you
can add this to the end of tags.yml playbook
- name: Check if image file exists
ansible.builtin.stat:
path: "~/Downloads"
register: file_stat
- name: Download png file from my repo
ansible.builtin.get_url:
url: https://github.com/cwise24/snopsy/raw/main/docs/module3/imgs/vault_play.png
dest: "~/Downloads"
when: file.stat.exists == False
Pause
Give a process time before running the next inline task
- pause:
seconds: 10
When an action fails, prompt user to accept and continue rather than stop/fail. Let’s add the below code to the end of your tags.yml playbook
- pause:
prompt: " Press Enter to continue "
when: fact_var is defined
Meta
In one of my playbooks I use dynamic inventory to populate my inventory file, meaning I must refresh (inventory files are loaded at runtime)
- meta: refresh_inventory
Ansible Git
Clone a git repo using Ansible. For this exercise we will clone an existing repo in Gitlab. We will use this repo to demo hostvar. Let’s create a new playbook called getrepo.yml and add the code below:
---
- name: Clone git repo
hosts: all
gather_facts: false
connection: local
tasks:
- name: Check if project folder exists
ansible.builtin.stat:
path: ./snopsy.hostvars
register: dir_exits
- name: Clone Repo for next exercise
ansible.builtin.git:
repo: https://gitlab.com/cwise24/snopsy.hostvars
dest: ~/ansible_lab/snopsy.hostvars
clone: yes
force: yes
when: dir_exits["stat"]["exists"] == false
Now to execute: ansible-playbook -i "localhost," getrepo.yml
Host Variables
You will not need to create the below file names.yml as this was cloned from Gitlab in the previous step. You only need to changed to the snopsy.hostvars directory and run the playbook:
cd snopsy.hostvars
ansible-playbook names.yml
If you now look at the files in your snopsy.hostvars directory you will also see an ansible.cfg file where we declare where our inventory is
---
- name: Show hostvar use cases
hosts: all
gather_facts: false
tasks:
- name: Show hostvars (all hosts)
ansible.builtin.debug:
var: hostvars
- name: Show inventory hostnames
ansible.builtin.debug:
var: inventory_hostname
- name: Show ip addresses of all hosts
ansible.builtin.debug:
msg: "{{ hostvars[inventory_hostname]['ansible_host'] }}"
- name: Show ip address of host_2 only
ansible.builtin.debug:
msg: "{{ hostvars['host_2']['ansible_host'] }}"
when: inventory_hostname == "host_2"
- name: Show groups and hosts within each group
ansible.builtin.debug:
msg: "{{ groups }}"
- name: Show group names
ansible.builtin.debug:
msg: "{{ group_names }}"
Lookup
app_cert: "{{ lookup('ansible.builtin.file', '/home/user/roles/role_certs/files/as3.lab.local.crt') }}"
Network Automation
No reason for me to repeat, Ansible Docs