web-dev-qa-db-ja.com

include_tasksとimport_tasksの違いは何ですか?

Ansible 2.4では、includeモジュールは非推奨になりました。その代わりに、import_tasksinclude_tasksの2つの交換モジュールが同梱されています。しかし、それらは非常に類似した説明を持っています:

  • include_tasks:現在のプレイブックで実行するタスクのリストを含むファイルを含めます。
  • import_tasks:後で実行するために現在のプレイブックに追加するタスクのリストをインポートします。

前者はいつ使用し、後者はいつ使用する必要がありますか?

77
Ben S

ドキュメントにはこのトピックに関するかなりの部分があります:

主な違いは次のとおりです。

すべて import*ステートメントは、プレイブックが解析されるときに前処理されます。
すべて include*ステートメントは、プレイブックの実行中に発生したとおりに処理されます。

したがって、importは静的であり、includeは動的です。

私の経験では、論理的な「ユニット」を扱う場合はimportを使用する必要があります。たとえば、タスクの長いリストをサブタスクファイルに分割します。

main.yml:

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

ただし、includeを使用してさまざまなワークフローを処理し、動的に収集されたいくつかのファクトに基づいて決定を下します。

install_prerequisites:

- include_tasks: prerequisites_{{ ansible_os_family | lower }}.yml
81

インポートは静的で、インクルードは動的です。インポートは解析時に行われ、実行時に含まれます。

インポートは基本的に、タスクをファイルのタスクに置き換えます。実行時にimport_taskはありません。したがって、tagswhenなどの属性(および他のほとんどの属性)は、インポートされたすべてのタスクにコピーされます。

includesは実際に実行されます。含まれるタスクのtagsおよびwhenは、タスク自体にのみ適用されます。

importタスクがタグ付けされていない場合、インポートされたファイルからタグ付けされたタスクが実行されます。 includeタスクがタグ付けされていない場合、インクルードファイルからタスクは実行されません。

importタスクがタグ付けされている場合、インポートされたファイルのすべてのタスクが実行されます。 includeタスクがタグ付けされている場合、インクルードファイルからタグ付けされたタスクのみが実行されます。

importsの制限:

  • with_*またはloop属性と一緒に使用することはできません
  • 変数に依存するファイルをインポートできません

includesの制限:

  • --list-tagsに含まれるファイルのタグが表示されない
  • --list-tasksは含まれているファイルからのタスクを表示しません
  • notifyを使用して、動的インクルード内からのハンドラー名をトリガーすることはできません
  • --start-at-taskを使用して動的インクルード内のタスクで実行を開始することはできません

さらに詳しく ここ および ここ

私にとっては、基本的にimportsはループ属性で使用できないという事実に帰着します。

importthis のような場合に必ず失敗します:

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

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

debugimport_tasksタスクからwhenを継承するため、実行されません。したがって、importwhen属性で使用される変数を変更するインポートタスクファイルはありません。

私はimportsから始めるという方針を持っていましたが、includeが必要になったら、そのインクルードファイルまたはインクルードファイルによって何もインポートされていないことを確認してください。しかし、それを維持するのはかなり大変です。そしてそれがトラブルから私を守るかどうかはまだはっきりしていません。つまり、推奨されないincludesとimportsを混合します。

importタスクをループする必要がある場合があるため、includesだけを使用することはできません。おそらくincludesのみに切り替えることができました。しかし、タスクが複数回実行されることになっている場合を除いて、どこでもインポートに切り替えることにしました。私はこれらすべてのトリッキーなEdgeケースを直接体験することにしました。多分私のプレイブックには何もないでしょう。またはうまくいけば、私はそれを動作させる方法を見つけるでしょう。

[〜#〜] upd [〜#〜]何度もインポートできるタスクファイルを作成するのに役立つ可能性がありますが、1回実行

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

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

...

- name: Set _file_executed
  set_fact:
    _file_executed: True

[〜#〜] upd [〜#〜]インクルードとインポートを混在させることで実際に予期されない効果の1つは、インクルード変数がインポートのものをオーバーライドすることです。

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

おそらく、include_tasksは最初にすべての追加の静的インポートを実行し、次にvarsディレクティブを介して渡される変数を変更するためです。

実際、それはインポートだけで発生するわけではありません。

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 [〜#〜]混合とインポートの別のケースです。

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

truetrueを取得します。前のケースを参照してください(インクルード変数はインポート変数よりも優先されます)。そこで、3.ymlのincludeに切り替えます。ただし、3.ymlの最初のインクルードはスキップされます。親タスクからwhen: httpsを継承し、後者はおそらくタスクのhttpsからvarsを取得するためです。解決策は、2.ymlのincludeにも切り替えることです。これにより、when: httpsが子タスクに伝達されなくなります。

20
x-yuri