はじめに
<バージョン>
ansible 2.9.1
jinja2 2.11
playbook実行時に、assertモジュールで入力が正しいことを確認することは大変重要です。
今回は、入力がIPv4アドレスであることを確認するにはどうすればよいかを調査します。
Playbook1 ~debugによる確認~
想定される入力を色々と書いてみました。
---
- 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にならないこと
---
- 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