mirror of
https://github.com/valitydev/salt.git
synced 2024-11-07 08:58:59 +00:00
Merge pull request #26903 from bersace/fix-defaults-modules
Review defaults.get
This commit is contained in:
commit
c2efb291e2
@ -1,17 +1,20 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import absolute_import
|
||||
import inspect
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import yaml
|
||||
|
||||
import salt.fileclient
|
||||
import salt.utils
|
||||
import salt.ext.six as six
|
||||
|
||||
|
||||
__virtualname__ = 'defaults'
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _mk_client():
|
||||
'''
|
||||
Create a file client and add it to the context
|
||||
@ -21,34 +24,44 @@ def _mk_client():
|
||||
salt.fileclient.get_file_client(__opts__)
|
||||
|
||||
|
||||
def _get_files(pillar_name):
|
||||
def _load(formula):
|
||||
'''
|
||||
Generates a list of salt://<pillar_name>/defaults.(json|yaml) files
|
||||
Generates a list of salt://<formula>/defaults.(json|yaml) files
|
||||
and fetches them from the Salt master.
|
||||
|
||||
Returns first defaults file as python dict.
|
||||
'''
|
||||
|
||||
# Compute possibilities
|
||||
_mk_client()
|
||||
pillar_name = pillar_name.replace('.', '/')
|
||||
paths = []
|
||||
|
||||
for ext in ('yaml', 'json'):
|
||||
source_url = 'salt://{0}/{1}'.format(pillar_name, 'defaults.' + ext)
|
||||
source_url = 'salt://{0}/{1}'.format(formula, 'defaults.' + ext)
|
||||
paths.append(source_url)
|
||||
# Fetch files from master
|
||||
defaults_files = __context__['cp.fileclient'].cache_files(paths)
|
||||
|
||||
return __context__['cp.fileclient'].cache_files(paths)
|
||||
for file_ in defaults_files:
|
||||
if not file_:
|
||||
# Skip empty string returned by cp.fileclient.cache_files.
|
||||
continue
|
||||
|
||||
suffix = file_.rsplit('.', 1)[-1]
|
||||
if suffix == 'yaml':
|
||||
loader = yaml
|
||||
elif suffix == 'json':
|
||||
loader = json
|
||||
else:
|
||||
log.debug("Failed to determine loader for %r", file_)
|
||||
continue
|
||||
|
||||
def _load(defaults_path):
|
||||
'''
|
||||
Given a pillar_name and the template cache location, attempt to load
|
||||
the defaults.json from the cache location. If it does not exist, try
|
||||
defaults.yaml.
|
||||
'''
|
||||
for loader in json, yaml:
|
||||
defaults_file = os.path.join(defaults_path, 'defaults.' + loader.__name__)
|
||||
if os.path.exists(defaults_file):
|
||||
with salt.utils.fopen(defaults_file) as fhr:
|
||||
if os.path.exists(file_):
|
||||
log.debug("Reading defaults from %r", file_)
|
||||
with salt.utils.fopen(file_) as fhr:
|
||||
defaults = loader.load(fhr)
|
||||
return defaults
|
||||
log.debug("Read defaults %r", defaults)
|
||||
|
||||
return defaults or {}
|
||||
|
||||
|
||||
def get(key, default=''):
|
||||
@ -57,79 +70,30 @@ def get(key, default=''):
|
||||
a default value for a pillar from defaults.json or defaults.yaml
|
||||
files that are stored in the root of a salt formula.
|
||||
|
||||
When called from the CLI it works exactly like pillar.get.
|
||||
|
||||
CLI Example:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt '*' defaults.get core:users:root
|
||||
|
||||
When called from an SLS file, it works by first reading a defaults.json
|
||||
and second a defaults.yaml file. If the key exists in these files and
|
||||
does not exist in a pillar named after the formula, the value from the
|
||||
defaults file is used.
|
||||
The defaults is computed from pillar key. The first entry is considered as
|
||||
the formula namespace.
|
||||
|
||||
Example core/defaults.json file for the 'core' formula:
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"users": {
|
||||
"root": 0
|
||||
}
|
||||
}
|
||||
|
||||
With this, from a state file you can use salt['defaults.get']('users:root')
|
||||
to read the '0' value from defaults.json if a core:users:root pillar
|
||||
key is not defined.
|
||||
For example, querying ``core:users:root`` will try to load
|
||||
``salt://core/defaults.yaml`` and ``salt://core/defaults.json``.
|
||||
'''
|
||||
|
||||
sls = None
|
||||
tmplpath = None
|
||||
# Determine formula namespace from query
|
||||
if ':' in key:
|
||||
namespace, key = key.split(':', 1)
|
||||
else:
|
||||
namespace, key = key, None
|
||||
|
||||
for frame in inspect.stack():
|
||||
if sls is not None and tmplpath is not None:
|
||||
break
|
||||
# Fetch and load defaults formula files from states.
|
||||
defaults = _load(namespace)
|
||||
|
||||
frame_args = inspect.getargvalues(frame[0]).locals
|
||||
|
||||
for _sls in (
|
||||
None if not isinstance(frame_args.get('context'), dict) else frame_args.get('context').get('__sls__'),
|
||||
frame_args.get('mods', [None])[0],
|
||||
frame_args.get('sls')
|
||||
):
|
||||
if sls is not None:
|
||||
break
|
||||
sls = _sls
|
||||
|
||||
for _tmpl in (
|
||||
frame_args.get('tmplpath'),
|
||||
frame_args.get('tmplsrc')
|
||||
):
|
||||
if tmplpath is not None:
|
||||
break
|
||||
tmplpath = _tmpl
|
||||
|
||||
if not sls: # this is the case when called from CLI
|
||||
return __salt__['pillar.get'](key, default)
|
||||
|
||||
pillar_name = sls.split('.')[0]
|
||||
defaults_path = tmplpath.split(pillar_name)[0] + pillar_name
|
||||
|
||||
_get_files(pillar_name)
|
||||
|
||||
defaults = _load(defaults_path)
|
||||
|
||||
value = __salt__['pillar.get']('{0}:{1}'.format(pillar_name, key), None)
|
||||
|
||||
if value is None:
|
||||
value = salt.utils.traverse_dict_and_list(defaults, key, None)
|
||||
|
||||
if value is None:
|
||||
value = default
|
||||
|
||||
if isinstance(value, six.text_type):
|
||||
value = str(value)
|
||||
|
||||
return value
|
||||
# Fetch value
|
||||
if key:
|
||||
return salt.utils.traverse_dict_and_list(defaults, key, default)
|
||||
else:
|
||||
return defaults
|
||||
|
Loading…
Reference in New Issue
Block a user