import_playbook
The static-vs-dynamic split from the previous chapter isn’t unique to tasks — it extends both upward, to combining whole playbooks together, and downward, into roles. This chapter covers both, plus one asymmetry worth knowing: at the playbook level, only the static half of the pair actually exists.
import_playbook: Combining Multiple Playbooks Into One Run
import_playbook combines several playbook files into a single run — used at the top level of a playbook file, not inside a play’s tasks: list, and each imported file contains a full play of its own (hosts:, tasks:, everything), not just a bare list of tasks.
- import_playbook: webservers.yaml
- import_playbook: databases.yaml- name: Configure web servers
hosts: webservers
tasks:
- name: Example task
ansible.builtin.debug:
msg: "Configuring web servers"- name: Configure databases
hosts: databases
tasks:
- name: Example task
ansible.builtin.debug:
msg: "Configuring web servers"This is how you’d maintain separate playbook files per concern or group — webservers.yaml, databases.yaml — and combine them into one overall entry point, commonly named something like site.yaml, run as a single ansible-playbook invocation.
site.yaml can also have own set of target hosts and tasks afterwards:
- import_playbook: webservers.yaml
- import_playbook: databases.yaml
- name: Play run in localhost
hosts: localhost
tasks:
- name: whoami_local
ansible.builtin.command:
cmd: whoami
register: whoami_localhost
- name: whoami_localhost check
ansible.builtin.debug:
var: whoami_localhost.stdout
taskslisted insite.yamlruns onlocalhost(because ofhosts: localhost) whereastaskson imported playbooks runs on whateverhostsare implied there. For more information, you can runansible-playbook site.yaml --list-tasks.
Why There’s No include_playbook
Worth stating directly, since it’s a reasonable assumption to make otherwise: there is no dynamic equivalent at the playbook level. import_playbook is always resolved statically, at parse time, with no runtime alternative available at all. Unlike tasks, where you genuinely choose between static and dynamic based on what you need, combining playbooks only ever has one option.
A First Look At Roles: import_role And include_role
Roles get a full section of their own later in this course — this is just enough to recognize the syntax now, since it follows the exact same naming convention already established:
- name: Import a role statically
ansible.builtin.import_role:
name: my_role- name: Include a role dynamically
ansible.builtin.include_role:
name: my_roleThe Same Static/Dynamic Rule Applies
Identical reasoning to Chapter 1, just one level up: import_role’s role name has to be fixed and known in advance, while include_role’s can depend on runtime data:
- name: Include a role determined at runtime
ansible.builtin.include_role:
name: "{{ ansible_facts['os_family'] | lower }}_setup"This works with include_role for exactly the reason include_tasks worked in the previous chapter’s example — and would fail with import_role for exactly the same reason import_tasks did.
Best Practices
- Use
import_playbookto compose multiple playbook files into one overall run — there’s no dynamic alternative to weigh against, so this is simply the way it’s done. - Recognize
import_role/include_rolenow, even without full role-authoring knowledge yet — the static/dynamic distinction transfers directly from what you already know about tasks. - Default to
include_rolewhen a role’s name might vary at runtime, following the exact same reasoning asinclude_tasks.