Home Ansible How To Work With Include And Import Statements In Ansible With Examples

How To Work With Include And Import Statements In Ansible With Examples

How to Include/Import Playbooks in Ansible

By Karthick
5.7K views

When you create an Ansible playbook for larger projects, putting all the tasks in a single playbook will make the project complex. As a best practice, you have to group the task into separate playbooks. This will help you break down your project and achieve modularity in Ansible. In ansible, you can break the playbook, and task and import them using the "import_*" and "include_*" directives. In this article, we will learn how to work with include and import statements in Ansible with examples.

In the following sections, I will demonstrate how to import playbooks, tasks, and roles with simple examples. If you need an ansible lab to practice, please take a look at our ansible lab setup guide using Vagrant and Virtualbox in the link below.

Automated Ansible Lab Setup With Vagrant And Virtualbox In Linux

Includes vs Imports

As stated in the Ansible official documentation,

the include and import statements are very similar, however the Ansible executor engine treats them very differently.

  • All import* statements are pre-processed at the time playbooks are parsed.
  • All include* statements are processed as they are encountered during the execution of the playbook.

The "import_playbook" directive is introduced in ansible version 2.4 and prior to that only include_playbook was available. Post version 2.4 only the import_playbook directive is available and If you try to use the include_playbook directive in older versions, you will get the following error.

ERROR! 'include_playbook' is not a valid attribute for a Play

Importing Ansible Playbook

You can create multiple playbooks according to the nature of the play and finally import them under a single YAML file and run the playbook.

I created three playbooks.

  • First playbook - playbook1.yml
  • Second playbook - playbook2.yml
  • Main playbook - main.yml
Project Structure
Project Structure

The first and second playbook contains the following play definition.

# playbook1.yml
- name: Playbook imports
  hosts: localhost
  connection: local
  gather_facts: False

  tasks:
    - name: Task Import 
      ansible.builtin.debug:
        msg: "Importing playbook1.yml"

# playbook2.yml
- name: Playbook imports
  hosts: localhost
  connection: local
  gather_facts: False

  tasks:
    - name: Task Import 2
      ansible.builtin.debug:
        msg: "Importing playbook2.yml"

The main playbook is used to import both playbook1.yml and playbook2.yml.

- import_playbook: playbook1.yml
- import_playbook: playbook2.yml

Running the ansible-playbook command against the main.yml will import playbook1.yml and playbook2.yml playbooks into the current namespace and execute the tasks.

$ ansible-playbook main.yml

PLAY [Playbook imports] **********************************************************************************

TASK [Task Import] ***************************************************************************************
ok: [localhost] => {
    "msg": "Importing playbook1.yml"
}

PLAY [Playbook imports] **********************************************************************************

TASK [Task Import 2] *************************************************************************************
ok: [localhost] => {
    "msg": "Importing playbook2.yml"
}
Importing Playbook
Importing Playbook

Applying Other Directives with import_playbook

You can apply other directives like tags, conditional statement etc., with the import_playbook directive. The directive at the import level will be inherited by all the playbook tasks.

To understand it better, consider the below example. All I did was simply added a conditional statement to the main.yml file.

- import_playbook: playbook1.yml
  when: run is defined
- import_playbook: playbook2.yml
  when: run is defined

When I run this playbook, the plays, and the task is imported into the namespace and checked if the variable "run" is defined against all tasks. Since the variable is not defined the tasks are skipped.

PLAY [Playbook imports] **********************************************************************************

TASK [Task Import] ***************************************************************************************
skipping: [localhost]

PLAY [Playbook imports] **********************************************************************************

TASK [Task Import 2] *************************************************************************************
skipping: [localhost]

I am running the playbook again by setting var=1 in playbook2 alone. This time the task under playbook2 ran fine and playbook1 tasks were skipped.

PLAY [Playbook imports] ********************************************************************************************************

TASK [Task Import] *************************************************************************************************************
skipping: [localhost]

PLAY [Playbook imports] ********************************************************************************************************

TASK [Task Import 2] ***********************************************************************************************************
ok: [localhost] => {
    "msg": "Importing playbook2.yml"
}

PLAY RECAP *********************************************************************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0  
Conditional Check - Importing Playbook
Conditional Check - Importing Playbook

Importing Ansible Playbook Tasks

Similar to importing playbooks, you can create separate task files and import them into a single file. While playbooks can only use import directive, tasks can use both import and include directive.

First, let’s take a look at the import_task directive which is similar to the import_playbook directive. The directive will pre-parse the task when the playbook is parsed.

I have created two files named task1.yml and main.yml. It contains the following play and task definitions.

# task1.yml
- name: importing_tasks
  ansible.builtin.debug:
    msg: "Importing the task from task1.yml"

# main.yml
---
- hosts: localhost
  connection: local
  gather_facts: false

 tasks:
   - import_tasks: task1.yml
Import Task Directive
Import Task Directive

If you take a look at the above output, the task will be imported into the main.yml namespace and run.

The include_tasks directive will be parsed only at the time of playbook execution. I am using the same main.yml and task1.yml playbook but with little modifications.

# main.yml
---
- hosts: localhost
  connection: local
  gather_facts: false

  tasks:
    - include_tasks: task1.yml


# task1.yml
- name: importing tasks using include directive
  ansible.builtin.debug:
    msg: "Importing the task from task1.yml using include directive"

When the playbook is submitted, two tasks ran, even though we have only one task defined in the playbook. The first task is for parsing the tasks from task1.yml and include them for execution. The second task executes the included tasks.

Include Task Directive
Include Task Directive

Similar to the import_playbook directive, you can apply other ansible directives to the import_tasks or include_tasks directive.

I have created a task2.yml file and used the block directive to import and include task1.yml and task2.yml.

# task2.yml
- name: importing tasks using include directive
  ansible.builtin.debug:
    msg: "Importing the task from task2.yml using import directive"


# main.yml
---
- hosts: localhost
  connection: local
  gather_facts: false

  tasks:
    - name: Import and include with block directive
      block:
        - include_tasks: task1.yml
        - import_tasks: task2.yml
Import and Include with Block Directive
Import and Include with Block Directive

Importing Ansible Playbook Roles

Roles are a great way to organize your project. We have a detailed article about ansible roles and how import and include directives are used as an alternative to roles directives. I suggest you take a look at it in the link below.

Ansible Roles Tutorial For Beginners

Conclusion

In this article we have seen what import_* and include_* directives are and how to use them to split your ansible project to achieve modularity.

You May Also Like

Leave a Comment

* By using this form you agree with the storage and handling of your data by this website.

This site uses Akismet to reduce spam. Learn how your comment data is processed.

This website uses cookies to improve your experience. By using this site, we will assume that you're OK with it. Accept Read More