diff --git a/.gitignore b/.gitignore index 26a361c070..52de524278 100644 --- a/.gitignore +++ b/.gitignore @@ -64,3 +64,7 @@ _version.py # Ignore grains file written out during tests tests/integration/files/conf/grains +/salt/_syspaths.py + +# ignore the local root +/root/** diff --git a/doc/cheatsheet/salt.tex b/doc/cheatsheet/salt.tex index ca34437eb9..fc1ea6a7ab 100644 --- a/doc/cheatsheet/salt.tex +++ b/doc/cheatsheet/salt.tex @@ -26,6 +26,17 @@ The \texttt{top.sls} file is used to map what SLS modules get loaded onto what minions via the state system.\\ +It is located in the file defined in the \texttt{file_roots} variable of the +salt master configuration file which is found in +\texttt{CONFIG_DIR}/master. + +The file roots is defined like this by default. +\begin{verbatim} +file_roots: + base: + - /srv/salt +\end{verbatim} + Here is an example \texttt{top.sls} file which uses \texttt{pkg}, \texttt{file} and \texttt{service} states: \begin{verbatim} diff --git a/doc/index.rst b/doc/index.rst index 4db5d04cfb..c856ae1074 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -67,6 +67,9 @@ States - Configuration Management with Salt: Masterless Quickstart: :doc:`Salt Quickstart ` +Running Salt without root access in userland: + - :doc:`Salt Usermode ` + A list of all tutorials can be found here: :doc:`All Salt tutorials ` @@ -288,4 +291,4 @@ More information about the project The SaltStack security disclosure policy .. _`salt-contrib`: https://github.com/saltstack/salt-contrib -.. _`salt-states`: https://github.com/saltstack/salt-states \ No newline at end of file +.. _`salt-states`: https://github.com/saltstack/salt-states diff --git a/doc/topics/troubleshooting/master.rst b/doc/topics/troubleshooting/master.rst index addcc8f4f3..bd9319ee6c 100644 --- a/doc/topics/troubleshooting/master.rst +++ b/doc/topics/troubleshooting/master.rst @@ -247,3 +247,30 @@ service. auth_timeout: The total time to wait for the authentication process to complete, regardless of the number of attempts. + + +===================== +Running state locally +===================== + +To debug the states, you can use call locally. + +.. code-block:: bash + + salt-call -l trace --local state.highstate + + +The top.sls file is used to map what SLS modules get loaded onto what minions via the state system. + +It is located in the file defined in the ``file_roots`` variable of the salt master +configuration file which is defined by found in ``CONFIG_DIR/master``, normally ``/etc/salt/master`` + +The default configuration for the ``file_roots`` is: + +.. code-block:: yaml + + file_roots: + base: + - /srv/salt + +So the top file is defaulted to the location ``/srv/salt/top.sls`` diff --git a/doc/topics/tutorials/rooted.rst b/doc/topics/tutorials/rooted.rst new file mode 100644 index 0000000000..d96be65548 --- /dev/null +++ b/doc/topics/tutorials/rooted.rst @@ -0,0 +1,80 @@ +==================================== +running salt as normal user tutorial +==================================== + +.. include:: /_incl/requisite_incl.rst + +Running Salt functions as non root user +======================================= + +If you dont want to run salt cloud as root or even install it you can +configure it to have a virtual root in your working directory. + +The salt system uses the ``salt.syspath`` module to find the variables + +If you run the salt-build, it will generated in: + +.. code-block:: bash + + ./build/lib.linux-x86_64-2.7/salt/_syspaths.py + +To generate it, run the command: + +.. code-block:: bash + + python setup.py build + +Copy the generated module into your salt directory + +.. code-block:: bash + + cp ./build/lib.linux-x86_64-2.7/salt/_syspaths.py salt/_syspaths.py + +Edit it to include needed variables and your new paths + +.. code-block:: python + + # you need to edit this + ROOT_DIR = *your current dir* + '/salt/root' + + # you need to edit this + INSTALL_DIR = *location of source code* + + CONFIG_DIR = ROOT_DIR + '/etc/salt' + CACHE_DIR = ROOT_DIR + '/var/cache/salt' + SOCK_DIR = ROOT_DIR + '/var/run/salt' + SRV_ROOT_DIR= ROOT_DIR + '/srv' + BASE_FILE_ROOTS_DIR = ROOT_DIR + '/srv/salt' + BASE_PILLAR_ROOTS_DIR = ROOT_DIR + '/srv/pillar' + BASE_MASTER_ROOTS_DIR = ROOT_DIR + '/srv/salt-master' + LOGS_DIR = ROOT_DIR + '/var/log/salt' + PIDFILE_DIR = ROOT_DIR + '/var/run' + CLOUD_DIR = INSTALL_DIR + '/cloud' + BOOTSTRAP = CLOUD_DIR + '/deploy/bootstrap-salt.sh' + + +Create the directory structure + +.. code-block:: bash + + mkdir -p root/etc/salt root/var/cache/run root/run/salt root/srv + root/srv/salt root/srv/pillar root/srv/salt-master root/var/log/salt root/var/run + + +Populate the configuration files: + +.. code-block:: bash + + cp -r conf/* root/etc/salt/ + +Edit your ``root/etc/salt/master`` configuration that is used by salt-cloud: + +.. code-block:: yaml + + user: *your user name* + +Run like this: + +.. code-block:: bash + + PYTHONPATH=`pwd` scripts/salt-cloud diff --git a/salt/cli/api.py b/salt/cli/api.py index 137a9d186b..4ac3435279 100644 --- a/salt/cli/api.py +++ b/salt/cli/api.py @@ -1,13 +1,25 @@ # -*- coding: utf-8 -*- -from __future__ import print_function -from __future__ import absolute_import +''' + salt.cli.api + ~~~~~~~~~~~~~ -import salt.ext.six as six + Salt's api cli parser. + +''' + +# Import Python libs +from __future__ import absolute_import, print_function import sys +import os.path import logging +# Import Salt libs import salt.utils.parsers as parsers import salt.version +import salt.syspaths as syspaths + +# Import 3rd-party libs +import salt.ext.six as six log = logging.getLogger(__name__) @@ -25,7 +37,7 @@ class SaltAPI(six.with_metaclass(parsers.OptionParserMeta, # pylint: disable=W0 # ConfigDirMixIn config filename attribute _config_filename_ = 'master' # LogLevelMixIn attributes - _default_logging_logfile_ = '/var/log/salt/api' + _default_logging_logfile_ = os.path.join(syspaths.LOGS_DIR, 'api') def setup_config(self): return salt.config.api_config(self.get_config_file_path()) diff --git a/salt/cloud/cli.py b/salt/cloud/cli.py index 544f947a7d..421bfb70b3 100644 --- a/salt/cloud/cli.py +++ b/salt/cloud/cli.py @@ -4,9 +4,9 @@ Primary interfaces for the salt-cloud system ''' # Need to get data from 4 sources! # CLI options -# salt cloud config - /etc/salt/cloud +# salt cloud config - CONFIG_DIR + '/cloud' # salt master config (for master integration) -# salt VM config, where VMs are defined - /etc/salt/cloud.profiles +# salt VM config, where VMs are defined - CONFIG_DIR + '/cloud.profiles' # # The cli, master and cloud configs will merge for opts # the VM data will be in opts['profiles'] @@ -31,7 +31,7 @@ from salt.utils.verify import check_user, verify_env, verify_files import salt.cloud from salt.exceptions import SaltCloudException, SaltCloudSystemExit import salt.ext.six as six - +import salt.syspaths as syspaths log = logging.getLogger(__name__) @@ -50,9 +50,10 @@ class SaltCloud(parsers.SaltCloudParser): 'If salt-cloud is running on a master machine, salt-cloud ' 'needs to run as the same user as the salt-master, {0!r}. If ' 'salt-cloud is not running on a salt-master, the appropriate ' - 'write permissions must be granted to /etc/salt/. Please run ' + 'write permissions must be granted to {1!r}. Please run ' 'salt-cloud as root, {0!r}, or change permissions for ' - '/etc/salt/.'.format(salt_master_user) + '{1!r}.'.format(salt_master_user, + syspaths.CONFIG_DIR) ) try: diff --git a/salt/scripts.py b/salt/scripts.py index 12aafbfb21..f00ed581fb 100644 --- a/salt/scripts.py +++ b/salt/scripts.py @@ -302,7 +302,8 @@ def salt_cloud(): try: import salt.cloud.cli has_saltcloud = True - except ImportError: + except ImportError as e: + log.error("Error importing salt cloud {0}".format(e)) # No salt cloud on Windows has_saltcloud = False if '' in sys.path: diff --git a/salt/syspaths.py b/salt/syspaths.py index 2286d041de..af546b1636 100644 --- a/salt/syspaths.py +++ b/salt/syspaths.py @@ -21,13 +21,19 @@ from __future__ import absolute_import import sys import os.path - +import logging +log = logging.getLogger(__name__) if 'SETUP_DIRNAME' in globals(): # This is from the exec() call in Salt's setup.py THIS_FILE = os.path.join(SETUP_DIRNAME, 'salt', 'syspaths.py') # pylint: disable=E0602 else: THIS_FILE = __file__ +# These defaults won't changes and are not to be overridden +INSTALL_DIR = os.path.dirname(os.path.realpath(THIS_FILE)) +CLOUD_DIR = os.path.join(INSTALL_DIR, 'cloud') +BOOTSTRAP = os.path.join(CLOUD_DIR, 'deploy', 'bootstrap-salt.sh') + try: # Let's try loading the system paths from the generated module at # installation time. @@ -42,11 +48,9 @@ try: BASE_MASTER_ROOTS_DIR, LOGS_DIR, PIDFILE_DIR, - CLOUD_DIR, - INSTALL_DIR, - BOOTSTRAP, ) -except ImportError: +except ImportError as error: + log.error('Error importing salt._syspaths with exception {0}'.format(error)) # The installation time was not generated, let's define the default values __platform = sys.platform.lower() if __platform.startswith('win'): @@ -68,6 +72,3 @@ except ImportError: BASE_MASTER_ROOTS_DIR = os.path.join(SRV_ROOT_DIR, 'salt-master') LOGS_DIR = os.path.join(ROOT_DIR, 'var', 'log', 'salt') PIDFILE_DIR = os.path.join(ROOT_DIR, 'var', 'run') - INSTALL_DIR = os.path.dirname(os.path.realpath(THIS_FILE)) - CLOUD_DIR = os.path.join(INSTALL_DIR, 'cloud') - BOOTSTRAP = os.path.join(CLOUD_DIR, 'deploy', 'bootstrap-salt.sh') diff --git a/salt/utils/parsers.py b/salt/utils/parsers.py index f3b5cf2e25..517f649624 100644 --- a/salt/utils/parsers.py +++ b/salt/utils/parsers.py @@ -9,10 +9,8 @@ This is where all the black magic happens on all of salt's CLI tools. ''' -from __future__ import absolute_import - # Import python libs -from __future__ import print_function +from __future__ import absolute_import, print_function import os import sys import getpass @@ -410,6 +408,7 @@ class ConfigDirMixIn(object): config_dir = os.environ.get('SALT_CONFIG_DIR', None) if not config_dir: config_dir = syspaths.CONFIG_DIR + logging.getLogger(__name__).debug('SYSPATHS setup as: {0}'.format(syspaths.CONFIG_DIR)) self.add_option( '-c', '--config-dir', default=config_dir, help=('Pass in an alternative configuration directory. Default: ' @@ -420,7 +419,7 @@ class ConfigDirMixIn(object): if not os.path.isdir(self.options.config_dir): # No logging is configured yet sys.stderr.write( - 'WARNING: {0!r} directory does not exist.\n'.format( + 'WARNING: CONFIG {0!r} directory does not exist.\n'.format( self.options.config_dir ) )