mirror of
https://github.com/valitydev/salt.git
synced 2024-11-07 00:55:19 +00:00
added support for order clauses in pillar top files
Conflicts: tests/unit/pillar_test.py
This commit is contained in:
parent
f0e7211893
commit
fafdfa1800
@ -15,6 +15,7 @@ import salt.crypt
|
||||
from salt._compat import string_types
|
||||
from salt.template import compile_template
|
||||
from salt.utils.dictupdate import update
|
||||
from salt.utils.odict import OrderedDict
|
||||
from salt.version import __version__
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
@ -209,25 +210,45 @@ class Pillar(object):
|
||||
Cleanly merge the top files
|
||||
'''
|
||||
top = collections.defaultdict(dict)
|
||||
orders = collections.defaultdict(dict)
|
||||
for ctops in tops.values():
|
||||
for ctop in ctops:
|
||||
for env, targets in ctop.items():
|
||||
if env == 'include':
|
||||
continue
|
||||
for tgt in targets:
|
||||
if tgt not in top[env]:
|
||||
top[env][tgt] = ctop[env][tgt]
|
||||
continue
|
||||
matches = []
|
||||
states = set()
|
||||
for comp in top[env][tgt]:
|
||||
orders[env][tgt] = 0
|
||||
for comp in ctop[env][tgt]:
|
||||
if isinstance(comp, dict):
|
||||
matches.append(comp)
|
||||
if 'match' in comp:
|
||||
matches.append(comp)
|
||||
if 'order' in comp:
|
||||
order = comp['order']
|
||||
if not isinstance(order, int):
|
||||
try:
|
||||
order = int(order)
|
||||
except ValueError:
|
||||
order = 0
|
||||
orders[env][tgt] = order
|
||||
if isinstance(comp, string_types):
|
||||
states.add(comp)
|
||||
top[env][tgt] = matches
|
||||
top[env][tgt].extend(list(states))
|
||||
return top
|
||||
return self.sort_top_targets(top, orders)
|
||||
|
||||
def sort_top_targets(self, top, orders):
|
||||
'''
|
||||
Returns the sorted high data from the merged top files
|
||||
'''
|
||||
sorted_top = collections.defaultdict(OrderedDict)
|
||||
for env, targets in top.items():
|
||||
sorted_targets = sorted(targets.keys(),
|
||||
key=lambda target: orders[env][target])
|
||||
for target in sorted_targets:
|
||||
sorted_top[env][target] = targets[target]
|
||||
return sorted_top
|
||||
|
||||
def get_top(self):
|
||||
'''
|
||||
|
@ -8,6 +8,8 @@
|
||||
:license: Apache 2.0, see LICENSE for more details.
|
||||
'''
|
||||
|
||||
import tempfile
|
||||
|
||||
# Import Salt Testing libs
|
||||
from salttesting import skipIf, TestCase
|
||||
from salttesting.helpers import ensure_in_syspath
|
||||
@ -103,3 +105,74 @@ class PillarTestCase(TestCase):
|
||||
pillar.render_pillar({'base': ['foo.sls']}),
|
||||
({'foo': 'bar2'}, [])
|
||||
)
|
||||
|
||||
@patch('salt.pillar.salt.fileclient.get_file_client', autospec=True)
|
||||
@patch('salt.pillar.salt.minion.Matcher', autospec=True)
|
||||
def test_topfile_order(self, Matcher, get_file_client):
|
||||
opts = {
|
||||
'renderer': 'yaml',
|
||||
'state_top': '',
|
||||
'pillar_roots': [],
|
||||
'extension_modules': '',
|
||||
'environment': 'base',
|
||||
}
|
||||
grains = {
|
||||
'os': 'Ubuntu',
|
||||
'os_family': 'Debian',
|
||||
'oscodename': 'raring',
|
||||
'osfullname': 'Ubuntu',
|
||||
'osrelease': '13.04',
|
||||
'kernel': 'Linux'
|
||||
}
|
||||
# glob match takes precedence
|
||||
self._setup_test_topfile_mocks(Matcher, get_file_client, 1, 2)
|
||||
pillar = salt.pillar.Pillar(opts, grains, 'mocked-minion', 'base')
|
||||
self.assertEqual(pillar.compile_pillar()['ssh'], 'bar')
|
||||
# nodegroup match takes precedence
|
||||
self._setup_test_topfile_mocks(Matcher, get_file_client, 2, 1)
|
||||
pillar = salt.pillar.Pillar(opts, grains, 'mocked-minion', 'base')
|
||||
self.assertEqual(pillar.compile_pillar()['ssh'], 'foo')
|
||||
|
||||
def _setup_test_topfile_mocks(self, Matcher, get_file_client,
|
||||
nodegroup_order, glob_order):
|
||||
# Write a simple topfile and two pillar state files
|
||||
self.top_file = tempfile.NamedTemporaryFile()
|
||||
self.top_file.write('''
|
||||
base:
|
||||
group:
|
||||
- match: nodegroup
|
||||
- order: {nodegroup_order}
|
||||
- ssh
|
||||
minion:
|
||||
- order: {glob_order}
|
||||
- ssh.minion
|
||||
'''.format(nodegroup_order=nodegroup_order, glob_order=glob_order))
|
||||
self.top_file.flush()
|
||||
self.ssh_file = tempfile.NamedTemporaryFile()
|
||||
self.ssh_file.write('''
|
||||
ssh:
|
||||
foo
|
||||
''')
|
||||
self.ssh_file.flush()
|
||||
self.ssh_minion_file = tempfile.NamedTemporaryFile()
|
||||
self.ssh_minion_file.write('''
|
||||
ssh:
|
||||
bar
|
||||
''')
|
||||
self.ssh_minion_file.flush()
|
||||
|
||||
# Setup Matcher mock
|
||||
matcher = Matcher.return_value
|
||||
matcher.confirm_top.return_value = True
|
||||
|
||||
# Setup fileclient mock
|
||||
client = get_file_client.return_value
|
||||
client.cache_file.return_value = self.top_file.name
|
||||
|
||||
def get_state(sls, env):
|
||||
return {
|
||||
'ssh': {'path': '', 'dest': self.ssh_file.name},
|
||||
'ssh.minion': {'path': '', 'dest': self.ssh_minion_file.name},
|
||||
}[sls]
|
||||
|
||||
client.get_state.side_effect = get_state
|
||||
|
Loading…
Reference in New Issue
Block a user