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

This commit is contained in:
Clint Savage 2012-08-02 09:51:18 -06:00
commit 034d2793ef
20 changed files with 156 additions and 103 deletions

7
debian/changelog vendored
View file

@ -1,3 +1,10 @@
salt (0.10.2) precise; urgency=low
* Non-maintainer upload.
* New upstream version
-- Dave Rawks <drawks@mint> Wed, 01 Aug 2012 13:34:10 -0700
salt (0.9.9) precise; urgency=low
* New upstream version

View file

@ -8,6 +8,11 @@ Node groups
A predefined group of minions declared in the master configuration file
:conf_master:`nodegroups` setting as a compound target.
Nodegroups are declared using a compound target specification. The compount
target documentation can be found here:
:doc:`Compound Matchers <topics/targeting/compound>`
For example, in the master config file :conf_master:`nodegroups` setting::
nodegroups:

View file

@ -264,6 +264,7 @@ def script(
else:
fn_ = __salt__['cp.cache_file'](source, env)
os.chmod(path, 320)
os.chown(path, __salt__['file.user_to_uid'](runas), -1)
ret = _run(
path,
cwd=cwd,

View file

@ -33,7 +33,8 @@ def usage(args=None):
cmd = 'df -kP'
else:
cmd = 'df'
cmd = cmd + ' -' + args
if args:
cmd = cmd + ' -' + args
ret = {}
out = __salt__['cmd.run'](cmd).split('\n')
for line in out:
@ -64,7 +65,8 @@ def inodeusage(args=None):
salt '*' disk.inodeusage
'''
cmd = 'df -i'
cmd = cmd + ' -' + args
if args is not None:
cmd = cmd + ' -' + args
ret = {}
out = __salt__['cmd.run'](cmd).split('\n')
for line in out:

View file

@ -24,6 +24,7 @@ Required python modules: MySQLdb
# Import Python libs
import time
import logging
import re
# Import third party libs
try:
@ -612,8 +613,8 @@ def __grant_generate(grant,
grant_option=False,
escape=True):
# todo: Re-order the grant so it is according to the SHOW GRANTS for xxx@yyy query (SELECT comes first, etc)
grant = grant.replace(',', ', ').upper()
grant = re.sub(r'\s*,\s*', ', ', grant).upper()
# MySQL normalizes ALL to ALL PRIVILEGES, we do the same so that
# grant_exists and grant_add ALL work correctly
if grant == 'ALL':
@ -693,7 +694,7 @@ def grant_add(grant,
CLI Example::
salt '*' mysql.grant_add 'SELECT|INSERT|UPDATE|...' 'database.*' 'frank' 'localhost'
salt '*' mysql.grant_add 'SELECT,INSERT,UPDATE,...' 'database.*' 'frank' 'localhost'
'''
# todo: validate grant
db = connect()

View file

@ -2,8 +2,8 @@
Install Python packages with pip to either the system or a virtualenv
'''
# Import python libs
import os
from salt.exceptions import CommandExecutionError
def _get_pip_bin(bin_env):
'''
@ -11,17 +11,14 @@ def _get_pip_bin(bin_env):
passed in, or from the global modules options
'''
if not bin_env:
pips = ['pip2',
'pip',
'pip-python']
return __salt__['cmd.which_bin'](pips)
else:
# try to get pip bin from env
if os.path.exists(os.path.join(bin_env, 'bin', 'pip')):
pip_bin = os.path.join(bin_env, 'bin', 'pip')
else:
pip_bin = bin_env
return pip_bin
return __salt__['cmd.which_bin'](['pip2', 'pip', 'pip-python'])
# try to get pip bin from env
if os.path.isdir(bin_env):
pip_bin = os.path.join(bin_env, 'bin', 'pip')
if os.path.isfile(pip_bin):
return pip_bin
return bin_env
def install(pkgs=None,
@ -68,7 +65,7 @@ def install(pkgs=None,
If installing into a virtualenv, just use the path to the virtualenv
(/home/code/path/to/virtualenv/)
env
depreicated, use bin_env now
deprecated, use bin_env now
log
Log file where a complete (maximum verbosity) record will be kept
proxy
@ -372,8 +369,14 @@ def freeze(bin_env=None,
salt '*' pip.freeze /home/code/path/to/virtualenv/
'''
cmd = '{0} freeze'.format(_get_pip_bin(bin_env))
pip_bin = _get_pip_bin(bin_env)
activate = os.path.join(os.path.dirname(pip_bin), 'activate')
if not os.path.isfile(activate):
raise CommandExecutionError(
"Could not find the path to the virtualenv's 'activate' binary"
)
cmd = 'source {0}; {1} freeze'.format(activate, pip_bin)
return __salt__['cmd.run'](cmd, runas=runas, cwd=cwd).split('\n')

View file

@ -52,7 +52,7 @@ _CONFIG_TRUE = ['yes', 'on', 'true', '1', True]
_CONFIG_FALSE = ['no', 'off', 'false', '0', False]
_IFACE_TYPES = [
'eth', 'bond', 'alias', 'clone',
'ipsec', 'dialup', 'slave', 'vlan',
'ipsec', 'dialup', 'bridge', 'slave', 'vlan',
]
@ -513,10 +513,11 @@ def _parse_settings_eth(opts, iface_type, enabled, iface):
if 'dns' in opts:
result['dns'] = opts['dns']
result['peernds'] = 'yes'
ethtool = _parse_ethtool_opts(opts, iface)
if ethtool:
result['ethtool'] = ethtool
if iface_type not in ['bridge']:
ethtool = _parse_ethtool_opts(opts, iface)
if ethtool:
result['ethtool'] = ethtool
if iface_type == 'slave':
result['proto'] = 'none'
@ -526,7 +527,7 @@ def _parse_settings_eth(opts, iface_type, enabled, iface):
if bonding:
result['bonding'] = bonding
if iface_type not in ['bond', 'vlan']:
if iface_type not in ['bond', 'vlan', 'bridge']:
if 'addr' in opts:
if _MAC_REGEX.match(opts['addr']):
result['addr'] = opts['addr']
@ -537,7 +538,31 @@ def _parse_settings_eth(opts, iface_type, enabled, iface):
if iface in ifaces and 'hwaddr' in ifaces[iface]:
result['addr'] = ifaces[iface]['hwaddr']
for opt in ['ipaddr', 'master', 'netmask', 'srcaddr']:
if iface_type == 'bridge':
result['devtype'] = 'Bridge'
bypassfirewall = True
valid = _CONFIG_TRUE + _CONFIG_FALSE
for opt in ['bypassfirewall']:
if opt in opts:
if opts[opt] in _CONFIG_TRUE:
bypassfirewall = True
elif opts[opt] in _CONFIG_FALSE:
bypassfirewall = False
else:
_raise_error_iface(iface, opts[opt], valid)
if bypassfirewall:
__salt__['sysctl.persist']('net.bridge.bridge-nf-call-ip6tables', '0')
__salt__['sysctl.persist']('net.bridge.bridge-nf-call-iptables', '0')
__salt__['sysctl.persist']('net.bridge.bridge-nf-call-arptables', '0')
else:
__salt__['sysctl.persist']('net.bridge.bridge-nf-call-ip6tables', '1')
__salt__['sysctl.persist']('net.bridge.bridge-nf-call-iptables', '1')
__salt__['sysctl.persist']('net.bridge.bridge-nf-call-arptables', '1')
else:
if 'bridge' in opts:
result['bridge'] = opts['bridge']
for opt in ['ipaddr', 'master', 'netmask', 'srcaddr', 'delay']:
if opt in opts:
result[opt] = opts[opt]
@ -612,13 +637,14 @@ def _parse_network_settings(opts, current):
else:
_raise_error_network('hostname', ['server1.example.com'])
if opts['nozeroconf'] in valid:
if opts['nozeroconf'] in _CONFIG_TRUE:
result['nozeroconf'] = 'true'
elif opts['nozeroconf'] in _CONFIG_FALSE:
result['nozeroconf'] = 'false'
else:
_raise_error_network('nozeroconf', valid)
if 'nozeroconf' in opts:
if opts['nozeroconf'] in valid:
if opts['nozeroconf'] in _CONFIG_TRUE:
result['nozeroconf'] = 'true'
elif opts['nozeroconf'] in _CONFIG_FALSE:
result['nozeroconf'] = 'false'
else:
_raise_error_network('nozeroconf', valid)
for opt in opts:
if opt not in ['networking', 'hostname', 'nozeroconf']:
@ -715,6 +741,9 @@ def build_interface(iface, iface_type, enabled, settings):
rh_major = __grains__['osrelease'][:1]
rh_minor = __grains__['osrelease'][2:]
iface = iface.lower()
iface_type = iface_type.lower()
if iface_type not in _IFACE_TYPES:
_raise_error_iface(iface, iface_type, _IFACE_TYPES)
@ -728,7 +757,10 @@ def build_interface(iface, iface_type, enabled, settings):
if iface_type == 'vlan':
settings['vlan'] = 'yes'
if iface_type in ['eth', 'bond', 'slave', 'vlan']:
if iface_type == 'bridge':
__salt__['pkg.install']('bridge-utils')
if iface_type in ['eth', 'bond', 'bridge', 'slave', 'vlan']:
opts = _parse_settings_eth(settings, iface_type, enabled, iface)
template = env.get_template('rh{0}_eth.jinja'.format(rh_major))
ifcfg = template.render(opts)

View file

@ -1,6 +1,6 @@
{% if networking %}NETWORKING={{networking}}
{%endif%}{% if hostname %}HOSTNAME={{hostname}}
{%endif%}{% if gateway %}GATEWAY={{gateway}}
{%endif%}{% if gatewaydev %}GATEWAYDEV={{gatewaydev}}{%endif%}
{%endif%}{% if nisdomain %}NISDOMAIN={{nisdomain}}{%endif%}
{%endif%}{% if gatewaydev %}GATEWAYDEV={{gatewaydev}}
{%endif%}{% if nisdomain %}NISDOMAIN={{nisdomain}}
{%endif%}{% if nozeroconf %}NOZEROCONF={{nozeroconf}}{%endif%}

View file

@ -4,6 +4,7 @@ DEVICE={{name}}
{%endif%}{% if master %}MASTER={{master}}
{%endif%}{% if slave %}SLAVE={{slave}}
{%endif%}{% if vlan %}VLAN={{vlan}}
{%endif%}{% if devtype %}TYPE={{devtype}}
{%endif%}{% if proto %}BOOTPROTO={{proto}}
{%endif%}{% if onboot %}ONBOOT={{onboot}}
{%endif%}{% if ipaddr %}IPADDR={{ipaddr}}
@ -11,6 +12,8 @@ DEVICE={{name}}
{%endif%}{% if gateway %}GATEWAY={{gateway}}
{%endif%}{% if srcaddr %}SRCADDR={{srcaddr}}
{%endif%}{% if peerdns %}PEERDNS={{peerdns}}
{%endif%}{% if bridge %}BRIDGE={{bridge}}
{%endif%}{% if delay %}DELAY={{delay}}
{%endif%}{%if bonding %}BONDING_OPTS="{%for item in bonding %}{{item}}={{bonding[item]}} {%endfor%}"
{%endif%}{% if ethtool %}ETHTOOL_OPTS="{%for item in ethtool %}{{item}} {{ethtool[item]}} {%endfor%}"
{%endif%}

View file

@ -4,6 +4,7 @@ DEVICE="{{name}}"
{%endif%}{% if master %}MASTER="{{master}}"
{%endif%}{% if slave %}SLAVE="{{slave}}"
{%endif%}{% if vlan %}VLAN="{{vlan}}"
{%endif%}{% if devtype %}TYPE="{{devtype}}"
{%endif%}{% if proto %}BOOTPROTO="{{proto}}"
{%endif%}{% if onboot %}ONBOOT="{{onboot}}"
{%endif%}{% if ipaddr %}IPADDR="{{ipaddr}}"
@ -11,6 +12,8 @@ DEVICE="{{name}}"
{%endif%}{% if gateway %}GATEWAY="{{gateway}}"
{%endif%}{% if srcaddr %}SRCADDR="{{srcaddr}}"
{%endif%}{% if peerdns %}PEERDNS="{{peerdns}}"
{%endif%}{% if bridge %}BRIDGE="{{bridge}}"
{%endif%}{% if delay %}DELAY="{{delay}}"
{%endif%}{%if bonding %}BONDING_OPTS="{%for item in bonding %}{{item}}={{bonding[item]}} {%endfor%}"
{%endif%}{% if ethtool %}ETHTOOL_OPTS="{%for item in ethtool %}{{item}} {{ethtool[item]}} {%endfor%}"
{%endif%}

View file

@ -5,7 +5,9 @@ Create virtualenv environments
from salt import utils
__opts__ = {}
__opts__ = {
'venv_bin': 'virtualenv'
}
__pillar__ = {}

View file

@ -315,12 +315,16 @@ def script(name,
'cwd': cwd,
'template': template})
# Changet the source to be the name arg if it is nto specified
run_check_cmd_kwargs = {'cwd': cwd,
'runas': user,
'shell': shell or __grains__['shell'], }
# Change the source to be the name arg if it is not specified
if source is None:
source = name
try:
cret = _run_check(cmd_kwargs, onlyif, unless, cwd, user, group, shell)
cret = _run_check(run_check_cmd_kwargs, onlyif, unless, cwd, user, group, shell)
if isinstance(cret, dict):
ret.update(cret)
return ret

View file

@ -112,10 +112,11 @@ def run(name, **kwargs):
except Exception:
ret['comment'] = 'Module function {0} threw an exception'.format(name)
ret['result'] = False
else:
ret['changes']['ret'] = mret
ret['comment'] = 'Module function {0} executed'.format(name)
ret['result'] = True
ret['changes']['ret'] = mret
return ret
mod_watch = run

View file

@ -41,6 +41,13 @@ supported. This module will therefore only work on RH/CentOS/Fedora.
- type: slave
- master: bond0
eth4:
network.managed:
- enabled: True
- type: eth
- proto: dhcp
- bridge: br0
bond0:
network.managed:
- type: bond
@ -114,6 +121,18 @@ supported. This module will therefore only work on RH/CentOS/Fedora.
- network: bond0
- require:
- network: bond0
br0:
network.managed:
- enabled: True
- type: bridge
- proto: dhcp
- bridge: br0
- delay: 0
- bypassfirewall: True
- use:
- network: eth4
- require:
- network: eth4
'''
import difflib

View file

@ -55,9 +55,13 @@ def present(name,
ret['result'] = None
ret['comment'] = 'User {0} is set to be created'.format(name)
return ret
if __salt__['postgres.user_create'](username=name, createdb=createdb,
createuser=createuser, encrypted=encrypted,
password=password, runas=runas):
if __salt__['postgres.user_create'](username=name,
createdb=createdb,
createuser=createuser,
encrypted=encrypted,
superuser=superuser,
password=password,
runas=runas):
ret['comment'] = 'The user {0} has been created'.format(name)
ret['changes'][name] = 'Present'
else:

View file

@ -421,6 +421,9 @@ def check_or_die(command):
Lazily import salt.modules.cmdmod to avoid any
sort of circular dependencies.
'''
if command is None:
raise CommandNotFoundError("'None' is not a valid command.")
import salt.modules.cmdmod
__salt__ = {'cmd.has_exec': salt.modules.cmdmod.has_exec}

View file

@ -36,27 +36,25 @@ class FileModuleTest(integration.ModuleCase):
group = 'staff'
elif sys.platform.startswith('linux'):
group = getpass.getuser()
ret = self.run_function('file.chown',
arg=[self.myfile, user, group])
ret = self.run_function('file.chown', arg=[self.myfile, user, group])
self.assertIsNone(ret)
fstat = os.stat(self.myfile)
self.assertTrue(fstat.st_uid, os.getuid())
self.assertTrue(fstat.st_gid, grp.getgrnam(group).gr_gid)
self.assertEqual(fstat.st_uid, os.getuid())
self.assertEqual(fstat.st_gid, grp.getgrnam(group).gr_gid)
@skipIf(sys.platform.startswith('win'), 'No chgrp on Windows')
def test_chown_no_user(self):
user = 'notanyuseriknow'
group = getpass.getuser()
ret = self.run_function('file.chown',
arg=[self.myfile, user, group])
ret = self.run_function('file.chown', arg=[self.myfile, user, group])
self.assertIn('not exist', ret)
@skipIf(sys.platform.startswith('win'), 'No chgrp on Windows')
def test_chown_no_user_no_group(self):
user = 'notanyuseriknow'
group = 'notanygroupyoushoulduse'
ret = self.run_function('file.chown',
arg=[self.myfile, user, group])
ret = self.run_function('file.chown', arg=[self.myfile, user, group])
self.assertIn('Group does not exist', ret)
self.assertIn('User does not exist', ret)
@ -75,12 +73,12 @@ class FileModuleTest(integration.ModuleCase):
def test_chown_noop(self):
user = ''
group = ''
ret = self.run_function('file.chown',
arg=[self.myfile, user, group])
ret = self.run_function('file.chown', arg=[self.myfile, user, group])
self.assertIsNone(ret)
fstat = os.stat(self.myfile)
self.assertTrue(fstat.st_uid, os.getuid())
self.assertTrue(fstat.st_gid, os.getgid())
self.assertEqual(fstat.st_uid, os.getuid())
self.assertEqual(fstat.st_gid, os.getgid())
@skipIf(sys.platform.startswith('win'), 'No chgrp on Windows')
def test_chgrp(self):
@ -88,17 +86,15 @@ class FileModuleTest(integration.ModuleCase):
group = 'everyone'
elif sys.platform.startswith('linux'):
group = getpass.getuser()
ret = self.run_function('file.chgrp',
arg=[self.myfile, group])
ret = self.run_function('file.chgrp', arg=[self.myfile, group])
self.assertIsNone(ret)
fstat = os.stat(self.myfile)
self.assertTrue(fstat.st_gid, grp.getgrnam(group).gr_gid)
self.assertEqual(fstat.st_gid, grp.getgrnam(group).gr_gid)
@skipIf(sys.platform.startswith('win'), 'No chgrp on Windows')
def test_chgrp_failure(self):
group = 'thisgroupdoesntexist'
ret = self.run_function('file.chgrp',
arg=[self.myfile, group])
ret = self.run_function('file.chgrp', arg=[self.myfile, group])
self.assertIn('not exist', ret)
def test_remove_file(self):
@ -112,7 +108,8 @@ class FileModuleTest(integration.ModuleCase):
def test_cannot_remove(self):
ret = self.run_function('file.remove', args=['/dev/tty'])
self.assertEqual(
'ERROR executing file.remove: File path must be absolute.', ret)
'ERROR executing file.remove: File path must be absolute.', ret
)
if __name__ == '__main__':
from integration import run_tests

View file

@ -1,28 +0,0 @@
# Import python libs
import integration
class PipModuleTest(integration.ModuleCase):
'''
Validate the pip module
'''
def setUp(self):
super(PipModuleTest, self).setUp()
ret = self.run_function(
'cmd.which_bin', [['pip2', 'pip', 'pip-python']]
)
if not ret:
self.skipTest("pip not installed")
def test_freeze(self):
'''
pip.freeze
'''
ret = self.run_function('pip.freeze')
self.assertIsInstance(ret, list)
self.assertGreater(len(ret), 1)
if __name__ == '__main__':
from integration import run_tests
run_tests(PipModuleTest)

View file

@ -26,27 +26,21 @@ class VirtualenvModuleTest(integration.ModuleCase):
def test_site_packages(self):
pip_bin = os.path.join(self.venv_dir, 'bin', 'pip')
self.run_function('virtualenv.create',
[self.venv_dir],
system_site_packages=True)
self.run_function(
'virtualenv.create', [self.venv_dir], system_site_packages=True
)
with_site = self.run_function('pip.freeze', bin_env=pip_bin)
self.run_function('file.remove', [self.venv_dir])
self.run_function('virtualenv.create',
[self.venv_dir])
self.run_function('virtualenv.create', [self.venv_dir])
without_site = self.run_function('pip.freeze', bin_env=pip_bin)
self.assertFalse(with_site == without_site)
def test_clear(self):
pip_bin = os.path.join(self.venv_dir, 'bin', 'pip')
self.run_function('virtualenv.create',
[self.venv_dir])
self.run_function('virtualenv.create', [self.venv_dir])
self.run_function('pip.install', [], pkgs='pep8', bin_env=pip_bin)
self.run_function('virtualenv.create',
[self.venv_dir],
clear=True)
packages = self.run_function('pip.list',
prefix='pep8',
bin_env=pip_bin)
self.run_function('virtualenv.create', [self.venv_dir], clear=True)
packages = self.run_function('pip.list', prefix='pep8', bin_env=pip_bin)
self.assertFalse('pep8' in packages)
def tearDown(self):

View file

@ -18,7 +18,7 @@ except ImportError:
TEST_DIR = os.path.dirname(os.path.normpath(os.path.abspath(__file__)))
PNUM = 50
PNUM = 70
def run_suite(opts, path, display_name, suffix='[!_]*.py'):