mirror of
https://github.com/valitydev/salt.git
synced 2024-11-09 01:36:48 +00:00
Merge remote branch 'upstream/develop' into debpackages
This commit is contained in:
commit
60e75873db
@ -226,6 +226,11 @@ def os_data():
|
||||
Return grains pertaining to the operating system
|
||||
'''
|
||||
grains = {}
|
||||
if 'os' in os.environ:
|
||||
if os.environ['os'].startswith('Windows'):
|
||||
grains['os'] = 'Windows'
|
||||
grains['kernel'] = 'Windows'
|
||||
return grains
|
||||
grains.update(_kernel())
|
||||
|
||||
if grains['kernel'] == 'Linux':
|
||||
|
@ -205,7 +205,7 @@ class Loader(object):
|
||||
log.info('Cython is enabled in options put not present '
|
||||
'on the system path. Skipping Cython modules.')
|
||||
for mod_dir in self.module_dirs:
|
||||
if not mod_dir.startswith('/'):
|
||||
if not os.path.isabs(mod_dir):
|
||||
continue
|
||||
if not os.path.isdir(mod_dir):
|
||||
continue
|
||||
@ -240,7 +240,7 @@ class Loader(object):
|
||||
mod.__grains__ = self.grains
|
||||
|
||||
if pack:
|
||||
if type(pack) == type(list()):
|
||||
if isinstance(pack, list):
|
||||
for chunk in pack:
|
||||
setattr(mod, chunk['name'], chunk['value'])
|
||||
else:
|
||||
@ -349,14 +349,14 @@ class Loader(object):
|
||||
if not key[key.index('.') + 1:] == 'core':
|
||||
continue
|
||||
ret = fun()
|
||||
if not type(ret) == type(dict()):
|
||||
if not isinstance(ret, dict):
|
||||
continue
|
||||
grains.update(ret)
|
||||
for key, fun in funcs.items():
|
||||
if key[key.index('.') + 1:] == 'core':
|
||||
continue
|
||||
ret = fun()
|
||||
if not type(ret) == type(dict()):
|
||||
if not isinstance(ret, dict):
|
||||
continue
|
||||
grains.update(ret)
|
||||
return grains
|
||||
|
@ -4,25 +4,25 @@ involves preparing the three listeners and the workers needed by the master.
|
||||
'''
|
||||
|
||||
# Import python modules
|
||||
import datetime
|
||||
import hashlib
|
||||
import logging
|
||||
import multiprocessing
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import tempfile
|
||||
import time
|
||||
import shutil
|
||||
import logging
|
||||
import hashlib
|
||||
import tempfile
|
||||
import datetime
|
||||
import multiprocessing
|
||||
|
||||
# Import zeromq
|
||||
from M2Crypto import RSA
|
||||
import zmq
|
||||
from M2Crypto import RSA
|
||||
|
||||
# Import salt modules
|
||||
import salt.client
|
||||
import salt.crypt
|
||||
import salt.payload
|
||||
import salt.utils
|
||||
import salt.client
|
||||
import salt.payload
|
||||
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
@ -106,7 +106,10 @@ class Master(SMaster):
|
||||
for jid in os.listdir(jid_root):
|
||||
if int(cur) - int(jid[:10]) > self.opts['keep_jobs']:
|
||||
shutil.rmtree(os.path.join(jid_root, jid))
|
||||
time.sleep(60)
|
||||
try:
|
||||
time.sleep(60)
|
||||
except KeyboardInterrupt:
|
||||
break
|
||||
|
||||
def start(self):
|
||||
'''
|
||||
@ -128,7 +131,13 @@ class Master(SMaster):
|
||||
aes_funcs,
|
||||
clear_funcs)
|
||||
reqserv.start_publisher()
|
||||
reqserv.run()
|
||||
|
||||
try:
|
||||
reqserv.run()
|
||||
except KeyboardInterrupt:
|
||||
# Shut the master down gracefully on SIGINT
|
||||
log.warn('Stopping the Salt Master')
|
||||
raise SystemExit('\nExiting on Ctrl-c')
|
||||
|
||||
|
||||
class Publisher(multiprocessing.Process):
|
||||
@ -137,7 +146,7 @@ class Publisher(multiprocessing.Process):
|
||||
commands.
|
||||
'''
|
||||
def __init__(self, opts):
|
||||
multiprocessing.Process.__init__(self)
|
||||
super(Publisher, self).__init__()
|
||||
self.opts = opts
|
||||
|
||||
def run(self):
|
||||
@ -155,10 +164,14 @@ class Publisher(multiprocessing.Process):
|
||||
pub_sock.bind(pub_uri)
|
||||
pull_sock.bind(pull_uri)
|
||||
|
||||
while True:
|
||||
package = pull_sock.recv()
|
||||
log.info('Publishing command')
|
||||
pub_sock.send(package)
|
||||
try:
|
||||
while True:
|
||||
package = pull_sock.recv()
|
||||
log.info('Publishing command')
|
||||
pub_sock.send(package)
|
||||
except KeyboardInterrupt:
|
||||
pub_sock.close()
|
||||
pull_sock.close()
|
||||
|
||||
|
||||
class ReqServer(object):
|
||||
@ -247,13 +260,16 @@ class MWorker(multiprocessing.Process):
|
||||
os.path.join(self.opts['sock_dir'], 'workers.ipc')
|
||||
)
|
||||
log.info('Worker binding to socket {0}'.format(w_uri))
|
||||
socket.connect(w_uri)
|
||||
try:
|
||||
socket.connect(w_uri)
|
||||
|
||||
while True:
|
||||
package = socket.recv()
|
||||
payload = self.serial.loads(package)
|
||||
ret = self.serial.dumps(self._handle_payload(payload))
|
||||
socket.send(ret)
|
||||
while True:
|
||||
package = socket.recv()
|
||||
payload = self.serial.loads(package)
|
||||
ret = self.serial.dumps(self._handle_payload(payload))
|
||||
socket.send(ret)
|
||||
except KeyboardInterrupt:
|
||||
socket.close()
|
||||
|
||||
def _handle_payload(self, payload):
|
||||
'''
|
||||
|
@ -8,6 +8,7 @@ import contextlib
|
||||
import glob
|
||||
import logging
|
||||
import multiprocessing
|
||||
import hashlib
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
@ -166,7 +167,7 @@ class Minion(object):
|
||||
self.functions, self.returners = self.__load_modules()
|
||||
|
||||
if self.opts['multiprocessing']:
|
||||
if type(data['fun']) == type(list()):
|
||||
if isinstance(data['fun'], list):
|
||||
multiprocessing.Process(
|
||||
target=lambda: self._thread_multi_return(data)
|
||||
).start()
|
||||
@ -175,7 +176,7 @@ class Minion(object):
|
||||
target=lambda: self._thread_return(data)
|
||||
).start()
|
||||
else:
|
||||
if type(data['fun']) == type(list()):
|
||||
if isinstance(data['fun'], list):
|
||||
threading.Thread(
|
||||
target=lambda: self._thread_multi_return(data)
|
||||
).start()
|
||||
@ -473,7 +474,7 @@ class Matcher(object):
|
||||
'''
|
||||
matcher = 'glob'
|
||||
for item in data:
|
||||
if type(item) == type(dict()):
|
||||
if isinstance(item, dict):
|
||||
if 'match' in item:
|
||||
matcher = item['match']
|
||||
if hasattr(self, matcher + '_match'):
|
||||
@ -631,6 +632,19 @@ class FileClient(object):
|
||||
self.socket.send(self.serial.dumps(payload))
|
||||
data = self.auth.crypticle.loads(self.serial.loads(self.socket.recv()))
|
||||
if not data['data']:
|
||||
if not fn_ and data['dest']:
|
||||
# This is a 0 byte file on the master
|
||||
dest = os.path.join(
|
||||
self.opts['cachedir'],
|
||||
'files',
|
||||
env,
|
||||
data['dest']
|
||||
)
|
||||
destdir = os.path.dirname(dest)
|
||||
if not os.path.isdir(destdir):
|
||||
os.makedirs(destdir)
|
||||
if not os.path.exists(dest):
|
||||
open(dest, 'w+').write(data['data'])
|
||||
break
|
||||
if not fn_:
|
||||
dest = os.path.join(
|
||||
@ -726,7 +740,19 @@ class FileClient(object):
|
||||
salt master file server prepend the path with salt://<file on server>
|
||||
otherwise, prepend the file with / for a local file.
|
||||
'''
|
||||
path = self._check_proto(path)
|
||||
try:
|
||||
path = self._check_proto(path)
|
||||
except MinionError:
|
||||
if not os.path.isfile(path):
|
||||
err = ('Specified file {0} is not present to generate '
|
||||
'hash').format(path)
|
||||
log.warning(err)
|
||||
return {}
|
||||
else:
|
||||
ret = {}
|
||||
ret['hsum'] = hashlib.md5(open(path, 'rb').read()).hexdigest()
|
||||
ret['hash_type'] = 'md5'
|
||||
return ret
|
||||
payload = {'enc': 'aes'}
|
||||
load = {'path': path,
|
||||
'env': env,
|
||||
|
@ -113,7 +113,7 @@ def set_fstab(
|
||||
salt '*' mount.set_fstab /mnt/foo /dev/sdz1 ext4
|
||||
'''
|
||||
# Fix the opts type if it is a list
|
||||
if type(opts) == type(list()):
|
||||
if isinstance(opts, list):
|
||||
opts = ','.join(opts)
|
||||
lines = []
|
||||
change = False
|
||||
@ -189,7 +189,7 @@ def mount(name, device, mkmnt=False, fstype='', opts='defaults'):
|
||||
|
||||
salt '*' mount.mount /mnt/foo /dev/sdz1 True
|
||||
'''
|
||||
if type(opts) == type(str()):
|
||||
if isinstance(opts, basestring):
|
||||
opts = opts.split(',')
|
||||
if not os.path.exists(name) and mkmnt:
|
||||
os.makedirs(name)
|
||||
@ -212,7 +212,7 @@ def remount(name, device, mkmnt=False, fstype='', opts='defaults'):
|
||||
|
||||
salt '*' mount.remount /mnt/foo /dev/sdz1 True
|
||||
'''
|
||||
if type(opts) == type(str()):
|
||||
if isinstance(opts, basestring):
|
||||
opts = opts.split(',')
|
||||
mnts = active()
|
||||
if name in mnts:
|
||||
|
@ -27,7 +27,7 @@ def add(name,
|
||||
|
||||
salt '*' user.add name <uid> <gid> <groups> <home> <shell>
|
||||
'''
|
||||
if type(groups) == type(str()):
|
||||
if isinstance(groups, basestring):
|
||||
groups = groups.split(',')
|
||||
cmd = 'pw useradd -s {0} '.format(shell)
|
||||
if uid:
|
||||
@ -169,7 +169,7 @@ def chgroups(name, groups, append=False):
|
||||
|
||||
salt '*' user.chgroups foo wheel,root True
|
||||
'''
|
||||
if type(groups) == type(str()):
|
||||
if isinstance(groups, basestring):
|
||||
groups = groups.split(',')
|
||||
ugrps = set(list_groups(name))
|
||||
if ugrps == set(groups):
|
||||
|
@ -112,10 +112,10 @@ def _get_none_or_value(value):
|
||||
'''
|
||||
if value is None:
|
||||
return None
|
||||
elif value:
|
||||
elif not value:
|
||||
return value
|
||||
# if it's a string, and it's not empty check for none
|
||||
elif type(value) == str:
|
||||
elif isinstance(value, basestring):
|
||||
if value.lower() == 'none':
|
||||
return None
|
||||
return value
|
||||
@ -333,11 +333,11 @@ def _merge_options(options):
|
||||
{option:boolean}
|
||||
'''
|
||||
defaults = __opts__['solr.dih.import_options']
|
||||
if type(options) == dict:
|
||||
if isinstance(options, dict):
|
||||
defaults.update(options)
|
||||
for (k,v) in defaults.items():
|
||||
if type(v) is bool:
|
||||
defaults[k] = str(bool(v)).lower()
|
||||
defaults[k] = str(v).lower()
|
||||
return defaults
|
||||
|
||||
def _pre_index_check(handler, host=None, core_name=None):
|
||||
@ -415,11 +415,11 @@ def _find_value(ret_dict, key, path=None):
|
||||
for (k, v) in ret_dict.items():
|
||||
if k == key:
|
||||
ret.append({path:v})
|
||||
if type(v) is list:
|
||||
if isinstance(v, list):
|
||||
for x in v:
|
||||
if type(x) is dict:
|
||||
if isinstance(x, dict):
|
||||
ret = ret + _find_value(x, key, path)
|
||||
if type(v) is dict:
|
||||
if isinstance(v, dict):
|
||||
ret = ret + _find_value(v, key, path)
|
||||
return ret
|
||||
|
||||
|
@ -26,7 +26,7 @@ def add(name,
|
||||
|
||||
salt '*' user.add name <uid> <gid> <groups> <home> <shell>
|
||||
'''
|
||||
if type(groups) == type(str()):
|
||||
if isinstance(groups, basestring):
|
||||
groups = groups.split(',')
|
||||
cmd = 'useradd -s {0} '.format(shell)
|
||||
if uid:
|
||||
@ -170,7 +170,7 @@ def chgroups(name, groups, append=False):
|
||||
|
||||
salt '*' user.chgroups foo wheel,root True
|
||||
'''
|
||||
if type(groups) == type(str()):
|
||||
if isinstance(groups, basestring):
|
||||
groups = groups.split(',')
|
||||
ugrps = set(list_groups(name))
|
||||
if ugrps == set(groups):
|
||||
|
@ -7,16 +7,13 @@ high data format for salt states.
|
||||
|
||||
import json
|
||||
import os
|
||||
from salt.utils.jinja import get_template
|
||||
|
||||
# Import Third Party libs
|
||||
from jinja2 import Template
|
||||
|
||||
|
||||
def render(template, env='', sls=''):
|
||||
def render(template_file, env='', sls=''):
|
||||
'''
|
||||
Render the data passing the functions and grains into the rendering system
|
||||
'''
|
||||
if not os.path.isfile(template):
|
||||
if not os.path.isfile(template_file):
|
||||
return {}
|
||||
|
||||
passthrough = {}
|
||||
@ -25,7 +22,8 @@ def render(template, env='', sls=''):
|
||||
passthrough['env'] = env
|
||||
passthrough['sls'] = sls
|
||||
|
||||
template = Template(open(template, 'r').read())
|
||||
template = get_template(template_file, __opts__, env)
|
||||
|
||||
json_data = template.render(**passthrough)
|
||||
|
||||
return json.loads(json_data)
|
||||
|
@ -6,17 +6,14 @@ high data format for salt states.
|
||||
'''
|
||||
|
||||
import os
|
||||
|
||||
# Import Third Party libs
|
||||
from jinja2 import Template
|
||||
import yaml
|
||||
from salt.utils.jinja import get_template
|
||||
|
||||
|
||||
def render(template, env='', sls=''):
|
||||
def render(template_file, env='', sls=''):
|
||||
'''
|
||||
Render the data passing the functions and grains into the rendering system
|
||||
'''
|
||||
if not os.path.isfile(template):
|
||||
if not os.path.isfile(template_file):
|
||||
return {}
|
||||
|
||||
passthrough = {}
|
||||
@ -25,7 +22,8 @@ def render(template, env='', sls=''):
|
||||
passthrough['env'] = env
|
||||
passthrough['sls'] = sls
|
||||
|
||||
template = Template(open(template, 'r').read())
|
||||
template = get_template(template_file, __opts__, env)
|
||||
|
||||
yaml_data = template.render(**passthrough)
|
||||
|
||||
return yaml.safe_load(yaml_data)
|
||||
|
@ -34,7 +34,7 @@ def returner(ret):
|
||||
col = db[ret['id']]
|
||||
back = {}
|
||||
|
||||
if type(ret['return']) == type(dict()):
|
||||
if isinstance(ret['return'], dict):
|
||||
for key in ret['return']:
|
||||
back[key.replace('.', '-')] = ret['return'][key]
|
||||
else:
|
||||
|
@ -29,19 +29,19 @@ def format_log(ret):
|
||||
Format the state into a log message
|
||||
'''
|
||||
msg = ''
|
||||
if type(ret) == type(dict()):
|
||||
if isinstance(ret, dict):
|
||||
# Looks like the ret may be a valid state return
|
||||
if 'changes' in ret:
|
||||
# Yep, looks like a valid state return
|
||||
chg = ret['changes']
|
||||
if not chg:
|
||||
msg = 'No changes made for {0[name]}'.format(ret)
|
||||
elif type(chg) == type(dict()):
|
||||
elif isinstance(chg, dict):
|
||||
if 'diff' in chg:
|
||||
if type(chg['diff']) == type(str()):
|
||||
if isinstance(chg['diff'], basestring):
|
||||
msg = 'File changed:\n{0}'.format(
|
||||
chg['diff'])
|
||||
if type(chg[chg.keys()[0]]) == type(dict()):
|
||||
if isinstance(chg[chg.keys()[0]], dict):
|
||||
if 'new' in chg[chg.keys()[0]]:
|
||||
# This is the return data from a package install
|
||||
msg = 'Installed Packages:\n'
|
||||
@ -319,9 +319,9 @@ class State(object):
|
||||
aspec = inspect.getargspec(self.states[ret['full']])
|
||||
arglen = 0
|
||||
deflen = 0
|
||||
if type(aspec[0]) == type(list()):
|
||||
if isinstance(aspec[0], list):
|
||||
arglen = len(aspec[0])
|
||||
if type(aspec[3]) == type(tuple()):
|
||||
if isinstance(aspec[3], tuple):
|
||||
deflen = len(aspec[3])
|
||||
kwargs = {}
|
||||
for ind in range(arglen - 1, 0, -1):
|
||||
@ -360,10 +360,10 @@ class State(object):
|
||||
funcs = set()
|
||||
names = set()
|
||||
for arg in run:
|
||||
if type(arg) == type(str()):
|
||||
if isinstance(arg, str):
|
||||
funcs.add(arg)
|
||||
continue
|
||||
if type(arg) == type(dict()):
|
||||
if isinstance(arg, dict):
|
||||
for key, val in arg.items():
|
||||
if key == 'names':
|
||||
names.update(val)
|
||||
@ -847,7 +847,7 @@ class HighState(object):
|
||||
if env not in matches:
|
||||
matches[env] = []
|
||||
for item in data:
|
||||
if type(item) == type(str()):
|
||||
if isinstance(item, basestring):
|
||||
matches[env].append(item)
|
||||
return matches
|
||||
|
||||
|
@ -21,6 +21,11 @@ makes use of the jinja templating system would look like this:
|
||||
- group: root
|
||||
- mode: 644
|
||||
- template: jinja
|
||||
- context:
|
||||
custom_var: "override"
|
||||
- defaults:
|
||||
custom_var: "default value"
|
||||
other_var: 123
|
||||
|
||||
Directories can be managed via the ``directory`` function. This function can
|
||||
create and enforce the permissions on a directory. A directory statement will
|
||||
@ -138,7 +143,7 @@ def _clean_dir(root, keep):
|
||||
return list(removed)
|
||||
|
||||
|
||||
def _mako(sfn, name, source, user, group, mode, env):
|
||||
def _mako(sfn, name, source, user, group, mode, env, context=None):
|
||||
'''
|
||||
Render a mako template, returns the location of the rendered file,
|
||||
return False if render fails.
|
||||
@ -154,7 +159,7 @@ def _mako(sfn, name, source, user, group, mode, env):
|
||||
'data': 'Failed to import jinja'}
|
||||
try:
|
||||
tgt = tempfile.mkstemp()[1]
|
||||
passthrough = {}
|
||||
passthrough = context if context else {}
|
||||
passthrough.update(__salt__)
|
||||
passthrough.update(__grains__)
|
||||
template = Template(open(sfn, 'r').read())
|
||||
@ -167,7 +172,7 @@ def _mako(sfn, name, source, user, group, mode, env):
|
||||
'data': trb}
|
||||
|
||||
|
||||
def _jinja(sfn, name, source, user, group, mode, env):
|
||||
def _jinja(sfn, name, source, user, group, mode, env, context=None):
|
||||
'''
|
||||
Render a jinja2 template, returns the location of the rendered file,
|
||||
return False if render fails.
|
||||
@ -177,13 +182,13 @@ def _jinja(sfn, name, source, user, group, mode, env):
|
||||
'data': <Error data or rendered file path>}
|
||||
'''
|
||||
try:
|
||||
from jinja2 import Template
|
||||
from salt.utils.jinja import get_template
|
||||
except ImportError:
|
||||
return {'result': False,
|
||||
'data': 'Failed to import jinja'}
|
||||
try:
|
||||
tgt = tempfile.mkstemp()[1]
|
||||
passthrough = {}
|
||||
passthrough = context if context else {}
|
||||
passthrough['salt'] = __salt__
|
||||
passthrough['grains'] = __grains__
|
||||
passthrough['name'] = name
|
||||
@ -192,7 +197,7 @@ def _jinja(sfn, name, source, user, group, mode, env):
|
||||
passthrough['group'] = group
|
||||
passthrough['mode'] = mode
|
||||
passthrough['env'] = env
|
||||
template = Template(open(sfn, 'r').read())
|
||||
template = get_template(sfn, __opts__, env)
|
||||
open(tgt, 'w+').write(template.render(**passthrough))
|
||||
return {'result': True,
|
||||
'data': tgt}
|
||||
@ -311,6 +316,8 @@ def managed(name,
|
||||
mode=None,
|
||||
template=None,
|
||||
makedirs=False,
|
||||
context=None,
|
||||
defaults=None,
|
||||
__env__='base'):
|
||||
'''
|
||||
Manage a given file, this function allows for a file to be downloaded from
|
||||
@ -346,6 +353,12 @@ def managed(name,
|
||||
the state will fail. If makedirs is set to True, then the parent
|
||||
directories will be created to facilitate the creation of the named
|
||||
file.
|
||||
|
||||
context
|
||||
Overrides default context variables passed to the template.
|
||||
|
||||
defaults
|
||||
Default context passed to the template.
|
||||
'''
|
||||
if mode:
|
||||
mode = str(mode)
|
||||
@ -360,6 +373,8 @@ def managed(name,
|
||||
sfn = __salt__['cp.cache_file'](source, __env__)
|
||||
t_key = '_{0}'.format(template)
|
||||
if t_key in globals():
|
||||
context_dict = defaults if defaults else {}
|
||||
if context: context_dict.update(context)
|
||||
data = globals()[t_key](
|
||||
sfn,
|
||||
name,
|
||||
@ -367,7 +382,8 @@ def managed(name,
|
||||
user,
|
||||
group,
|
||||
mode,
|
||||
__env__
|
||||
__env__,
|
||||
context_dict
|
||||
)
|
||||
else:
|
||||
ret['result'] = False
|
||||
|
@ -71,7 +71,7 @@ def mounted(
|
||||
|
||||
# Make sure that opts is correct, it can be a list or a comma delimited
|
||||
# string
|
||||
if type(opts) == type(str()):
|
||||
if isinstance(opts, basestring):
|
||||
opts = opts.split(',')
|
||||
|
||||
# Get the active data
|
||||
@ -79,7 +79,7 @@ def mounted(
|
||||
if name not in active:
|
||||
# The mount is not present! Mount it
|
||||
out = __salt__['mount.mount'](name, device, mkmnt, fstype, opts)
|
||||
if type(out) == type(str()):
|
||||
if isinstance(out, basestring):
|
||||
# Failed to remount, the state has failed!
|
||||
ret['comment'] = out
|
||||
ret['result'] = False
|
||||
|
76
salt/utils/jinja.py
Normal file
76
salt/utils/jinja.py
Normal file
@ -0,0 +1,76 @@
|
||||
from os import path
|
||||
from jinja2 import Template, BaseLoader, Environment
|
||||
from jinja2.loaders import split_template_path
|
||||
from jinja2.exceptions import TemplateNotFound
|
||||
import salt
|
||||
|
||||
def get_template(filename, opts, env):
|
||||
loader = SaltCacheLoader(opts, env)
|
||||
if filename.startswith(loader.searchpath):
|
||||
jinja = Environment(loader=loader)
|
||||
relpath = path.relpath(filename, loader.searchpath)
|
||||
# the template was already fetched
|
||||
loader.cached.append(relpath)
|
||||
return jinja.get_template(relpath)
|
||||
else:
|
||||
# fallback for templates outside the state tree
|
||||
return Template(open(filename, 'r').read())
|
||||
|
||||
class SaltCacheLoader(BaseLoader):
|
||||
'''
|
||||
A special jinja Template Loader for salt.
|
||||
Requested templates are always fetched from the server
|
||||
to guarantee that the file is up to date.
|
||||
Templates are cached like regular salt states
|
||||
and only loaded once per loader instance.
|
||||
'''
|
||||
def __init__(self, opts, env='base', encoding='utf-8'):
|
||||
self.opts = opts
|
||||
self.env = env
|
||||
self.encoding = encoding
|
||||
self.searchpath = path.join(opts['cachedir'], 'files', env)
|
||||
self._file_client = None
|
||||
self.cached = []
|
||||
|
||||
def file_client(self):
|
||||
'''
|
||||
Return a file client. Instantiates on first call.
|
||||
'''
|
||||
if not self._file_client:
|
||||
self._file_client = salt.minion.FileClient(self.opts)
|
||||
return self._file_client
|
||||
|
||||
def cache_file(self, template):
|
||||
'''
|
||||
Cache a file from the salt master
|
||||
'''
|
||||
saltpath = path.join('salt://', template)
|
||||
self.file_client().get_file(saltpath, '', True, self.env)
|
||||
|
||||
def check_cache(self, template):
|
||||
'''
|
||||
Cache a file only once
|
||||
'''
|
||||
if template not in self.cached:
|
||||
self.cache_file(template)
|
||||
self.cached.append(template)
|
||||
|
||||
def get_source(self, environment, template):
|
||||
# checks for relative '..' paths
|
||||
template = path.join(*split_template_path(template))
|
||||
self.check_cache(template)
|
||||
filepath = path.join(self.searchpath, template)
|
||||
try:
|
||||
f = open(filepath, 'rb')
|
||||
contents = f.read().decode(self.encoding)
|
||||
except IOError:
|
||||
raise TemplateNotFound(template)
|
||||
finally:
|
||||
f.close()
|
||||
mtime = path.getmtime(filepath)
|
||||
def uptodate():
|
||||
try:
|
||||
return path.getmtime(filepath) == mtime
|
||||
except OSError:
|
||||
return False
|
||||
return contents, filepath, uptodate
|
@ -14,4 +14,7 @@ def main():
|
||||
client.run()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
try:
|
||||
main()
|
||||
except KeyboardInterrupt:
|
||||
raise SystemExit('\nExiting gracefully on Ctrl-c')
|
||||
|
@ -15,4 +15,7 @@ def main():
|
||||
client.run()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
try:
|
||||
main()
|
||||
except KeyboardInterrupt:
|
||||
raise SystemExit('\nExiting gracefully on Ctrl-c')
|
||||
|
@ -14,4 +14,7 @@ def main():
|
||||
cp_.run()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
try:
|
||||
main()
|
||||
except KeyboardInterrupt:
|
||||
raise SystemExit('\nExiting gracefully on Ctrl-c')
|
||||
|
@ -14,4 +14,7 @@ def main():
|
||||
saltkey.run()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
try:
|
||||
main()
|
||||
except KeyboardInterrupt:
|
||||
raise SystemExit('\nExiting gracefully on Ctrl-c')
|
||||
|
@ -14,4 +14,7 @@ def main():
|
||||
client.run()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
try:
|
||||
main()
|
||||
except KeyboardInterrupt:
|
||||
raise SystemExit('\nExiting gracefully on Ctrl-c')
|
||||
|
Loading…
Reference in New Issue
Block a user