はじめに
以前の記事でもご紹介しましたが、ロールの実行に必要な変数をチェックする「Role argument validation」という機能があります。
ロールの meta/argument_specs.yml というファイルに、どういう変数が必須か、型は何かなどを定義すると、Playbook からロールを呼ぶ際に、冒頭で変数のチェックをしてくれます。要件を満たさない場合はロールが実行されません。
ロールの実行と変数のチェックがセットであるため、ただ変数のチェックのみしたい(テスト目的など)場合は少々不都合です。
そこで利用できるのが、ansible.builtin.validate_argument_spec モジュールです。
この記事では簡単な検証をした結果をまとめます。
- 検証環境
- ansible-core 2.16.0
サンプル
roles ディレクトリ配下に myapp ロールを作成し、その中の meta/argument_specs.yml に以下のファイルを用意します。
myapp_int は int で必須、myapp_str は str で任意、という定義です。
--- argument_specs: main: # main.yml に対応 short_description: The main entry point for the myapp role options: #ここから変数の仕様定義 myapp_int: type: "int" required: true description: "The integer value" myapp_str: type: "str" description: "The string value"
上記のファイルを利用し、変数のチェックをする Playbook は以下の通りです。
--- - name: Test Play hosts: localhost connection: local gather_facts: false tasks: - name: Verify variables by argument_specs.yml ansible.builtin.validate_argument_spec: argument_spec: "{{ (lookup('ansible.builtin.file', spec_file) | from_yaml)['argument_specs']['main']['options'] }}" provided_arguments: "{{ my_parameters }}" # チェックさせたい変数 vars: spec_file: roles/myapp/meta/argument_specs.yml my_parameters: # チェックさせたい変数を束ねてる myapp_int: 12345 # チェックさせたい変数 myapp_str: sakana # チェックさせたい変数
argument_spec オプションに、argument_specs.yml の中身を渡しています。
provided_arguments オプションにはチェックさせたい変数を指定します。ここでは、vars ディレクティブ配下の my_parameters の中身(myapp_int、myapp_str)がチェックさせたい変数です。provided_arguments オプションの指定なので、チェックしたい変数が別の場所(インベントリ変数、Play 変数、extra vars など)してあるなら指定不要です。
正常時の結果
先程の my_parameters は要件を満たしています。この状態で Playbook を実行します。
PLAY [Test Play] ***************************************************************************************************** TASK [Verify variables by argument_specs.yml] ************************************************************************* ok: [localhost] PLAY RECAP *********************************************************************************************************** localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
ok になりました。
チェックだけなので、ロール自体の処理は実行されません。
異常時の結果
今度は要件を満たさないようにしてみます。
# 略 my_parameters: # チェックさせたい変数を束ねてる myapp_int: damedesuyo # int にすべきところを意図的に文字列 myapp_str: sakana
Playbook 実行結果は以下のとおりです。myapp_int の int にできないという親切なメッセージが表示されました。
fatal: [localhost]: FAILED! => {
"argument_errors": [
"argument 'myapp_int' is of type <class 'str'> and we were unable to convert to int: <class 'str'> cannot be converted to an int"
],
"argument_spec_data": {
"myapp_int": {
"description": "The integer value",
"required": true,
"type": "int"
},
"myapp_str": {
"description": "The string value",
"required": true,
"type": "str"
}
},
"changed": false,
"msg": "Validation of arguments failed:\nargument 'myapp_int' is of type <class 'str'> and we were unable to convert to int: <class 'str'> cannot be converted to an int",
"validate_args_context": {}
}
PLAY RECAP ***********************************************************************************************************
localhost : ok=0 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
まとめ
用途は限られるかもしれませんが、ロールの処理はしたくないけど変数のチェックだけしたい、というときには有効な手段だと思います。
参考
おまけ
ロールの実行に必要な変数のチェックという用途とは異なりますが、何かしらの変数のチェックを JSON Schema で行いたい場合は、ansible.utils コレクション内の validate モジュールなどが利用できます。