1.4 - Generate a Role
You have a working playbook that sets up web servers with Apache and a status page, configures MariaDB on the database tier, creates users, and deploys templates. In this module, you will use the coding assistant to create a similar setup as an Ansible role — the standard way to organize and reuse automation in production.
1. Understanding Roles
💡 What is an Ansible role?
A role is a structured way to organize automation into reusable components. Instead of putting everything in one playbook file, a role separates concerns into a standard directory layout:
roles/
└── system_setup/
├── tasks/main.yml # The tasks to execute
├── handlers/main.yml # Handlers (e.g., restart services)
├── templates/ # Jinja2 template files
├── vars/main.yml # Variables specific to this role
├── defaults/main.yml # Default variable values
└── meta/main.yml # Role metadata and dependencies
Roles make automation:
-
Reusable — apply the same role to different playbooks and projects
-
Shareable — publish roles to Ansible Galaxy for others to use
-
Maintainable — each concern lives in its own file, making changes easier to track
A playbook that uses a role looks like this:
---
- name: Configure infrastructure
hosts: all
become: true
roles:
- system_setup_role
One line replaces an entire playbook of tasks, variables, handlers, and templates.
2. Hands-On Experience
☑️ Task 1 - Generate a role with the automation coding assistant
|
Switch to the VS Code tab. |
Before generating a role, the extension needs to know which collection to place it in. Your lab workspace already has a galaxy.yml file that defines a collection called lab.system_automation — this was pre-created as part of the lab setup. You can view it in the VS Code file explorer at ansible-files/galaxy.yml. The extension reads this file to determine where to save generated roles.
-
Click on the Ansible extension icon in the left sidebar to open the Ansible extension panel.
-
Click the "Generate a Role" button in the extension panel.
-
When prompted, paste this prompt — it is similar to the one you used to generate your playbook:
Create an Ansible role that sets up web and database infrastructure. Define variables for user_name (padawan), web_package (httpd), web_service (httpd), db_package (mariadb-server), and db_service (mariadb). Include these tasks in order: 1. Create a user with the name from user_name variable, ensuring a home directory is created 2. Install the package from web_package variable, only on the web group using the conditional: when: inventory_hostname in groups['web'] 3. Ensure the web service (from web_service) is running and enabled, only on the web group using the same conditional 4. Deploy a Jinja2 template from templates/index.html.j2 to /var/www/html/index.html, only on the web group using the same conditional 5. Install the package from db_package variable, only on the database group using the conditional: when: inventory_hostname in groups['database'] 6. Ensure the database service (from db_service) is running and enabled, only on the database group using the same conditional 7. Deploy a Jinja2 template from templates/motd.j2 to /etc/motd on all hosts Include a handler to restart Apache when needed, and use ansible.builtin modules throughout. -
The automation coding assistant will analyze your prompt and show you a role name field and a step outline. Set the role name to system_setup_role, review the steps, then click "Continue".
-
On the next page, review the generated files. When asked to select a collection, choose lab.system_automation, then click "Save files".
-
The role will be created under
roles/system_setup_role/in your workspace.
|
Notice how the prompt is almost identical to the one you used for playbook generation — but this time the automation coding assistant organizes the output into the role directory structure instead of a single YAML file. The extension places roles inside a collection (defined by the |
☑️ Task 2 - Explore the role structure
|
Stay in the VS Code tab. |
-
In the VS Code file explorer, expand the
roles/system_setup_role/directory that was just created. You should see several folders inside. -
Open
tasks/main.yml— this contains the tasks, similar to what you see in yoursystem_setup.ymlplaybook. But notice what is missing:-
No
hosts:orbecome:— those are set by the playbook that calls the role -
No
vars:section inline — variables have moved to their own file
-
-
Open
handlers/main.yml— the Apache restart handler lives here instead of at the bottom of a playbook. -
Check the
vars/ordefaults/directory for your variable definitions (the user name, web package, database package, and service names you specified in the prompt). -
Notice that the role does not contain a
templates/directory. The automation coding assistant’s role generator createstasks/,handlers/, andvars/files, but does not copy template files into the role. This is fine — Ansible’sansible.builtin.templatemodule searches multiple paths for template files, including the playbook’s directory. Sincetemplates/motd.j2andtemplates/index.html.j2already exist in your workspace’sansible-files/templates/directory (pre-created by the lab), Ansible will find them automatically when the role runs.In a production environment, you would typically copy your Jinja2 templates into the role’s
templates/directory to keep the role self-contained and portable. For this lab, the workspace-level templates work because the role runs from the same workspace where the templates live.
☑️ Task 3 - Understand the difference
Here is where each section of your playbook ended up in the role:
| Playbook Section | Role Location | Why |
|---|---|---|
|
Removed (set by calling playbook) |
Roles are host-agnostic — the playbook that imports the role decides where to run it |
|
|
Separated so callers can override values without editing the role |
|
|
The core automation, isolated for clarity |
|
|
Handlers are role-scoped — they only trigger from tasks in this role |
|
|
Same files, but now the |
The key insight: a role is not new automation — it is the same automation reorganized so it can be reused, shared, and maintained independently.
☑️ Task 4 - Run the role-based playbook
|
Open a terminal in VS Code if you don’t have one open: click Terminal → New Terminal, or press Ctrl+`. |
Now verify that the role produces the same results as your original system_setup.yml playbook.
-
Create a simple playbook that uses the role. In the terminal, run:
cat > /home/rhel/ansible-files/role_playbook.yml << 'EOF' --- - name: Configure infrastructure using role hosts: all become: true roles: - system_setup_role EOF -
Run the role-based playbook:
cd /home/rhel/ansible-files && ansible-navigator run role_playbook.yml -
Compare the output to your earlier
system_setup.ymlrun. You should see the same tasks execute in the same order — the only difference is that Ansible now reads them from the role’s directory structure instead of a single playbook file.Because the infrastructure is already configured from the previous module, all tasks should show
ok(green) withchanged=0. This confirms the role is functionally identical to the playbook.
3. Learning Outcomes
By completing this module, you now understand:
-
What an Ansible role is and why roles exist
-
How to use the automation coding assistant to convert a playbook into a role
-
How a role’s directory structure maps to playbook sections
-
The difference between
vars/(role-specific) anddefaults/(overridable) variables -
How roles make automation reusable across different playbooks and projects
4. Embracing the Next Challenge
✅ Next Challenge
Once you have completed the tasks, press the
button to proceed to the wrap-up.
-
The
button will validate that a role structure exists in your workspace. -
You can also click
to auto-complete the challenge.
🐛 Encountered an issue?
If you have encountered an issue or noticed something not quite right, please open an issue on the Introduction to automation coding assistant repository.