【Ansible】ソートされたリストの並び順をチェックする方法

f:id:hira98:20190719004012p:plain

【結論】

  • Pythonであればindex()でリストの添字を取得できるので簡単に比較できる。
  • 同じことをAnsibleでも実装したかったのですが、いくら探してもPythonindex()に相当する書き方を見つけることができませんでした。
  • よって、苦肉の索として辞書型に変換して比較することにしました。
  • 本記事で紹介する書き方より良いAnsibleの書き方をご存知の方は教えて欲しいです。

【目次】

はじめに

現在業務でAnsibleを使ってファイアウォールの設定を自動で行うプレイブックの開発を行っています。

ファイアウォールにポリシーを追加して並び替える部分はAPIを叩いて実装できたのですが、ポリシーが意図通りに並び変わっていることを確認する処理の実装にかなり手間取ったのでブログにまとめました。

前提条件

Ansibleでソートされたリストの並び順をチェックする方法の解説がメインであるため、ファイアウォールAPIを叩いてポリシーを取得する方法についての説明は省略します。

ポリシーの一覧は既に優先度の高い順にリストに格納されているものとします。

pythonの場合

policy_list = ["red", "green", "aaaa", "yellow", "purple"]

Ansibleの場合

- set_fact:
    policy_list: ["red", "green", "aaaa", "yellow", "purple"]

Pythonで書いた場合

policy_check()ではリストの要素のインデックス(何番目か)を取得して比較しています。

これが一般的な実装方法だと思われます。

しかし、policy_check_yml()ではリスト型をわざわざ辞書型に変換してから、優先度を比較しています。

理由は、Ansibleでindex()に相当するモジュールを見つけれなかったので、苦肉の策として辞書型に変換して書いた処理を解説するためにPythonでも書いています。

ソース(.py)

def policy_check(policy_list, base_policy, sorted_policy):
    # ポリシーの優先度チェック1
    if policy_list.index(base_policy) < policy_list.index(sorted_policy):
        print(f"優先度高:{base_policy}")
    else: # ポリシーの優先度チェック2
        print(f"優先度高:{sorted_policy}")


def policy_check_yml(policy_list, base_policy, sorted_policy):
    # ポリシーリストを辞書型に変換
    rank_dic = {}
    for i,v in enumerate(policy_list):
        rank_dic[v] = i

    # ポリシーの優先度チェック1
    if rank_dic[base_policy] < rank_dic[sorted_policy]:
        print(f"優先度高:{base_policy}")
    else: # ポリシーの優先度チェック2
        print(f"優先度高:{sorted_policy}")


def main():
    # 変数初期化
    policy_list = ["red", "green", "aaaa", "yellow", "purple"]
    base_policy = "aaaa"
    sorted_policy = "green"

    # Pythonde書く場合
    policy_check(policy_list, base_policy, sorted_policy)

    # Ansibleの実装をPythonに置き換えた場合
    policy_check_yml(policy_list, base_policy, sorted_policy)

main()

実行結果

優先度高:green
優先度高:green

Ansibleで書いた場合

かなり強引に書いている自覚はあります。

ソース(.yml)

---
- hosts: localhost  # 自分自身に接続する
  tasks:

  - naeme: 変数初期化
    set_fact:
      base_policy: "aaaa"
      sorted_policy: "green"
      policy_list: ["red", "green", "aaaa", "yellow", "purple"]
      num_id: 1

  - name: ポリシーリストを辞書型に変換
    set_fact:
      num_id: "{{(num_id|int) + (1|int)}}"
      rank_dic: "{{ rank_dic | default({}) | combine( {item: num_id} ) }}"
    with_items: "{{ policy_list }}"

  - debug: msg="{{rank_dic}}"

  - name: ポリシーの優先度チェック1
    debug: msg="優先度高:{{base_policy}}"
    when: rank_dic[base_policy] < rank_dic[sorted_policy]

  - name: ポリシーの優先度チェック2
    debug: msg="優先度高:{{sorted_policy}}"
    when: rank_dic[base_policy] > rank_dic[sorted_policy]

実行結果

f:id:hira98:20190719004050p:plain

💩コードを撲滅するために...

以下のような「俺ならこう書くぜ」的なのが出てくるのを期待してます🥺

参考情報

Python, enumerateの使い方: リストの要素とインデックスを取得 | note.nkmk.me

Ansible勉強&実践結果(随時更新) - Qiita

さいごに

Aさん:「なんで、配布されているディスプレイを使わないんですか?」

Bさん:「谷に落ちても大丈夫なように、普段から鍛えているんです。」

Aさん:「なるほどww。ひどいところは、ノートPCだけでマウスすら配布されないですからね。」

職場でこんな会話が聞こえてきて、笑ってしまった🤣