Core Idea
Imports are resolved statically at parse time while includes are resolved dynamically at run time; roles package tasks into redistributable units, and Galaxy is where you share them.
import_tasksandimport_role: everything expands up front, in listed order.- Includes: dynamic includes and role includes that decide what runs at execution time.
- Roles: directory structure, pre-tasks and post-tasks, and Ansible Galaxy.
Imports & Includes
The import_* feature allows you to include tasks, or even whole roles, in the tasks section of a play through the use of the keywords import_tasks and import_role.
When importing files in other playbooks statically, Ansible runs the plays and tasks in each imported playbook in the order they are listed, just as if they had been defined directly in the main playbook.
The include_* features allow you to dynamically include tasks, vars, or even whole roles by the use of the keywords include_tasks, include_vars, and include_role.
This is often used in roles to separate or even group tasks and task arguments to each task in the included file.
Included roles and tasks mayβor may notβrun, depending on the results of other tasks in the playbook. When a loop is used with include_tasks or include_role, the included tasks or role will be executed once for each item in the loop.
Imports
Import variable files
vars_files:
- vars.ymlTasks can easily be included in a similar way. In the tasks: section of your playbook, you can add import_tasks directives like so:
tasks:
- import_tasks: imported-tasks.ymlExample
# user.yml
---
- name: Add profile info for user
ansible.builtin.copy:
src: example_profile
dest: "/home/{{ username }}/.profile"
owner: "{{ username }}"
group: "{{ username }}"
mode: 0744
- name: Add private keys for user
ansible.builtin.copy:
src: "{{ item.src }}"
dest: "/home/{{ username }}/.ssh/{{ item.dest }}"
owner: "{{ username }}"
group: "{{ username }}"
mode: 0600
with_items: "{{ ssh_private_keys }}"
- name: Restart example service
ansible.builtin.service:
name: example
state: restarted# main.yml
- name: Configure users
hosts: all
vars:
username: johndoe
ssh_private_keys:
- { src: /path/to/johndoe/key1, dest: id_rsa }
- { src: /path/to/johndoe/key2, dest: id_rsa_2 }
tasks:
- import_tasks: user.yml
vars:
username: johndoe
ssh_private_keys:
- { src: /path/to/johndoe/key1, dest: id_rsa }
- { src: /path/to/johndoe/key2, dest: id_rsa_2 }
- import_tasks: user.yml
vars:
username: janedoe
ssh_private_keys:
- { src: /path/to/janedoe/key1, dest: id_rsa }
- { src: /path/to/janedoe/key2, dest: id_rsa_2 }Includes
---
- name: Setup Web Server
hosts: webservers
become: true
vars_files:
- vars/main.yml
tasks:
- name: Load environment-specific variables
include_vars: "vars/{{ env }}.yml"
- name: Install required packages
include_tasks: tasks/install-packages.yml
- name: Configure web server
include_tasks: tasks/configure-webserver.yml
- name: Start and enable web server
include_tasks: tasks/start-service.ymlDynamic Includes
Depending on the number of operating systems supported by the role, this can lead to a lot of boilerplate for the include_tasks:
- include_tasks: Redhat.yml
when: ansible_os_family == 'Redhat'
- include_tasks: Debian.yml
when: ansible_os_family == 'Debian'Ansible has allowed users to include a file dynamically by using variable substitution. This is called a dynamic include:
- name: Play platform specific actions
include_tasks: "{{ ansible_os_family }}.yml"However, there is a drawback to using dynamic includes. If Ansible does not have enough information to populate the variables that determine which file will be included, ansible-playbook --list-tasks might not list the tasks.
Role Includes
The include_role clause differs from the import_role clause, which statically imports all parts of the role. By contrast, include_role allows us to select what parts of a role to include and use, as well as where in the play:
- name: Install nginx
yum:
pkg: nginx
- name: Install php
include_role:
name: php
- name: Configure nginx
template:
src: nginx.conf.j2
dest: /etc/nginx/nginx.confRoles
Ansible roles are a structured way to organize and reuse configuration, code, and tasks in Ansible projects.
Directory Structure
my_role/
βββ tasks/ # Main tasks of the role (defined in main.yml).
βββ handlers/ # Handlers to trigger upon task completion.
βββ files/ # Static files to copy to managed hosts.
βββ templates/ # Jinja2 templates for dynamic configuration files.
βββ vars/ # Variables with high priority (defined in main.yml).
βββ defaults/ # Default variables with low priority (defined in main.yml).
βββ meta/ # Metadata about the role, e.g., dependencies.
βββ tests/ # Test playbooks to verify the role.There are only two directories required to make a working Ansible role:
role_name/
βββ meta/
βββ tasks/Pre-Tasks & Post-Tasks
Ansible allows you to define the order in your playbooks:
- A list of tasks that execute before the roles with a
pre_taskssection - A list of roles to execute
- A list of tasks that execute after the roles with a
post_taskssection
- name: Deploy
hosts: web
vars_files:
- secrets.yml
pre-tasks:
# Pre Task Here
roles:
# Role
post-tasks:
# Post tasks here..Ansible Galaxy
Collection of pre-made ansible roles.
ansible-galaxy role install geerlingguy.apache \
geerlingguy.mysql geerlingguy.phpansible-galaxy role listdisplays a list of installed roles, with version numbersansible-galaxy role remove [role]removes an installed roleansible-galaxy role initcan be used to create a role template suitable for submission to Ansible Galaxy