てくなべ (tekunabe)

ansible / network / automation

[Ansible] IPv4/v6アドレスをホストとして利用可能かどうか assert でチェックする

はじめに

Ansible には、ipaddr という、IPv4/v6アドレスを扱う便利なフィルターがあります。

この記事では、与えられたIPv4/v6アドレス(プレフィックス数付き)が、ホストとして利用可能なアドレス かどうかassert するサンプルをご紹介します。

  • 動作確認環境
    • Ansible 2.9.11
    • netaddr 0.8.0
      • Ansible 標準では含まれないので必要に応じて pip install netaddr でインストール

Playbook

以下の Playbook を利用します。変数 addresses にチェック対象の IPv4/v6 アドレスをプレフィックス数付きで定義します。 利用可能アドレス とコメントしたアドレスが assert 成功して、それ意外は失敗する想定です。

---
- hosts: localhost
  gather_facts: false

  vars:
    addresses:
      - 10.0.0.0/24
      - 10.0.0.1/24     # 利用可能アドレス
      - 10.0.0.254/24   # 利用可能アドレス
      - 10.0.0.255/24
      - fe80::/64
      - fe80::1/64    # 利用可能アドレス
      - fe80::ffff:ffff:ffff:fffe/64  # 利用可能アドレス
      - fe80::ffff:ffff:ffff:ffff/64

  tasks:
    - name: asset usable address
      assert:
        that:
          - item | ipaddr('host')    # ホストアドレスであること
          - item != (item | ipaddr(-1))   # ブロードキャストアドレスでないこと
      loop: "{{ addresses }}" 

ipaddr('host') でホストアドレスかどうかをチェックします。 10.0.0.0/24 はネットワークアドレスなので失敗します。個人的な直感とは違い、10.0.0.255/24 のようなブロードキャストアドレスは成功します。

そのため、もう一つの 条件で item != (item | ipaddr(-1)) も併せてチェックします。 たとえば、10.0.0.1/24 | ipaddr(-1)10.0.0.255/24 になります。

実行結果

Playbook を実行します。

$ ansible-playbook -i localhost, net.yml 

PLAY [localhost] ***************************************************************************************************

TASK [asset usable address] ****************************************************************************************
failed: [localhost] (item=10.0.0.0/24) => {
    "ansible_loop_var": "item",
    "assertion": "item | ipaddr('host')",
    "changed": false,
    "evaluated_to": false,
    "item": "10.0.0.0/24",
    "msg": "Assertion failed"
}
ok: [localhost] => (item=10.0.0.1/24) => {
    "ansible_loop_var": "item",
    "changed": false,
    "item": "10.0.0.1/24",
    "msg": "All assertions passed"
}
ok: [localhost] => (item=10.0.0.254/24) => {
    "ansible_loop_var": "item",
    "changed": false,
    "item": "10.0.0.254/24",
    "msg": "All assertions passed"
}
failed: [localhost] (item=10.0.0.255/24å) => {
    "ansible_loop_var": "item",
    "assertion": "item | ipaddr('host')",
    "changed": false,
    "evaluated_to": false,
    "item": "10.0.0.255/24å",
    "msg": "Assertion failed"
}
failed: [localhost] (item=fe80::/64) => {
    "ansible_loop_var": "item",
    "assertion": "item | ipaddr('host')",
    "changed": false,
    "evaluated_to": false,
    "item": "fe80::/64",
    "msg": "Assertion failed"
}
ok: [localhost] => (item=fe80::1/64) => {
    "ansible_loop_var": "item",
    "changed": false,
    "item": "fe80::1/64",
    "msg": "All assertions passed"
}
ok: [localhost] => (item=fe80::ffff:ffff:ffff:fffe/64) => {
    "ansible_loop_var": "item",
    "changed": false,
    "item": "fe80::ffff:ffff:ffff:fffe/64",
    "msg": "All assertions passed"
}
failed: [localhost] (item=fe80::ffff:ffff:ffff:ffff/64) => {
    "ansible_loop_var": "item",
    "assertion": "item != (item | ipaddr(-1))",
    "changed": false,
    "evaluated_to": false,
    "item": "fe80::ffff:ffff:ffff:ffff/64",
    "msg": "Assertion failed"
}

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

無事に、利用可能アドレス としていたアドレスのみが All assertions passed となりました。

おわりに

ipaddr フィルターには他にもたくさんの機能がありますので、IPアドレスに関する操作をしたい場合は、リファレンスを参照することをおすすめします。

docs.ansible.com