はじめに
pip でいう pip freeze
で requirements.txt
のフォーマットを出力できるのと同じように、Ansible のコレクションでもコレクションの一覧を requirementst.yml
のフォーマットで出力できれば便利かもしれないなと思いました。
ansible-galaxy collection
コマンド自体にはそのような機能はなさそうだったでした(もしあったら教えてください!)。ちょっとしたスクリプトを書けばできそうですが、今回はPlaybook でやってみることにしました。
- 環境
- ansible-core 2.14.1
ansible-galaxy collection list
の--format
オプションが使える必要あり
- ansible-core 2.14.1
Playbook
ansible-galaxy collection list
の --format
オプションで JSON を指定して、その結果を Jinja2 テンプレートにあててファイルを生成します。コレクションの保存先パスが複数あることと想定して、保存先パスごとにディレクトリを用意して、その中に requirements.yml
を生成します。
また、Ansible がインストールされているコントロールノード自身を対象とするため、hosts: localhost
を指定しています。
--- - name: Generate requirements.yml hosts: localhost gather_facts: false connection: local vars: ansible_python_interpreter: "{{ ansible_playbook_python }}" tasks: # コレクションのリストを JSON で出力 - name: Execute ansible-galaxy collection list ansible.builtin.command: cmd: ansible-galaxy collection list --format json changed_when: false register: collection_list # コレクションの保存ディレクトリに基づいて requiirements.yml 保存先ディレクトリを作成 - name: Create directories ansible.builtin.file: path: "{{ item.key | replace('/', '_') }}" state: directory loop: "{{ collection_list.stdout | from_json | dict2items }}" loop_control: label: "{{ item.key }}" # 各ディレクトリに requiirements.yml を出力 - name: Output requirements.yml ansible.builtin.copy: content: |- --- collections: {% for c in (item.value | dict2items) %} - name: {{ c.key }} version: {{ c.value.version }} {% endfor %} dest: "{{ item.key | replace('/', '_') }}/requirements.yml" loop: "{{ collection_list.stdout | from_json | dict2items }}" loop_control: label: "{{ item.key }}"
なんとなく、別の Jinja2 テンプレートファイルを作りたくなかったため、ansible.builtin.template
ではなく ansible.builtin.copy
モジュールの content
オプションを利用しました。
実行結果
% ansible-playbook -i localhost, list.yml PLAY [Generate requirements.yml] ****************************************************************************** TASK [Execute ansible-galaxy collection list] ***************************************************************** ok: [localhost] TASK [Create directories] ************************************************************************************* changed: [localhost] => (item=/Users/sakana/envs/a7/lib/python3.9/site-packages/ansible_collections) changed: [localhost] => (item=/Users/sakana/.ansible/collections/ansible_collections) TASK [Output requirements.yml] ******************************************************************************** changed: [localhost] => (item=/Users/sakana/envs/a7/lib/python3.9/site-packages/ansible_collections) changed: [localhost] => (item=/Users/sakana/.ansible/collections/ansible_collections) PLAY RECAP **************************************************************************************************** localhost : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
今回、2つのディレクトリ保存パスが存在するため、以下の2つの requirements.yml
が生成されました。
_Users_sakana_.ansible_collections_ansible_collections/requirements.yml
_Users_sakana_envs_a7_lib_python3.9_site-packages_ansible_collections/requirements.yml
ディレクトリが深くなることを避けるため、 /
を _
に変換したため若干不格好ですが一応元ネタが識別できます。
代表して一つ、_Users_sakana_.ansible_collections_ansible_collections/requirements.yml
の中身を確認します。
--- collections: - name: arista.eos version: 6.0.0 - name: amazon.aws version: 5.3.0 - name: azure.azcollection version: 1.15.0 - name: cisco.ios version: 4.0.0 - name: ansible.netcommon version: 4.1.0 - name: ansible.utils version: 2.8.0
これで、使えそうなファイルになりました。