はじめに
Playbookではモジュールにオプションを指定してさまざまな処理を自動化していきます。
Playbookを書いていくうちに、このモジュール(またはコレクション単位)のこのオプションにはいつも同じ値を設定する、というときはないでしょうか。
たとえば ansible.builtin.uri
モジュールをたくさん使っていて、毎回 force_basic_auth: true
を指定しているようなケースです。
モジュールの仕様としてデフォルト値が設定されている場合もありますが、別のデフォルト値を設定したかったり、そもそもデフォルト値がないオプションにデフォルト値を設定したくなります。
こんなときに便利な module_defaults
というキーワードがあります。
module_defaults
を使うと、都度都度モジュールごとに毎回同じオプションを指定しなくて良くなります。
module_defaults
は、モジュール単位で指定する方法と、「グループ」によって複数モジュールにまるごと指定する方法があります。
指定方法1: モジュール単位で指定
公式ドキュメントのサンプルを引用します。
- hosts: localhost module_defaults: ansible.builtin.uri: force_basic_auth: true user: some_user password: some_password tasks: - name: Interact with a web service ansible.builtin.uri: url: http://some.api.host/v1/whatever1 - name: Interact with a web service ansible.builtin.uri: url: http://some.api.host/v1/whatever2 - name: Interact with a web service ansible.builtin.uri: url: http://some.api.host/v1/whatever3
冒頭の module_defaults
のところで、ansible.builtin.uri
モジュールに対して3つのオプションのデフォルト値を設定しています。
ansible.builtin.uri
モジュールの仕様としては、force_basic_auth
オプションのデフォルト値は yes
、user
と password
オプションはデフォルト値なしです。これらのデフォルト値を上書き、または新たに設定している、ということです。
これを、仮に module_defautls
を使わずタスクごとに指定する場合は、以下のような Playbook になります。少々ノイジーになってしまうかなと思います。
- hosts: localhost tasks: - name: Interact with a web service ansible.builtin.uri: url: http://some.api.host/v1/whatever1 force_basic_auth: true # タスクごとに指定 user: some_user # タスクごとに指定 password: some_password # タスクごとに指定 - name: Interact with a web service ansible.builtin.uri: url: http://some.api.host/v1/whatever2 force_basic_auth: true # タスクごとに指定 user: some_user # タスクごとに指定 password: some_password # タスクごとに指定 - name: Interact with a web service ansible.builtin.uri: url: http://some.api.host/v1/whatever3 force_basic_auth: true # タスクごとに指定 user: some_user # タスクごとに指定 password: some_password # タスクごとに指定
オプションの値は変数にすれば統一管理できますが、タスクごとにオプションを指定すること自体は避けられません。module_defaults
を使うとこのような重複を避けられて便利です。
指定方法2: グループによる複数モジュールまとめた指定
モジュールの中には、共通のオプションをもったものがあります。こういうときのために、これらを「グループ」で定義してまとめてデフォルト値を設定する Module defaults groupsという機能があります。
以前からも、aws
や、azure
、gcp
など向けのモジュールのいくつかのグループが、Ansible本体に定義されていました。
module_defaults
でグループまとめて指定する場合は、以下のようにします。
module_defaults: group/グループ名: オプション名1: 値1 オプション名2: 値2
ansible-core 2.12 からは、コレクション側でグループを定義できるようになりました。これが後押しになったのか、グループ化されたモジュールも増えてきました。これはかなり便利だなと思っています。
グループ名は各コレクションの meta/runtime.yml
ファイル内の、action_group
キー配下で確認できます。
meta/runtime.yml
は、コレクションを管理しているリポジトリ側でも確認できます(利用するバージョンと同じものを確認する)し、もちろんインストールした手元の環境でも確認できます。
以下、一つのコレクションをもとに説明します。
netbox.netbox
コレクションの場合
netbox.netbox
コレクション 3.8.0 の場合は、meta/runtime.ymlに以下の定義があります。(この定義は 3.8.0 からできました)
action_groups: netbox: - netbox_aggregate - netbox_cable - netbox_circuit #...(略)...
これは、netbox_aggregate
、netbox_cable
などモジュールなどを netbox
というグループでまとめてるよ、という意味です。
なので、module_defaults
の指定の仕方は以下のようになります。
module_defaults: group/netbox.netbox.netbox: オプション名1: 値1 オプション名2: 値2 #...(略)...
グループ名が netbox.netbox.netbox
と、わけがわからない感じになってますが、netbox.netbox
コレクション内の netbox
グループ、という指定です。最後の netbox
が meta/runtime.yml
に定義されているグループ名です。
[2022/11/14 追記]
netbox.netbox
コレクション 3.9.0 の段階で、公式ドキュメントにも module_defaults
に関する記述が追記されました。
netbox-ansible-collection.readthedocs.io
おためし
netbox.netbox コレクション内のモジュールでで試した結果をまとめます
- 環境
- ansible-core 2.13.1
- netbox.netbox コレクション 3.8.0 (これ未満のバージョンにはグループ名の定義がないため機能しません)
netbox.netbox
コレクションの各モジュールは、netbox_url
や netbox_token
など接続関連のオプションを共通で持っています。netbox_url
や netbox_token
オプションは必須なので、通常であれば各タスクに都度指定する必要があります。
module_defaults
を利用すると、各タスクに都度指定する必要がなくなります。
以下は、module_defaults
を利用したPlaybook例です。タスク側には netbox_url
や netbox_token
を指定していません。
--- - hosts: netbox01 gather_facts: false module_defaults: group/netbox.netbox.netbox: netbox_url: "{{ netbox_url }}" # Playごとに指定 netbox_token: "{{ netbox_token }}" # Playごとに指定 tasks: - name: Create a site netbox.netbox.netbox_site: data: name: Nagoya state: present - name: Create a device netbox.netbox.netbox_device: data: name: Test Device device_type: C9200-48P device_role: Access Switch site: Nagoya state: present
ホスト変数定義ファイル、host_vars/netbox.01.yml
には、以下のように netbox_url
、netbox_token
変数を定義しておきます(機密情報は ansible-vault
などで暗号化推奨)。
--- ansible_connection: local netbox_url: https://netbox.example.com netbox_token: xxxxxxxxxxxxx_dummy_xxxxxxxxxxxx ansible_python_interpreter: "{{ ansible_playbook_python }}"
以下、Playbook 実行例です。
% ansible-playbook -i inventory.ini netbox.yml PLAY [netbox01] **************************************************************************************************** TASK [Create a site] *********************************************************************************************** changed: [netbox01] TASK [Create a device] ********************************************************************************************* changed: [netbox01] PLAY RECAP ********************************************************************************************************* netbox01 : ok=2 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
無事に実行できました。
なお、仮にこのタスクの定義方法で modulue_defautls
の定義をしなかった場合は、missing required arguments: netbox_token, netbox_url
というエラーになります。今回正常に実行できるのは、netbox_token
と netbox_url
オプションは必須のオプションでタスク側には定義がないけど、modulue_defautls
で定義してあるから大丈夫ということです。
NetBox 側の結果です。
(おためしには NetBox のデモサイト https://demo.netbox.dev/ を利用させていただきました。便利です。)
他のコレクションのグループ名
他のコレクションのグループ名の定義も、現時点の最新バージョンのものを少し覗いてみます。
コレクションに含まれる全モジュールをグループ化している傾向にあるようです。
コレクション名前 | 調査バージョン | meta/runtime.yml |
グループ名(FQCN) |
---|---|---|---|
awx.awx |
21.6.0 | meta/runtime.yml |
awx.awx.controller |
community.grafana |
1.5.2 | meta/runtime.yml |
community.grafana.grafana |
communityhashi_vault |
3.2.0 | meta/runtime.yml |
communityhashi_vault.vault |
他、もともと Ansible 本体で定義されていたグループは、コレクション側の定義に紐づけるような仕組みになったようです。
補足: module_defaults
キーワードを指定できる場所
今回は Play 単位で、module_defaults
キーワードを指定しましたが、他にも block や role 、 task 単位でも指定で来ます。