はじめに
Cisco IOS のネットワーク機器に任意のコンフィグを投入する、cisco.ios.ios_config
というモジュールがあります。
本モジュールを使ったPlaybookを実行して changed
になると、以下のような冪等性に関する警告が表示されます。
% ansible-playbook -i inventory.ini test_ios_config.yml PLAY [ios01] ********************************************************************** TASK [ios_config test] ************************************************************ [WARNING]: To ensure idempotency and correct diff the input configuration lines should be similar to how they appear if present in the running configuration on device changed: [ios01] PLAY RECAP ************************************************************************ ios01 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
こちらについて説明します。
警告の意味
この警告は、冪等性を確保するために、各オプションで指定するコマンドは、機器の show running-config
で表示される形式と同じにしてくださいね、いう警告です。
(仮に同じ形式にしてもこの警告は表示されます)
cisco.ios.ios_config
モジュールの Notes に同じようなことが書かれています。
To ensure idempotency and correct diff the configuration lines in the relevant module options should be similar to how they appear if present in the running configuration on device including the indentation.
他、*_config
モジュール共通の仕様として、FAQ にも関連の項目 "Why do the *_config modules always return changed=true with abbreviated commands?
" があります。
本モジュールは、まず lines
や src
、parents
オプションに与えられるコンフィグの内容と、機器側の show running-config
の内容を比較して、実際に投入が必要なコンフィグ差分を求めてから、コンフィグを生成、投入する動作です。
この比較は文字列の比較のため、フル表記と省略表記、大文字小文字違い、スペース有無の違いなどは別物として扱われます。
たとえば、以下のとおりです。
interface GigabitEthernet0/0
とint Gi0/0
は別物- 省略してしまっている
interface GigabitEthernet0/0
とinterface gigabitethernet0/0
は別物- 大文字のところが小文字になっている
interface GigabitEthernet0/0
とinterface GigabitEthernet 0/0
は別物- スペースが空いている
※ 本警告は、cisco.ios
コレクション 1.3.0
から表示されるようになりました。しばらくは changed
でも ok
でも表示される仕様でした。cisco.ios
コレクション 2.3.0
で、changed
のときのみ表示されるように変更されました。
合わせないと毎回 changed
になる
実際は、show running-config
の内容と異なる形式でもコマンドとして有効な場合は、エラーにならずにコマンド自体は実行できます。しかし、同じPlaybookをもう一度実行すると、また差分ありと判断され、またコンフィグを投入します。
結果的に、毎回 changed
になります。2回目の実行以降、設定が実質的に変わらないのに changed
になってしまうのは少し混乱の元ですね。
具体的にどう指定するのが良いのか
たとえば、show running-config
上、
interface GigabitEthernet0/0
とあったら、Playbook 上も以下のように表記を合わせます。
- name: ios_config test cisco.ios.ios_config: lines: - description kingyo parents: - interface GigabitEthernet0/0 # 表記を合わせる
src
オプション利用時は、インデントの数も合わせる必要があります。詳細は以下の記事を参照してください。
https://tekunabe.hatenablog.jp/entry/2018/12/22/ansible_ios_config_src_needs_indents
なお、このように表記を合わせても、changed
の場合は警告自体は表示されます。Ansibleとしては「changed
になったけど意図通りですか?冪等性保つためにこうしてくださいね」という親切心からの警告なのだと思います。
どうしても警告を非表示したいときは、ansible.cfg
の [defaults]
セクションで action_warnings=False
を指定するという対策もありますが、他の警告も無効にしてしまうので注意が必要です。
駄目なパターン
だめな例1: 省略表記にしてしまっている
- name: ios_config test cisco.ios.ios_config: lines: - description kingyo parents: - iint Gi0/0 # 表記があってない
だめな例2: 小文字になってしまっている
- name: ios_config test cisco.ios.ios_config: lines: - description kingyo parents: - interface gigabitethernet0/0 # 表記があってない
だめな例3: スペースが入ってしまっている
- name: ios_config test cisco.ios.ios_config: lines: - description kingyo parents: - interface GigabitEthernet 0/0 # 表記があってない
だめな例4: lines
で省略表記にしてしまっている
事情は lines
オプションでも同様です。
- name: ios_config test cisco.ios.ios_config: lines: - desc kingyo # ここがあっていない parents: - interface GigabitEthernet0/0 # ここはあってても
ほか、デフォルトのコンフィグを投入する場合も注意が必要です。たとえば、no shutdown
がデフォルトな機器に対して no shutdown
を実行するのも、やはり毎回 changed
になってしまいます。show running-config
上に no shutdown
がデフォルトのため存在しなく、Ansible が投入が必要だと判断するためです。この場合については、cisco.ios.ios_interfaces
モジュールの enabled
オプションで制御するほうが良いです。毎回 changed
にならない仕様になってます。
参考: 専用モジュールだと
本警告はあくまでも cisco.ios.ios_config
モジュールによるものです。
ここまでの例で出した、インターフェースの description
の設定であれば、インターフェースの基本設定の専用モジュール cisco.ios.ios_interfaces
でもできます。cisco.ios.ios_interfaces
モジュールの場合は、以下のようにインターフェース名が show running-config
の表記とあっていなくても、冪等性が担保されます。内部でノーマライズされるようです。
- name: ios_interfaces test cisco.ios.ios_interfaces: config: - name: Gi 0/0 # 省略してる上にスペースが余分 description: kingyo
ただ、省略の仕方にはばらつきがあるので、やはりshow running-config
と合わせるほうが丁寧で良いかなと思います。
おわりに
手動の場合は、省略形のまま実行したり、大文字小文字も気にせずコマンドを実行することも多いと思います。
本モジュール利用時は、手癖や習慣にとらわれず、実機を確認するのが良さそうです。