@@ -1,6 +1,6 @@
====================
Opening the Firewall
====================
================================
Opening the Firewall up for Salt
================================

The Salt master communicates with the minions using an AES-encrypted ZeroMQ
connection. These communications are done over ports 4505 and 4506, which need
@@ -25,11 +25,11 @@ some of the more common locations, but your mileage may vary.

**Arch Linux** ::

/etc/iptables/iptables.ruls
/etc/iptables/iptables.rules

**Debian/Ubuntu** ::
**Debian**

???
Follow these instructions: http://wiki.debian.org/iptables

Once you've found your firewall rules, you'll need to add the two lines below
to allow traffic on ``tcp/4505`` and ``tcp/4506``:
@@ -39,6 +39,15 @@ to allow traffic on ``tcp/4505`` and ``tcp/4506``:
+ -A INPUT -m state --state new -m tcp -p tcp --dport 4505 -j ACCEPT
+ -A INPUT -m state --state new -m tcp -p tcp --dport 4506 -j ACCEPT

**Ubuntu**

Create a file named ``/etc/ufw/applications.d/salt-master`` ::

[Salt Master]
title=Salt master
description=Salt is a remote execution and configuration management tool.
ports=4205,4206/tcp

pf.conf
=======

@@ -5,26 +5,25 @@ How Do I Use Salt States?
Simplicity, Simplicity, Simplicity

Many of the most powerful and useful engineering solutions are founded on
simple principals, the Salt SLS system strives to do just that.
simple principals, the Salt SLS system strives to do just that. K.I.S.S.

The core of the Salt State system is the SLS, or the SaLt State file. The SLS
is a representation of the state in which a system should be in, and is set up
to contain this data in the most simple way possible.
to contain this data simply. This is often called configuration management.

It is All Just Data
===================

Before delving into the particulars, it will help to understand that the SLS
is just a data structure under the hood. While understanding that the SLS is
just a data structure is not at all critical to understand to make use Salt States,
it should help bolster the understanding of where the real power is.
just a data structure is not at all critical to understand to make use Salt
States, it should help bolster the understanding of where the real power is.

SLS files are therefore, in reality, just dictionaries, lists, strings and
numbers. By using this approach Salt can be much more flexible, and as someone
writes more SLS files it becomes clear exactly what is being written. The result
is a system that is easy to understand, yet grows with the needs of the admin
or developer, offering simple constructs that grow to encompass the most
complicated needs.
numbers. By using this approach Salt can be much more flexible. As someone
writes more state files, it becomes clear exactly what is being written. The
result is a system that is easy to understand, yet grows with the needs of
the admin or developer.

In the section titled "State Data Structures" a reference exists, explaining
in depth how the data is laid out.
@@ -35,7 +34,7 @@ Default Data - YAML
By default Salt represents the SLS data in what is one of the simplest
serialization formats available - YAML.

A typical, small SLS file will often look like this in YAML:
A typical SLS file will often look like this in YAML:

.. code-block:: yaml
:linenos:
@@ -63,14 +62,14 @@ lines are the function to run. This function defines what state the named
package and service should be in. Here the package is to be installed, and
the service should be running.

Finally, on line 6, is the word ``require``, this is called a Requisite
Statement, and it makes sure that the apache service is only started after
Finally, on line 6, is the word ``require``. This is called a Requisite
Statement, and it makes sure that the Apache service is only started after
the successful installation of the apache package.

Adding Configs and Users
========================

When setting up a service like an apache server many more components may
When setting up a service like an apache web server, many more components may
need to be added. The apache configuration file will most likely be managed,
and a user and group may need to be set up.

@@ -130,14 +129,14 @@ config file will also trigger a restart of the respective service.
Moving Beyond a Single SLS
==========================

When setting up Salt States more than one SLS will need to be used, the above
When setting up Salt States, more than one SLS will need to be used. The above
examples were just in a single SLS file, but more than one SLS file can be
combined to build out a State Tree. The above example also references a file
with a strange source - salt://apache/httpd.conf, that file will need to be
available as well.
with a strange source - ``salt://apache/httpd.conf``. That file will need to
be available as well.

The SLS files are laid out in a directory on the salt master. Files are laid
out as just files, an sls is just a file and files to download are just files.
out as just files. A sls is just a file and files to download are just files.

The apache example would be laid out in the root of the salt file server like
this: ::
@@ -268,7 +267,7 @@ These examples will add more watchers to apache and change the ssh banner.
pkg:
- installed
The custom-server.sls file uses the extend statement to overwrite where the
The ``custom-server.sls`` file uses the extend statement to overwrite where the
banner is being downloaded from, and therefore changing what file is being used
to configure the banner.

@@ -298,18 +297,18 @@ python or ``py`` renderer. The ``py`` renderer allows for SLS files to be
written in pure python, allowing for the utmost level of flexibility and
power when preparing SLS data.

Geting to Know the Default - yaml_jinja
---------------------------------------
Getting to Know the Default - yaml_jinja
----------------------------------------

The default renderer - ``yaml_jinja``, allows for the use of the jinja
templating system. A guide to the jinja templating system can be found here:
<link to the jinga templating docs page>.
http://jinja.pocoo.org/docs

When working with renderers a few very useful bits of data are passed in. In
the case of templating engine based renderers two critical components are
available, ``salt`` and ``grains``. The salt object allows for any salt
function to be called from within the template, and grains allows for the
grains to be accessed from within the template. A few examples are in order:
available, ``salt``, ``grains``, and ``pillar``. The salt object allows for
any salt function to be called from within the template, and grains allows for
the grains to be accessed from within the template. A few examples:

``/apache/init.sls:``

@@ -353,7 +352,7 @@ grains to be accessed from within the template. A few examples are in order:
- group: root
- mode: 644
This example is simple, if the os grain states that the operating system is
This example is simple. If the ``os`` grain states that the operating system is
Red Hat, then the name of the apache package and service needs to be httpd.

A more aggressive way to use Jinja can be found here, in a module to set up
@@ -453,7 +452,7 @@ This is a very simple example, the first line has a SLS shebang line that
tells Salt to not use the default renderer, but to use the ``py`` renderer.
Then the run function is defined, the return value from the run function
must be a Salt friendly data structure, or better known as a Salt
``HighState`` data structure.
:doc:`HighState data structure</ref/states/highstate>`.

This python example would look like this if it were written in YAML:

@@ -471,3 +470,4 @@ This clearly illustrates, that not only is using the YAML renderer a wise
decision as the default, but that unbridled power can be obtained where
needed by using a pure python SLS.

Now onto the :doc:`States tutorial, part 1</topics/tutorials/states_pt1>`.
@@ -49,7 +49,7 @@ Using Grains in SLS modules
===========================

Often times a state will need to behave differently on different systems.
:doc:`Salt grains </ref/grains>` can be used from within sls modules. An object
:doc:`Salt grains </topics/targeting/grains>` can be used from within sls modules. An object
called ``grains`` is made available in the template context:

.. code-block:: yaml
@@ -208,7 +208,7 @@ def __parse(self):
# Catch invalid invocations of salt such as: salt run
if len(args) <= 1:
parser.print_help()
parser.exit()
parser.exit(1)

if opts['list']:
opts['tgt'] = args[0].split(',')
@@ -457,9 +457,10 @@ def __parse(self):
if v is not None:
opts[k] = v

# salt-cp needs arguments
if len(args) <= 1:
parser.print_help()
parser.exit()
parser.exit(1)

if opts['list']:
opts['tgt'] = args[0].split(',')
@@ -635,7 +636,8 @@ def __parse(self):
'''
Parse the command line arguments
'''
parser = optparse.OptionParser(version="%%prog %s" % VERSION)
usage = "%prog [options] <function> [arguments]"
parser = optparse.OptionParser(version='%%prog %s'.format(VERSION), usage=usage)

parser.add_option('-g',
'--grains',
@@ -710,8 +712,9 @@ def __parse(self):
opts['fun'] = args[0]
opts['arg'] = args[1:]
else:
opts['fun'] = ''
opts['arg'] = []
# salt-call should not ever be called without arguments
parser.print_help()
parser.exit(1)

verify_env([opts['pki_dir'],
opts['cachedir'],
@@ -51,7 +51,7 @@ def call(self):
sys.stderr.write(msg.format(fun, str(exc)))
sys.exit(1)
except CommandNotFoundError as exc:
msg = 'Command not found in \'{0}\': {1}\n'
msg = 'Command required for \'{0}\' not found: {1}\n'
sys.stderr.write(msg.format(fun, str(exc)))
sys.exit(1)
if hasattr(self.minion.functions[fun], '__outputter__'):
@@ -240,7 +240,7 @@ def _thread_return(self, data):
args, kw = salt.state.build_args(func, data['arg'], data)
ret['return'] = func(*args, **kw)
except CommandNotFoundError as exc:
msg = 'Command not found in \'{0}\': {1}'
msg = 'Command required for \'{0}\' not found: {1}'
log.debug(msg.format(function_name, str(exc)))
ret['return'] = msg.format(function_name, str(exc))
except CommandExecutionError as exc:
@@ -3,6 +3,7 @@
'''

import os
from salt import utils

def _git_getdir(cwd, user=None):
'''
@@ -18,14 +19,31 @@ def _git_getdir(cwd, user=None):
cmd_toplvl = 'git rev-parse --show-toplevel'
return __salt__['cmd.run'](cmd_toplvl, cwd)

def _check_git():
utils.check_or_die('git')

def revision(cwd, rev='HEAD', short=False, user=None):
'''
Returns the long hash of a given identifier (hash, branch, tag, HEAD, etc)
Usage::
cwd
The path to the Git repository
rev: HEAD
The revision
short: False
Return an abbreviated SHA1 git hash
user : None
Run git as a user other than what the minion runs as
CLI Example::
salt '*' git.revision /path/to/repo mybranch
'''
_check_git()

cmd = 'git rev-parse {0}{1}'.format('--short ' if short else '', rev)
result = __salt__['cmd.run_all'](cmd, cwd, runas=user)

@@ -38,14 +56,28 @@ def clone(cwd, repository, opts=None, user=None):
'''
Clone a new repository
Usage::
cwd
The path to the Git repository
repository
The git uri of the repository
opts : None
Any additional options to add to the command line
user : None
Run git as a user other than what the minion runs as
CLI Example::
salt '*' git.clone /path/to/repo git://github.com/saltstack/salt.git
salt '*' git.clone /path/to/repo.git\\
git://github.com/saltstack/salt.git '--bare --origin github'
'''
_check_git()

if not opts:
opts = ''
cmd = 'git clone {0} {1} {2}'.format(repository, cwd, opts)
@@ -56,21 +88,50 @@ def describe(cwd, rev='HEAD', user=None):
'''
Returns the git describe string (or the SHA hash if there are no tags) for
the given revision
cwd
The path to the Git repository
rev: HEAD
The revision to describe
user : None
Run git as a user other than what the minion runs as
'''
cmd = 'git describe {0}'.format(rev)
return __salt__['cmd.run_stdout'](cmd, cwd=cwd, runas=user)

def archive(cwd, output, rev='HEAD', fmt='', prefix='', user=None):
def archive(cwd, output, rev='HEAD', fmt=None, prefix=None, user=None):
'''
Export a tarball from the repository
cwd
The path to the Git repository
output
The path to the archive tarball
rev: HEAD
The revision to create an archive from
fmt: None
Format of the resulting archive, zip and tar are commonly used
prefix : None
Prepend <prefix>/ to every filename in the archive
user : None
Run git as a user other than what the minion runs as
If ``prefix`` is not specified it defaults to the basename of the repo
directory.
Usage::
CLI Example::
salt '*' git.archive /path/to/repo /path/to/archive.tar.gz
'''
_check_git()

basename = '{0}/'.format(os.path.basename(_git_getdir(cwd, user=user)))

cmd = 'git archive{prefix}{fmt} -o {output} {rev}'.format(
@@ -85,10 +146,23 @@ def fetch(cwd, opts=None, user=None):
'''
Perform a fetch on the given repository
Usage::
cwd
The path to the Git repository
opts : None
Any additional options to add to the command line
user : None
Run git as a user other than what the minion runs as
CLI Example::
salt '*' git.fetch /path/to/repo '--all'
salt '*' git.fetch cwd=/path/to/repo opts='--all' user=johnny
'''
_check_git()

if not opts:
opts = ''
cmd = 'git fetch {0}'.format(opts)
@@ -99,26 +173,82 @@ def pull(cwd, opts=None, user=None):
'''
Perform a pull on the given repository
Usage::
cwd
The path to the Git repository
salt '*' git.pull /path/to/repo '--rebase origin master'
opts : None
Any additional options to add to the command line
user : None
Run git as a user other than what the minion runs as
CLI Example::
salt '*' git.pull /path/to/repo opts='--rebase origin master'
'''
_check_git()

if not opts:
opts = ''
return __salt__['cmd.run']('git pull {0}'.format(opts), cwd=cwd, runas=user)

def rebase(cwd, rev='master', opts=None, user=None):
'''
Rebase the current branch
cwd
The path to the Git repository
rev : master
The revision to rebase onto the current branch
opts : None
Any additional options to add to the command line
user : None
Run git as a user other than what the minion runs as
CLI Example::
salt '*' git.rebase /path/to/repo master
That is the same as: git rebase master
'''
_check_git()

if not opts:
opts = ''
return __salt__['cmd.run']('git rebase {0}'.format(opts), cwd=cwd, runas=user)

def checkout(cwd, rev, force=False, opts=None, user=None):
'''
Checkout a given revision
Usage::
cwd
The path to the Git repository
rev
The remote branch or revision to checkout
force : False
Force a checkout even if there might be overwritten changes
opts : None
Any additional options to add to the command line
user : None
Run git as a user other than what the minion runs as
CLI Examples::
salt '*' git.checkout /path/to/repo somebranch user=jeff
salt '*' git.checkout /path/to/repo opts='testbranch -- conf/file1 file2'
salt '*' git.checkout /path/to/repo 'origin/mybranch --track'
salt '*' git.checkout /path/to/repo rev=origin/mybranch opts=--track
'''
_check_git()

if not opts:
opts = ''
cmd = 'git checkout {0} {1} {2}'.format(' -f' if force else '', rev, opts)
@@ -130,16 +260,23 @@ def merge(cwd, branch='@{upstream}', opts=None, user=None):
cwd
The path to the Git repository
branch : @{upstream}
The remote branch or revision to merge into the current branch
opts : (none)
opts : None
Any additional options to add to the command line
Usage::
user : None
Run git as a user other than what the minion runs as
CLI Example::
salt '*' git.fetch /path/to/repo
salt '*' git.merge /path/to/repo @{upstream}
'''
_check_git()

if not opts:
opts = ''
cmd = 'git merge {0}{1} {2}'.format(
@@ -150,11 +287,22 @@ def merge(cwd, branch='@{upstream}', opts=None, user=None):

def init(cwd, opts=None, user=None):
'''
Init a new repository
Initialize a new git repository
cwd
The path to the Git repository
opts : None
Any additional options to add to the command line
Usage::
user : None
Run git as a user other than what the minion runs as
salt '*' git.init /path/to/repo.git '--bare'
CLI Example::
salt '*' git.init /path/to/repo.git opts='--bare'
'''
_check_git()

cmd = 'git init {0} {1}'.format(cwd, opts)
return __salt__['cmd.run'](cmd, runas=user)
@@ -2,86 +2,185 @@
Support for the Mercurial SCM
'''

def revision(cwd, rev='tip', short=False):
from salt import utils

__outputter__ = {
'clone': 'txt',
'revision': 'txt',
}

def _check_hg():
utils.check_or_die('hg')

def revision(cwd, rev='tip', short=False, user=None):
'''
Returns the long hash of a given identifier (hash, branch, tag, HEAD, etc)
Usage::
cwd
The path to the Mercurial repository
rev: tip
The revision
short: False
Return an abbreviated commit hash
user : None
Run hg as a user other than what the minion runs as
CLI Example::
salt '*' hg.revision /path/to/repo mybranch
'''
cmd = 'hg id -i{short} {ref}'.format(
_check_hg()

cmd = 'hg id -i{short} {rev}'.format(
short = ' --debug' if not short else '',
rev = ' -r {0}'.format(rev))

result = __salt__['cmd.run_all'](cmd, cwd=cwd)
result = __salt__['cmd.run_all'](cmd, cwd=cwd, runas=user)

if result['retcode'] == 0:
return result['stdout'].strip('\n')
return result['stdout']
else:
return ''

def describe(cwd, rev='tip'):
def describe(cwd, rev='tip', user=None):
'''
Mimick git describe and return an identifier for the given revision
Usage::
cwd
The path to the Mercurial repository
rev: tip
The path to the archive tarball
user : None
Run hg as a user other than what the minion runs as
CLI Example::
salt '*' hg.describe /path/to/repo
'''
_check_hg()

cmd = "hg log -r {0} --template"\
" '{{latesttag}}-{{latesttagdistance}}-{{node|short}}'".format(rev)
desc = __salt__['cmd.run_stdout'](cmd, cwd=cwd)
desc = __salt__['cmd.run_stdout'](cmd, cwd=cwd, runas=user)

return desc or revision(cwd, rev, short=True)

def archive(cwd, output, rev='tip', fmt='', prefix=''):
def archive(cwd, output, rev='tip', fmt=None, prefix=None, user=None):
'''
Export a tarball from the repository
cwd
The path to the Mercurial repository
output
The path to the archive tarball
rev: tip
The revision to create an archive from
fmt: None
Format of the resulting archive. Mercurial supports: tar,
tbz2, tgz, zip, uzip, and files formats.
prefix : None
Prepend <prefix>/ to every filename in the archive
user : None
Run hg as a user other than what the minion runs as
If ``prefix`` is not specified it defaults to the basename of the repo
directory.
Usage::
CLI Example::
salt '*' hg.archive /path/to/repo /path/to/archive.tar.gz
salt '*' hg.archive /path/to/repo output=/tmp/archive.tgz fmt=tgz
'''
_check_hg()

cmd = 'hg archive {output}{rev}{fmt}'.format(
rev = ' --rev {0}'.format(rev),
output = output,
fmt = ' --type {0}'.format(fmt) if fmt else '',
prefix = ' --prefix "{0}"'.format(prefix if prefix else ''))

return __salt__['cmd.run'](cmd, cwd=cwd)
return __salt__['cmd.run'](cmd, cwd=cwd, runas=user)

def pull(cwd, opts=''):
def pull(cwd, opts=None, user=None):
'''
Perform a pull on the given repository
Usage::
cwd
The path to the Mercurial repository
opts : None
Any additional options to add to the command line
user : None
Run hg as a user other than what the minion runs as
CLI Example::
salt '*' hg.pull /path/to/repo '-u'
'''
return __salt__['cmd.run']('hg pull {0}'.format(opts), cwd=cwd)
_check_hg()

if not opts:
opts = ''
return __salt__['cmd.run']('hg pull {0}'.format(opts), cwd=cwd, runas=user)

def update(cwd, rev, force=False):
def update(cwd, rev, force=False, user=None):
'''
Checkout a given revision
Update to a given revision
cwd
The path to the Mercurial repository
rev
The revision to update to
Usage::
force : False
Force an update
salt '*' hg.update /path/to/repo somebranch
user : None
Run hg as a user other than what the minion runs as
CLI Example::
salt devserver1 hg.update /path/to/repo somebranch
'''
_check_hg()

cmd = 'hg update {0}{1}'.format(rev, ' -C' if force else '')
return __salt__['cmd.run'](cmd, cwd=cwd)
return __salt__['cmd.run'](cmd, cwd=cwd, runas=user)

def clone(cwd, repository, opts=''):
def clone(cwd, repository, opts=None, user=None):
'''
Clone a new repository
Usage::
cwd
The path to the Mercurial repository
repository
The hg uri of the repository
opts : None
Any additional options to add to the command line
user : None
Run hg as a user other than what the minion runs as
CLI Example::
salt '*' hg.clone /path/to/repo https://bitbucket.org/birkenfeld/sphinx
'''
_check_hg()

if not opts:
opts = ''
cmd = 'hg clone {0} {1} {2}'.format(repository, cwd, opts)
return __salt__['cmd.run'](cmd)
return __salt__['cmd.run'](cmd, runas=user)
@@ -2,7 +2,7 @@
Execute puppet routines
'''

from salt.exceptions import CommandNotFoundError
from salt import utils

__outputter__ = {
'run': 'txt',
@@ -18,13 +18,13 @@ def _check_puppet():
# I thought about making this a virtual module, but then I realized that I
# would require the minion to restart if puppet was installed after the
# minion was started, and that would be rubbish
return __salt__['cmd.has_exec']('puppetd')
utils.check_or_die('puppetd')

def _check_facter():
'''
Checks if facter is installed
'''
return __salt__['cmd.has_exec']('facter')
utils.check_or_die('facter')

def _format_fact(output):
try:
@@ -49,8 +49,7 @@ def run(tags=None):
salt '*' puppet.run basefiles::edit,apache::server
'''
if not _check_puppet():
raise CommandNotFoundError('puppetd not available')
_check_puppet()

if not tags:
cmd = 'puppetd --test'
@@ -71,8 +70,7 @@ def noop(tags=None):
salt '*' puppet.noop web::server,django::base
'''
if not _check_puppet():
raise CommandNotFoundError('puppetd not available')
_check_puppet()

if not tags:
cmd = 'puppetd --test --noop'
@@ -89,8 +87,7 @@ def facts():
salt '*' puppet.facts
'''
if not _check_facter():
raise CommandNotFoundError('facter not available')
_check_facter()

ret = {}
output = __salt__['cmd.run']('facter')
@@ -114,8 +111,7 @@ def fact(name):
salt '*' puppet.fact kernel
'''
if not _check_facter():
raise CommandNotFoundError('facter not available')
_check_facter()

ret = __salt__['cmd.run']('facter {0}'.format(name))
if not ret:
@@ -89,7 +89,7 @@ def cross_test(func, args=None):

def kwarg(**kwargs):
'''
Print out the data passed into the function **kwargs, this is used to
Print out the data passed into the function ``**kwargs``, this is used to
both test the publication data and cli kwarg passing, but also to display
the information available within the publication data.
@@ -8,7 +8,7 @@

import os
import re
from salt.exceptions import CommandNotFoundError
from salt import utils


def __virtual__():
@@ -80,8 +80,7 @@ def status(name, sig=None):

def _get_service_exec():
executable = 'update-rc.d'
if not __salt__['cmd.has_exec'](executable):
raise CommandNotFoundError('Missing {0}'.format(executable))
utils.check_or_die(executable)
return executable


@@ -1,7 +1,7 @@
'''
Create virtualenv environments
'''
from salt.exceptions import CommandNotFoundError
from salt import utils


__opts__ = {
@@ -51,9 +51,8 @@ def create(path,
salt '*' pip.virtualenv /path/to/new/virtualenv
'''
if not __salt__['cmd.has_exec'](venv_bin):
raise CommandNotFoundError(
"Please install {venv_bin}".format(venv_bin=venv_bin))
# raise CommandNotFoundError if venv_bin is missing
utils.check_or_die(venv_bin)

cmd = '{venv_bin} {args} {path}'.format(
venv_bin=venv_bin,
@@ -1,11 +1,11 @@
'''
Module for gathering disk information on Windows
'''
is_windows = True
try:
import ctypes
import string
import win32api
is_windows = True
except ImportError:
is_windows = False

@@ -37,24 +37,24 @@ def usage():
try:
sectorspercluster, bytespersector, freeclusters, totalclusters =\
win32api.GetDiskFreeSpace('{0}:\\'.format(drive))
totalsize = sectorspercluster * bytespersector * totalclusters
available_space = sectorspercluster * bytespersector * freeclusters
totalsize = sectorspercluster * bytespersector * totalclusters
available_space = sectorspercluster * bytespersector * freeclusters
used = totalsize - available_space
capacity = int(used / float(totalsize) * 100)
ret['{0}:\\'.format(drive)] = {
'filesystem': '{0}:\\'.format(drive),
'1K-blocks': totalsize,
'used': used,
'1K-blocks': totalsize,
'used': used,
'available': available_space,
'capacity': '{0}%'.format(capacity),
}
except:
ret['{0}:\\'.format(drive)] = {
'filesystem': '{0}:\\'.format(drive),
'1K-blocks': None,
'used': None,
'1K-blocks': None,
'used': None,
'available': None,
'capacity': None,
'capacity': None,
}
return ret

@@ -12,101 +12,101 @@
.. code-block:: yaml
rvm:
group:
- present
user:
- present
- gid: rvm
- home: /home/rvm
- require:
- group: rvm
rvm-deps:
pkg:
- installed
- names:
- bash
- coreutils
- gzip
- bzip2
- gawk
- sed
- curl
- git-core
- subversion
- sudo
mri-deps:
pkg:
- installed
- names:
- build-essential
- openssl
- libreadline6
- libreadline6-dev
- curl
- git-core
- zlib1g
- zlib1g-dev
- libssl-dev
- libyaml-dev
- libsqlite3-0
- libsqlite3-dev
- sqlite3
- libxml2-dev
- libxslt1-dev
- autoconf
- libc6-dev
- libncurses5-dev
- automake
- libtool
- bison
- subversion
- ruby
jruby-deps:
pkg:
- installed
- names:
- curl
- g++
- openjdk-6-jre-headless
ruby-1.9.2:
rvm:
- installed
- default: True
- runas: rvm
- require:
- pkg: rvm-deps
- pkg: mri-deps
- user: rvm
jruby:
rvm:
- installed
- runas: rvm
- require:
- pkg: rvm-deps
- pkg: jruby-deps
- user: rvm
jgemset:
rvm:
- gemset_present
- ruby: jruby
- runas: rvm
- require:
- rvm: jruby
mygemset:
rvm:
- gemset_present
- ruby: ruby-1.9.2
- runas: rvm
- require:
- rvm: ruby-1.9.2
rvm:
group:
- present
user:
- present
- gid: rvm
- home: /home/rvm
- require:
- group: rvm
rvm-deps:
pkg:
- installed
- names:
- bash
- coreutils
- gzip
- bzip2
- gawk
- sed
- curl
- git-core
- subversion
- sudo
mri-deps:
pkg:
- installed
- names:
- build-essential
- openssl
- libreadline6
- libreadline6-dev
- curl
- git-core
- zlib1g
- zlib1g-dev
- libssl-dev
- libyaml-dev
- libsqlite3-0
- libsqlite3-dev
- sqlite3
- libxml2-dev
- libxslt1-dev
- autoconf
- libc6-dev
- libncurses5-dev
- automake
- libtool
- bison
- subversion
- ruby
jruby-deps:
pkg:
- installed
- names:
- curl
- g++
- openjdk-6-jre-headless
ruby-1.9.2:
rvm:
- installed
- default: True
- runas: rvm
- require:
- pkg: rvm-deps
- pkg: mri-deps
- user: rvm
jruby:
rvm:
- installed
- runas: rvm
- require:
- pkg: rvm-deps
- pkg: jruby-deps
- user: rvm
jgemset:
rvm:
- gemset_present
- ruby: jruby
- runas: rvm
- require:
- rvm: jruby
mygemset:
rvm:
- gemset_present
- ruby: ruby-1.9.2
- runas: rvm
- require:
- rvm: ruby-1.9.2
"""

import re
@@ -9,7 +9,7 @@
import logging
from calendar import month_abbr as months

from salt.exceptions import SaltClientError
from salt.exceptions import SaltClientError, CommandNotFoundError


log = logging.getLogger(__name__)
@@ -302,3 +302,18 @@ def required_modules_error(name, docstring):
filename = os.path.basename(name).split('.')[0]
msg = '\'{0}\' requires these python modules: {1}'
return msg.format(filename, ', '.join(modules))

def check_or_die(command):
'''
Simple convienence function for modules to use
for gracefully blowing up if a required tool is
not available in the system path.
Lazily import salt.modules.cmdmod to avoid any
sort of circular dependencies.
'''
import salt.modules.cmdmod
__salt__ = {'cmd.has_exec': salt.modules.cmdmod.has_exec}

if not __salt__['cmd.has_exec'](command):
raise CommandNotFoundError(command)