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.

  1. Click on the Ansible extension icon in the left sidebar to open the Ansible extension panel.

  2. Click the "Generate a Role" button in the extension panel.

  3. 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.
  4. 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".

  5. On the next page, review the generated files. When asked to select a collection, choose lab.system_automation, then click "Save files".

  6. 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 galaxy.yml in your workspace), which is how Ansible organizes reusable content for sharing and distribution.

☑️ Task 2 - Explore the role structure

Stay in the VS Code tab.

  1. In the VS Code file explorer, expand the roles/system_setup_role/ directory that was just created. You should see several folders inside.

  2. Open tasks/main.yml — this contains the tasks, similar to what you see in your system_setup.yml playbook. But notice what is missing:

    • No hosts: or become: — those are set by the playbook that calls the role

    • No vars: section inline — variables have moved to their own file

  3. Open handlers/main.yml — the Apache restart handler lives here instead of at the bottom of a playbook.

  4. Check the vars/ or defaults/ directory for your variable definitions (the user name, web package, database package, and service names you specified in the prompt).

  5. Notice that the role does not contain a templates/ directory. The automation coding assistant’s role generator creates tasks/, handlers/, and vars/ files, but does not copy template files into the role. This is fine — Ansible’s ansible.builtin.template module searches multiple paths for template files, including the playbook’s directory. Since templates/motd.j2 and templates/index.html.j2 already exist in your workspace’s ansible-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

hosts: all, become: true

Removed (set by calling playbook)

Roles are host-agnostic — the playbook that imports the role decides where to run it

vars:

vars/main.yml or defaults/main.yml

Separated so callers can override values without editing the role

tasks:

tasks/main.yml

The core automation, isolated for clarity

handlers:

handlers/main.yml

Handlers are role-scoped — they only trigger from tasks in this role

templates/motd.j2, templates/index.html.j2

templates/motd.j2, templates/index.html.j2

Same files, but now the ansible.builtin.template module finds them relative to the role

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.

  1. 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
  2. Run the role-based playbook:

    cd /home/rhel/ansible-files && ansible-navigator run role_playbook.yml
  3. Compare the output to your earlier system_setup.yml run. 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) with changed=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) and defaults/ (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 Next button to proceed to the wrap-up.

  • The Next button will validate that a role structure exists in your workspace.

  • You can also click Solve 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.