Chapter 3: Implementing an Ansible Playbook

Exercise: Implementing multiple plays

You will write intranet.yml, a playbook with two plays. The first configures servera as an intranet web server with root privileges. The second runs unprivileged on localhost and checks that the site answers.

The project ~/playbook-multi already has an ansible.cfg and an inventory that defines servera.lab.example.com.

A playbook with two plays: Plays run in order. The first configures servera with root privileges; the second runs on localhost (inside the execution environment) to test the result.

Implementing multiple plays

  • Build and run a playbook with two plays.
  • Enable privilege escalation for one play and disable it for another.

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 playbook-multi

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.

Make the verification require a specific phrase in the returned page as well as HTTP 200.

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

Deliver an intranet site on servera and verify it in the same run. Save your work in intranet.yml.

  • The host must have current httpd and firewalld packages, with both services running and enabled.
  • /var/www/html/index.html must contain Welcome to the example.com intranet! and HTTP must be allowed now and after reboot.
  • A separate, unprivileged play on localhost must confirm an HTTP 200 response and retrieve the content.
  • Show that the verification runs after deployment and that a repeat run has no unexpected changes.

Start the first play

In ~/playbook-multi, create intranet.yml with the document marker and a play named Enable intranet services for servera.lab.example.com, with privilege escalation on and an empty task list to fill in.

---
- name: Enable intranet services
  hosts: servera.lab.example.com
  become: true
  tasks:

Install the latest httpd and firewalld

One ansible.builtin.dnf task can handle both packages: give name a list.

    - name: Latest version of httpd and firewalld installed
      ansible.builtin.dnf:
        name:
          - httpd
          - firewalld
        state: latest

The task starts at four spaces, the module at six, its arguments at eight, and the package list items at ten.

Deploy a test page

Use ansible.builtin.copy with inline content rather than a source file.

    - name: Test html page is installed
      ansible.builtin.copy:
        content: "Welcome to the example.com intranet!\n"
        dest: /var/www/html/index.html

Start firewalld and open HTTP

Two tasks: make sure firewalld is enabled and running, then allow the http service permanently and immediately.

    - name: Firewall enabled and running
      ansible.builtin.service:
        name: firewalld
        enabled: true
        state: started

    - name: Firewall permits access to httpd service
      ansible.posix.firewalld:
        service: http
        permanent: true
        state: enabled
        immediate: true

Note that firewalld comes from the ansible.posix collection, not ansible.builtin.

Start the web server

    - name: Web server enabled and running
      ansible.builtin.service:
        name: httpd
        enabled: true
        state: started

Add the test play

Start a second play at the left margin (no indentation). It targets localhost, which with navigator is the execution environment (on the home lab, where no container is used, it is workstation itself), and does not need privilege escalation.

- name: Test intranet web server
  hosts: localhost
  become: false
  tasks:
    - name: Connect to intranet web server
      ansible.builtin.uri:
        url: http://servera.lab.example.com
        return_content: true
        status_code: 200

return_content: true adds the server's response to the task result, and status_code: 200 makes the task fail if the page does not load.

---
- name: Enable intranet services
  hosts: servera.lab.example.com
  become: true
  tasks:
    - name: Latest version of httpd and firewalld installed
      ansible.builtin.dnf:
        name:
          - httpd
          - firewalld
        state: latest

    - name: Test html page is installed
      ansible.builtin.copy:
        content: "Welcome to the example.com intranet!\n"
        dest: /var/www/html/index.html

    - name: Firewall enabled and running
      ansible.builtin.service:
        name: firewalld
        enabled: true
        state: started

    - name: Firewall permits access to httpd service
      ansible.posix.firewalld:
        service: http
        permanent: true
        state: enabled
        immediate: true

    - name: Web server enabled and running
      ansible.builtin.service:
        name: httpd
        enabled: true
        state: started

- name: Test intranet web server
  hosts: localhost
  become: false
  tasks:
    - name: Connect to intranet web server
      ansible.builtin.uri:
        url: http://servera.lab.example.com
        return_content: true
        status_code: 200

Check the syntax

[student@workstation playbook-multi]$ ansible-navigator run \
> -m stdout intranet.yml --syntax-check
playbook: /home/student/playbook-multi/intranet.yml

Run it and read the recap

[student@workstation playbook-multi]$ ansible-navigator run -m stdout intranet.yml
PLAY [Enable intranet services] ************************************************
...output omitted...
PLAY [Test intranet web server] ************************************************
...output omitted...
PLAY RECAP *********************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0  ...
servera.lab.example.com    : ok=6    changed=5    unreachable=0    failed=0  ...

Both plays appear in order, and each host gets its own line in the recap.

Confirm from the workstation

[student@workstation playbook-multi]$ curl http://servera.lab.example.com
Welcome to the example.com intranet!

Finish

Check your work with lab grade playbook-multi, then put the exercise away with lab finish playbook-multi.