I'm creating a requirements.yml
in an Ansible project, and I want to identify all of the modules that need to be installed from ansible-galaxy
that are used by project playbooks. ansible-doc --list --playbook-dir foo
seems like the right tool for the job, but it lists all locally available modules, not just the ones which are actually used in the foo
directory. ansible-galaxy list
doesn't account for any which are needed but not installed.
Is there a way to do this where I don't end up writing a shell script to sed|awk|grep
the info I want?
The best approach I've been able to come up with so far is to ansible-playbook --syntax-check
each of the playbooks. This will throw errors such as
ERROR! the role 'foo' was not found ...
ERROR! couldn't resolve module/action 'bar'. This often indicates a misspelling, missing collection, or incorrect module path.
but this is not ideal because it exits as soon as any error occurs. I have to fix each one and run the syntax check again.
FWIW, as a concept, the playbook below lists the modules used in a role
- hosts: localhost
vars:
keywords:
- always
- become
- block
- loop
- loop_control
- name
- notify
- register
- tags
- vars
- when
tasks:
- name: The variable my_role_path is mandatory
assert:
that: my_role_path|d('')|length > 0
- name: Find tasks files
find:
path: "{{ my_role_path }}/tasks"
patterns: '*.yml,*.yaml'
recurse: true
register: result
- name: Create list of tasks
set_fact:
lft: "{{ lft|d([]) + lookup('file', item)|from_yaml }}"
loop: "{{ result.files|map(attribute='path')|list }}"
- name: Get list of keys
set_fact:
lfk: "{{ lfk|d([]) + item.keys()|list }}"
loop: "{{ lft }}"
- name: Get list of keys from block/rescue/always
set_fact:
lfk: "{{ lfk|d([]) + item.keys()|list }}"
loop: "{{ lft|json_query('[].[block, rescue, always]')|flatten }}"
- name: Display list of modules
debug:
var: lfk|unique|sort|difference(keywords)
For example, analyze the role systemd
shell> ansible-playbook pb.yml -e my_role_path=roles/ansible-role-systemd
...
lfk|unique|sort|difference(keywords):
- command
- file
- include_tasks
- meta
- systemd
- template
Complete the list of the keywords.
Use the tasks below to analyze a playbook
tasks:
- name: The variable my_playbook_path is mandatory
assert:
that: my_playbook_path|d('')|length > 0
- name: Create list of tasks
set_fact:
lft: "{{ _playbook|map(attribute='tasks')|flatten }}"
vars:
_playbook: "{{ lookup('file', my_playbook_path)|from_yaml }}"
- name: Get list of keys
set_fact:
lfk: "{{ lfk|d([]) + item.keys()|list }}"
loop: "{{ lft }}"
- name: Get list of keys from block/rescue/always
set_fact:
lfk: "{{ lfk|d([]) + item.keys()|list }}"
loop: "{{ lft|json_query('[].[block, rescue, always]')|flatten }}"
- name: Display list of modules
debug:
var: lfk|unique|sort|difference(keywords)
For example, analyzing the first playbook gives
lfk|unique|sort|difference(keywords):
- assert
- debug
- find
- set_fact