はじめに
以下の記事で、Junos のインターフェースの状態を取得して debug
で表示するという Playbook が紹介されていました。
面白いネタだなと思って、拝見しました。特に、以下のディクショナリをループする書き方が参考になりました。
with_items: "{{ int_results.keys() | list }}"
自分でしたら、with_dict
を使うところだったので、なるほどと思いました。
そんなことを思ったので、この記事では「Playbook紹介2~interfaceの状態確認~」の別の書き方をした Playbook をご紹介します。
この記事の書き方のほうが良いと主張するつもりはまったくなく「こんな書き方もできるんだなぁ〜」程度に思っていただければと思います。
動作確認環境
- Ansible 2.9.1
- vMX Junos OS 18.3R1.9
Playbook
Playbook はこんな感じです。
- name: Junos Module TEST hosts: junos gather_facts: yes # ポイント(1) vars: ansible_python_interpreter: /usr/bin/python3 tasks: - name: debug debug: msg: "admin_status : {{ admin_status }} / oper_status : {{ oper_status }}" with_dict: "{{ ansible_net_interfaces }}" # ポイント(2) vars: admin_status: "{{ item.value['admin-status'] }}" # ポイント(3) oper_status: "{{ item.value['oper-status']}}"
ポイント・相違点
ポイント、オリジナルとの相違点は以下のとおりです。
ポイント(1)
オリジナルでは gather_facts: no
としていましたが、yes
にしました。これは、Ansible 2.9 から gather_facts
でネットワーク機器の facts を収集する仕様に変わったためです。代わりに、junos_facts
モジュールを使うタスクは定義していません。gather_facts: yes
によって暗黙的に junos_facts
モジュールが利用されます。
この方式のデメリットは、Ansible コントロールノード自身の fact も収集してしまう点です。
なお、デフォルトが gather_facts: yes
なので、gather_facts
自体を指定しなくても構いません。
ポイント(2)
オリジナルでは、
with_items: "{{ int_results.keys() | list }}"
としていましたが、
with_dict: "{{ ansible_net_interfaces }}"
にしました。
with_dict
は、ディクショナリのキーの数だけループする書き方です。ループ中の item.key
にキーが、item.value
に値が入ります。
ループで回すディクショナリの変数は、ansible_net_interfaces
にしています。
オリジナルでは、ansible_facts.net_interfaces
を一旦 set_fact
で別の変数 int_results
に格納していますが、ansible_net_interfaces
という変数も同じ内容です。set_fact
をなくして、いきなり ansible_net_interfaces
を指定するようにしました。このあたりは好みの問題かもしれません。
ポイント(3)
ポイント(2)で with_dict
を利用した関係で、ディクショナリの値の階層の指定を item.value['admin-status']
のようにしています。
なお、admin-status
のように -
が含まれるキーの指定は [
]
で囲う必要があります。item.value.admin-status
のように、ドット表記にしてしまうと、途中の -
が演算子とみなされて admin
というキーを参照した結果、そんなキーないよというエラーにってしまいます。
実行結果
Playbook の実行結果です。
$ ansible-playbook -i hosts fact_test2.yml PLAY [Junos Module TEST] ****************************************************************************************** TASK [Gathering Facts] ******************************************************************************************** [WARNING]: Ignoring timeout(10) for junos_facts ok: [junos] TASK [debug] ****************************************************************************************************** ok: [junos] => (item={'key': 'ge-0/0/0', 'value': {'oper-status': 'down', 'admin-status': 'up', 'speed': '1000mbps', 'macaddress': '00:50:56:a2:45:a2', 'mtu': '1514', 'type': None}}) => { "msg": "admin_status : up / oper_status : down" } ok: [junos] => (item={'key': 'lc-0/0/0', 'value': {'oper-status': 'up', 'admin-status': 'up', 'speed': '800mbps', 'macaddress': 'Unspecified', 'mtu': '0', 'type': 'Unspecified'}}) => { "msg": "admin_status : up / oper_status : up" } ok: [junos] => (item={'key': 'pfe-0/0/0', 'value': {'oper-status': 'up', 'admin-status': 'up', 'speed': '800mbps', 'macaddress': 'Unspecified', 'mtu': '0', 'type': 'Unspecified'}}) => { "msg": "admin_status : up / oper_status : up" ...(略)... PLAY RECAP ******************************************************************************************************** vmx : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
なお、[WARNING]: Ignoring timeout(10) for junos_facts
という警告については、以下の記事を参照してください。
[Ansible] "[WARNING]: Ignoring timeout(10) for ios_facts" の正体とタイムアウトの設定方法 - てくなべ (tekunabe)
補足
実行結果でご覧いただいたとおり、ループのたびにディクショナリの内容が表示されるのが少々うるさいですね。デバッグのときには役に立つのですが。
ok: [junos] => (item={'key': 'ge-0/0/0', 'value': {'oper-status': 'down', 'admin-status': 'up', 'speed': '1000mbps', 'macaddress': '00:50:56:a2:45:a2', 'mtu': '1514', 'type': None}}) => { "msg": "admin_status : up / oper_status : down" } ...(略)...
この出力を調整したい場合は、loop_control
の label
を使うと便利です。
- name: debug debug: msg: "admin_status : {{ admin_status }} / oper_status : {{ oper_status }}" with_dict: "{{ ansible_net_interfaces }}" vars: admin_status: "{{ item.value['admin-status'] }}" oper_status: "{{ item.value['oper-status']}}" loop_control: # ポイント label: "{{ item.key }}" # ポイント
このように出力を調整することで、以下のように、オリジナルと同じログになります。
ok: [junos] => (item=ge-0/0/0) => { "msg": "admin_status : up / oper_status : down" } ...(略)...
おわりに
タスクとしては1つにまとめるかたちにしてみました。とはいえ、タスクが少なければいいというわけではありません。 わかりやすさ、シンプルさ、メンテンナンスしやすさ、は意外と両立させるのは難しいかもしれません。
参考
show interfaces terse | display json コマンド相当の処理を利用する場合はこちら。