Closed glukinho closed 8 years ago
And if I remove srv1 from [sql_hosts] group and re-apply the playbook, I see my pbx rules applied on it instead of sql ones:
[root@srv1 filter.d]# iptables -L -n
Chain INPUT (policy DROP)
target prot opt source destination
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0 icmp type 8
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 multiport dports 10050,10051
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
ACCEPT udp -- 0.0.0.0/0 0.0.0.0/0 udp dpt:514
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:514
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:8080
ACCEPT udp -- 0.0.0.0/0 0.0.0.0/0 udp dpt:5060
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:5060
ACCEPT udp -- 0.0.0.0/0 0.0.0.0/0 multiport dports 10000:20000
ACCEPT udp -- 0.0.0.0/0 0.0.0.0/0 multiport dports 4000:4999
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:5029
Chain FORWARD (policy DROP)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0 icmp type 0
I understood ansible group variables inheritance mechanism, so for my expected behavior I have done that:
---
firewall_v4_group_rules_pbx:
300 allow sip and rtp:
- -A INPUT -p udp --dport 5060 -j ACCEPT
- -A INPUT -p tcp --dport 5060 -j ACCEPT
- -A INPUT -p udp --match multiport --dports 10000:20000 -j ACCEPT
301 allow T.38 UDPTL:
- -A INPUT -p udp --match multiport --dports 4000:4999 -j ACCEPT
302 allow voipmonitor sensor:
- -A INPUT -p tcp --dport 5029 -j ACCEPT
---
firewall_v4_group_rules_sql:
320 Allow Percona XtraDB Cluster ports:
- -A INPUT -p tcp --match multiport --dports 3306,4444,4567,4568 -j ACCEPT
321 allow mysql through haproxy:
- -A INPUT -p tcp --dport 13306 -j ACCEPT
#!/bin/sh
# {{ ansible_managed }}
{% set merged = firewall_v4_default_rules.copy() %}
{% set _ = merged.update(firewall_v4_group_rules) %}
{% set _ = merged.update(firewall_v4_group_rules_pbx) %} # here
{% set _ = merged.update(firewall_v4_group_rules_sql) %} # and here
{% set _ = merged.update(firewall_v4_host_rules) %}
...
After that, all my rules were applied:
[root@srv1 filter.d]# iptables -L -n
Chain INPUT (policy DROP)
target prot opt source destination
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0 icmp type 8
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 multiport dports 10050,10051
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
ACCEPT udp -- 0.0.0.0/0 0.0.0.0/0 udp dpt:514
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:514
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:8080
ACCEPT udp -- 0.0.0.0/0 0.0.0.0/0 udp dpt:5060
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:5060
ACCEPT udp -- 0.0.0.0/0 0.0.0.0/0 multiport dports 10000:20000
ACCEPT udp -- 0.0.0.0/0 0.0.0.0/0 multiport dports 4000:4999
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:5029
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 multiport dports 3306,4444,4567,4568
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:13306
...
Thinking how to manage this without hard-coding dictionary names in library code...
Another session of googling led me to the decision. All I had to do is to set
# if inventory variables overlap, does the higher precedence one win
# or are hash values merged together? The default is 'replace' but
# this can also be set to 'merge'.
hash_behaviour = merge
in ansible.cfg. All rules were applied as they should have been, in right order, without any trick with dictionary names.
Thanks to http://stackoverflow.com/questions/23525546/ansible-host-in-multiple-groups
I think you should include this important thing into the documentation.
@glukinho such settings can broke other roles, so i think change hash_behaviour a not so good idea.
I agree, but at least write about this issue and user will choose himself. Is it possible to have hash_behaviour defined on per role basis?
@glukinho from doc for Ansible 2.0 - "If you want to merge hashes without changing the global settings, use the combine filter described in Jinja2 filters"
Thanks. I'm on 1.9 now.
Hello guys and thanks for your interest in this role.
I think the overwrite is normal in this case. See this complete example given here: http://serverfault.com/questions/666457/ansible-a-host-appears-in-more-than-one-group-and-both-groups-have-the-same-ta
The problem here is that two "separate instances" of the firewall role is applied to the same host consecutively, with the last one overwriting the previous. Hence your results.
I suggest you re-organize your inventory so that a host appears only one time (is in a single group).
You could have pbx servers being children of webservers. I like to describe groups in my inventories to define the behavior as a whole of the hosts in that group.
See http://docs.ansible.com/ansible/intro_inventory.html for examples on how to define group hierarchies.
Hope this helps!
@mikegleasonjr thanks for the reply. In my case the role is applied once, but must be applied with the whole set of rules: default set for all hosts, each 'group' rule of all groups the host belongs to, and each 'host' rules created for the particular host (not in this my case, but in general), mixed between each other. This is because of my infrastructure when some servers have both PBX and DB functionality at the same time (and some don't), so iptables must allow both PBX ports (5060 + 10000:20000) and DB ports (3306 and some else). And I can't imagine how to reorganize my inventory to have only one host per group (BTW, ansible docs allow that possibility and I find it quite useful too) and stay flexible and easy to use.
Of course, I could have inventory like that:
[db_hosts]
srv3
[pbx_and_db_hosts]
srv1
srv2
and corresponding dictionaries in group_vars/ files. But I find it not flexible: I have to reorganize groups and group based rules in case of changing one server's functionality. This kills the whole idea of groups that can contain any hosts and intercept with another groups with sharing of functionality.
@glukinho Thanks for the feedback, can you provide an exemple of your playbook?
@mikegleasonjr It is very simple:
---
- hosts: all
roles:
- iptables # I renamed folder 'mikegleasonjr.firewall' to 'iptables'
This appies iptables rules according to groups membership of hosts.
@glukinho cool I'll have a look when I'll have my computer around and see what we can do!
Please reopen issue.
The link provided above explains the issue. Also, I found: https://github.com/ansible/ansible/issues/9065
I'll still see what can be done here for you, I'm still away from my computer right now... Stay tuned!
My solution with 'hash_behaviour = merge' satisfied me, after all :)
https://github.com/ansible/ansible/issues/9065#issuecomment-77695853
This comment sums up perfectly why Ansible is behaving that way...
Should we close the issue?
@mikegleasonjr i think we need update README with that info and update templates for asible 2.0 with combine jinja2 filter. This filter allow vars merging, so it will help without change hash_behaviour. Ansible developers dont recommend that.
@mightydok I can update the README to explain the "shortcomings" of Ansible in this particular scenario. Ansible 2.0 won't help here because the jinja2 filter will act on variables already constructed by Ansible.
If you carefully read the issue ansible/ansible#9065 (in particular this comment https://github.com/ansible/ansible/issues/9065#issuecomment-77695853), Ansible has a procedure to determine what the variable will hold at execution time. In this case the variable will already hold an "incorrect" value before even you'll have the chance to play with it. So having a jinja2 filter to merge dictionaries won't help.
Besides, I already use a dictionary merge function under the hood (the python method update) in the template file: https://github.com/mikegleasonjr/ansible-role-firewall/blob/master/templates/generated.v4.j2#L4
I'm really afraid that this is a matter related to Ansible.
I understand. In any case, I like how it works with 'hash_behaviour = merge' and it corresponds with my notion of groups and roles. I just wanted you to mention this issue in README. Thanks a lot,
@glukinho good news =). @mikegleasonjr i can view ansible code tomorrow, maybe will find cause of this problem.
Allright let's leave it open until we all agree or find a workaround!
Closing since this is the normal behaviour in Ansible, OP found a workaround to his problem and no one proposed something else.
Thank you
I have some group based rules:
1.ansible/group_vars/sql_hosts:
2.ansible/group_vars/pbx_hosts:
3.In 'ansible/hosts' file I have some servers intercepted between groups:
After applying playbook to all hosts I see only sql_hosts-based rules and not pbx_hosts-based:
I supposed I should have seen all rules I described in both files.