てくなべ (tekunabe)

ansible / network / automation / 学習の記録

[Ansible] 「つまずき Ansible 【Part29】フィルター」ふりかえり

はじめに

2021/02/06 に、YouTube Live で「つまずき Ansible 【Part29】フィルター」という配信をしました。

実際に作業しながら(ときには)エラーと戦って進めるシリーズです。

今回は、値を変換したり抽出したりするフィルターをいくつか試しました。

参考 https://docs.ansible.com/ansible/latest/user_guide/playbooks_filters.html

tekunabe.connpass.com

  • 環境
    • Ansible 2.9.16


動画

youtu.be

  • 0:00 イントロダクション
  • 4:11 抽出系
    • gt のとこを「以上」と説明してしまいましたが、正しくは「より大きい」です。失礼しました。
  • 13:11 変換系
  • 13:53 結合系
  • 15:05 正規表現
  • 16:29 パス操作系
  • 17:57 ネットワーク系
  • 22:22 その他
  • 23:30 試行錯誤1 ansible-console
  • 25:32 試行錯誤2 debugger
  • 29:37 おわりに

■ やったこと

抽出系

selectattr フィルター

条件にあったものを抽出。

---
- hosts: localhost
  gather_facts: no
  connection: local
  debugger: always

  vars:
    users:
      - name: yamada
        age: 42
      - name: tanaka
        age: 26
      - name: suzuki
        age: 32
      - name: sato
        age: 27

  tasks:
    - name: debug 1
      debug: #  select * from users where age > 30 のようなイメージ
        msg: "{{ users | selectattr('age', 'gt', 30) | list }}" # gt は > でも可

実行結果

ok: [localhost] => {
    "msg": [
        {
            "age": 42,
            "name": "yamada"
        },
        {
            "age": 32,
            "name": "suzuki"
        }
    ]
}

map フィルター

様々な機能がある。今回は SQL でいうカラムの選択。

    - name: debug 2
      debug:  # select name from users where age >= 30  のようなイメージ
        msg: "{{ users | selectattr('age', 'gt', 30) | map(attribute='name') | list }}"

実行結果

ok: [localhost] => {
    "msg": [
        "yamada",
        "suzuki"
    ]
}

以下は説明のみ

  • json_query: jmethpath を利用した複雑なクエリー

変換系

説明のみ

結合系

説明のみ

正規表現

regex_replace フィルター

正規表現を使用した置換。後方参照利用できる。

    - name: regex
      debug:
        msg:  "{{ 'foobar' | regex_replace('^f.*o(.*)$', '\\1') }}"

実行結果

ok: [localhost] => {
    "msg": "bar"
}

パス操作系

説明のみ


ネットワーク系

parse_cli_textfsm フィルター

TextFSM テンプレートを利用して、ネットワーク機器の show コマンドの実行結果を構造化データにパースする。

---
- hosts: ios
  gather_facts: false

  tasks:
    - name: show
      ios_command:
        commands:
          - show interfaces
      register: res

    - name: debug
      debug:
        msg: "{{ res.stdout[0] | parse_cli_textfsm(path_template) }}"
      vars:
        path_template: "/home/admin/envs/a29/lib/python3.6/site-packages/ntc_templates/templates/cisco_ios_show_interfaces.textfsm"

実行結果

ok: [ios01] => {
    "msg": [
        {
            "ABORT": "",
            "ADDRESS": "5254.00xx.xxxx",
            "BANDWIDTH": "1000000 Kbit",
            "BIA": "5254.00xx.xxxx",
            "CRC": "0",
            "DELAY": "10 usec",
            "DESCRIPTION": "",
            "DUPLEX": "Auto Duplex",
            "ENCAPSULATION": "ARPA",
            "HARDWARE_TYPE": "iGbE",
            "INPUT_ERRORS": "0",
            "INPUT_PACKETS": "854394",
            "INPUT_RATE": "0",
            "INTERFACE": "GigabitEthernet0/0",
            "IP_ADDRESS": "192.168.1.11/24",
            "LAST_INPUT": "00:00:00",
            "LAST_OUTPUT": "00:00:00",
            "LAST_OUTPUT_HANG": "never",
            "LINK_STATUS": "up",
            "MEDIA_TYPE": "RJ45",
            "MTU": "1500",
            "OUTPUT_ERRORS": "0",
            "OUTPUT_PACKETS": "127122",
            "OUTPUT_RATE": "0",
            "PROTOCOL_STATUS": "up",
            "QUEUE_STRATEGY": "fifo",
            "SPEED": "Auto Speed"
        },
// ....(略)...

参考: show コマンド結果をパースする方法あれこれ(TextFSM / Genie Parser と Netmiko / Ansible の組み合わせ) - てくなべ (tekunabe)

その他

説明のみ

試行錯誤に便利

フィルターを色々試したい時に便利な方法。

ansible-console

ansible-console コマンド

対話的な操作。

(a29) [admin@gitlab stumble]$ ansible-console -i localhost, 
Welcome to the ansible console.
Type help or ? to list commands.

admin@all (1)[f:5]$ debug msg="{{ [1,2,3] | max  }} "
localhost | SUCCESS => {
    "msg": "3 "
}
admin@all (1)[f:5]$ debug msg="{{ [1,2,3] | min  }} "
localhost | SUCCESS => {
    "msg": "1 "
}

参考: [Ansible] フィルターを手軽に試行錯誤したいときの ansible-console コマンドの使い方 - てくなべ (tekunabe)

Playbook Debugger

Playbook Debugger

たとえば、Play に debugger: always を指定すると、各タスク実行後にデバッガーが起動する。

---
- hosts: localhost
  gather_facts: no
  connection: local
  debugger: always    # ここ

以下が、デバッガーが起動した状態。

[localhost] TASK: debug 1 (debug)>

task.args で、タスクのオプションの書き換えができる。そのが r で再実行できる。

[localhost] TASK: debug 1 (debug)> task.args['msg'] = "{{ users | selectattr('age', 'gt', 40) | list }}"
[localhost] TASK: debug 1 (debug)> r
ok: [localhost] => {
    "msg": [
        {
            "age": 42,
            "name": "yamada"
        }
    ]
}


おわりに

フィルターは数も多く、奥が深いです。

全ては覚えられないので、フィルター的なことをしたい場合は、Ansible や Jinja2 の公式ドキュメントを眺めて探しています。

Filters — Ansible Documentation

Jinja — Jinja Documentation (2.11.x)


Part30にむけて

ベータですが、Ansible 3.0.0b1 がリリースされたので、こちらを扱ってみます。

tekunabe.connpass.com

他、以下のネタを検討中です。気が向いたものをやります。 connpass申込時のアンケートでいただいたものも含めています。

  • Katakoda Ansible 101
  • connection: local ななにか
  • Windows
  • cli_parse モジュール(Part15 の続き)
  • Ansible 2.10 関連
  • Ansible 3.0.0 関連
  • モジュールのテスト
  • AWXとの共存を念頭に入れたDirectory構成