はじめに
多くのモジュールがコレクションに移行してから、モジュール名は namespace.collection.module_name
のようにどのコレクションのモジュールなのかを指定ができるようになりました。ここではこの指定方法を FQCN と呼びます。
Ansible本体 (ansible-core / ansible-base) に組み込まれているモジュールは ansible.builtin
というコレクションの扱いです。たとえばユーザー管理のモジュールは ansible.buitlin.user
という指定になります。
基本的に FCQN でモジュール名を指定するのが良いと思っていますが、モジュール名のみを指定した場合でもリダイレクト等の仕組みによって、問題なく利用できることも多々あります。
一方で、FQCN でモジュールを指定しないと困るケースもあります。 この記事では、ansible.builtin
内のモジュールの例で再現してみます。
- 検証環境
- Ansible 7.6.0
困るケース
困りがちなのは以下のようなケースです。(だいぶわざとらしいですが)
--- - name: Manage Users hosts: web01 gather_facts: false collections: - awx.awx tasks: - name: Create a user user: name: sakana groups: - admin append: true # 略
一見、ansible.buitlin.user
モジュールを実行してくれそうですが、Playbook を実行すると以下のエラーになります。
TASK [Create a user] ************************************************************************************************************************************************** fatal: [web01]: FAILED! => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"}, "changed": false, "msg": "missing required arguments: username"}
"missing required arguments: username"
というエラーで、username
という必須のパラメーターが指定されてないよ、と言われています。ところが ansible.buitlin.user
モジュールのドキュメントには username
パラメーターはありません。
これは、Playbook 内の collections
キーワードで指定した awx.awx
によって、users
モジュールは awx.awx.user
モジュールと解釈されたためです。そして、awx.awx.user
モジュールでは usersname
パラメーターが必須であるのに対して、Playbook では指定されていないため、前述のエラーが発生します。
このように、モジュール名のみで見た時にある種の衝突が起き、一意に特定できないことがあるため、困るケースです。
ちなみに、以前は awx.awx.awx_user
モジュールのように、モジュール名の _
より前の部分があることによってモジュール名のみでも特定しやすい状態でした。コレクションによる配布が落ち着くにつれて「コレクション名 awx.awx
があるからモジュール名には awx
はなくてもいいでしょ」となったのか、モジュール名としては単に user
となりました。
少し分かりにくい例
前述の例は、Playbook 内に collections
キーワードがあったため原因を追いやすいかもしれません。
この collections
キーワードは Play の単位だけでなく、さまざまな箇所で定義できます。この仕様により collections
の定義に気が付きにくかったり、複数個所で定義された場合にどう適用されるんだっけと戸惑ったりしまいそうです。
たとえばロールにした場合は、以下の例のように meta/main.yml
内に collections
を定義できます。
--- collections: - awx.awx
この状態で tasks/main.yml
に以下のように、モジュール名を単に user
と指定すると、awx.awx.user
モジュールとして解釈されます。
--- - name: Create user user: name: sakana groups: - admin append: true
ロールを呼び出す Playbook は以下のように collecttions
の定義なしで実行すると・・
--- - name: Manage Users hosts: web01 gather_facts: false tasks: - name: Import manage_users ansible.builtin.import_role: name: manage_users
やはり "missing required arguments: username"
というエラーになります。
Playboook にも タスクファイルにも collections
キーワードがないため、やや気づきにくいかと思います。
トラブルシューティング
こういう事象を目の当たりにすると、モジュール名のみの指定した場合にどのコレクションとして解釈されたかを調べたくなるかもしれません。
いくつか方法はあるかもしれませんが、私が試した範囲では、Playbook 実行時に ansible-playbook
コマンドに -vvv
を付ける方法があります。チェックモード(-C
)でも大丈夫です。
% ansible-playbook -i inventory.yml playbook.yml -vvv -C ...(略)... TASK [manage_users : Create user] *************************************************************************************************** ..(略)... Using module file /Users/sakana/.ansible/collections/ansible_collections/awx/awx/plugins/modules/user.py ...(略)...
awx/awx/plugins/modules/user.py
というパスから、awx.awx.user
モジュールを実行しようとしたことが分かります。
おわりに
FQCN でモジュールを指定しないと困るケースをご紹介しました。
公式ドキュメントにも、FQCN を推奨する旨の説明がありますし、省略しないほうがトラブル防止になって良いかなと思います。
This is one of the reasons we recommend you always use FQCN.