はじめに
<バージョン>
ansible 2.9.7
jsonschema 3.2.0
変数が正しく入力されているかの確認は、以下のようにassertモジュールで行えますが、
validateモジュールでも可能らしいので検証します。
- name: "check string"
assert:
that:
- sample_string is defined
- sample_string is string
vars:
sample_string: 'abc'
0. 下準備
validate モジュールを使うには、ansible.utils collectionとJSON Schemaが必要になりますので、
以下のコマンドでインストールしてください。
ansible-galaxy collection install ansible.utils
pip install jsonschema
1. 参考playbook
今回は以下のplaybookで7パターンの検証を行います。
データ型 | 変数名 | 例 |
---|---|---|
string型 | sample_string | "aaa" |
integer型(整数) | sample_integer | 22 |
double型(小数) | sample_double | 10.5 |
array型(配列) | sample_array | ["aaa", 10] |
dict型 | sample_dict | {"name": "Taro", "age": 10 } |
boolean型 | sample_boolean | true |
ipv4 | sample_ipv4 | 192.168.0.1/24(または192.168.0.1) |
---
- name: schema test
hosts: localhost
gather_facts: false
vars:
sample_data:
sample_string: "aaa"
sample_integer: 22
sample_double: 10.5
sample_array:
- "aaa"
- 10
sample_dict:
name: "Taro"
age: 10
sample_boolean: true
sample_ipv4: "192.168.0.1/24"
tasks:
- name: validate
ansible.utils.validate:
data: "{{ sample_data }}"
criteria: "{{ lookup('file', 'validate.json') }}"
engine: ansible.utils.jsonschema
vars:
ansible_jsonschema_draft: draft7
2. validate用変数ファイル
今回は以下のようなJSONファイルを作成しました。。
「required」で変数自体の存在確認を行い、「properties」で変数ごとに判定を行います。
「properties」直下には確認したい変数名を記載し、さらにその下に確認内容を記載します。
データ型ごとのオプションの説明は以下にまとめますが、他にも様々なオプションがありますので、
Understanding JSON Schemaをご参照ください。
string型
「"minLength": 1」-> 文字数は1文字以上
integer型(整数)/double型(小数)
「"exclusiveMinimum": 0」-> 0より大きい数字
array型(配列)
「"minItems": 1」-> 要素数は1以上
「items」配下に要素ごとの条件を記載。今回は1要素目がstring型、2要素目がinteger型。
dict型
「properties」配下にkeyごとの条件を記載。今回はnameがstring型、ageがinteger型。
ipv4
「pattern」にipv4を正規表現にて記載。
正規表現だと結構複雑になるので別の方法を検討した方がよいかもしれません。
書き方としてはLet'sプログラミング-IPアドレス(IPv4)の正規表現を参考にしつつ、
192.168.0.1/24と192.168.0.1の両方に対応できるように修正。
マスクの部分は0-32しか入らないので、以下のように表現している。
ちなみに、「"format": "ipv4"」が使えるようですがバグがありうまく動作しません。
正規表現 | 対応範囲 |
---|---|
/3[0-2] | /30 ~ /32 |
/[1-2]?[0-9] | /0 ~ /29 |
{
"required": [
"sample_string",
"sample_integer",
"sample_double",
"sample_array",
"sample_dict",
"sample_boolean",
"sample_ipv4"
],
"properties": {
"sample_string": {
"type": "string",
"minLength": 1
},
"sample_integer": {
"type": "integer",
"exclusiveMinimum": 0
},
"sample_double": {
"type": "number",
"exclusiveMinimum": 10.49
},
"sample_array": {
"type": "array",
"minItems": 1,
"items": [
{
"type": "string",
"minLength": 1
},
{
"type": "integer",
"exclusiveMinimum": 0
}
]
},
"sample_dict": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"age": {
"type": "integer"
}
}
},
"sample_boolean": {
"type": "boolean"
},
"sample_ipv4": {
"type": "string",
"pattern": "^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(/3[0-2]|/[1-2]?[0-9])?$"
},
}
}
3. Playbook動作確認
3-1. 変数sample_stringが未定義だった場合
実行結果の最後にメッセージとして、
「At 'required' u'sample_string' is a required property.」
と出力されており、未定義の変数があることを見つけることが出来ました。
[ec2-user@ip-<ip addr> ansible]$ ansible-playbook validate.yml
PLAY [schema test] ***********************************************************************************************************************************
TASK [validate] **************************************************************************************************************************************
fatal: [localhost]: FAILED! => changed=false
errors:
- data_path: ''
expected:
- sample_string
- sample_integer
- sample_double
- sample_array
- sample_dict
- sample_boolean
- sample_ipv4
found:
sample_array:
- aaa
- 10
sample_boolean: true
sample_dict:
age: 10
name: Taro
sample_double: 10.5
sample_integer: 22
sample_ipv4: 192.168.0.1/24
json_path: $
message: u'sample_string' is a required property
relative_schema:
properties:
sample_array:
items:
- minLength: 1
type: string
- exclusiveMinimum: 0
type: integer
minItems: 1
type: array
sample_boolean:
type: boolean
sample_dict:
properties:
age:
type: integer
name:
type: string
type: object
sample_double:
exclusiveMinimum: 10.49
type: number
sample_integer:
exclusiveMinimum: 0
type: integer
sample_ipv4:
pattern: ^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])(/3[0-2]|/[1-2]?[0-9])?$
type: string
sample_string:
minLength: 1
type: string
required:
- sample_string
- sample_integer
- sample_double
- sample_array
- sample_dict
- sample_boolean
- sample_ipv4
schema_path: required
validator: required
msg: |-
Validation errors were found.
At 'required' u'sample_string' is a required property.
PLAY RECAP *******************************************************************************************************************************************
localhost : ok=0 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
3-2. 変数sample_stringがinteger型(今回は100)だった場合
実行結果の最後にメッセージとして、
「At 'properties.sample_string.type' 100 is not of type u'string'.」
と出力されており、データ型に誤りがあることを見つけることが出来ました。
[ec2-user@ip-<ip addr> ansible]$ ansible-playbook validate.yml
PLAY [schema test] ***********************************************************************************************************************************
TASK [validate] **************************************************************************************************************************************
fatal: [localhost]: FAILED! => changed=false
errors:
- data_path: sample_string
expected: string
found: 100
json_path: $.sample_string
message: 100 is not of type u'string'
relative_schema:
minLength: 1
type: string
schema_path: properties.sample_string.type
validator: type
msg: |-
Validation errors were found.
At 'properties.sample_string.type' 100 is not of type u'string'.
PLAY RECAP *******************************************************************************************************************************************
localhost : ok=0 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
まとめ
データ型ごとの確認用にさまざまなオプションがあるので今後もいろいろ使ってみましょう。
参考URL
[Ansible] 「つまずき Ansible 【Part21】ansible.utils collection を試す」ふりかえり
json schemaのよく利用する機能まとめ
Understanding JSON Schema
Understanding JSON Schema - Regular Expressions
Let'sプログラミング-IPアドレス(IPv4)の正規表現
python - IPアドレスを検証するJSONスキーマが機能していません