Ansibleのntc-ansibleモジュール群まとめ (③設定変更モジュール実行編)

# はじめに

前回と前々回の記事で、Ansibleのサードパーティー製ネットワークモジュール群である`ntc-ansible`の概要、セットアップと、確認コマンドモジュールの実行を行いました。

[Ansibleのntc-ansibleモジュール群まとめ (①概要、セットアップ編)](https://qiita.com/tech_kitara/items/422f34e1f327b0f8b7f8)
[Ansibleのntc-ansibleモジュール群まとめ (②確認コマンドモジュール実行編)](https://qiita.com/tech_kitara/items/748701d243b0181e462b)

本記事では、8つあるモジュールの内、設定変更を実施するための`ntc_config_command`モジュールの動作確認結果をまとめました。


# 2. Inventoryファイル
前回同様、対象機器は、test3(Cisco CSR1000V)とします。
以下のInventoryファイルを作成し、`/home/user/ntc-ansible/`配下に格納します。

```text:inventory
[cisco]
192.168.100.201

[cisco:vars]
hostname=test3
ansible_username=test3
ansible_password=cisco
enable_secret=test3
```

# 3. 実行例1: IPアドレス設定(コマンドをPlaybookに記載)

### 3.1. Playbook
以下のPlaybookを作成し、`/home/user/ntc-ansible/`配下に格納します。
`ntc_config_command`モジュール内で、物理インターフェースへのIPアドレス設定を行っています。
公式の`ios_config`モジュール等では、冪等性の観点から、`interface GigabitEthernet3`コマンドを`parents`オプション内で定義する必要がありますが、`ntc_config_command`モジュールは冪等性が考慮されず、同じ`commands`オプション配下に記載しています。

また、後続の`ntc_config_command`と`debug`モジュールで、該当インターフェースのRunning Config抜粋の取得・表示を行っています。

```yaml:playbook2.yml
---

- hosts: cisco
  gather_facts: no
  connection: local

  tasks:
    - name: change configuration on remote devices
      ntc_config_command:
        connection: telnet   # 今回はログイン方式としてtelnetを指定。デフォルト値はssh
        commands:
          - interface GigabitEthernet3
          - ip address 10.10.10.10 255.255.255.0
        provider: "{{ cli }}"

    - name: run show command on remote devices
      ntc_show_command:
        connection: telnet
        command: show running-config interface GigabitEthernet3
        use_templates: false
        provider: "{{ cli }}"
      register: result

    - name: display show command
      debug:
        var: result.response

  vars:
    cli:
      host: "{{ inventory_hostname }}"
      username: "{{ ansible_username }}"
      password: "{{ ansible_password }}"
      secret: "{{ enable_secret }}"
      platform: cisco_ios   # 対象機器のOSに合わせて指定する必要あり
```

### 3.2. 実行結果
`debug`モジュール(display show command)の実行結果から、IPアドレスが問題なく`10.10.10.10`に設定されていることが分かります。

```yaml:
[user@localhost ntc-ansible]$ ansible-playbook -i inventory playbook2.yml

PLAY [cisco] ******************************************************************************************************************

TASK [change configuration on remote devices] *********************************************************************************
changed: [192.168.100.201]

TASK [run show command on remote devices] *************************************************************************************
ok: [192.168.100.201]

TASK [display show command] ***************************************************************************************************
ok: [192.168.100.201] => {
    "result.response": [
        "Building configuration...\n\nCurrent configuration : 90 bytes\n!\ninterface GigabitEthernet3\n ip address 10.10.10.10 255.255.255.0\n negotiation auto\nend\n"
    ]
}

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


# 4. 実行例2: IPアドレス設定(設定コマンドを別ファイルに記載)

### 4.1. Playbook、設定ファイル
次に、設定コマンドを記載したファイルをPlaybook内で読み込んで、IPアドレス設定を行ってみます。
以下のPlaybookを作成し、`/home/user/ntc-ansible/`配下に格納します。
実行例1との違いは、`commands_file`オプションで設定ファイルの保管先を指定する点です。

```yaml:playbook3.yml
---

- hosts: cisco
  gather_facts: no
  connection: local

  tasks:
    - name: change configuration on remote devices
      ntc_config_command:
        connection: telnet
        commands_file: './{{ hostname }}_setup_config.txt'
        provider: "{{ cli }}"

    - name: run show command on remote devices
      ntc_show_command:
        connection: telnet
        command: show running-config interface GigabitEthernet3
        use_templates: false
        provider: "{{ cli }}"
      register: result

    - name: display show command
      debug:
        var: result.response

  vars:
    cli:
      host: "{{ inventory_hostname }}"
      username: "{{ ansible_username }}"
      password: "{{ ansible_password }}"
      secret: "{{ enable_secret }}"
      platform: cisco_ios
```

設定ファイルでは、`ntc_config_command`モジュールが、公式モジュールのようにConfigの階層構造を考慮するか確認するため、敢えて2行目の`ip address ～`のインデントを削除しています。

```text:test3_setup_config.text
interface GigabitEthernet3
ip address 10.10.10.11 255.255.255.0
```

### 4.2. 実行結果
IPアドレスが問題なく`10.10.10.11`に書き換えられていることから、`ntc_config_command`モジュールはConfigの階層構造を考慮せず、単純に上からコマンドを実行しているだけと推測されます。

```yaml:
[user@localhost ntc-ansible]$ ansible-playbook -i inventory playbook3.yml

PLAY [cisco] ******************************************************************************************************************

TASK [change configuration on remote devices] *********************************************************************************
changed: [192.168.100.201]

TASK [run show command on remote devices] *************************************************************************************
ok: [192.168.100.201]

TASK [display show command] ***************************************************************************************************
ok: [192.168.100.201] => {
    "result.response": [
        "Building configuration...\n\nCurrent configuration : 90 bytes\n!\ninterface GigabitEthernet3\n ip address 10.10.10.11 255.255.255.0\n negotiation auto\nend\n"
    ]
}

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

# 5. 最後に
今回はntc-ansibleの設定変更モジュールを見て行きました。
冪等性が考慮されない点はデメリットですが、公式モジュールで、ファイルを使った設定ができ、かつTelnetまでサポートしているものはないことから、限定的なケースで使い道はあるかもしれません。