Chapter 11: Comprehensive Review

Exercise: Deploying Ansible

Set up workstation as a control node for servera and serverb, then write, fix and extend small playbooks that use variables, facts and loops. Solutions are hidden under each task. Try each one yourself first.

This lab covers chapters 2 to 5 and 9. Your project directory is ~/review-deploy; lab start puts two playbooks in it, packages.yml and verify_user.yml. You write everything else.

Deploying Ansible

  • Install and configure Ansible.
  • Create, modify and troubleshoot playbooks.

Prerequisites: Complete control-node setup and the preceding lessons in this chapter. Run commands as student on workstation unless a step names another machine.

From the project directory, run the relevant home-lab check. For an exercise with several checkpoints, grade each state before changing or removing it:

lab grade review-deploy

The grader reads project files and host state. A passing report covers the listed checks; also perform the task’s independent connection, repeat-run, and reboot checks where requested.

Add a third disposable user through the existing list, then verify all accounts without duplicating the task.

Record the published result first. The grader checks the original requirements, so a changed name or value may intentionally fail those checks.

Prepare and use a reproducible control-node project for servera and serverb.

  • The project must have a discoverable inventory and configuration, with the privileged connections appropriate to the environment (root in the home walkthrough). Use the runtime appropriate to your environment.
  • users.yml must provision joe and sam through one list-driven task.
  • packages.yml must install the packages described in the exercise, httpd and mariadb-server, plus redis only on hosts with more than 10 MiB of swap.
  • Repair verify_user.yml so it checks for sam without creating that account and records the result in /home/student/verify.txt. Confirm both hosts and repeat the playbooks.

Reset the servers first: rht-vmctl reset servers on the Ubuntu host. ansible-navigator is already installed on workstation (section 1.6), and the home lab runs without an execution environment, so the first task's EE steps do not apply.

Install the control node tools

Install automation content navigator on workstation; the repository that contains it is already configured.

[student@workstation ~]$ sudo dnf install ansible-navigator
...output omitted...
Complete!

Nothing to install: check that it is there.

[student@workstation ~]$ ansible-navigator --version
ansible-navigator 26.9.0

Inventory and configuration

In ~/review-deploy, create an inventory with a group dev containing servera.lab.example.com and serverb.lab.example.com, and an ansible.cfg that uses it.

[dev]
servera.lab.example.com
serverb.lab.example.com
[defaults]
inventory=./inventory

In a classroom, ansible-navigator runs the playbooks inside an execution environment, which connects to the managed hosts as root. The home lab runs them directly on workstation, as student, who cannot add users. Add remote_user=root to [defaults] to get the same behaviour; section 1.6 installed student's key for root on every server.

[defaults]
inventory=./inventory
remote_user=root

The execution environment

Create ansible-navigator.yml so that navigator uses the image utility.lab.example.com/ee-supported-rhel8:latest, and pulls it only if it is missing. Log in to the private automation hub on utility.lab.example.com (user admin, password redhat), then run ansible-navigator once to pull the image.

---
ansible-navigator:
  execution-environment:
    image: utility.lab.example.com/ee-supported-rhel8:latest
    pull:
      policy: missing
[student@workstation review-deploy]$ podman login utility.lab.example.com
Username: admin
Password: redhat
Login Succeeded!
[student@workstation review-deploy]$ ansible-navigator
...output omitted...
Execution environment image name:     utility.lab.example.com/ee-supported-rhel8:latest
Execution environment pull policy:    missing
Execution environment pull needed:    True
...output omitted...

Skip this task: the home lab has no private automation hub and runs without an execution environment, which your ~/.ansible-navigator.yml already says.

Two users with one task

Write users.yml with one play for dev that adds the users joe and sam, with a single task. Run it.

---
- name: Add users
  hosts: dev

  tasks:
    - name: Add the users joe and sam
      ansible.builtin.user:
        name: "{{ item }}"
      loop:
        - joe
        - sam
[student@workstation review-deploy]$ ansible-navigator run -m stdout users.yml

PLAY [Add users] ***************************************************************

TASK [Gathering Facts] *********************************************************
ok: [servera.lab.example.com]
ok: [serverb.lab.example.com]

TASK [Add the users joe and sam] ***********************************************
changed: [serverb.lab.example.com] => (item=joe)
changed: [servera.lab.example.com] => (item=joe)
changed: [serverb.lab.example.com] => (item=sam)
changed: [servera.lab.example.com] => (item=sam)

PLAY RECAP *********************************************************************
servera.lab.example.com    : ok=2    changed=1    unreachable=0    failed=0  ...
serverb.lab.example.com    : ok=2    changed=1    unreachable=0    failed=0  ...

In the home lab without remote_user=root, every item fails with useradd: Permission denied: the playbook connected as student.

Packages from a variable

Look at packages.yml. In its play, define a variable packages with the list httpd and mariadb-server. Run it.

---
- name: Install packages
  hosts: dev
  vars:
    packages:
      - httpd
      - mariadb-server

  tasks:
    - name: Install the required packages
      ansible.builtin.dnf:
        name: "{{ packages }}"
        state: latest
[student@workstation review-deploy]$ ansible-navigator run -m stdout packages.yml
...output omitted...
TASK [Install the required packages] *******************************************
changed: [servera.lab.example.com]
changed: [serverb.lab.example.com]
...output omitted...

A package that depends on a fact

Add a task to packages.yml that installs redis only if the host has more than 10 MB of swap space. Run the playbook again.

    - name: Install redis
      ansible.builtin.dnf:
        name: redis
        state: latest
      when: ansible_facts['swaptotal_mb'] > 10
[student@workstation review-deploy]$ ansible-navigator run -m stdout packages.yml
...output omitted...
TASK [Install redis] ***********************************************************
skipping: [servera.lab.example.com]
skipping: [serverb.lab.example.com]
...output omitted...
[student@workstation review-deploy]$ ansible dev -m ansible.builtin.setup -a 'filter=ansible_swaptotal_mb'
servera.lab.example.com | SUCCESS => {
    "ansible_facts": {
        "ansible_swaptotal_mb": 0,
...output omitted...

The home-lab servers have no swap, so both skip the task. In a classroom where one server has swap, that one installs redis.

Fix verify_user.yml

verify_user.yml should check, without creating it, that the user sam exists, and then write a line to /home/student/verify.txt. Run it with --check and fix what it reports, until a check run passes. Then run it normally.

[student@workstation review-deploy]$ ansible-navigator run -m stdout verify_user.yml --check
ERROR! couldn't resolve module/action 'ansible.buildin.user'. This often indicates a misspelling, missing collection, or incorrect module path.

The error appears to be in '/home/student/review-deploy/verify_user.yml': line 6, column 7, but may
be elsewhere in the file depending on the exact syntax problem.
...output omitted...

The module name is misspelled: ansible.buildin.user should be ansible.builtin.user. Fix it and check again:

[student@workstation review-deploy]$ ansible-navigator run -m stdout verify_user.yml --check
...output omitted...
TASK [Output sam user status to file] ******************************************
fatal: [serverb.lab.example.com]: FAILED! => {"changed": false, "msg": "Unsupported parameters for (ansible.builtin.lineinfile) module: when. Supported parameters include: attributes, backrefs, backup, create, firstmatch, group, insertafter, insertbefore, line, ...output omitted..."}
...output omitted...

when is indented as if it were an option of lineinfile. It is a task keyword, so it belongs at the level of the module name:

---
- name: Verify the sam user was created
  hosts: dev

  tasks:
    - name: Verify the sam user exists
      ansible.builtin.user:
        name: sam
      check_mode: true
      register: sam_check

    - name: Sam was created
      ansible.builtin.debug:
        msg: "Sam was created"
      when: sam_check['changed'] == false

    - name: Output sam user status to file
      ansible.builtin.lineinfile:
        path: /home/student/verify.txt
        line: "Sam was created"
        create: true
      when: sam_check['changed'] == false
[student@workstation review-deploy]$ ansible-navigator run -m stdout verify_user.yml
...output omitted...
TASK [Sam was created] *********************************************************
ok: [servera.lab.example.com] => {
    "msg": "Sam was created"
}
...output omitted...
TASK [Output sam user status to file] ******************************************
changed: [servera.lab.example.com]
changed: [serverb.lab.example.com]

PLAY RECAP *********************************************************************
servera.lab.example.com    : ok=4    changed=1    unreachable=0    failed=0  ...
serverb.lab.example.com    : ok=4    changed=1    unreachable=0    failed=0  ...

check_mode: true on the user task means it can never create sam: if it would have to, it reports changed, and that is the test.

Grade and finish

Check your work with lab grade review-deploy, then put the exercise away with lab finish review-deploy.