You can merge such lists on your own if you control the roles and the namespace. For example, create defaults
shell> cat roles/mailserver/defaults/main/fw.yml
ms_fw_allow: [25]
shell> cat roles/webserver/defaults/main/fw.yml
ws_fw_allow: [80, 443]
shell> cat roles/firewall/defaults/main/fw.yml
fw_fw_allow: []
In a play, include the roles and set public: true
"This option dictates whether the role’s vars and defaults are exposed to the play. If set to true the variables will be available to tasks following the include_role task."
- include_role:
name: "{{ item_role }}"
public: true
loop:
- webserver
- mailserver
- firewall
loop_control:
loop_var: item_role
In the role firewall find all variables that match the pattern .*_fw_allow
- debug:
msg: "{{ lookup( varnames , .*_fw_allow ) }}"
gives
msg: ws_fw_allow,ms_fw_allow,fw_fw_allow
and merge(flatten) the lists
- set_fact:
fw_allow: "{{ lookup( vars , *q( varnames , .*_fw_allow ))|
flatten|unique }}"
gives
fw_allow: [80, 443, 25]
Depending on your use case you can put the declaration of fw_allow elsewhere. For example, into the role s defaults
shell> cat roles/firewall/defaults/main/fw.yml
fw_fw_allow: []
fw_allow: "{{ lookup( vars , *q( varnames , .*_fw_allow ))|
flatten|unique }}"
Make sure the name of the variable fw_allow doesn t conflict with the pattern .*_fw_allow . Use this list to configure the firewall.
Example of a complete project for testing
shell> tree .
.
├── ansible.cfg
├── hosts
├── pb.yml
└── roles
├── firewall
│ ├── defaults
│ │ └── main
│ │ └── fw.yml
│ └── tasks
│ └── main.yml
├── mailserver
│ ├── defaults
│ │ └── main
│ │ └── fw.yml
│ └── tasks
│ └── main.yml
└── webserver
├── defaults
│ └── main
│ └── fw.yml
└── tasks
└── main.yml
shell> cat ansible.cfg
[defaults]
gathering = explicit
collections_path = $HOME/.local/lib/python3.9/site-packages/
inventory = $PWD/hosts
roles_path = $PWD/roles
retry_files_enabled = false
stdout_callback = yaml
shell> cat hosts
localhost
shell> cat roles/webserver/defaults/main/fw.yml
ws_fw_allow: [80, 443]
shell> cat roles/mailserver/defaults/main/fw.yml
ms_fw_allow: [25]
shell> cat roles/firewall/defaults/main/fw.yml
fw_fw_allow: []
fw_allow: "{{ lookup( vars , *q( varnames , .*_fw_allow ))|
flatten|unique }}"
shell> cat roles/webserver/tasks/main.yml
- debug:
msg: Install webserver.
shell> cat roles/mailserver/tasks/main.yml
- debug:
msg: Install mailserver.
shell> cat roles/firewall/tasks/main.yml
- debug:
msg: "{{ lookup( varnames , .*_fw_allow ) }}"
when: debug|d(false)|bool
- debug:
var: fw_allow|to_yaml
when: debug|d(false)|bool
Add other lists if you want to. For example, local_fw_allow
shell> cat pb.yml
- hosts: all
vars:
local_fw_allow: [22]
tasks:
- include_role:
name: "{{ item_role }}"
public: true
loop:
- webserver
- mailserver
- firewall
loop_control:
loop_var: item_role
gives
shell> ansible-playbook -e debug=true pb.yml
PLAY [all] ************************************************************************************
TASK [include_role : {{ item_role }}] **************************************************************
TASK [webserver : debug] **********************************************************************
ok: [localhosts] =>
msg: Install webserver.
TASK [mailserver : debug] *********************************************************************
ok: [localhosts] =>
msg: Install mailserver.
TASK [firewall : debug] ***********************************************************************
ok: [localhosts] =>
msg: ws_fw_allow,ms_fw_allow,fw_fw_allow,local_fw_allow
TASK [firewall : debug] ***********************************************************************
ok: [localhosts] =>
fw_allow|to_yaml: |-
[80, 443, 25, 22]
PLAY RECAP ************************************************************************************
localhosts: ok=4 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0