4.1 Ansible Playbooks - Variables and Loops

In this lab we’ll start to use variables and loops.

Task 1

  • In your playbook webserver.yml you have two tasks for starting and enabling httpd and firewalld. Merge these 2 tasks into one.
Solution Task 1

Delete the 2 tasks “start and enable [httpd,firewalld]”. Add a new task with the following content:

1
2
3
4
5
6
7
8
- name: start and enable services
  service:
    name: "{{ item }}"
    state: started
    enabled: yes
  loop:
    - httpd
    - firewalld

Task 2

  • In your playbook webserver.yml, ensure that that the package firewalld is installed. Do the installation of httpd and firewalld in one task. Do you really need to use a loop? Have a look at the description of Ansible’s dnf module.
Solution Task 2
1
2
3
4
5
6
7
tasks:
  - name: install httpd and firewalld
    dnf:
      name:
        - httpd
        - firewalld
      state: installed

Task 3

  • Write a new playbook motd.yml which sets the content of /etc/motd on all servers to a custom text. Use the variable motd_content and the copy module with the option content containing the variable.
Solution Task 3

Content of motd.yml:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
---
- hosts: all
  become: true
  vars:
    motd_content: "Thi5 1s some r3ally stR4nge teXT!\n"
  tasks:
   - name: set content of /etc/motd
     copy:
       dest: /etc/motd
       content: "{{ motd_content }}"
1
ansible-playbook motd.yml

Take a look at what your playbook just did:

1
2
3
4
$ ssh -l ansible <node1-ip>
Last login: Fri Nov  1 14:16:08 2019 from 5-102-146-174.cust.cloudscale.ch
Thi5 1s some r3ally stR4nge teXT! # <-- it worked!
[ansible@node1 ~]$

Task 4

  • Using the command line, overwrite the content of motd by providing the variable motd_content with a different value.
  • Modify the content again, but use a vars.yml file.
Solution Task 4
1
2
3
4
5
6
$ ansible-playbook motd.yml --extra-vars motd_content="0th3r_5trang3_TExt"

$ ssh -l ansible <node1-ip>
Last login: Fri Nov  1 14:18:52 2019 from 5-102-146-174.cust.cloudscale.ch
0th3r_5trang3_TExt # <-- it worked
[ansible@node1 ~]$
1
2
3
4
$ cat vars.yml
---
motd_content: "st1ll m0r3 str4ng3 TexT!"
$ ansible-playbook motd.yml --extra-vars @vars.yml

Login via SSH again and check if the new text was set.

Task 5

  • Set the motd_content from Task 4 using group_vars for node1 and host_vars for node2.
  • Make sure you remove the variable definition in motd.yml. Reason being it will have a higher priority.
  • Limit the run to node1 and node2.
Solution Task 5

Your motd.yml should look something like this:

1
2
3
4
5
6
7
8
---
- hosts: all
  become: true
  tasks:
    - name: set content of /etc/motd
      copy:
        dest: /etc/motd
        content: "{{ motd_content }}"

After creating the new directories and files you should have something similar to this:

1
2
3
4
5
6
$ cat inventory/group_vars/web.yml
---
motd_content: "This is a webserver\n"
$ cat inventory/host_vars/node2.yml
---
motd_content: "This is node2\n"

Run your playbook and check if the text was changed accordingly on the two nodes:

1
2
3
ansible-playbook motd.yml -l node1,node2

ansible web,node2 -a "cat /etc/motd"

Task 6

  • Get a feeling for errors: Remove the quotes around the curly brackets and have a look at the output.
Solution Task 6
1
2
3
4
5
6
7
8
---
- hosts: all
  become: true
  tasks:
    - name: set content of /etc/motd
      copy:
        dest: /etc/motd
        content: {{ motd_content }} #<-- missing quotes here

Task 7 (BONUS!)

  • Create a playbook takemehome.yml that does the following:
    • Create a compressed archive containing all the content from your /home/ansible/techlab/ folder
    • Don’t include the subfolder /home/ansible/techlab/awx with all its content in the archive.
    • Compress the archive using any supported type of compression.
    • Ensure an archive is created even if the source is one single file.
    • Send this file via mail to your own email adress. Note that you have to have valid credentials for a smtp server. Put these credentials into a password file password_file.yml.
    • Run the playbook using the smtp password from the file password_file.yml
    • remove the password file password_file.yml
Solution Task 7

Write your SMTP Password to a file:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
$ cat password_file.yml
password: "<my_secret_password>"

Create the playbook:
```bash
$ cat takemehome.yml
---
- hosts: localhost
  #vars_files:              # if the vars file is not provided here, you'll have to use it with
  #  - password_file.yml    # --extra-vars on cmdline as shown below
  tasks:
    - name: Create archive, excluding awx folder
      archive:
        path: /home/ansible/techlab/*
        dest: /home/ansible/techlab.tar.bz2
        exclude_path: /home/ansible/techlab/awx
        format: bz2
        force_archive: true
    - name: Send archive via email
      mail:
        host: smtp.puzzle.ch
        port: 587
        username: "tux.puzzler@puzzle.ch"
        password: "{{ password }}"
        secure: starttls
        sender: tux.puzzler@puzzle.ch
        to: bill.gates@gmail.com
        subject: Techlab stuff
        body: Sending my stuff home
        attach: /home/ansible/techlab.tar.bz2
      no_log: true

Run the playbook by using the SMTP password from the file created before. After the playbook was sent, delete the password file.

1
2
3
ansible-playbook takemehome.yml --extra-vars "@password_file.yml"
ansible-playbook takemehome.yml # if vars file provided in playbook
rm -f password_file.yml

All done?

  • Wow! Well done. :-)
Last modified November 14, 2022: add http headers (7f665a8)