るつぼっと

NWエンジニアな人たちに向けて

[Ansible] ansible_hostのIPをPlayの途中で変更する方法

はじめに

Ansibleはansible_hostで定義したIPで対象ノードへ接続する。
ただNW機器の障害試験を自動化したい場合など、障害ケースによっては
指定のIPへ接続できない状況も起こりうる。
別名&別IPでinventoryを定義して一時的に使い分けてもいいが、それだとファイルや
フォルダ名に{{ inventory_hostname }} を使いたい場合に名称が変わってしまう。
そこでinventory_hostnameはそのままにansible_hostの値を変更してみる。

実装方法

非常に単純で、set_factで書き換えてしまえばいい。 以下に例を示す。

構成
  • ×印の箇所をPlayの途中でdisableにする。 f:id:yoloz:20220326173912p:plain
playbook
  • 最初は192.168.56.101で接続して状態を確認する
  • 途中でansible_host10.10.10.254へ変更する
  • 192.168.56.101をdisableにする
---
- hosts: rt1
  gather_facts: false
  tasks:
    - name: check ansible_host
      debug:
        var: hostvars['rt1']['ansible_host']

    - name: show interfaces
      vyos_command:
        commands:
          - show interfaces
      register: res_interfaces

    - name: print interfaces
      debug:
        var: res_interfaces.stdout

### ここでansible_hostを変更。
### 変数はホストごとに個別管理されるため、
### hosts: rt1 のPlayにTaskを書かないとうまくいかない点に注意。
    - name: modify ansible_host
      set_fact:
        ansible_host: 10.10.10.254

    - name: check ansible_host
      debug:
        var: hostvars['rt1']['ansible_host']

    - name: disable interface
      vyos_config:
        lines:
          - set interface ethernet eth0 disable

    - name: show interfaces
      vyos_command:
        commands:
          - show interfaces
      register: res_interfaces

    - name: check ansible_host
      debug:
        var: res_interfaces.stdout
実行結果
PLAY [rt1] ***********************************************************************************************************************

TASK [check ansible_host] ********************************************************************************************************
ok: [rt1] => 
  hostvars['rt1']['ansible_host']: 192.168.56.101

TASK [show interfaces] ***********************************************************************************************************
ok: [rt1]

TASK [print interfaces] **********************************************************************************************************
ok: [rt1] => 
  res_interfaces.stdout:
  - |-
    Codes: S - State, L - Link, u - Up, D - Down, A - Admin Down
    Interface        IP Address                        S/L  Description
    ---------        ----------                        ---  -----------
    eth0             192.168.56.101/24                 u/u
    eth1             10.10.10.254/24                   u/u
    eth2             20.20.20.254/24                   u/u
    lo               127.0.0.1/8                       u/u
                     ::1/128

TASK [modify ansible_host] *******************************************************************************************************
ok: [rt1]

TASK [check ansible_host] ********************************************************************************************************
ok: [rt1] => 
  hostvars['rt1']['ansible_host']: 10.10.10.254

TASK [disable interface] *********************************************************************************************************
changed: [rt1]

TASK [show interfaces] ***********************************************************************************************************
ok: [rt1]

TASK [check ansible_host] ********************************************************************************************************
ok: [rt1] => 
  res_interfaces.stdout:
  - |-
    Codes: S - State, L - Link, u - Up, D - Down, A - Admin Down
    Interface        IP Address                        S/L  Description
    ---------        ----------                        ---  -----------
    eth0             192.168.56.101/24                 A/D
    eth1             10.10.10.254/24                   u/u
    eth2             20.20.20.254/24                   u/u
    lo               127.0.0.1/8                       u/u
                     ::1/128

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

別解 add_host

add_hostモジュールでも同じことが可能。

Playbook
---
- hosts: rt1
  gather_facts: false
  tasks:
    - name: check ansible_host
      debug:
        var: hostvars['rt1']['ansible_host']

    - name: show interfaces
      vyos_command:
        commands:
          - show interfaces
      register: res_interfaces

    - name: print interfaces
      debug:
        var: res_interfaces.stdout

### ここでansible_hostを変更。
### add_hostならこのようにhostsがrt1以外のPlayで実行しても上手くいく
### (もちろんrt1が対象のPlayでも上手くいく)
- hosts: localhost
  gather_facts: false
  tasks:
    - name: modify ansible_host
      add_host:
        name: rt1
        ansible_host: 10.10.10.254

- hosts: rt1
  gather_facts: false
  tasks:
    - name: check ansible_host
      debug:
        var: hostvars['rt1']['ansible_host']

    - name: disable interface
      vyos_config:
        lines:
          - set interface ethernet eth0 disable

    - name: show interfaces
      vyos_command:
        commands:
          - show interfaces
      register: res_interfaces

    - name: check ansible_host
      debug:
        var: res_interfaces.stdout
実行結果
PLAY [rt1] ***********************************************************************************************************************

TASK [check ansible_host] ********************************************************************************************************
ok: [rt1] => 
  hostvars['rt1']['ansible_host']: 192.168.56.101

TASK [show interfaces] ***********************************************************************************************************
ok: [rt1]

TASK [print interfaces] **********************************************************************************************************
ok: [rt1] => 
  res_interfaces.stdout:
  - |-
    Codes: S - State, L - Link, u - Up, D - Down, A - Admin Down
    Interface        IP Address                        S/L  Description
    ---------        ----------                        ---  -----------
    eth0             192.168.56.101/24                 u/u
    eth1             10.10.10.254/24                   u/u
    eth2             20.20.20.254/24                   u/u
    lo               127.0.0.1/8                       u/u
                     ::1/128

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

TASK [modify ansible_host] *******************************************************************************************************
changed: [localhost]

PLAY [rt1] ***********************************************************************************************************************

TASK [check ansible_host] ********************************************************************************************************
ok: [rt1] => 
  hostvars['rt1']['ansible_host']: 10.10.10.254

TASK [disable interface] *********************************************************************************************************
changed: [rt1]

TASK [show interfaces] ***********************************************************************************************************
ok: [rt1]

TASK [check ansible_host] ********************************************************************************************************
ok: [rt1] => 
  res_interfaces.stdout:
  - |-
    Codes: S - State, L - Link, u - Up, D - Down, A - Admin Down
    Interface        IP Address                        S/L  Description
    ---------        ----------                        ---  -----------
    eth0             192.168.56.101/24                 A/D
    eth1             10.10.10.254/24                   u/u
    eth2             20.20.20.254/24                   u/u
    lo               127.0.0.1/8                       u/u
                     ::1/128

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

所感

動くものの、こういう使い方って想定されるんだろうか。