Jaka jest różnica między parametrami include_tasks i import_tasks?

62

W Ansible 2.4 includemoduł jest przestarzały. Na swoim miejscu jest dostarczany z dwoma wymiennymi modułami import_tasksi include_tasks. Ale mają bardzo podobne opisy:

  • include_tasks: Zawiera plik z listą zadań do wykonania w bieżącym podręczniku.
  • import_tasks: Importuje listę zadań, które zostaną dodane do bieżącego podręcznika w celu późniejszego wykonania.

Kiedy powinienem użyć pierwszego, a kiedy drugiego?

Ben S.
źródło
(Również: ostrzeżenie o wycofaniu odnosi się do zadań „dynamicznych” i „statycznych”. Czytałem dokumenty, ale ich nie rozumiałem.)
Ben S

Odpowiedzi:

68

W dokumentacji znajduje się całkiem sporo na ten temat:

Główną różnicą jest:

Wszystkie import*wyciągi są wstępnie przetwarzane podczas analizowania podręczników.
Wszystkie include*instrukcje są przetwarzane tak, jak napotkano podczas wykonywania instrukcji.

importJest więc statyczny, includedynamiczny.

Z mojego doświadczenia wynika, że ​​powinieneś używać go, importgdy masz do czynienia z logicznymi „jednostkami”. Na przykład oddziel długą listę zadań do plików podzadań:

main.yml:

- import_tasks: prepare_filesystem.yml
- import_tasks: install_prerequisites.yml
- import_tasks: install_application.yml

Ale używałbyś includedo radzenia sobie z różnymi przepływami pracy i podejmowania decyzji w oparciu o niektóre dynamicznie gromadzone fakty:

wymagania_instalacyjne:

- include_tasks: prerequisites_{{ ansible_os_family | lower }}.yml
Konstantin Suworow
źródło
8
Uważam, że ten link jest bardzo przydatny: docs.ansible.com/ansible/latest/… Wywołuje przypadek, w którym import i dołącz zachowują się inaczej - warunek „kiedy”, w którym zadania w pliku mogą zmienić kryteria stosowane do określenia importu . W przypadku import_tasks każde zadanie sprawdza kryteria, więc zachowanie zmienia się wraz ze zmianą kryteriów. W przypadku instrukcji include_tasks zadania są obecne lub nie w zależności od tego, czy warunek został oceniony jako prawdziwy, gdy wykonano instrukcję include_tasks. Jeśli dobrze rozumiem ...
Ethel Evans,
Jakie było zachowanie include? Gdybyśmy korzystali, includebyłby import_tasksto odpowiednik?
Andy Shinn
includemiał static: yes(zachowywał się import_tasks) i static: no(podobny include_tasks).
Konstantin Suworow
Jakie jest ustawienie domyślne static?
Andy Shinn
staticjest Nonedomyślnie: Od Ansible 2.0 dołączanie zadań jest dynamiczne i zachowuje się bardziej jak prawdziwe zadania. Oznacza to, że można je zapętlać, pomijać i używać zmiennych z dowolnego źródła. Ansible próbuje to automatycznie wykryć, ale możesz użyć dyrektywy statycznej (która została dodana w Ansible 2.1), aby ominąć automatyczne wykrywanie.
Konstantin Suworow
15

Import jest statyczny, w tym dynamiczny. Importowanie odbywa się w czasie analizy, w tym w czasie wykonywania.

Import zasadniczo zastępuje zadanie zadaniami z pliku. Nie ma import_taskw czasie wykonywania. Tak, atrybuty jak tagsi when(i prawdopodobnie inne atrybuty) są kopiowane do każdego importowanego zadania.

includesą rzeczywiście stracone. tagsi whendołączonego zadania dotyczą tylko samego zadania.

Oznaczone zadania z importowanego pliku są wykonywane, jeśli importzadanie nie jest oznaczone . Żadne zadania nie są wykonywane z dołączonego pliku, jeśli includezadanie nie jest oznaczone.

Wszystkie zadania z importowanego pliku zostaną wykonane, jeśli importzadanie jest oznaczone. Tylko oznaczone zadania z dołączonego pliku są wykonywane, jeśli includezadanie jest oznaczone.

Ograniczenia imports:

  • nie może być stosowany z with_*lub loopatrybuty
  • nie można zaimportować pliku, którego nazwa zależy od zmiennej

Ograniczenia includes:

  • --list-tags nie pokazuje tagów z dołączonych plików
  • --list-tasks nie pokazuje zadań z dołączonych plików
  • nie można użyć notifydo wyzwolenia nazwy modułu obsługi, która pochodzi z dynamicznego włączenia
  • nie można użyć --start-at-taskdo rozpoczęcia wykonywania zadania w ramach dynamicznego dołączania

Więcej na ten temat tutaj i tutaj .

Dla mnie w zasadzie sprowadza się to do tego, że importnie można używać s z atrybutami pętli.

importna pewno nie w przypadkach takich jak ten :

# playbook.yml
- import_tasks: set-x.yml
  when: x is not defined

# set-x.yml
- set_fact
  x: foo
- debug:
  var: x

debugnie jest wykonywany, ponieważ dziedziczy whenpo import_taskszadaniu. Więc żadne pliki zadaniowe importujących które zmieniają zmienne używane w import„s whenatrybut.

Miałem zasady, aby zacząć od imports, ale kiedy potrzebuję, includeupewnij się, że nic nie jest importowane przez ten dołączony plik lub pliki, które zawiera. Ale to jest cholernie trudne do utrzymania. I nadal nie jest jasne, czy uchroni mnie przed problemami. Znaczenie, miksowanie includesi innych, importktórych nie zalecają.

Nie mogę używać tylko imports, ponieważ czasami muszę zapętlać includezadania. Prawdopodobnie mógłbym przejść na tylko includes. Ale postanowiłem przejść na import wszędzie, z wyjątkiem przypadków, w których zadanie ma być uruchamiane kilka razy. Postanowiłem doświadczyć tych wszystkich trudnych przypadków z pierwszej ręki. Może nie będzie ich w moich podręcznikach. Albo mam nadzieję, że znajdę sposób, aby to zadziałało.

UPD Prawdopodobnie przydatna sztuczka, aby utworzyć plik zadania, który można zaimportować wiele razy, ale wykonać raz :

- name: ...
  ...
  when: not _file_executed | default(False)

- name: ...
  ...
  when: not _file_executed | default(False)

...

- name: Set _file_executed
  set_fact:
    _file_executed: True

UPD Jednym z nieoczekiwanych efektów mieszania włączeń i importów jest to, że vars zastępują importowane:

playbook.yml:

- hosts: all
  tasks:
    - import_tasks: 2.yml
      vars:
        v1: 1
    - include_tasks: 2.yml
      vars:
        v1: 1

2.yml:

- import_tasks: 3.yml
  vars:
    v1: 2

3.yml:

- debug:
    var: v1    # 2 then 1

Prawdopodobnie dlatego, że include_tasksnajpierw dokonuje wszystkich dodatkowych importów statycznych, a następnie zmienia zmienne przekazane przez jego varsdyrektywę.

W rzeczywistości dzieje się tak nie tylko w przypadku importu:

playbook.yml:

- hosts: all
  tasks:
    - import_tasks: 2.yml
      vars:
        v1: 1
    - include_tasks: 2.yml
      vars:
        v1: 1

2.yml:

- debug:
    var: v1    # 2 then 1
  vars:
    v1: 2

UPD Kolejny przypadek mieszania obejmuje i import.

playbook.yml:

- hosts: all
  tasks:
    # here you're bound to use include, some sort of loop
    - include_tasks: 2.yml
      vars:
        https: yes

2.yml:

- import_tasks: 3.yml
  when: https

3.yml:

- import_tasks: 4.yml
  vars:
    https: no  # here we're trying to temporarily override https var
- import_tasks: 4.yml

4.yml:

- debug:
    var: https

Otrzymujemy truei true, patrz poprzedni przypadek (uwzględnij zmienne mają pierwszeństwo przed zmiennymi importowymi). Więc przełączamy się na włączenie w 3.yml. Ale wtedy pierwsze włączenie 3.ymljest pomijane. Ponieważ dziedziczy when: httpspo zadaniu nadrzędnym, a to ostatnie przypuszczalnie bierze się httpsz zadania nadrzędnego vars. Rozwiązaniem jest również przejście na włączone 2.yml. Zapobiega to propagacji when: httpszadań podrzędnych.

x-yuri
źródło
4
Świetna odpowiedź!. Byłem sfrustrowany tym, że wszyscy w Internecie powtarzali tylko to, co mówi dokumentacja. Dziękuję Ci.
Sergio Acosta