Ansible::json_query
複雑なディクショナリデータを json データとみなして、jq コマンド風にフィルターをかけ、
特定のデータのみ抽出することができます。
ケーススタディ
1つの例として pip インストールするケースです
pip install xxxxx したときに、python-devel がないとか言われたことありますよねー。
pip パッケージ名とそれに依存する yum/deb パッケージ名の依存関係を記述して、一気にインストールする例です。
Ansible コード
airflow_pip_packages:
- name: 'pip==9.0.1'
require_packages_yum:
- 'gcc'
- 'python-pip'
- 'python-devel'
- name: "airflow=={{ airflow_version }}"
- name: "airflow[hive]=={{ airflow_version }}"
- name: 'cryptography'
require_packages_yum:
- 'openssl-devel'
- name: '[python/pip] install require packages'
become: true
package:
name: "{{ item }}"
with_flattened:
- "{{ airflow_pip_packages | json_query('[*].require_packages_' + ansible_pkg_mgr) }}"
- name: '[python/pip] install'
become: true
pip:
name: "{{ item }}"
with_flattened:
- "{{ airflow_pip_packages | json_query('[*].name') }}"
ある pip パッケージをインストールするのに、yum/deb パッケージが必要だったりなかったりします。
この'あったりなかったり'を ansible で表現するのはいままで一筋縄でいかなかった
※ python_pip_packages | map(attribute='ごにょごにょ' | list ) と書いてなおかつ
※ 'なかったり'の場合は、require_package_yum: [] をわざわざ記述しなくてはいけない (undefined がリストされてしまう)
のですが、json_query を使うことによって、undefined 値を除外して、必要なデータのみを取得できます。
値は実際に [ ["gcc", "python-pip", "python-devel" ], [ "openssl-devel" ] ] で返ってきますので、
with_flattened でリストを平らにしてループ処理をします。
なかなかスッキリしたコードですよね
json_query + with_flattened コンビでいろいろと応用が利きそうですね。
それでは、良い 自動インフラ ライフを。