paloma blog

NWエンジニアやってます。主に自宅環境のお遊びを書きます。Pythonもちょっと。タイトルは好きなカクテルから。

pythonのjinja2で1:Nの可変パラメータをテンプレートに渡した時のメモ debug編

前回書いたコードで各変数の中身がどうなっているか見てみます。

手動debug

手動ですが、中身を見ます。

今回の環境はubuntu20.04LTSのpython仮想環境です。

(python3) masashi@PC-ubuntu:~$ uname -a ; python --version
Linux PC-ubuntu 5.4.0-66-generic #74-Ubuntu SMP Wed Jan 27 22:54:38 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
Python 3.8.5
csv読み込み

辞書型で格納されています。 3.6からOrderdDictで返ってきましたが、3.8から辞書型になったそうです。
職場のは3.6ですが、どちらでも動きは同じですね。

>>> import csv
>>> with open('poolsetting.csv', 'r') as f:
 ...     data = csv.DictReader(f)
...     settings = [ x for x in data ]
...
with>>> with open('poolmember.csv', 'r') as f:
...     data = csv.DictReader(f)
...     members = [x for x in data]
...
>>> settings
[{'poolname': 'POOLA', 'port': '80', 'monitor': 'tcp'}, {'poolname': 'POOLA_test', 'port': '80', 'monitor': 'tcp'}, {'poolname': 'POOLB', 'port': '8080', 'monitor': 'tcp'}]
>>> members
[{'POOLA': 'node1', 'POOLA_test': 'node4', 'POOLB': 'node6'}, {'POOLA': 'node2', 'POOLA_test': 'node5', 'POOLB': None}, {'POOLA': 'node3', 'POOLA_test': None, 'POOLB': None}]

それぞれcsv.DictReaderで読み込んだ値が入っていますね。

membersの中身をキー毎にまとめる
>>> poolmember = {}
>>> # キーとリストを格納
>>> for k in members[0]:
...     poolmember[k] = []
...
>>> # 各キーに中身を追加
>>> for m in members:
...     for k,v in m.items():
...        poolmember[k].append(v)
...
>>> poolmember
{'POOLA': ['node1', 'node2', 'node3'], 'POOLA_test': ['node4', 'node5', None], 'POOLB': ['node6', None, None]}

ここでmembersの中身をキーごとにまとめてます。

テンプレートに渡すように各csvを各行にマージする

updateが肝ですね。
settingsのキーにpoolmemberのキーがマッチしたら辞書をマージします。
そしてテンプレートファイルの変数になるようキーをリネームします。

>>> for s in settings:
...     for k,v in poolmember.items():
...         # キーが同じだったらマージ
...         if s['poolname'] == k:
...             s.update({k:v})
...             # テンプレートに渡すようにリネーム
...             s['member'] = s.pop(k)
...
>>> settings
[{'poolname': 'POOLA', 'port': '80', 'monitor': 'tcp', 'member': ['node1', 'node2', 'node3']}, {'poolname': 'POOLA_test', 'port': '80', 'monitor': 'tcp', 'member': ['node4', 'node5', None]}, {'poolname': 'POOLB', 'port': '8080', 'monitor': 'tcp', 'member': ['node6', None, None]}]
>>> settings[0]
{'poolname': 'POOLA', 'port': '80', 'monitor': 'tcp', 'member': ['node1', 'node2', 'node3']}
>>>

これでテンプレートに渡す各キーと値がセットできました!

出力のサンプル

サンプルとしてsettings1つ目の各値をテンプレートと比較してみます、

データを整形したものです。

{
 'poolname': 'POOLA', 
 'port': '80', 
 'monitor': 'tcp', 
 'member': ['node1', 'node2', 'node3']
}

各データのキーがこのテンプレートに渡り、

### create {{ poolname }}

tmsh create ltm pool {{ poolname }} { \
  load-balancing-mode least-connections-members \
{%- for node in member %}
{%- if node != None %}
  members add { \
    {{ node }}:{{ port }} \
  } \
{%- endif %}
{%- endfor %}
  monitor {{ monitor }} \
}

紐づかれた値がこう出力されます。

### create POOLA

tmsh create ltm pool POOLA { \
  load-balancing-mode least-connections-members \
  members add { \
    node1:80 \
  } \
  members add { \
    node2:80 \
  } \
  members add { \
    node3:80 \
  } \
  monitor tcp \
}

というわけで中身のデバッグでした。
手動じゃなくちゃんとした手法も覚えないといけませんね。