Import tenzij: geef de voorkeur aan statisch hergebruik in Ansible

Geef de voorkeur aan import_tasks, import_role of de play-level roles-sectie voor herbruikbare Ansible-content. Gebruik include_tasks of include_role alleen wanneer dynamisch runtime-gedrag nodig is.

Probleem

Ansible biedt zowel import_*- als include_*-vormen om taken en rollen te hergebruiken.

Zonder een duidelijke regel ontstaat in codebases al snel een mix van statisch en dynamisch hergebruik. Dat maakt playbooks moeilijker leesbaar, lastiger om over te redeneren en ingewikkelder om te troubleshooten. Taken verschijnen dan mogelijk niet meer duidelijk in --list-tasks, tags kunnen zich onverwacht uiten en de uitvoering kan afhankelijk worden van runtime-status op manieren die voor reviewers en operators minder goed vooraf zichtbaar zijn.

Context

Volgens de Ansible-documentatie is import_* statisch hergebruik en wordt het verwerkt terwijl Ansible het playbook parseert. De geïmporteerde taken of roltaken worden dan onderdeel van de play alsof ze daar direct waren uitgeschreven.

Dat geeft praktische voordelen:

  • Beter zichtbaar in --list-tasks en --list-tags.
  • Betere ondersteuning voor --start-at-task.
  • Eenvoudiger tag-gedrag omdat tags direct op de geïmporteerde child tasks worden toegepast.
  • Voorspelbaardere structuur omdat de taakgrafiek al vóór uitvoering bekend is.
  • Minder runtime-overhead, omdat imports lichter zijn dan includes.

De Ansible-documentatie vermeldt expliciet dat imports tijdens het parsen van het playbook worden voorverwerkt, terwijl includes dynamisch tijdens runtime worden verwerkt. Die documentatie vermeldt ook dat imports lichter en sneller zijn, terwijl includes meer beheer en bookkeeping vereisen.

De Red Hat COP-richtlijn laat eveneens een voorkeur zien voor een statische structuur wanneer dat volstaat. Die richtlijn beveelt aan om in een playbook óf de roles-sectie óf de tasks-sectie te gebruiken, niet allebei, en toont import_role als het eenvoudigere tagmodel wanneer een playbook uit rollen is opgebouwd.

Oplossing

  1. Gebruik standaard import_tasks voor herbruikbare task-bestanden.
  2. Gebruik standaard import_role of de play-level roles-sectie voor herbruikbare rollen.
  3. Gebruik include_tasks of include_role alleen wanneer je dynamisch gedrag tijdens runtime nodig hebt.
  4. Behandel dynamische inclusion als een uitzondering die door de use case moet worden gerechtvaardigd, niet als de normale stijl.
  5. Als je statische role-executie op play-niveau nodig hebt, geef dan de voorkeur aan de roles-sectie. Als je een rol in een specifieke volgorde binnen de tasks-sectie nodig hebt, gebruik dan import_role.
  6. Vermijd het mengen van statisch en dynamisch hergebruik in hetzelfde playbook tenzij daar een duidelijke reden voor is.

Voordelen

  • Maakt de structuur van de play eerder zichtbaar.
  • Verbetert leesbaarheid en reviewbaarheid.
  • Maakt taaklijsten, taglijsten en taakselectie bruikbaarder.
  • Vermindert verrassingen die worden veroorzaakt door uitbreiding pas tijdens runtime.
  • Presteert meestal beter dan dynamische includes.

Wanneer include_* wel de juiste keuze is

Gebruik include_tasks of include_role wanneer het playbook echt dynamisch runtime-gedrag nodig heeft.

Typische gevallen zijn:

  1. Loopen over een task-bestand of rol include_* kan één keer per loop-item worden uitgevoerd. import_* kan niet in een loop worden gebruikt.
  2. Een task-bestand tijdens runtime selecteren Bijvoorbeeld provider-specifieke of platform-specifieke task-bestanden die gekozen worden met lookup('first_found') of een bestandsnaam afgeleid van facts.
  3. Content alleen includen wanneer de runtime-status dat vereist Bijvoorbeeld wanneer de inclusion-beslissing afhangt van facts, geregistreerde resultaten of wijzigingen die eerdere taken in dezelfde play hebben aangebracht.
  4. Dynamische role-orkestratiepatronen Bijvoorbeeld een loop over acties waarbij elk item variabelen aan een included role doorgeeft.
  5. Specifieke handler-patronen die vereisen dat de include zelf wordt genotificeerd Bij dynamische includes is de include-task zelf wat tijdens runtime bestaat.

Als geen van deze gevallen van toepassing is, gebruik dan import.

Aanvullende richtlijn voor rollen

Voor rollen zijn er drie veelvoorkomende opties:

  • Gebruik de play-level roles-sectie voor normale statische rolsamenstelling.
  • Gebruik import_role wanneer de rol op een specifieke plaats binnen de tasks-volgorde moet verschijnen.
  • Gebruik include_role alleen wanneer je dynamisch gedrag nodig hebt, zoals loopen of runtime-selectie.

Gebruik include_role niet alleen uit gewoonte. Als de rolnaam en de plaats in uitvoering al bekend zijn wanneer het playbook wordt geschreven, is statische compositie duidelijker.

Voorbeelden en implementatie

Geef de voorkeur aan import_tasks voor een vaste task-structuur

- name: Main tasks
  hosts: all
  gather_facts: false
  tasks:
    - name: Import install tasks
      ansible.builtin.import_tasks: install.yml

    - name: Import configure tasks
      ansible.builtin.import_tasks: configure.yml

Dit is de normale keuze wanneer beide task-bestanden vooraf bekend zijn.

Gebruik include_tasks voor runtime bestandsselectie

- name: Main tasks
  hosts: all
  gather_facts: true
  tasks:
    - name: Include platform-specific tasks
      ansible.builtin.include_tasks: >-
        {{ lookup('first_found', params) }}
      vars:
        params:
          files:
            - "{{ ansible_facts['distribution'] }}.yml"
            - "{{ ansible_facts['os_family'] }}.yml"
            - default.yml
          paths:
            - "{{ role_path }}/tasks/setup"

Hier staat het geselecteerde bestand pas tijdens runtime vast, dus is include_tasks het juiste hulpmiddel.

Geef de voorkeur aan import_role voor vaste role-executie in task-volgorde

- name: Configure servers
  hosts: all
  gather_facts: false
  tasks:
    - name: Import base role
      ansible.builtin.import_role:
        name: c2platform.core.base

    - name: Import application role
      ansible.builtin.import_role:
        name: c2platform.app.web

Dit houdt de role-executie statisch en zichtbaar.

Gebruik include_role wanneer je over role-input loept

- name: Execute actions
  hosts: all
  gather_facts: false
  tasks:
    - name: Run action role per item
      ansible.builtin.include_role:
        name: mycollection.run
      vars:
        action: "{{ item }}"
      loop: "{{ actions }}"

Dit is een geldige reden om include_role te gebruiken, omdat de rol één keer per loop-item wordt uitgevoerd.

Gebruik de play-level roles-sectie voor eenvoudige samenstelling

- name: Build web server
  hosts: web
  gather_facts: false
  roles:
    - role: c2platform.core.base
    - role: c2platform.web.apache

Dit is vaak de duidelijkste optie wanneer geen dynamisch gedrag nodig is.

Aanvullende informatie


Laatst gewijzigd 2026.09.16: guideline imprort-unless C2-1638 (4ca61ef)