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 verbose
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

Strategy Per Play
---
- name:
  hosts:
  gather_facts: false
  strategy: free
Strategy ansible.cfg
[defaults]
strategy = free

External Vars

Let’s create a new playbook called ext.yml and use the contents below

vim ext.yml

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 local
ansible-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'"
../_images/ext_play.png

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

Limit
1 ansible-playbook -i inventory someplay.yml --limit "host1"
2 ansible-playbook -i inventory someplay.yml --limit "all:!host1"

Tags

Adding tags to individual plays can greatly help when you only want to test or skip specific plays.

tags.yml
---
- hosts: all
  connection: local

  tasks:

  - name: Ansible Date Example
    tags:
      - tag1
    ansible.builtin.debug:
         var=ansible_date_time.date

  - name: Set a fact
    ansible.builtin.set_fact:
       fact_var: ansible_date_time.date

  - name: Ansible Date Example
    tags:
      - tag2
    ansible.builtin.debug:
         var=ansible_date_time.epoch
Only show date
ansible-playbook -i "localhost," tags.yml --tags "tag1"
Only show epoch
ansible-playbook -i "localhost," tags.yml --skip-tags "tag1"
../_images/date_tag.png

Fig 2

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

loop.yml
---
- hosts: all
  gather_facts: false
  connection: local

  tasks:

  - name: A loop
    ansible.builtin.debug:
      msg: "{{ item }}"
    loop:
      - one
      - two
      - three
with_items.yml
---
- 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

File Exists Check
- 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
- 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
- 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)

refresh inventory
- 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:

getrepo.yml
---
- 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

names.yml
---
- 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

Ansible Lookup Plugin

File contents to variable
 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