3
votes

I'm in a situation where I can't see the proper approach to use. I have multiple servers assigned various roles, distributed across several groups. I'm experiencing some difficulty with group_vars in my local Vagrant environment when contrasted with the production/staging environments. In production, there are a bunch more servers, that are assigned fewer groups. In my Vagrant environment, I have fewer machines that are assigned more roles/groups each. I have one machine in particular that is member of a bunch of groups, and each group has its own variable, "tcp_ports", which lists the ports that should be opened in my iptables role for servers that are members of that group. The problem is, of course, that Ansible will not automatically merge this variable across all group_vars.

My solution so far has been to rename the variable tcp_ports_<group name> and then, in my iptables role, I have the following task:

- name: Combine tcp_ports_<group> into tcp_ports
  set_fact:
    tcp_ports: "{{ tcp_ports|default([])|union(hostvars[inventory_hostname]['tcp_ports_' + item]|default([])) }}"
  with_items: "{{ group_names }}"

...which aggregates the tcp_vars_<group> group vars into tcp_ports for all the groups the current machine is member of. This works... but it feels dirty. I know about enabling merge mode in ansible.cfg, but this project is enormous, and I don't want to make such a fundamental change to Ansible's operation, because of the time consuming test phase of making sure things don't break. I've also read the mantra "fiddling with group_vars means you're doing it wrong," which I'm convinced I am... I just don't know how to do it right in this case.

Anyone out there fixed this in a more appropriate way?

1

1 Answers

5
votes

You can make iptables_config role and define supported service groups there like this:

service_ports:
  web:
    - 80
    - 443
  node:
    - 3000
  mysql:
    - 3128

and make rules like:

- debug: msg="allow port {{ item }}"
  with_items: "{{ group_names | intersect(service_ports.keys()) | map('extract',service_ports) | sum(start=[]) }}"

So when you apply role iptables_config, intersection of current host groups names and known services names is made and ports defined for these services are looped.