koh’s blog

Sys Admin who loves automation

AnsibleでIPアドレスが特定のレンジに含まれるかの判別

For English

データセンタ、クラウドのゾーンごとに処理を分岐したいときにIPアドレスをみて判別できるようにしたかったが、意外とすんなりいかなかったのでメモ。

TL;DR

こんな感じでwhen句を書いてあげるとあるIPアドレスが特定のレンジに含まれているかを判別してくれます。

- name: test
  debug:
    msg: work
  when: ansible_default_ipv4.address | ipaddr('10.0.2.0/24') | ipaddr('bool')

ansible_default_ipv4.addressが10.0.2.0/24の範囲に含まれているとworkと出力する。

解説

使うのはAnsibleのipaddr filter
https://docs.ansible.com/ansible/latest/user_guide/playbooks_filters_ipaddr.html  

前半部分

ipアドレスリスト | ipaddr('172.30.0.0/16')

この書き方で、ipアドレスリストの中で172.30.0.0/16の範囲内のipを抽出します。

% cat test.yml
---
- hosts: Vag1
  gather_facts: True
  tasks:
    - set_fact:
        testip:
          - "192.168.1.2"
          - "10.0.2.15"

    - name: test
      debug:
        msg: "{{ testip | ipaddr('10.0.2.0/24') }}"

これを実行すると

[koh@kohs-MacBook-Pro] ~/vag_test
% ansible-playbook test.yml
PLAY [Vag1] ***************************************************************************************************************************

TASK [set_fact] ***********************************************************************************************************************
ok: [Vag1]

TASK [test] ***************************************************************************************************************************
ok: [Vag1] => {
    "msg": [
        "10.0.2.15"
    ]
}

PLAY RECAP ****************************************************************************************************************************
Vag1                       : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

[koh@kohs-MacBook-Pro] ~/vag_test
%

2つのIPのうち、10.0.2.0/24の範囲に含まれる10.0.2.15のみが出力される。

後半部分

ipアドレス | ipaddr('bool')

これで、ipアドレスが有効なipアドレスであればTrueを返す。

% cat test2.yml
---
- hosts: Vag1
  gather_facts: True
  tasks:
    - set_fact:
        testip:
          - "192.168.1.2"
          - "10.0.2.15.14.22"
          - "hogehoge"
          - ""

    - name: test
      debug:
        msg: "{{ item | ipaddr('bool')  }}"
      with_items: "{{ testip }}"

これで実行すると

[koh@kohs-MacBook-Pro] ~/vag_test
% ansible-playbook test2.yml

PLAY [Vag1] ****************************************************************************************************************************

TASK [set_fact] ****************************************************************************************************************************
ok: [Vag1]

TASK [test] ****************************************************************************************************************************
ok: [Vag1] => (item=192.168.1.2) => {
    "msg": true
}
ok: [Vag1] => (item=10.0.2.15.14.22) => {
    "msg": false
}
ok: [Vag1] => (item=hogehoge) => {
    "msg": false
}
ok: [Vag1] => (item=) => {
    "msg": false
}

PLAY RECAP ****************************************************************************************************************************
Vag1                       : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

[koh@kohs-MacBook-Pro] ~/vag_test
%

上2つを組み合わせて、ansible_default_ipv4.addressとかを判別してあげるとそのホストのIPを機械的に判別できます。

参考

https://stackoverflow.com/questions/38725204/regular-expression-matching-for-ip-range-in-ansible-playbooks-for-grouping