Difference between include & import in Ansible

Heshan Dharmasena
5 min readJun 7, 2021

What We’ll Cover

  • Why this topic ?
  • Why tasks need inject from separate files ?
  • What is include ?
  • What is import ?
  • Quick Demo
  • Conclusion

Why this topic ?

Include and Import are pair of words in Ansible which bit tricky to understand. Here are some examples and small explanations to get understand the difference and use of these two.

First of all, this is related to ansible tasks files only. Ansible tasks can be either imported or included, but ansible playbooks can only be imported. Hence this discussion is for tasks which support both include(include_tasks) and import (import_tasks) key words.

Why tasks need inject from separate files ?

When you have a complex ansible playbook (eg: lets say there are 20 different tasks), it is very hard to identify logic, if you are not the person who write the playbook. To make it simple, you can divide tasks into set of tasks files and keep them in separate file. Let’s assume you have a large playbook of application installations, which include

  • user creations
  • groups creations
  • files and directories
  • setting up permissions
  • repository configuration
  • package installations
  • update configurations
  • service starts/restart enablement
  • test/confirmation of application runtime

Now you can divide above tasks into separate tasks files as below.

  • user_management.yml
  • file_dir_permissions.yml
  • repo_package_service_management.yml
  • test_application.yml

Okay, so now you can write your main playbook which can inject above tasks file into main playbook. Number of lines in main playbook and complexity reduce and this increase the readability as well.

There are two ways of injecting tasks into main playbook.

  1. Include
  2. Import

Further reading : Official Documentation

What is include ?

Include statements are processed as they are encountered during the execution of the playbook.

What is import ?

Import tasks pre-processed at the time playbooks are parsed before the execution of the playbook.

Quick Demo

Above is the explanation in ansible documentation and I wanted to explain this in the easiest way.

Let's write two playbooks with a ansible cfg file and a single host inventory file.

$ cat example_1_include_tasks.yml
$ cat example_1_include_tasks.yml
$ cat example_2_import_tasks.yml
$ cat user_creation.yml
  1. First, run example_1_include_tasks.yml playbook and see the output below.
$ ansible-playbook example_1_include_tasks.yml

Here we can see 4 tasks got executed.

  1. Gathering facts
  2. Printing Message
  3. Including Task File
  4. Execution on Task inside included file

If you think deeply, you can identify Task 4 triggers from Tasks 3. Task 3 includes another task file (include_tasks: user_creation.yml ) and Task 4 is included Task in that file.

That is the reason for having 4 execution tasks in the above run.

If you need fresh execution, delete both users in manage nodes(before running the second playbook).

# userdel -r peter; userdel -r john

2. Then run example_2_import_tasks.yml playbook and see the output below.

$ ansible-playbook example_2_import_tasks.yml

Here we can see only 3 tasks got executed.

  1. Gathering facts
  2. Printing Message
  3. Execution of Task inside the imported file

Right, here you can see only 3 tasks got executed. In here the imported task file’s task name directly executed as a 3rd task here. Point is, import_tasks feature directly grabs the importing file content.

Right, let's see the reason behind that.

Execute both playbooks again with increasing verbosity (-vv)

$ ansible-playbook example_1_include_tasks.yml -vv
$ ansible-playbook example_2_import_tasks.yml -vv

If you look at both outputs, you can identify the special output in the second playbook execution. It says statically imported: /home/student/user_creation.yml. But you can not see such output in the first playbook execution.

That means import_tasks is importing its tasks file at the very beginning of the playbook. But include_tasks include its tasks file when the statement execution happens.

In other words, import is a static operation, and include is a dynamic operation.

Another quick command to show which tasks execute for each playbook.

See the difference below.

Here the included task is not displayed, the reason is included tasks are getting executed during the runtime of playbook only.

Here the imported task is displayed, the reason is imported tasks are getting pre-parsed with the beginning of the playbook.

Due to this difference, there are few limitations when it comes to conditions, loops & some other keywords.

Let’s see one last example. Let’s take the loop into the main playbooks. Create new playbooks as follows.

$ cat example_3_include_tasks.yml
$ cat example_4_import_tasks.yml

Edit existing user_creation.yml as follows.

Then run your playbooks.

$ ansible-playbook example_3_include_tasks.yml

Here, you can see under including there are 2 iterations (peter & john) occurred. The reason is, there are two items in the loop and each iteration ansible included its attached file and get the module executed.

$ ansible-playbook example_4_import_tasks.yml

But here, you got an ERROR message, since import_task can not be pre-processed due to the loop iterations are inside the main playbook and actual tasks are in the attached file.

Conclusion

Finally, in very basics import will capture everything before playbook starts and include will capture whenever exact line parses. There are the pros and cons of ansible include and import that is understanding. Anyway, I’ve tried my best to give some sort of example and explain in a really simple way.

Please leave a comment if you have any concerns or any corrections need to be added. Thank you very much for reading this article.

--

--

Heshan Dharmasena

Passionate on Linux | DevOps | Cloud | Automation | Platform Engineering | Red Hat Certified Architect | Technical Trainer | Organizer DevOps Sri Lanka