Revert "Make possible to reference previous pillars from subsequent pillars, as they specified in the top file"

This commit is contained in:
Andrew Pashkin 2017-07-19 12:25:22 +03:00 committed by GitHub
parent 3e39526009
commit b0148c15c7
5 changed files with 37 additions and 182 deletions

View File

@ -263,51 +263,6 @@ Since both pillar SLS files contained a ``bind`` key which contained a nested
dictionary, the pillar dictionary's ``bind`` key contains the combined contents dictionary, the pillar dictionary's ``bind`` key contains the combined contents
of both SLS files' ``bind`` keys. of both SLS files' ``bind`` keys.
Referencing Other Pillars
=========================
.. versionadded:: Nitrogen
It is possible to reference pillar values that are defined in other
pillar files. To do this, place any pillar SLS files with referenced pillar
values *before* referencing SLS files in the Top file.
For example with such Top file:
.. code-block:: yaml
base:
'*':
- settings
- postgres
And such ``settings.sls`` file:
.. code-block:: yaml
db:
name: qux
user: baz
password: supersecret
Values from ``settings`` can be referenced from ``postgres`` like that:
.. code-block:: yaml
postgres:
users:
{{ salt['pillar.get']('db:user', 'bar') }}:
ensure: present
password: {{ salt['pillar.get']('db:password', 'secret') }}
databases:
{{ salt['pillar.get']('db:name', 'foo') }}:
owner: '{{ salt['pillar.get']('db:user', 'bar') }}'
template: 'template0'
lc_ctype: 'en_US.UTF-8'
lc_collate: 'en_US.UTF-8'
Including Other Pillars Including Other Pillars
======================= =======================

View File

@ -396,21 +396,6 @@ class Pillar(object):
envs.update(list(self.opts['file_roots'])) envs.update(list(self.opts['file_roots']))
return envs return envs
def __merge(self, *items):
'''
Merge 'items' according to Pillar's merge strategy and other options.
'''
return six.moves.reduce(
lambda a, b: merge(
a,
b,
self.merge_strategy,
self.opts.get('renderer', 'yaml'),
self.opts.get('pillar_merge_lists', False)
),
items
)
def get_tops(self): def get_tops(self):
''' '''
Gather the top files Gather the top files
@ -613,12 +598,10 @@ class Pillar(object):
env_matches.append(item) env_matches.append(item)
return matches return matches
def render_pstate(self, sls, saltenv, mods, renderers=None, defaults=None): def render_pstate(self, sls, saltenv, mods, defaults=None):
''' '''
Collect a single pillar sls file and render it Collect a single pillar sls file and render it
''' '''
if renderers is None:
renderers = self.rend
if defaults is None: if defaults is None:
defaults = {} defaults = {}
err = '' err = ''
@ -658,7 +641,7 @@ class Pillar(object):
state = None state = None
try: try:
state = compile_template(fn_, state = compile_template(fn_,
renderers, self.rend,
self.opts['renderer'], self.opts['renderer'],
self.opts['renderer_blacklist'], self.opts['renderer_blacklist'],
self.opts['renderer_whitelist'], self.opts['renderer_whitelist'],
@ -715,7 +698,12 @@ class Pillar(object):
key_fragment: nstate key_fragment: nstate
} }
state = self.__merge(state, nstate) state = merge(
state,
nstate,
self.merge_strategy,
self.opts.get('renderer', 'yaml'),
self.opts.get('pillar_merge_lists', False))
if err: if err:
errors += err errors += err
@ -726,10 +714,7 @@ class Pillar(object):
Extract the sls pillar files from the matches and render them into the Extract the sls pillar files from the matches and render them into the
pillar pillar
''' '''
pillar = self.__merge( pillar = copy.copy(self.pillar_override)
self.opts.get('pillar', {}),
self.pillar_override
)
if errors is None: if errors is None:
errors = [] errors = []
for saltenv, pstates in six.iteritems(matches): for saltenv, pstates in six.iteritems(matches):
@ -750,16 +735,7 @@ class Pillar(object):
pstatefiles.append(sls_match) pstatefiles.append(sls_match)
for sls in pstatefiles: for sls in pstatefiles:
opts = dict(self.opts, pillar=pillar) pstate, mods, err = self.render_pstate(sls, saltenv, mods)
utils = salt.loader.utils(opts)
functions = salt.loader.minion_mods(opts, utils=utils)
renderers = salt.loader.render(opts, functions)
pstate, mods, err = self.render_pstate(
sls,
saltenv,
mods,
renderers=renderers
)
if err: if err:
errors += err errors += err
@ -778,7 +754,12 @@ class Pillar(object):
) )
) )
continue continue
pillar = self.__merge(pillar, pstate) pillar = merge(
pillar,
pstate,
self.merge_strategy,
self.opts.get('renderer', 'yaml'),
self.opts.get('pillar_merge_lists', False))
return pillar, errors return pillar, errors
@ -840,7 +821,11 @@ class Pillar(object):
ext = None ext = None
# Bring in CLI pillar data # Bring in CLI pillar data
if self.pillar_override: if self.pillar_override:
pillar = self.__merge(pillar, self.pillar_override) pillar = merge(pillar,
self.pillar_override,
self.merge_strategy,
self.opts.get('renderer', 'yaml'),
self.opts.get('pillar_merge_lists', False))
for run in self.opts['ext_pillar']: for run in self.opts['ext_pillar']:
if not isinstance(run, dict): if not isinstance(run, dict):
@ -873,7 +858,12 @@ class Pillar(object):
key, ''.join(traceback.format_tb(sys.exc_info()[2])) key, ''.join(traceback.format_tb(sys.exc_info()[2]))
) )
if ext: if ext:
pillar = self.__merge(pillar, ext) pillar = merge(
pillar,
ext,
self.merge_strategy,
self.opts.get('renderer', 'yaml'),
self.opts.get('pillar_merge_lists', False))
ext = None ext = None
return pillar, errors return pillar, errors
@ -890,7 +880,11 @@ class Pillar(object):
self.rend = salt.loader.render(self.opts, self.functions) self.rend = salt.loader.render(self.opts, self.functions)
matches = self.top_matches(top) matches = self.top_matches(top)
pillar, errors = self.render_pillar(matches, errors=errors) pillar, errors = self.render_pillar(matches, errors=errors)
pillar = self.__merge(self.opts['pillar'], pillar) pillar = merge(self.opts['pillar'],
pillar,
self.merge_strategy,
self.opts.get('renderer', 'yaml'),
self.opts.get('pillar_merge_lists', False))
else: else:
matches = self.top_matches(top) matches = self.top_matches(top)
pillar, errors = self.render_pillar(matches) pillar, errors = self.render_pillar(matches)
@ -914,7 +908,11 @@ class Pillar(object):
pillar['_errors'] = errors pillar['_errors'] = errors
if self.pillar_override: if self.pillar_override:
pillar = self.__merge(pillar, self.pillar_override) pillar = merge(pillar,
self.pillar_override,
self.merge_strategy,
self.opts.get('renderer', 'yaml'),
self.opts.get('pillar_merge_lists', False))
decrypt_errors = self.decrypt_pillar(pillar) decrypt_errors = self.decrypt_pillar(pillar)
if decrypt_errors: if decrypt_errors:

View File

@ -1,9 +1 @@
sub: sub_minion sub: sub_minion
lowercase_knights:
{% for knight in pillar.get('knights') %}
- {{ knight|lower }}
{% endfor %}
uppercase_knights:
{% for knight in salt['pillar.get']('knights') %}
- {{ knight|upper }}
{% endfor %}

View File

@ -61,17 +61,3 @@ class PillarModuleTest(ModuleCase):
self.assertDictContainsSubset( self.assertDictContainsSubset(
{'knights': ['Lancelot', 'Galahad', 'Bedevere', 'Robin']}, {'knights': ['Lancelot', 'Galahad', 'Bedevere', 'Robin']},
get_items) get_items)
def test_referencing_preceding_pillars(self):
'''
Pillars, that come first in the top file can be referenced from
the subsequent pillars.
'''
items = self.run_function('pillar.items', minion_tgt='sub_minion')
self.assertDictContainsSubset(
{'lowercase_knights': ['lancelot', 'galahad',
'bedevere', 'robin'],
'uppercase_knights': ['LANCELOT', 'GALAHAD',
'BEDEVERE', 'ROBIN']},
items
)

View File

@ -22,82 +22,6 @@ import salt.pillar
@skipIf(NO_MOCK, NO_MOCK_REASON) @skipIf(NO_MOCK, NO_MOCK_REASON)
class PillarTestCase(TestCase): class PillarTestCase(TestCase):
def test_referencing_preceding_pillars(self):
'''
Pillars, that come first in the top file can be referenced from
the subsequent pillars.
'''
opts = {
'renderer': 'py',
'renderer_blacklist': [],
'renderer_whitelist': [],
'state_top': '',
'pillar_roots': [],
'file_roots': {},
'extension_modules': ''
}
grains = {
'os': 'Ubuntu',
'os_family': 'Debian',
'oscodename': 'raring',
'osfullname': 'Ubuntu',
'osrelease': '13.04',
'kernel': 'Linux'
}
pillar = salt.pillar.Pillar(opts, grains, 'mocked-minion', 'base')
top = tempfile.NamedTemporaryFile()
top.write(
b'''#!yaml
base:
'*':
- foo
- bar
'''
)
top.flush()
foo = tempfile.NamedTemporaryFile()
foo.write(
b'''#!py
def run():
return {'foo': {'spam': 'eggs'}}
'''
)
foo.flush()
bar = tempfile.NamedTemporaryFile()
bar.write(
b'''#!py
def run():
return {
'bar': {
'bacon': __pillar__.get('foo', {}).get('spam', 'cheddar'),
'sausage': __salt__['pillar.get']('foo:spam', 'cheddar')
}
}
'''
)
bar.flush()
def get_state(sls, env):
return {
'foo': {'path': '', 'dest': foo.name},
'bar': {'path': '', 'dest': bar.name}
}[sls]
pillar.client = MagicMock(**{
'get_state.side_effect': get_state,
'cache_file.return_value': top.name
})
pillar.matcher = MagicMock()
pillar.matcher.confirm_top.return_value = True
actual_pillar_data = pillar.compile_pillar()
expected_pillar_data = {
'foo': {'spam': 'eggs'},
'bar': {'bacon': 'eggs', 'sausage': 'eggs'}
}
self.assertEqual(actual_pillar_data, expected_pillar_data)
def tearDown(self): def tearDown(self):
for attrname in ('generic_file', 'generic_minion_file', 'ssh_file', 'ssh_minion_file', 'top_file'): for attrname in ('generic_file', 'generic_minion_file', 'ssh_file', 'ssh_minion_file', 'top_file'):