-
Notifications
You must be signed in to change notification settings - Fork 37
/
groupvars.py
113 lines (98 loc) · 3.96 KB
/
groupvars.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
import ansible.inventory
from ansiblereview import Result, Error
from ansible.errors import AnsibleError
import inspect
import os
try:
import ansible.parsing.dataloader
from ansible.vars.manager import VariableManager
ANSIBLE = 2
except ImportError:
try:
from ansible.vars.manager import VariableManager
ANSIBLE = 2
except ImportError:
ANSIBLE = 1
_vars = dict()
_inv = None
def get_group_vars(group, inventory):
try:
from ansible.inventory.helpers import get_group_vars
return get_group_vars(inventory.groups.values())
except ImportError:
pass
# http://stackoverflow.com/a/197053
vars = inspect.getargspec(inventory.get_group_vars)
if 'return_results' in vars[0]:
return inventory.get_group_vars(group, return_results=True)
else:
return inventory.get_group_vars(group)
def remove_inherited_and_overridden_vars(vars, group, inventory):
if group not in _vars:
_vars[group] = get_group_vars(group, inventory)
gv = _vars[group]
for (k, v) in vars.items():
if k in gv:
if gv[k] == v:
vars.pop(k)
else:
gv.pop(k)
def remove_inherited_and_overridden_group_vars(group, inventory):
if group not in _vars:
_vars[group] = get_group_vars(group, inventory)
for ancestor in group.get_ancestors():
remove_inherited_and_overridden_vars(_vars[group], ancestor, inventory)
def same_variable_defined_in_competing_groups(candidate, options):
result = Result(candidate.path)
# assume that group_vars file is under an inventory *directory*
invfile = os.path.dirname(os.path.dirname(candidate.path))
global _inv
try:
if ANSIBLE > 1:
loader = ansible.parsing.dataloader.DataLoader()
try:
from ansible.inventory.manager import InventoryManager
inv = _inv or InventoryManager(loader=loader, sources=invfile)
except ImportError:
var_manager = VariableManager()
inv = _inv or ansible.inventory.Inventory(loader=loader,
variable_manager=var_manager,
host_list=invfile)
_inv = inv
else:
inv = _inv or ansible.inventory.Inventory(invfile)
_inv = inv
except AnsibleError as e:
result.errors = [Error(None, "Inventory is broken: %s" % e.message)]
return result
if hasattr(inv, 'groups'):
group = inv.groups.get(os.path.basename(candidate.path))
else:
group = inv.get_group(os.path.basename(candidate.path))
if not group:
# group file exists in group_vars but no related group
# in inventory directory
return result
remove_inherited_and_overridden_group_vars(group, inv)
group_vars = set(_vars[group].keys())
child_hosts = group.hosts
child_groups = group.child_groups
siblings = set()
for child_host in child_hosts:
siblings.update(child_host.groups)
for child_group in child_groups:
siblings.update(child_group.parent_groups)
for sibling in siblings:
if sibling != group:
remove_inherited_and_overridden_group_vars(sibling, inv)
sibling_vars = set(_vars[sibling].keys())
common_vars = sibling_vars & group_vars
common_hosts = [host.name for host in set(child_hosts) & set(sibling.hosts)]
if common_vars and common_hosts:
for var in common_vars:
error_msg_template = "Sibling groups {0} and {1} with common hosts {2} " + \
"both define variable {3}"
error_msg = error_msg_template.format(group.name, sibling.name,
", ".join(common_hosts), var)
result.errors.append(Error(None, error_msg))
return result