Permalink
Browse files

Merge branch 'develop' of https://github.com/saltstack/salt into develop

  • Loading branch information...
2 parents bb2a466 + 3feb8e8 commit a06f5f9f8e5319136cdff17dc3c76fdc4eaaa067 @trane trane committed Mar 20, 2012
Showing with 133 additions and 33 deletions.
  1. +26 −17 salt/modules/cmdmod.py
  2. +4 −8 salt/modules/file.py
  3. +16 −3 salt/modules/linux_sysctl.py
  4. +72 −0 salt/state.py
  5. +15 −5 salt/states/file.py
@@ -141,7 +141,7 @@ def run(cmd, cwd=None, runas=None, shell=DEFAULT_SHELL, env=()):
'''
out = _run(cmd, runas=runas, shell=shell,
cwd=cwd, stderr=subprocess.STDOUT, env=env)['stdout']
- log.debug(out)
+ log.debug('output: {0}'.format(out))
return out
@@ -154,7 +154,7 @@ def run_stdout(cmd, cwd=None, runas=None, shell=DEFAULT_SHELL, env=()):
salt '*' cmd.run_stdout "ls -l | awk '/foo/{print $2}'"
'''
stdout = _run(cmd, runas=runas, cwd=cwd, shell=shell, env=())["stdout"]
- log.debug(stdout)
+ log.debug('stdout: {0}'.format(stdout))
return stdout
@@ -167,7 +167,7 @@ def run_stderr(cmd, cwd=None, runas=None, shell=DEFAULT_SHELL, env=()):
salt '*' cmd.run_stderr "ls -l | awk '/foo/{print $2}'"
'''
stderr = _run(cmd, runas=runas, cwd=cwd, shell=shell, env=env)["stderr"]
- log.debug(stderr)
+ log.debug('stderr: {0}'.format(stderr))
return stderr
@@ -181,13 +181,20 @@ def run_all(cmd, cwd=None, runas=None, shell=DEFAULT_SHELL, env=()):
'''
ret = _run(cmd, runas=runas, cwd=cwd, shell=shell, env=env)
if ret['retcode'] != 0:
- log.error('Command {0} failed'.format(cmd))
- log.error('retcode: {0}'.format(ret['retcode']))
- log.error('stdout: {0}'.format(ret['stdout']))
- log.error('stderr: {0}'.format(ret['stderr']))
+ rcode = ret['retcode']
+ msg = 'Command \'{0}\' failed with return code: {1}'
+ log.error(msg.format(cmd, rcode))
+ # Don't log a blank line if there is no stderr or stdout
+ if ret['stdout']:
+ log.error('stdout: {0}'.format(ret['stdout']))
+ if ret['stderr']:
+ log.error('stderr: {0}'.format(ret['stderr']))
else:
- log.info('stdout: {0}'.format(ret['stdout']))
- log.info('stderr: {0}'.format(ret['stderr']))
+ # No need to always log output on success to the logs
+ if ret['stdout']:
+ log.debug('stdout: {0}'.format(ret['stdout']))
+ if ret['stderr']:
+ log.debug('stderr: {0}'.format(ret['stderr']))
return ret
@@ -202,25 +209,27 @@ def retcode(cmd, cwd=None, runas=None, shell=DEFAULT_SHELL, env=()):
return _run(cmd, runas=runas, cwd=cwd, shell=shell, env=env)['retcode']
-def has_exec(cmd):
+def which(cmd):
'''
- Returns true if the executable is available on the minion, false otherwise
+ Returns the path of an executable available on the minion, None otherwise
CLI Example::
- salt '*' cmd.has_exec cat
+ salt '*' cmd.which cat
'''
- return bool(salt.utils.which(cmd))
+ return salt.utils.which(cmd)
-def which(cmd):
+
+def has_exec(cmd):
'''
- Returns the path of an executable available on the minion, None otherwise
+ Returns true if the executable is available on the minion, false otherwise
CLI Example::
- salt '*' cmd.which cat
+ salt '*' cmd.has_exec cat
'''
- return salt.utils.which(cmd)
+ return bool(which(cmd))
+
def exec_code(lang, code, cwd=None):
'''
View
@@ -20,18 +20,14 @@ def __virtual__():
'''
Only work on posix-like systems
'''
-
- # Disable on these platforms, specific file modules exist:
- disable = [
- 'Windows',
- ]
- if __grains__['os'] in disable:
+ # win_file takes care of windows
+ if __grains__['os'] == 'Windows':
return False
return 'file'
-
+
__outputter__ = {
- 'touch': 'txt',
+ 'touch': 'txt',
'append': 'txt',
}
@@ -8,6 +8,7 @@
__outputter__ = {
'assign': 'txt',
+ 'get': 'txt',
}
@@ -106,9 +107,21 @@ def persist(name, value, config='/etc/sysctl.conf'):
if '=' not in line:
nlines.append(line)
continue
- comps = line.split('=')
- comps[0] = comps[0].strip()
- comps[1] = comps[1].strip()
+
+ # Strip trailing whitespace and split the k,v
+ comps = [i.strip() for i in line.split('=', 1)]
+
+ # On Linux procfs, files such as /proc/sys/net/ipv4/tcp_rmem or any
+ # other sysctl with whitespace in it consistently uses 1 tab. Lets
+ # allow our users to put a space or tab between multi-value sysctls
+ # and have salt not try to set it every single time.
+ if isinstance(comps[1], basestring) and ' ' in comps[1]:
+ comps[1] = re.sub('\s+', '\t', comps[1])
+
+ # Do the same thing for the value 'just in case'
+ if isinstance(value, basestring) and ' ' in value:
+ value = re.sub('\s+', '\t', value)
+
if len(comps) < 2:
nlines.append(line)
continue
View
@@ -591,6 +591,78 @@ def reconcile_extend(self, high):
high[name][state].append(arg)
return high, errors
+ def requisite_in(self, high):
+ '''
+ Extend the data reference with requisite_in arguments
+ '''
+ req_in = set(['require_in', 'watch_in'])
+ extend = {}
+ for id_, body in high.items():
+ for state, run in body.items():
+ if state.startswith('__'):
+ continue
+ for arg in run:
+ if isinstance(arg, dict):
+ # It is not a function, verify that the arg is a
+ # requisite in statement
+ if len(arg) < 1:
+ # Empty arg dict
+ # How did we get this far?
+ continue
+ # Split out the components
+ key = arg.keys()[0]
+ if not key in req_in:
+ continue
+ rkey = key[:-3]
+ items = arg[key]
+ if isinstance(items, dict):
+ # Formated as a single req_in
+ for _state, name in items.items():
+ found = False
+ if not name in extend:
+ extend[name] = {}
+ if not _state in extend[name]:
+ extend[name][_state] = []
+ for ind in range(len(extend[name][_state])):
+ if extend[name][_state][ind].keys()[0] == rkey:
+ # Extending again
+ extend[name][_state][ind].append(
+ {state: id_}
+ )
+ found = True
+ if found:
+ continue
+ # The rkey is not present yet, create it
+ extend[name][_state].append(
+ {rkey: [{state: id_}]}
+ )
+ if isinstance(items, list):
+ # Formed as a list of requisite additions
+ for ind in items:
+ if not isinstance(ind, dict):
+ # Malformed req_in
+ continue
+ if len(ind) < 1:
+ continue
+ _state = ind.keys()[0]
+ name = ind[_state]
+ found = False
+ for ind in range(len(extend[name][_state])):
+ if extend[name][_state][ind].keys()[0] == rkey:
+ # Extending again
+ extend[name][_state][ind].append(
+ {state: id_}
+ )
+ found = True
+ if found:
+ continue
+ # The rkey is not present yet, create it
+ extend[name][_state].append(
+ {rkey: [{state: id_}]}
+ )
+ high['__extend__'] = extend
+ return self.reconcile_extend(high)
+
def call(self, data):
'''
Call a state directly with the low data structure, verify data
View
@@ -761,19 +761,29 @@ def managed(name,
else:
__clean_tmp(sfn)
return _error(ret, 'Parent directory not present')
- # Create the file, user-rw-only if mode will be set
+
+ # Create the file, user rw-only if mode will be set to prevent
+ # a small security race problem before the permissions are set
if mode:
- cumask = os.umask(384)
+ current_umask = os.umask(077)
+
+ # Create a new file when test is False and source is None
+ if not __opts__['test']:
+ if __salt__['file.touch'](name):
+ ret['changes']['new'] = 'file {0} created'.format(name)
+ ret['comment'] = 'Empty file'
+ else:
+ return _error(ret, 'Empty file {0} not created'.format(name))
+
if mode:
- os.umask(cumask)
- ret['changes']['new'] = 'file {0} created'.format(name)
- ret['comment'] = 'Empty file'
+ os.umask(current_umask)
# Now copy the file contents if there is a source file
if sfn:
shutil.copyfile(sfn, name)
__clean_tmp(sfn)
+ # Check and set the permissions if necessary
ret, perms = _check_perms(name, ret, user, group, mode)
if not ret['comment']:

0 comments on commit a06f5f9

Please sign in to comment.