2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Ansible】validateモジュールで変数チェックしたい

Last updated at Posted at 2021-03-29

はじめに

<バージョン>
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)
validate.yml
---
- 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
validate.json
{
  "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スキーマが機能していません

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?