4
1

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】入力がIPv4アドレスであることを確認する最適解とは

Last updated at Posted at 2020-12-14

はじめに

<バージョン>
ansible 2.9.1
jinja2 2.11

playbook実行時に、assertモジュールで入力が正しいことを確認することは大変重要です。
今回は、入力がIPv4アドレスであることを確認するにはどうすればよいかを調査します。

Playbook1 ~debugによる確認~

想定される入力を色々と書いてみました。

ipv4_sample_1.yml
---
- name: "check ip address"
  hosts: localhost
  gather_facts: no
  vars:
    input_vars:
      - "192.168.0.1"
      - "192.168.0.1/24"
      - ["192.168.0.1", "192.168.0.2"]
      - ["192.168.0.1", "a"]
      - "192.168.0.256"
      - 1.2
      - "1.2"
      - -255
      - 255
      - "a"
      - ""

  tasks:
    - name: "debug result of filter"
      debug:
        msg:
         - "{{ item }}"
         - "{{ item | type_debug }}"
         - "{{ item | ipv4 }}"
      loop: "{{ input_vars }}"

Playbook1 実行結果

実行結果をまとめると以下のようになり、わかることとしては
(1)ipv4フィルタで変換が出来なかった場合はfalseになる
(2)ipv4フィルタにはlistで渡すことも可能で、変換できた変数だけが戻ってくる(項番4より)
(3)ipv4フィルタは、__後半に0を補填する機能がある__ため、"1.2" -> "1.2.0.0"
  になり、結果がfalseにならない(項番7より)
(4)ipv4フィルタは正の整数をIPv4アドレスに変換する(項番9より)
  →10進数を2進数に変換しているので誤りではない

項番 入力 データ型 ipv4変換結果
1 "192.168.0.1" unicode 192.168.0.1
2 "192.168.0.1/24" unicode 192.168.0.1/24
3 ["192.168.0.1", "192.168.0.2"] list ["192.168.0.1", "192.168.0.2"]
4 ["192.168.0.1", "a"] list ["192.168.0.1"]
5 "192.168.0.256" unicode false
6 1.2 float false
7 "1.2" unicode 1.2.0.0
8 -255 int false
9 255 int 0.0.0.255
10 "a" unicode false
11 "" unicode false

ちなみに、実行ログは以下になります。

出力
[ec2-user@ip-<ip addr> ansible]$ ansible-playbook ipv4_sample_1.yml

PLAY [check ip address] ************************************************************************************************

TASK [debug result of filter] ******************************************************************************************
ok: [localhost] => (item=192.168.0.1) =>
  msg:
  - 192.168.0.1
  - unicode
  - 192.168.0.1
ok: [localhost] => (item=192.168.0.1/24) =>
  msg:
  - 192.168.0.1/24
  - unicode
  - 192.168.0.1/24
ok: [localhost] => (item=[u'192.168.0.1', u'192.168.0.2']) =>
  msg:
  - - 192.168.0.1
    - 192.168.0.2
  - list
  - - 192.168.0.1
    - 192.168.0.2
ok: [localhost] => (item=[u'192.168.0.1', u'a']) =>
  msg:
  - - 192.168.0.1
    - a
  - list
  - - 192.168.0.1
ok: [localhost] => (item=192.168.0.256) =>
  msg:
  - 192.168.0.256
  - unicode
  - false
ok: [localhost] => (item=1.2) =>
  msg:
  - 1.2
  - float
  - false
ok: [localhost] => (item=1.2) =>
  msg:
  - '1.2'
  - unicode
  - 1.2.0.0
ok: [localhost] => (item=-255) =>
  msg:
  - -255
  - int
  - false
ok: [localhost] => (item=255) =>
  msg:
  - 255
  - int
  - 0.0.0.255
ok: [localhost] => (item=a) =>
  msg:
  - a
  - unicode
  - false
ok: [localhost] => (item=) =>
  msg:
  - ''
  - unicode
  - false

PLAY RECAP *************************************************************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

Playbook2 ~IPv4であることの確認~

上記の結果を元に、「IPv4アドレスが文字列で入力されたこと(表の項番1と項番2)」を
assertで確認するplaybookを作成しました。
assertでは以下3点を確認します。
(1)入力が文字列であること
  ->前提条件。「項番9:入力が正の整数だった場合」の対策にもなる。
(2)splitの結果、要素数が4つになること
  ->「項番7:入力が "." を含む文字列だった場合」の対策
(3)ipv4フィルタの結果がfalseにならないこと

ipv4_sample_2.yml
---
- name: "check ip address"
  hosts: localhost
  gather_facts: no
  vars:
    input_vars:
      - "192.168.0.1"
      - "192.168.0.1/24"
      - ["192.168.0.1", "192.168.0.2"]
      - ["192.168.0.1", "a"]
      - "192.168.0.256"
      - 1.2
      - "1.2"
      - -255
      - 255
      - "a"
      - ""

  tasks:
    - name: "check ipv4 address"
      assert:
        that:
          - item is string
          - item.split('.') | length == 4
          - item | ipv4 is not false
      loop: "{{ input_vars }}"
      ignore_errors: true

Playbook2 実行結果

想定通りのassert結果を得ることが出来ました。

出力
[ec2-user@ip-<ip addr> ansible]$ ansible-playbook ipv4_sample_2.yml

PLAY [check ip address] ************************************************************************************************

TASK [check ipv4 address] **********************************************************************************************
ok: [localhost] => (item=192.168.0.1) => changed=false
  ansible_loop_var: item
  item: 192.168.0.1
  msg: All assertions passed
ok: [localhost] => (item=192.168.0.1/24) => changed=false
  ansible_loop_var: item
  item: 192.168.0.1/24
  msg: All assertions passed
failed: [localhost] (item=[u'192.168.0.1', u'192.168.0.2']) => changed=false
  ansible_loop_var: item
  assertion: item is string
  evaluated_to: false
  item:
  - 192.168.0.1
  - 192.168.0.2
  msg: Assertion failed
failed: [localhost] (item=[u'192.168.0.1', u'a']) => changed=false
  ansible_loop_var: item
  assertion: item is string
  evaluated_to: false
  item:
  - 192.168.0.1
  - a
  msg: Assertion failed
failed: [localhost] (item=192.168.0.256) => changed=false
  ansible_loop_var: item
  assertion: item | ipv4 is not false
  evaluated_to: false
  item: 192.168.0.256
  msg: Assertion failed
failed: [localhost] (item=1.2) => changed=false
  ansible_loop_var: item
  assertion: item is string
  evaluated_to: false
  item: 1.2
  msg: Assertion failed
failed: [localhost] (item=1.2) => changed=false
  ansible_loop_var: item
  assertion: item.split('.') | length == 4
  evaluated_to: false
  item: '1.2'
  msg: Assertion failed
failed: [localhost] (item=-255) => changed=false
  ansible_loop_var: item
  assertion: item is string
  evaluated_to: false
  item: -255
  msg: Assertion failed
failed: [localhost] (item=255) => changed=false
  ansible_loop_var: item
  assertion: item is string
  evaluated_to: false
  item: 255
  msg: Assertion failed
failed: [localhost] (item=a) => changed=false
  ansible_loop_var: item
  assertion: item.split('.') | length == 4
  evaluated_to: false
  item: a
  msg: Assertion failed
failed: [localhost] (item=) => changed=false
  ansible_loop_var: item
  assertion: item.split('.') | length == 4
  evaluated_to: false
  item: ''
  msg: Assertion failed
...ignoring

PLAY RECAP *************************************************************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=1

参考資料

Ansible Documentation - ipaddr filter

4
1
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
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?