AnsibleでIPアドレスをインクリメントする

Ansibleのフィルターを使ってIPアドレスのインクリメントをしたかったので簡単に備忘録として書いておきます。

# 1. ipaddr filter

https://docs.ansible.com/ansible/latest/user_guide/playbooks_filters_ipaddr.html

# 2. 環境

|   項目  | バージョン |
|---------|------------|
| Ansible | 2.6.5      |

# 3. 必要なモジュール

* python-netaddr

# 4. IPアドレスのインクリメント

## 4-1. モジュールをインストール

必要なモジュールをインストールします。

```shell-session
[root@66091d5a51be ~]# yum -y install python-netaddr
```

## 4-2. インクリメント例

以下は `192.168.0.1` のIPアドレスに `+1` して `192.168.0.2` にするPlaybookです。

```yaml:example.yml
---
- name: example
  hosts: localhost
  gather_facts: no
  vars:
    ip: 192.168.0.1
  tasks:
    - debug: msg="{{ (( ip | ipaddr('int')) + 1 ) | ipaddr }}"
```

実行すると `192.168.0.2` になっています。

```shell-session
[root@66091d5a51be ~]# ansible-playbook example.yml
 [WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'


PLAY [example] ************************************************************************************************************************************************

TASK [debug] **************************************************************************************************************************************************
ok: [localhost] => {
    "msg": "192.168.0.2"
}

PLAY RECAP ****************************************************************************************************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0
```

ただし、普通に数値をプラス、マイナスするだけだとブロードキャストやネットワークアドレスも含まれてしまいます。

```yaml:example.yml
---
- name: example
  hosts: localhost
  gather_facts: no
  vars:
    ip: 192.168.0.254
  tasks:
    - debug: msg="{{ (( ip | ipaddr('int')) + 1 ) | ipaddr }}"
```

実行します。

```shell-session
[root@66091d5a51be ~]# ansible-playbook example.yml
 [WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'


PLAY [example] ************************************************************************************************************************************************

TASK [debug] **************************************************************************************************************************************************
ok: [localhost] => {
    "msg": "192.168.0.255"
}

PLAY RECAP ****************************************************************************************************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0
```

例えば(乱暴な書き方ですが)、/24のブロードキャストを含まない場合は以下のような条件式を書きます。

```yaml:example.yml
---
- name: example
  hosts: localhost
  gather_facts: no
  vars:
    ip: 192.168.0.254
  tasks:
    - set_fact:
        ip: "{{ (( ip | ipaddr('int')) + 1 ) | ipaddr }}"

    - set_fact:
        ip: "{{ (( ip | ipaddr('int')) + 2 ) | ipaddr }}"
      when: ip.split('.')[3] == "255"

    - debug: msg="{{ ip }}"
```

実行します。

```shell-session
[root@66091d5a51be ~]# ansible-playbook example.yml
 [WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'


PLAY [example] ************************************************************************************************************************************************

TASK [set_fact] ***********************************************************************************************************************************************
ok: [localhost]

TASK [set_fact] ***********************************************************************************************************************************************
ok: [localhost]

TASK [debug] **************************************************************************************************************************************************
ok: [localhost] => {
    "msg": "192.168.1.1"
}

PLAY RECAP **************************************************************************************************************************************************** localhost                  : ok=3    changed=0    unreachable=0    failed=0
```

結果は `192.168.1.1` と3オクテット目の位が上がっていることが確認できます。