In Ansible, playbooks are used to define a series of tasks that automate server configurations, application deployments, and more. However, as your automation projects grow, managing all tasks within a single playbook can become complex. This is where importing or including playbooks can help.
You can import or include playbooks using import_playbook or include_tasks. This is useful when you want to break down large playbooks into smaller, reusable components.
In this article, we’ll explore how to use import and include playbook in Ansible.
Table of Contents
Difference Between import_playbook and include_tasks
Let’s start by understanding the key differences:
import_playbook
- Used to include another playbook.
- It is a static import, meaning the playbook is read and processed before execution begins.
- Useful when you want to reuse complete playbooks.
include_tasks
- Used to include a set of tasks dynamically during playbook execution.
- It is a dynamic inclusion, meaning tasks are read and processed only when they are executed.
- Useful for including tasks conditionally based on variables or facts.
When to Use Which
- Use import_playbook when you need to include an entire playbook with a defined set of tasks.
- Use include_tasks when you want to include specific tasks based on conditions or variables.
Basic Syntax
Here’s how to use import_playbook and include_tasks in Ansible:
Using import_playbook
# main_playbook.yml
- import_playbook: playbooks/webserver_setup.yml
Using include_tasks
# main_playbook.yml
- include_tasks: tasks/configure_firewall.yml
The main difference is that import_playbook is processed before execution, while include_tasks is processed dynamically during execution.
Example 1: Using import_playbook
Let’s look at a scenario where we use import_playbook to include another playbook.
Here is a directory structure of the Ansible project:
my_ansible_project/
├── main_playbook.yml
└── playbooks/
└── webserver_setup.yml
Content of webserver_setup.yml
---
- name: Setup Web Server
hosts: webservers
tasks:
- name: Install NGINX
ansible.builtin.yum:
name: nginx
state: present
- name: Start and Enable NGINX
ansible.builtin.systemd:
name: nginx
state: started
enabled: true
Content of main_playbook.yml
---
- import_playbook: playbooks/webserver_setup.yml
Now, run the main playbook.
# ansible-playbook main_playbook.yml
Output:
PLAY [Setup Web Server] ********************************************************
TASK [Install NGINX] ***********************************************************
changed: [webserver1]
TASK [Start and Enable NGINX] **************************************************
changed: [webserver1]
PLAY RECAP *********************************************************************
webserver1 : ok=2 changed=2 unreachable=0 failed=0
In this example, we used import_playbook to include the webserver_setup.yml playbook. The tasks from the imported playbook are executed as if they were written directly in the main playbook.
Example 2: Using include_tasks
Now, let’s see an example of using include_tasks to dynamically include tasks based on conditions.
Here is a directory structure:
my_ansible_project/
├── main_playbook.yml
└── tasks/
├── setup_dev.yml
└── setup_prod.yml
Content of setup_dev.yml
---
- name: Install Development Tools
ansible.builtin.yum:
name: git
state: present
Content of setup_prod.yml
---
- name: Install Production Monitoring Tools
ansible.builtin.yum:
name: htop
state: present
Content of main_playbook.yml
---
- hosts: all
tasks:
- include_tasks: tasks/setup_dev.yml
when: env == 'dev'
- include_tasks: tasks/setup_prod.yml
when: env == 'prod'
Now, run the main playbook with an extra variable (env=dev).
# ansible-playbook main_playbook.yml -e "env=dev"
Output:
PLAY [all] *********************************************************************
TASK [Install Development Tools] ***********************************************
changed: [host1]
PLAY RECAP *********************************************************************
host1 : ok=1 changed=1 unreachable=0 failed=0
In this example, include_tasks is used to dynamically include either setup_dev.yml or setup_prod.yml based on the value of the env variable. This allows for conditional task execution, providing flexibility in how tasks are executed.
Advanced Usage: Conditional Task Inclusion
You can use include_tasks with conditions based on facts gathered during the playbook run.
The following example executes tasks conditionally using the when statement:
---
- hosts: all
tasks:
- include_tasks: tasks/setup_ubuntu.yml
when: ansible_os_family == 'Debian'
- include_tasks: tasks/setup_centos.yml
when: ansible_os_family == 'RedHat'
This setup dynamically includes task files based on the detected OS family (Debian or RedHat). It helps in executing platform-specific tasks.
Conclusion
In this article, we explored the usage of import_playbook and include_tasks in Ansible. We demonstrated how to organize playbooks effectively using these features, allowing for better modularity and maintainability.
FAQs
1. Can I use conditions with import_playbook?
No, conditions (like when) are not supported with import_playbook. Use include_tasks if you need conditional logic.
2. How do I include tasks from another playbook file?
Use import_playbook: filename.yml in your main playbook or include_tasks: filename.yml within a task block.
3. Why should I use include_tasks instead of copying tasks directly?
Using include_tasks helps keep your playbooks modular, making them easier to read, maintain, and reuse across multiple playbooks.