Ansible Playbook Task Import
When using Playbooks, there may be some frequently used Plays. In this case, you can utilize the import method in Playbooks to reuse the same Play. The imported tasks serve as a task template (without the <span>hosts</span> and <span>tasks</span> fields, as shown in the example below).
There are two modes for Playbook task import:
- •
<span>ansible.builtin.import_tasks</span>: Static import of<span>tasks</span>, imported before the Playbook execution - •
<span>ansible.builtin.include_tasks</span>: Dynamic import of<span>tasks</span>, imported when the Playbook reaches a specific task - •
<span>ansible.builtin.import_role</span>: Static import of<span>role</span>, imported before the Playbook execution - •
<span>ansible.builtin.include_role</span>: Dynamic import of<span>role</span>, imported when the Playbook reaches a specific task - •
<span>ansible.builtin.import_playbook</span>: Static import of<span>Playbook</span>, imported before the Playbook execution
The main distinction here is between static and dynamic. Whether it is
<span>tasks</span>or<span>role</span>does not make much difference; we will only use<span>ansible.builtin.import_tasks</span>and<span>ansible.builtin.include_tasks</span>as examples.
Creating Importable Templates
Below is a reusable Play template, saved as <span>/tmp/other.yml</span>:
[root@study ansible]# cat /tmp/other.yml
- name: set
set_fact:
x: foo
- name: print
debug:
var: x
Static Import
Below is a Playbook for static import:
[root@study ansible]# cat /tmp/import.yml
- name: test
hosts: localhost
tasks:
- import_tasks: /tmp/other.yml
when: x is not defined
To explain briefly, <span>import_tasks</span> will import the tasks from <span>/tmp/other.yml</span> before executing the tasks, thus the actual Playbook executed is as follows:
- name: test
hosts: localhost
gather_facts: false
tasks:
- name: set
set_fact:
x: foo
when: x is not defined
- name: print
debug:
var: x
when: x is not defined
Each imported Play will have a <span>when</span> condition added. The first Play will set the variable <span>x</span>, and since the variable <span>x</span> now exists, the second Play will be skipped. The execution result is as follows:
[root@study ansible]# ansible-playbook /tmp/import.yml
PLAY [test] *****************************************************************************************************
TASK [set] ******************************************************************************************************
ok: [localhost]
TASK [print] ****************************************************************************************************
skipping: [localhost]
PLAY RECAP ******************************************************************************************************
localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
Dynamic Import
Below is a Playbook for dynamic import:
[root@study ansible]# cat /tmp/include.yml
- name: test
hosts: localhost
gather_facts: false
tasks:
- include_tasks: /tmp/other.yml
when: x is not defined
This will execute the <span>include_tasks</span> Play only when the Playbook reaches that task. Although there is a condition, it only checks whether the task should be imported (import the Play if the variable does not exist, skip if it does). Therefore, all imported Plays will be executed, and the execution result is as follows:
[root@study ansible]# ansible-playbook /tmp/include.yml
PLAY [test] *****************************************************************************************************
TASK [include_tasks] ********************************************************************************************
included: /tmp/other.yml for localhost
TASK [set] ******************************************************************************************************
ok: [localhost]
TASK [print] ****************************************************************************************************
ok: [localhost] => {
"x": "foo"
}
PLAY RECAP ******************************************************************************************************
localhost : ok=3 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Differences Between Static and Dynamic Import
https://docs.ansible.org.cn/ansible/latest/playbook_guide/playbooks_reuse.html#comparing-includes-and-imports-dynamic-and-static-reuse
Here is a direct quote from the official website’s table:
| Include_* | Import_* | |
|---|---|---|
| Reuse Type | Dynamic | Static |
| When Processed | At runtime, when encountered | Pre-processed during Playbook parsing |
| Task or Play | All includes are tasks | <span>import_playbook</span> cannot be a task |
| Task Options | Only applied to the included task itself | Applied to all sub-tasks in the import |
| From Loop Calls | Executed once for each loop item | Cannot be used in loops |
Using <span>--list-tags</span> |
Tags in includes are not listed | All tags are displayed with <span>--list-tags</span> |
Using <span>--list-tasks</span> |
Tasks in includes are not listed | All tasks are displayed with <span>--list-tasks</span> |
| Notify Handlers | Cannot trigger handlers in includes | Can trigger handlers from imports |
Using <span>--start-at-task</span> |
Cannot start from a task in includes | Can start from an imported task |
| Using Inventory Variables | Can use <span>include_*: {{ inventory_var }}</span> |
Cannot use <span>import_*: {{ inventory_var }}</span> |
| For Playbooks | No <span>include_playbook</span> |
Can import entire playbooks |
| For Variable Files | Can include variable files | Use <span>vars_files:</span> to import variables |
For
<span>notify</span>,<span>include_tasks</span>only supports overall triggering, while<span>import_tasks</span>supports triggering individual Plays from imports.
Referencing an example from the official website:
https://docs.ansible.org.cn/ansible/latest/playbook_guide/playbooks_reuse.html#re-using-tasks-as-handlers
Imported Play template:
# restarts.yml
- name: Restart apache
ansible.builtin.service:
name: apache
state: restarted
- name: Restart mysql
ansible.builtin.service:
name: mysql
state: restarted
Dynamic import of <span>notify</span>:
- name: Trigger an included (dynamic) handler
hosts: localhost
handlers:
- name: Restart services
include_tasks: restarts.yml
tasks:
- command: "true"
notify: Restart services
Static import of <span>notify</span>:
- name: Trigger an imported (static) handler
hosts: localhost
handlers:
- name: Restart services
import_tasks: restarts.yml
tasks:
- command: "true"
notify: Restart apache
- command: "true"
notify: Restart mysql