Ansible 2.4では、include
モジュールは非推奨になりました。その代わりに、import_tasks
とinclude_tasks
の2つの交換モジュールが同梱されています。しかし、それらは非常に類似した説明を持っています:
include_tasks
:現在のプレイブックで実行するタスクのリストを含むファイルを含めます。import_tasks
:後で実行するために現在のプレイブックに追加するタスクのリストをインポートします。前者はいつ使用し、後者はいつ使用する必要がありますか?
ドキュメントにはこのトピックに関するかなりの部分があります:
主な違いは次のとおりです。
すべて
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
インポートは静的で、インクルードは動的です。インポートは解析時に行われ、実行時に含まれます。
インポートは基本的に、タスクをファイルのタスクに置き換えます。実行時にimport_task
はありません。したがって、tags
やwhen
などの属性(および他のほとんどの属性)は、インポートされたすべてのタスクにコピーされます。
include
sは実際に実行されます。含まれるタスクのtags
およびwhen
は、タスク自体にのみ適用されます。
import
タスクがタグ付けされていない場合、インポートされたファイルからタグ付けされたタスクが実行されます。 include
タスクがタグ付けされていない場合、インクルードファイルからタスクは実行されません。
import
タスクがタグ付けされている場合、インポートされたファイルのすべてのタスクが実行されます。 include
タスクがタグ付けされている場合、インクルードファイルからタグ付けされたタスクのみが実行されます。
import
sの制限:
with_*
またはloop
属性と一緒に使用することはできませんinclude
sの制限:
--list-tags
に含まれるファイルのタグが表示されない--list-tasks
は含まれているファイルからのタスクを表示しませんnotify
を使用して、動的インクルード内からのハンドラー名をトリガーすることはできません--start-at-task
を使用して動的インクルード内のタスクで実行を開始することはできません私にとっては、基本的にimport
sはループ属性で使用できないという事実に帰着します。
import
は this のような場合に必ず失敗します:
# playbook.yml
- import_tasks: set-x.yml
when: x is not defined
# set-x.yml
- set_fact
x: foo
- debug:
var: x
debug
はimport_tasks
タスクからwhen
を継承するため、実行されません。したがって、import
のwhen
属性で使用される変数を変更するインポートタスクファイルはありません。
私はimport
sから始めるという方針を持っていましたが、include
が必要になったら、そのインクルードファイルまたはインクルードファイルによって何もインポートされていないことを確認してください。しかし、それを維持するのはかなり大変です。そしてそれがトラブルから私を守るかどうかはまだはっきりしていません。つまり、推奨されないinclude
sとimport
sを混合します。
import
タスクをループする必要がある場合があるため、include
sだけを使用することはできません。おそらくinclude
sのみに切り替えることができました。しかし、タスクが複数回実行されることになっている場合を除いて、どこでもインポートに切り替えることにしました。私はこれらすべてのトリッキーな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
true
とtrue
を取得します。前のケースを参照してください(インクルード変数はインポート変数よりも優先されます)。そこで、3.yml
のincludeに切り替えます。ただし、3.yml
の最初のインクルードはスキップされます。親タスクからwhen: https
を継承し、後者はおそらくタスクのhttps
からvars
を取得するためです。解決策は、2.yml
のincludeにも切り替えることです。これにより、when: https
が子タスクに伝達されなくなります。