Chapter 8: Simplifying Playbooks with Roles and Collections
Exercise: Deploying roles from external content sources
You will install a role that another team keeps in a Git repository, use it to set the default shell environment for new users, and then switch to a newer branch of the same role and see what changes.
The project ~/role-galaxy has an ansible.cfg and an inventory with servera.lab.example.com in the devservers group. The role, bash_env, writes .bashrc, .bash_profile and .vimrc into /etc/skel, so every user created afterwards gets them.
Deploying roles from external content sources
- Record a project’s role dependencies in a requirements file.
- Install roles from a requirements file and list them.
- Switch an installed role to another branch.
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 role-galaxy
lab grade role-galaxy --checkpoint appliedThe 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.
Choose a different prompt color supported by the role and verify which files change.
Record the published result first. The grader checks the original requirements, so a changed name or value may intentionally fail those checks.
Manage a role dependency through roles/requirements.yml and prove its behavior through a fresh user login.
- Install the supplied Git role as
student.bash_env, initially frommain, into the project's role directory. use-bash_env-role.ymlmust apply its default prompt and recreatestudent2so the account receives the updated skeleton files. The disposable login password isredhat.- Change the dependency to
dev, make the project role path discoverable, and configure a blue prompt. - Prove the installed version and login result. Explain why changing
/etc/skelalone does not rewrite an existing user's home files.
lab start role-galaxy creates the Git repository on workstation, in ~/git-repos/student/bash_env.git, with two branches: main and dev. Wherever the steps below use the repository, use its file:// path.
Write the requirements file
In ~/role-galaxy, create roles/requirements.yml. It installs the bash_env role from Git, on the main branch, under the name student.bash_env.
---
# requirements.yml
- src: git@workstation.lab.example.com:student/bash_env
scm: git
version: main
name: student.bash_env---
# requirements.yml
- src: file:///home/student/git-repos/student/bash_env.git
scm: git
version: main
name: student.bash_envInstall the role into the project
[student@workstation role-galaxy]$ ls roles/
requirements.yml
[student@workstation role-galaxy]$ ansible-galaxy install -r roles/requirements.yml -p roles
Starting galaxy role install process
- extracting student.bash_env to /home/student/role-galaxy/roles/student.bash_env
- student.bash_env (main) was installed successfully
[student@workstation role-galaxy]$ ls roles/
requirements.yml student.bash_envList the roles
[student@workstation role-galaxy]$ ansible-galaxy list -p roles
# /home/student/role-galaxy/roles
- student.bash_env, main
# /usr/share/ansible/roles
- rhel-system-roles.firewall, (unknown version)
...output omitted...
[WARNING]: - the configured path /home/student/.ansible/roles does not exist.Run the same command without -p roles: the project's role is not listed, because roles/ is not in the configured roles_path yet. The warning is harmless; it only says that one of the default directories does not exist.
Use the role
Create use-bash_env-role.yml. Before the role, make sure a test user student2 does not exist; after it, create that user again, so it gets the new files from /etc/skel. Set the prompt through the role's default_prompt variable.
---
- name: Use student.bash_env role playbook
hosts: devservers
vars:
default_prompt: '[\u on \h in \W dir]\$ '
pre_tasks:
- name: Ensure test user does not exist
ansible.builtin.user:
name: student2
state: absent
force: true
remove: true
roles:
- student.bash_env
post_tasks:
- name: Create the test user
ansible.builtin.user:
name: student2
state: present
password: "{{ 'redhat' | password_hash('sha512', 'mysecretsalt') }}"The password_hash filter turns the plain-text password into the hash that /etc/shadow expects. The fixed salt keeps the task idempotent.
Run it
[student@workstation role-galaxy]$ ansible-navigator run -m stdout use-bash_env-role.yml
PLAY [Use student.bash_env role playbook] **************************************
TASK [Gathering Facts] *********************************************************
ok: [servera.lab.example.com]
TASK [Ensure test user does not exist] *****************************************
ok: [servera.lab.example.com]
TASK [student.bash_env : put away .bashrc] *************************************
changed: [servera.lab.example.com]
TASK [student.bash_env : put away .bash_profile] *******************************
changed: [servera.lab.example.com]
TASK [student.bash_env : put away .vimrc] **************************************
changed: [servera.lab.example.com]
TASK [Create the test user] ****************************************************
changed: [servera.lab.example.com]
PLAY RECAP *********************************************************************
servera.lab.example.com : ok=6 changed=4 unreachable=0 failed=0 ...You may also see a deprecation warning about the Python crypt module, from password_hash. It does not affect the result.
Log in as the new user
Connect as student2, with the password redhat. The prompt is the one from the role:
[student@workstation role-galaxy]$ ssh student2@servera
student2@servera's password: redhat
...output omitted...
[student2 on servera in ~ dir]$ exitSwitch to the dev branch
The dev branch of the role adds a prompt_color variable. Change version: main to version: dev in roles/requirements.yml.
This time, add roles_path to the [defaults] section of ansible.cfg, so you no longer need -p roles:
[defaults]
inventory = ./inventory
remote_user = devops
interpreter_python = auto_silent
roles_path = roles
...output omitted...Remove the installed role and install it again from the new branch:
[student@workstation role-galaxy]$ ansible-galaxy remove student.bash_env
- successfully removed student.bash_env
[student@workstation role-galaxy]$ ansible-galaxy install -r roles/requirements.yml
Starting galaxy role install process
- extracting student.bash_env to /home/student/role-galaxy/roles/student.bash_env
- student.bash_env (dev) was installed successfullyUse the new variable
Add prompt_color: blue to the play's vars, next to default_prompt, and run the playbook again:
[student@workstation role-galaxy]$ ansible-navigator run -m stdout use-bash_env-role.yml
...output omitted...
TASK [Ensure test user does not exist] *****************************************
changed: [servera.lab.example.com]
TASK [student.bash_env : put away .bashrc] *************************************
changed: [servera.lab.example.com]
TASK [student.bash_env : put away .bash_profile] *******************************
ok: [servera.lab.example.com]
TASK [student.bash_env : put away .vimrc] **************************************
ok: [servera.lab.example.com]
TASK [Create the test user] ****************************************************
changed: [servera.lab.example.com]
PLAY RECAP *********************************************************************
servera.lab.example.com : ok=6 changed=3 unreachable=0 failed=0 ...Only .bashrc changed between the branches. Log in as student2 again: the prompt is now blue.
Finish
Check your work with lab grade role-galaxy, then put the exercise away with lab finish role-galaxy.