Merge pull request #22900 from basepi/merge-forward-develop

Merge forward from 2015.2 to develop
This commit is contained in:
Justin Findlay 2015-04-21 12:01:39 -06:00
commit 3565816876
31 changed files with 1161 additions and 183 deletions

View File

@ -102,6 +102,7 @@ disable=R,
W0631,
W0704,
W1202,
W1307,
F0220,
F0401,
E8501,
@ -116,6 +117,7 @@ disable=R,
E8129,
E8131,
E8265,
E8266,
E8402,
E8731
@ -151,9 +153,11 @@ disable=R,
# F0220 (unresolved-interface)
# F0401 (import-error)
# W1202 (logging-format-interpolation) Use % formatting in logging functions but pass the % parameters as arguments
# W1307 (invalid-format-index) Using invalid lookup key '%s' in format specifier "0['%s']"
#
# E812* All PEP8 E12*
# E8265 PEP8 E265 - block comment should start with "# "
# E8266 PEP8 E266 - too many leading '#' for block comment
# E8501 PEP8 line too long
# E8402 module level import not at top of file
# E8731 do not assign a lambda expression, use a def

View File

@ -20,6 +20,10 @@ minion exe>` should match the contents of the corresponding md5 file.
.. admonition:: Download here
* 2014.7.5
* `Salt-Minion-2014.7.5-x86-Setup.exe <http://docs.saltstack.com/downloads/Salt-Minion-2014.7.5-x86-Setup.exe>`__ | `md5 <http://docs.saltstack.com/downloads/Salt-Minion-2014.7.5-x86-Setup.exe.md5>`__
* `Salt-Minion-2014.7.5-AMD64-Setup.exe <http://docs.saltstack.com/downloads/Salt-Minion-2014.7.5-AMD64-Setup.exe>`__ | `md5 <http://docs.saltstack.com/downloads/Salt-Minion-2014.7.5-AMD64-Setup.exe.md5>`__
* 2014.7.4
* `Salt-Minion-2014.7.4-x86-Setup.exe <http://docs.saltstack.com/downloads/Salt-Minion-2014.7.4-x86-Setup.exe>`__ | `md5 <http://docs.saltstack.com/downloads/Salt-Minion-2014.7.4-x86-Setup.exe.md5>`__
* `Salt-Minion-2014.7.4-AMD64-Setup.exe <http://docs.saltstack.com/downloads/Salt-Minion-2014.7.4-AMD64-Setup.exe>`__ | `md5 <http://docs.saltstack.com/downloads/Salt-Minion-2014.7.4-AMD64-Setup.exe.md5>`__
@ -35,9 +39,7 @@ minion exe>` should match the contents of the corresponding md5 file.
* 2014.7.0
* Salt-Minion-2014.7.0-1-win32-Setup.exe | md5
* Salt-Minion-2014.7.0-AMD64-Setup.exe | md5
.. note::
The 2014.7.0 installers have been removed because of a regression. Please use the 2014.7.1 release instead.
* 2014.1.13
@ -135,7 +137,7 @@ minion exe>` should match the contents of the corresponding md5 file.
.. note::
The executables above will install all dependencies that the Salt minion
The executables above will install dependencies that the Salt minion
requires.
The 64bit installer has been tested on Windows 7 64bit and Windows Server
@ -163,7 +165,7 @@ line. The options `/master` and `/minion-name` allow for configuring the master
hostname and minion name, respectively. Here's an example of using the silent
installer:
.. code-block:: bash
.. code-block:: bat
Salt-Minion-0.17.0-Setup-amd64.exe /S /master=yoursaltmaster /minion-name=yourminionname
@ -171,142 +173,305 @@ installer:
Setting up a Windows build environment
======================================
1. Install the Microsoft Visual C++ 2008 SP1 Redistributable, `vcredist_x86`_
or `vcredist_x64`_.
This document will explain how to set up a development environment for salt on
Windows. The development environment allows you to work with the source code to
customize or fix bugs. It will also allow you to build your own installation.
2. Install `msysgit`_
The Easy Way
------------
3. Clone the Salt git repository from GitHub
Prerequisite Software
^^^^^^^^^^^^^^^^^^^^^
.. code-block:: bash
To do this the easy way you only need to install `Git for Windows <https://github.com/msysgit/msysgit/releases/download/Git-1.9.5-preview20150319/Git-1.9.5-preview20150319.exe/>`_.
git clone https://github.com/saltstack/salt.git
Create the Build Environment
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4. Install the latest point release of `Python 2.7`_ for the architecture you
wish to target
1. Clone the `Salt-Windows-Dev <https://github.com/saltstack/salt-windows-dev/>`_
repo from github.
5. Add ``C:\\Python27`` and ``C:\\Python27\\Scripts`` to your system path
Open a command line and type:
6. Download and run the Setuptools bootstrap - `ez_setup.py`_
.. code-block:: bat
.. code-block:: bash
git clone https://github.com/saltstack/salt-windows-dev
python ez_setup.py
2. Build the Python Environment
7. Install Pip
Go into the salt-windows-dev directory. Right-click the file named
**dev_env.ps1** and select **Run with PowerShell**
.. code-block:: bash
If you get an error, you may need to change the execution policy.
easy_install pip
Open a powershell window and type the following:
8. Install the latest point release of `OpenSSL for Windows`_
.. code-block:: powershell
#. During setup, choose first option to install in Windows system
directory
Set-ExecutionPolicy RemoteSigned
9. Install the latest point release of `M2Crypto`_
This will download and install Python with all the dependencies needed to
develop and build salt.
#. In general, be sure to download installers targeted at py2.7 for your
chosen architecture
3. Build the Salt Environment
10. Install the latest point release of `pycrypto`_
Right-click on the file named **dev_env_salt.ps1** and select **Run with
Powershell**
11. Install the latest point release of `pywin32`_
This will clone salt into ``C:\Salt-Dev\salt`` and set it to the 2015.2
branch. You could optionally run the command from a powershell window with a
``-Version`` switch to pull a different version. For example:
12. Install the latest point release of `Cython`_
.. code-block:: powershell
13. Install the latest point release of `jinja2`_
dev_env_salt.ps1 -Version '2014.7'
14. Install the latest point release of `msgpack`_
To view a list of available branches and tags, open a command prompt in your
`C:\Salt-Dev\salt` directory and type:
15. Install psutil
.. code-block:: bat
.. code-block:: bash
easy_install psutil
16. Install pyzmq
.. code-block:: bash
easy_install pyzmq
17. Install PyYAML
.. code-block:: bash
easy_install pyyaml
18. Install bbfreeze
.. code-block:: bash
easy_install bbfreeze
19. Install wmi
.. code-block:: bash
pip install wmi
20. Install requests
.. code-block:: bash
pip install requests
21. Install markupsafe
.. code-block:: bash
pip install markupsafe
22. Install six
.. code-block:: bash
pip install six
23. Install esky
.. code-block:: bash
pip install esky
24. Install certifi
.. code-block:: bash
pip install certifi
25. Install Salt
.. code-block:: bash
cd salt
python setup.py install
26. Build a frozen binary distribution of Salt
.. code-block:: bash
python setup.py bdist_esky
A zip file has been created in the ``dist/`` folder, containing a frozen copy
of Python and the dependency libraries, along with Windows executables for each
of the Salt scripts.
git branch -a
git tag -n
Building the installer
======================
The Hard Way
------------
The Salt Windows installer is built with the open-source NSIS compiler. The
source for the installer is found in the pkg directory of the Salt repo here:
:blob:`pkg/windows/installer/Salt-Minion-Setup.nsi`. To create the installer,
extract the frozen archive from ``dist/`` into ``pkg/windows/buildenv/`` and
run NSIS.
Prerequisite Software
^^^^^^^^^^^^^^^^^^^^^
The NSIS installer can be found here: http://nsis.sourceforge.net/Main_Page
Install the following software:
1. `Git for Windows <https://github.com/msysgit/msysgit/releases/download/Git-1.9.5-preview20150319/Git-1.9.5-preview20150319.exe/>`_
2. `Nullsoft Installer <http://downloads.sourceforge.net/project/nsis/NSIS%203%20Pre-release/3.0b1/nsis-3.0b1-setup.exe/>`_
Download the Prerequisite zip file for your CPU architecture from the
SaltStack download site:
* `Salt32.zip <http://docs.saltstack.com/downloads/windows-deps/Salt32.zip/>`_
* `Salt64.zip <http://docs.saltstack.com/downloads/windows-deps/Salt64.zip/>`_
These files contain all sofware required to build and develop salt. Unzip the
contents of the file to ``C:\Salt-Dev\temp``.
Create the Build Environment
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1. Build the Python Environment
* Install Python:
Browse to the ``C:\Salt-Dev\temp`` directory and find the Python
installation file for your CPU Architecture under the corresponding
subfolder. Double-click the file to install python.
Make sure the following are in your **PATH** environment variable:
.. code-block:: bat
C:\Python27
C:\Python27\Scripts
* Install Pip
Open a command prompt and navigate to ``C:\Salt-Dev\temp``
Run the following command:
.. code-block:: bat
python get-pip.py
* Easy Install compiled binaries.
M2Crypto, PyCrypto, and PyWin32 need to be installed using Easy Install.
Open a command prompt and navigate to ``C:\Salt-Dev\temp\<cpuarch>``.
Run the following commands:
.. code-block:: bat
easy_install -Z <M2Crypto file name>
easy_install -Z <PyCrypto file name>
easy_install -Z <PyWin32 file name>
.. note::
You can type the first part of the file name and then press the tab key
to auto-complete the name of the file.
* Pip Install Additional Prerequisites
All remaining prerequisites need to be pip installed. These prerequisites
are as follow:
* MarkupSafe
* Jinja
* MsgPack
* PSUtil
* PyYAML
* PyZMQ
* WMI
* Requests
* Certifi
Open a command prompt and navigate to ``C:\Salt-Dev\temp``. Run the following
commands:
.. code-block:: bat
pip install <cpuarch>\<MarkupSafe file name>
pip install <Jinja file name>
pip install <cpuarch>\<MsgPack file name>
pip install <cpuarch>\<psutil file name>
pip install <cpuarch>\<PyYAML file name>
pip install <cpuarch>\<pyzmq file name>
pip install <WMI file name>
pip install <requests file name>
pip install <certifi file name>
2. Build the Salt Environment
* Clone Salt
Open a command prompt and navigate to ``C:\Salt-Dev``. Run the following command
to clone salt:
.. code-block:: bat
git clone https://github.com/saltstack/salt
* Checkout Branch
Checkout the branch or tag of salt you want to work on or build. Open a
command prompt and navigate to ``C:\Salt-Dev\salt``. Get a list of
available tags and branches by running the following commands:
.. code-block:: bat
git fetch --all
To view a list of available branches:
git branch -a
To view a list of availabel tags:
git tag -n
Checkout the branch or tag by typing the following command:
.. code-block:: bat
git checkout <branch/tag name>
* Clean the Environment
When switching between branches residual files can be left behind that
will interfere with the functionality of salt. Therefore, after you check
out the branch you want to work on, type the following commands to clean
the salt environment:
.. code-block: bat
git clean -fxd
git reset --hard HEAD
Developing with Salt
====================
There are two ways to develop with salt. You can run salt's setup.py each time
you make a change to source code or you can use the setup tools develop mode.
Configure the Minion
--------------------
Both methods require that the minion configuration be in the ``C:\salt``
directory. Copy the conf and var directories from ``C:\Salt-Dev\salt\pkg\
windows\buildenv`` to ``C:\salt``. Now go into the ``C:\salt\conf`` directory
and edit the file name ``minion`` (no extension). You need to configure the
master and id parameters in this file. Edit the following lines:
.. code-block:: bat
master: <ip or name of your master>
id: <name of your minion>
Setup.py Method
---------------
Go into the ``C:\Salt-Dev\salt`` directory from a cmd prompt and type:
.. code-block:: bat
python setup.py install --force
This will install python into your python installation at ``C:\Python27``.
Everytime you make an edit to your source code, you'll have to stop the minion,
run the setup, and start the minion.
To start the salt-minion go into ``C:\Python27\Scripts`` from a cmd prompt and
type:
.. code-block:: bat
salt-minion
For debug mode type:
.. code-block:: bat
salt-minion -l debug
To stop the minion press Ctrl+C.
Setup Tools Develop Mode (Preferred Method)
-------------------------------------------
To use the Setup Tools Develop Mode go into ``C:\Salt-Dev\salt`` from a cmd
prompt and type:
.. code-block:: bat
pip install -e .
This will install pointers to your source code that resides at
``C:\Salt-Dev\salt``. When you edit your source code you only have to restart
the minion.
Build the windows installer
===========================
This is the method of building the installer as of version 2014.7.4.
Clean the Environment
---------------------
Make sure you don't have any leftover salt files from previous versions of salt
in your Python directory.
1. Remove all files that start with salt in the ``C:\Python27\Scripts``
directory
2. Remove all files and directorys that start with salt in the
``C:\Python27\Lib\site-packages`` directory
Install Salt
------------
Install salt using salt's setup.py. From the ``C:\Salt-Dev\salt`` directory
type the following command:
.. code-block:: bat
python setup.py install --force
Build the Installer
-------------------
From cmd prompt go into the ``C:\Salt-Dev\salt\pkg\windows`` directory. Type
the following command for the branch or tag of salt you're building:
.. code-block:: bat
BuildSalt.bat <branch or tag>
This will copy python with salt installed to the ``buildenv\bin`` directory,
make it portable, and then create the windows installer . The .exe for the
windows installer will be placed in the ``installer`` directory.
Testing the Salt minion
@ -361,7 +526,7 @@ salt, including all dependencies:
This script is not up to date. Please use the installer found above
.. code-block:: bash
.. code-block:: powershell
# (All in one line.)
@ -381,12 +546,10 @@ Packages management under Windows 2003
On windows Server 2003, you need to install optional component "wmi windows
installer provider" to have full list of installed packages. If you don't have
this, salt-minion can't report some installed packages.
this, salt-minion can't report some installed softwares.
.. _http://csa-net.dk/salt: http://csa-net.dk/salt
.. _vcredist_x86: http://www.microsoft.com/en-us/download/details.aspx?id=5582
.. _vcredist_x64: http://www.microsoft.com/en-us/download/details.aspx?id=2092
.. _msysgit: http://code.google.com/p/msysgit/downloads/list?can=3
.. _Python 2.7: http://www.python.org/downloads
.. _ez_setup.py: https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py
@ -397,3 +560,4 @@ this, salt-minion can't report some installed packages.
.. _Cython: http://www.lfd.uci.edu/~gohlke/pythonlibs/#cython
.. _jinja2: http://www.lfd.uci.edu/~gohlke/pythonlibs/#jinja2
.. _msgpack: http://www.lfd.uci.edu/~gohlke/pythonlibs/#msgpack

View File

@ -59,14 +59,13 @@ be used to install it:
If pygit2_ is not packaged for the platform on which the Master is running, the
pygit2_ website has installation instructions here__. Keep in mind however that
following these instructions will install libgit2 and pygit2_ without system
packages. Also, while this is not explicitly mentioned in the pygit2_
installation instructions, libssh2 development headers must be installed before
building libgit2 in order to enable access to SSH-protected git repositories.
Luckily, these are available in most distros' repositories, usually as either
``libssh2-devel`` or ``libssh2-dev``, depending on platform. On some distros
(debian based) ``pkg-config`` is also required to link libgit2 with libssh2.
packages. Additionally, keep in mind that :ref:`SSH authentication in pygit2
<pygit2-authentication-ssh>` requires libssh2_ (*not* libssh) development
libraries to be present before libgit2 is built. On some distros (debian based)
``pkg-config`` is also required to link libgit2 with libssh2.
.. __: http://www.pygit2.org/install.html
.. _libssh2: http://www.libssh2.org/
GitPython
---------
@ -544,6 +543,8 @@ an ``insecure_auth`` parameter:
- password: mypassword
- insecure_auth: True
.. _pygit2-authentication-ssh:
SSH
~~~

View File

@ -41,6 +41,7 @@ Var MinionName_State
!define MUI_ABORTWARNING
!define MUI_ICON "salt.ico"
!define MUI_UNICON "salt.ico"
!define MUI_WELCOMEFINISHPAGE_BITMAP "panel.bmp"
; Welcome page
!insertmacro MUI_PAGE_WELCOME

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 KiB

View File

@ -291,10 +291,13 @@ class Shell(object):
ret = self._run_cmd(cmd)
return ret
def send(self, local, remote):
def send(self, local, remote, makedirs=False):
'''
scp a file or files to a remote system
'''
if makedirs:
self.exec_cmd('mkdir -p {0}'.format(os.path.dirname(remote)))
cmd = '{0} {1}:{2}'.format(local, self.host, remote)
cmd = self._cmd_str(cmd, ssh='scp')

View File

@ -6,18 +6,39 @@ from __future__ import absolute_import
# Import salt libs
import salt.client.ssh
import logging
from salt.exceptions import CommandExecutionError
log = logging.getLogger(__name__)
def get_file(path, dest, saltenv='base'):
def get_file(path,
dest,
saltenv='base',
makedirs=False,
template=None,
gzip=None):
'''
Send a file from the master to the location in specified
.. note::
gzip compression is not supported in the salt-ssh version of
cp.get_file. The argument is only accepted for interface compatibility.
'''
if gzip is not None:
log.warning('The gzip argument to cp.get_file in salt-ssh is '
'unsupported')
if template is not None:
(path, dest) = _render_filenames(path, dest, saltenv, template)
src = __context__['fileclient'].cache_file(path, saltenv)
single = salt.client.ssh.Single(
__opts__,
'',
**__salt__.kwargs)
ret = single.shell.send(src, dest)
ret = single.shell.send(src, dest, makedirs)
return not ret[2]
@ -74,3 +95,56 @@ def list_master_symlinks(saltenv='base', prefix=''):
List all of the symlinks stored on the master
'''
return __context__['fileclient'].symlink_list(saltenv, prefix)
def _render_filenames(path, dest, saltenv, template):
'''
Process markup in the :param:`path` and :param:`dest` variables (NOT the
files under the paths they ultimately point to) according to the markup
format provided by :param:`template`.
'''
if not template:
return (path, dest)
# render the path as a template using path_template_engine as the engine
if template not in salt.utils.templates.TEMPLATE_REGISTRY:
raise CommandExecutionError(
'Attempted to render file paths with unavailable engine '
'{0}'.format(template)
)
kwargs = {}
kwargs['salt'] = __salt__
kwargs['pillar'] = __pillar__
kwargs['grains'] = __grains__
kwargs['opts'] = __opts__
kwargs['saltenv'] = saltenv
def _render(contents):
'''
Render :param:`contents` into a literal pathname by writing it to a
temp file, rendering that file, and returning the result.
'''
# write out path to temp file
tmp_path_fn = salt.utils.mkstemp()
with salt.utils.fopen(tmp_path_fn, 'w+') as fp_:
fp_.write(contents)
data = salt.utils.templates.TEMPLATE_REGISTRY[template](
tmp_path_fn,
to_str=True,
**kwargs
)
salt.utils.safe_rm(tmp_path_fn)
if not data['result']:
# Failed to render the template
raise CommandExecutionError(
'Failed to render file path with error: {0}'.format(
data['data']
)
)
else:
return data['data']
path = _render(path)
dest = _render(dest)
return (path, dest)

View File

@ -2083,7 +2083,7 @@ def create(vm_=None, call=None):
)
try:
node_data = conn.create_node(**kwargs) # pylint: disable=W0142
node_data = conn.create_node(**kwargs)
except Exception as exc: # pylint: disable=W0703
log.error(
'Error creating {0} on GCE\n\n'
@ -2179,7 +2179,6 @@ def create(vm_=None, call=None):
transport=__opts__['transport']
)
# pylint: disable=W0142
deployed = salt.utils.cloud.deploy_script(**deploy_kwargs)
if deployed:
log.info('Salt installed on {0}'.format(vm_['name']))

View File

@ -573,6 +573,8 @@ def list_nodes(call=None):
ret[node]['public_ips'] = nodes[node]['primaryIpAddress']
if 'primaryBackendIpAddress' in nodes[node]:
ret[node]['private_ips'] = nodes[node]['primaryBackendIpAddress']
if 'status' in nodes[node]:
ret[node]['state'] = str(nodes[node]['status']['name'])
return ret

View File

@ -577,7 +577,7 @@ def _verify_auth(repo):
'''
Helper function to log errors about missing auth parameters
'''
log.error(
log.critical(
'Incomplete authentication information for remote {0}. Missing '
'parameters: {1}'.format(remote_url, ', '.join(missing))
)
@ -600,9 +600,9 @@ def _verify_auth(repo):
user = address.split('@')[0]
if user == address:
# No '@' sign == no user. This is a problem.
log.error(
'Password / keypair specified for remote {0}, but remote '
'URL is missing a username'.format(repo['url'])
log.critical(
'Keypair specified for remote {0}, but remote URL is missing '
'a username'.format(repo['url'])
)
_failhard()
@ -625,7 +625,7 @@ def _verify_auth(repo):
return True
if password_ok:
if transport == 'http' and not repo['insecure_auth']:
log.error(
log.critical(
'Invalid configuration for gitfs remote {0}. '
'Authentication is disabled by default on http remotes. '
'Either set gitfs_insecure_auth to True in the master '
@ -641,7 +641,7 @@ def _verify_auth(repo):
missing_auth = [x for x in required_params if not bool(repo[x])]
_incomplete_auth(repo['url'], missing_auth)
else:
log.error(
log.critical(
'Invalid configuration for remote {0}. Unsupported transport '
'{1!r}.'.format(repo['url'], transport)
)
@ -705,7 +705,7 @@ def init():
six.iteritems(salt.utils.repack_dictlist(remote[repo_url]))]
)
if not per_remote_conf:
log.error(
log.critical(
'Invalid per-remote configuration for gitfs remote {0}. '
'If no per-remote parameters are being specified, there '
'may be a trailing colon after the URL, which should be '
@ -816,7 +816,7 @@ def init():
'{0}'.format(exc))
if provider == 'gitpython':
msg += ' Perhaps git is not available.'
log.error(msg, exc_info_on_loglevel=logging.DEBUG)
log.critical(msg, exc_info_on_loglevel=logging.DEBUG)
_failhard()
if new_remote:
@ -1152,7 +1152,21 @@ def update():
except KeyError:
# No credentials configured for this repo
pass
fetch = origin.fetch()
try:
fetch = origin.fetch()
except pygit2.errors.GitError as exc:
# Using exc.__str__() here to avoid deprecation warning
# when referencing exc.message
if 'unsupported url protocol' in exc.__str__().lower() \
and isinstance(repo.get('credentials'),
pygit2.Keypair):
log.error(
'Unable to fetch SSH-based gitfs remote {0}. '
'libgit2 must be compiled with libssh2 to support '
'SSH authentication.'.format(repo['url'])
)
continue
raise
try:
# pygit2.Remote.fetch() returns a dict in pygit2 < 0.21.0
received_objects = fetch['received_objects']
@ -1160,10 +1174,16 @@ def update():
# pygit2.Remote.fetch() returns a class instance in
# pygit2 >= 0.21.0
received_objects = fetch.received_objects
log.debug(
'gitfs received {0} objects for remote {1}'
.format(received_objects, repo['url'])
)
if received_objects != 0:
log.debug(
'gitfs received {0} objects for remote {1}'
.format(received_objects, repo['url'])
)
else:
log.debug(
'gitfs remote {0} is up-to-date'
.format(repo['url'])
)
# Clean up any stale refs
refs_post = repo['repo'].listall_references()
cleaned = _clean_stale(repo['repo'], refs_post)
@ -1180,14 +1200,14 @@ def update():
try:
refs_post = client.fetch(path, repo['repo'])
except dulwich.errors.NotGitRepository:
log.critical(
log.error(
'Dulwich does not recognize remote {0} as a valid '
'remote URL. Perhaps it is missing \'.git\' at the '
'end.'.format(repo['url'])
)
continue
except KeyError:
log.critical(
log.error(
'Local repository cachedir {0!r} (corresponding '
'remote: {1}) has been corrupted. Salt will now '
'attempt to remove the local checkout to allow it to '
@ -1198,7 +1218,7 @@ def update():
try:
salt.utils.rm_rf(repo['cachedir'])
except OSError as exc:
log.critical(
log.error(
'Unable to remove {0!r}: {1}'
.format(repo['cachedir'], exc)
)
@ -1626,7 +1646,7 @@ def _file_lists(load, form):
try:
os.makedirs(list_cachedir)
except os.error:
log.critical('Unable to make cachedir {0}'.format(list_cachedir))
log.error('Unable to make cachedir {0}'.format(list_cachedir))
return []
list_cache = os.path.join(
list_cachedir,

View File

@ -203,7 +203,7 @@ def cql_query(query, contact_points=None, port=None, cql_user=None, cql_pass=Non
if results:
for result in results:
values = {}
for key, value in result.iteritems():
for key, value in six.iteritems(result):
# Salt won't return dictionaries with odd types like uuid.UUID
if not isinstance(value, six.text_type):
value = str(value)

View File

@ -48,7 +48,7 @@ def load():
datastore_path = os.path.join(__opts__['cachedir'], 'datastore')
fn_ = salt.utils.fopen(datastore_path, 'rb')
return serial.load(fn_)
except (IOError, OSError):
except (IOError, OSError, NameError):
return {}
@ -76,7 +76,7 @@ def dump(new_data):
return True
except (IOError, OSError):
except (IOError, OSError, NameError):
return False

View File

@ -1696,7 +1696,7 @@ def replace(path,
raise CommandExecutionError("Exception: {0}".format(exc))
if not found and (append_if_not_found or prepend_if_not_found):
if None == not_found_content:
if not_found_content is None:
not_found_content = repl
if prepend_if_not_found:
new_file.insert(0, not_found_content + '\n')

View File

@ -587,7 +587,11 @@ def find_cached_job(jid):
buf = fp_.read()
fp_.close()
if buf:
data = serial.loads(buf)
try:
data = serial.loads(buf)
except NameError:
# msgpack error in salt-ssh
return
else:
return
if not isinstance(data, dict):

View File

@ -736,7 +736,7 @@ def bootstrap(directory='.',
with salt.utils.fopen(b_py) as fic:
content = fic.read()
if (
(False != test_release)
(test_release is not False)
and ' --accept-buildout-test-releases' in content
):
bootstrap_args += ' --accept-buildout-test-releases'

View File

@ -1,11 +1,9 @@
# encoding: utf-8
from __future__ import print_function
from __future__ import absolute_import
from __future__ import absolute_import, print_function
import hashlib
import logging
import distutils.version
import distutils.version # pylint: disable=no-name-in-module
__virtualname__ = 'rest_tornado'

View File

@ -26,12 +26,12 @@ returns a list of key/value pairs for all of the EC2 tags assigned to
the instance.
'''
from __future__ import absolute_import
# Import python libs
from __future__ import absolute_import
import re
import logging
from distutils.version import StrictVersion
from distutils.version import StrictVersion # pylint: disable=no-name-in-module
# Import AWS Boto libs
try:

View File

@ -457,7 +457,7 @@ def ext_pillar(minion_id, pillar, resource, sequence, subkey=False, subkey_only=
immutable[rkey] = True
if rkey not in output:
log.error('Cant\'t merge key {0} doesn\'t exist'.format(rkey))
elif type(results[key]) is not type(output[rkey]):
elif not isinstance(results[key], type(output[rkey])):
log.error('Can\'t merge different types for key {0}'.format(rkey))
elif isinstance(results[key], dict):
output[rkey].update(results[key])

View File

@ -81,9 +81,9 @@ def downloaded(name, artifact, target_dir='/tmp', target_file=None):
log.debug("ret=%s", str(ret))
return ret
except Exception as e:
except Exception as exc:
ret['result'] = False
ret['comment'] = e
ret['comment'] = exc
return ret

View File

@ -276,7 +276,8 @@ def _load_accumulators():
with open(path, 'rb') as f:
loaded = serial.load(f)
return loaded if loaded else ret
except IOError:
except (IOError, NameError):
# NameError is a msgpack error from salt-ssh
return ret
loaded = _deserialize(_get_accumulator_filepath())
@ -290,8 +291,12 @@ def _persist_accummulators(accumulators, accumulators_deps):
'accumulators_deps': accumulators_deps}
serial = salt.payload.Serial(__opts__)
with open(_get_accumulator_filepath(), 'w+b') as f:
serial.dump(accumm_data, f)
try:
with open(_get_accumulator_filepath(), 'w+b') as f:
serial.dump(accumm_data, f)
except NameError:
# msgpack error from salt-ssh
pass
def _check_user(user, group):

View File

@ -146,7 +146,6 @@ def sig4(method, endpoint, params, prov_dict, aws_api_version, location,
http://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html
'''
timenow = datetime.datetime.utcnow()
timestamp = timenow.strftime('%Y-%m-%dT%H:%M:%SZ')
# Retrieve access credentials from meta-data, or use provided
access_key_id, secret_access_key, token = creds(prov_dict)
@ -155,11 +154,10 @@ def sig4(method, endpoint, params, prov_dict, aws_api_version, location,
params_with_headers['Version'] = aws_api_version
keys = sorted(params_with_headers.keys())
values = list(map(params_with_headers.get, keys))
querystring = urlencode(list(zip(keys, values)))
querystring = urlencode(list(zip(keys, values))).replace('+', '%20')
amzdate = timenow.strftime('%Y%m%dT%H%M%SZ')
datestamp = timenow.strftime('%Y%m%d')
payload_hash = hashlib.sha256('').hexdigest()
canonical_headers = 'host:{0}\nx-amz-date:{1}\n'.format(
endpoint,
@ -167,11 +165,6 @@ def sig4(method, endpoint, params, prov_dict, aws_api_version, location,
)
signed_headers = 'host;x-amz-date'
request = '\n'.join((
method, endpoint, querystring, canonical_headers,
signed_headers, payload_hash
))
algorithm = 'AWS4-HMAC-SHA256'
# Create payload hash (hash of the request body content). For GET

View File

@ -22,7 +22,7 @@ class DecoratorTest(integration.ModuleCase):
def not_test_depends(self):
ret = self.run_function('runtests_decorators.depends')
self.assertTrue(ret['ret'])
self.assertTrue(type(ret['time']) == float)
self.assertTrue(isinstance(ret['time'], float))
def test_missing_depends(self):
self.assertIn(
@ -49,7 +49,7 @@ class DecoratorTest(integration.ModuleCase):
def not_test_depends_will_fallback(self):
ret = self.run_function('runtests_decorators.depends_will_fallback')
self.assertTrue(ret['ret'])
self.assertTrue(type(ret['time']) == float)
self.assertTrue(isinstance(ret['time'], float))
def test_missing_depends_again(self):
self.assertIn(

View File

@ -0,0 +1,142 @@
# -*- coding: utf-8 -*-
'''
:codeauthor: :email:`Jayesh Kariya <jayeshk@saltstack.com>`
'''
# Import Python libs
from __future__ import absolute_import
# Import Salt Testing Libs
from salttesting import skipIf, TestCase
from salttesting.mock import (
NO_MOCK,
NO_MOCK_REASON,
MagicMock,
patch)
from salttesting.helpers import ensure_in_syspath
ensure_in_syspath('../../')
# Import Salt Libs
from salt.modules import postfix
# Globals
postfix.__salt__ = {}
@skipIf(NO_MOCK, NO_MOCK_REASON)
class PostfixTestCase(TestCase):
'''
Test cases for salt.modules.postfix
'''
def test_show_master(self):
'''
Test for return a dict of active config values
'''
with patch.object(postfix, '_parse_master',
return_value=({'A': 'a'}, ['b'])):
self.assertDictEqual(postfix.show_master('path'), {'A': 'a'})
def test_set_master(self):
'''
Test for set a single config value in the master.cf file
'''
with patch.object(postfix, '_parse_master',
return_value=({'A': 'a'}, ['b'])):
with patch.object(postfix, '_write_conf', return_value=None):
self.assertTrue(postfix.set_master('a', 'b'))
def test_show_main(self):
'''
Test for return a dict of active config values
'''
with patch.object(postfix, '_parse_main',
return_value=({'A': 'a'}, ['b'])):
self.assertDictEqual(postfix.show_main('path'), {'A': 'a'})
def test_set_main(self):
'''
Test for set a single config value in the master.cf file
'''
with patch.object(postfix, '_parse_main',
return_value=({'A': 'a'}, ['b'])):
with patch.object(postfix, '_write_conf', return_value=None):
self.assertTrue(postfix.set_main('key', 'value'))
def test_show_queue(self):
'''
Test for show contents of the mail queue
'''
with patch.dict(postfix.__salt__, {'cmd.run':
MagicMock(return_value='A\nB')}):
self.assertEqual(postfix.show_queue(), [])
def test_delete(self):
'''
Test for delete message(s) from the mail queue
'''
with patch.object(postfix, 'show_queue', return_value={}):
self.assertDictEqual(postfix.delete('queue_id'),
{'result': False, 'message':
'No message in queue with ID queue_id'})
with patch.dict(postfix.__salt__,
{'cmd.run_all':
MagicMock(return_value={'retcode': 0})}):
self.assertDictEqual(postfix.delete('ALL'),
{'result': True, 'message':
'Successfully removed all messages'})
def test_hold(self):
'''
Test for set held message(s) in the mail queue to unheld
'''
with patch.object(postfix, 'show_queue', return_value={}):
self.assertDictEqual(postfix.hold('queue_id'),
{'result': False, 'message':
'No message in queue with ID queue_id'})
with patch.dict(postfix.__salt__,
{'cmd.run_all':
MagicMock(return_value={'retcode': 0})}):
self.assertDictEqual(postfix.hold('ALL'),
{'result': True, 'message':
'Successfully placed all messages on hold'})
def test_unhold(self):
'''
Test for put message(s) on hold from the mail queue
'''
with patch.object(postfix, 'show_queue', return_value={}):
self.assertDictEqual(postfix.unhold('queue_id'),
{'result': False, 'message':
'No message in queue with ID queue_id'})
with patch.dict(postfix.__salt__,
{'cmd.run_all':
MagicMock(return_value={'retcode': 0})}):
self.assertDictEqual(postfix.unhold('ALL'),
{'result': True, 'message':
'Successfully set all message as unheld'})
def test_requeue(self):
'''
Test for requeue message(s) in the mail queue
'''
with patch.object(postfix, 'show_queue', return_value={}):
self.assertDictEqual(postfix.requeue('queue_id'),
{'result': False, 'message':
'No message in queue with ID queue_id'})
with patch.dict(postfix.__salt__,
{'cmd.run_all':
MagicMock(return_value={'retcode': 0})}):
self.assertDictEqual(postfix.requeue('ALL'),
{'result': True, 'message':
'Successfully requeued all messages'})
if __name__ == '__main__':
from integration import run_tests
run_tests(PostfixTestCase, needs_daemon=False)

View File

@ -154,11 +154,11 @@ class BuildoutTestCase(Base):
# These lines are throwing pylint errors - disabling for now since we are skipping
# these tests
#self.assertTrue(
# u''
# u'OUTPUT:\n'
# u'foo\n'
# u''
#in ret1['outlog']
# u''
# u'OUTPUT:\n'
# u'foo\n'
# u''
# in ret1['outlog']
#)
# These lines are throwing pylint errors - disabling for now since we are skipping
@ -167,11 +167,11 @@ class BuildoutTestCase(Base):
# These lines are throwing pylint errors - disabling for now since we are skipping
# these tests
# self.assertTrue(
# u'INFO: ibar\n'
# u'WARN: wbar\n'
# u'DEBUG: dbar\n'
# u'ERROR: ebar\n'
#in ret1['outlog']
# u'INFO: ibar\n'
# u'WARN: wbar\n'
# u'DEBUG: dbar\n'
# u'ERROR: ebar\n'
# in ret1['outlog']
#)
# These lines are throwing pylint errors - disabling for now since we are skipping
# these tests

View File

@ -0,0 +1,72 @@
# -*- coding: utf-8 -*-
'''
:codeauthor: :email:`Jayesh Kariya <jayeshk@saltstack.com>`
'''
# Import Python libs
from __future__ import absolute_import
# Import Salt Testing Libs
from salttesting import skipIf, TestCase
from salttesting.mock import (
NO_MOCK,
NO_MOCK_REASON,
MagicMock,
patch,
mock_open)
from salttesting.helpers import ensure_in_syspath
ensure_in_syspath('../../')
# Import Salt Libs
from salt.states import apache
import salt.utils
apache.__opts__ = {}
apache.__salt__ = {}
@skipIf(NO_MOCK, NO_MOCK_REASON)
class ApacheTestCase(TestCase):
'''
Test cases for salt.states.apache
'''
# 'configfile' function tests: 1
@patch('os.path.exists', MagicMock(return_value=True))
def test_configfile(self):
'''
Test to allows for inputting a yaml dictionary into a file
for apache configuration files.
'''
name = 'yaml'
config = 'VirtualHost: this: "*:80"'
ret = {'name': name,
'result': True,
'changes': {},
'comment': ''}
mock = MagicMock(side_effect=[config, '', ''])
with patch.object(salt.utils, 'fopen', mock_open(read_data=config)):
with patch.dict(apache.__salt__,
{'apache.config': mock}):
ret.update({'comment': 'Configuration is up to date.'})
self.assertDictEqual(apache.configfile(name, config), ret)
ret.update({'comment': 'Configuration will update.',
'changes': {'new': '',
'old': 'VirtualHost: this: "*:80"'},
'result': None})
with patch.dict(apache.__opts__, {'test': True}):
self.assertDictEqual(apache.configfile(name, config), ret)
ret.update({'comment': 'Successfully created configuration.',
'result': True})
with patch.dict(apache.__opts__, {'test': False}):
self.assertDictEqual(apache.configfile(name, config), ret)
if __name__ == '__main__':
from integration import run_tests
run_tests(ApacheTestCase, needs_daemon=False)

View File

@ -0,0 +1,52 @@
# -*- coding: utf-8 -*-
'''
:codeauthor: :email:`Jayesh Kariya <jayeshk@saltstack.com>`
'''
# Import Python libs
from __future__ import absolute_import
# Import Salt Testing Libs
from salttesting import skipIf, TestCase
from salttesting.mock import (
NO_MOCK,
NO_MOCK_REASON,
MagicMock,
patch)
from salttesting.helpers import ensure_in_syspath
ensure_in_syspath('../../')
# Import Salt Libs
from salt.states import apt
apt.__opts__ = {}
apt.__salt__ = {}
@skipIf(NO_MOCK, NO_MOCK_REASON)
class AptTestCase(TestCase):
'''
Test cases for salt.states.apt
'''
# 'held' function tests: 1
def test_held(self):
'''
Test to set package in 'hold' state, meaning it will not be upgraded.
'''
name = 'tmux'
ret = {'name': name,
'result': False,
'changes': {},
'comment': 'Package {0} does not have a state'.format(name)}
mock = MagicMock(return_value=False)
with patch.dict(apt.__salt__, {'pkg.get_selections': mock}):
self.assertDictEqual(apt.held(name), ret)
if __name__ == '__main__':
from integration import run_tests
run_tests(AptTestCase, needs_daemon=False)

View File

@ -0,0 +1,64 @@
# -*- coding: utf-8 -*-
'''
:codeauthor: :email:`Jayesh Kariya <jayeshk@saltstack.com>`
'''
# Import Python libs
from __future__ import absolute_import
# Import Salt Testing Libs
from salttesting import skipIf, TestCase
from salttesting.mock import (
NO_MOCK,
NO_MOCK_REASON,
MagicMock,
patch)
from salttesting.helpers import ensure_in_syspath
ensure_in_syspath('../../')
# Import Salt Libs
from salt.states import artifactory
artifactory.__salt__ = {}
@skipIf(NO_MOCK, NO_MOCK_REASON)
class ArtifactoryTestCase(TestCase):
'''
Test cases for salt.states.artifactory
'''
# 'downloaded' function tests: 1
def test_downloaded(self):
'''
Test to ensures that the artifact from artifactory exists at
given location.
'''
name = 'jboss'
arti_url = 'http://artifactory.intranet.company.com/artifactory'
artifact = {'artifactory_url': arti_url, 'artifact_id': 'module',
'repository': 'libs-release-local', 'packaging': 'jar',
'group_id': 'com.company.module', 'classifier': 'sources',
'version': '1.0'}
ret = {'name': name,
'result': False,
'changes': {},
'comment': ''}
mck = MagicMock(return_value={'status': False, 'changes': {},
'comment': ''})
with patch.dict(artifactory.__salt__, {'artifactory.get_release': mck}):
self.assertDictEqual(artifactory.downloaded(name, artifact), ret)
with patch.object(artifactory, '__fetch_from_artifactory',
MagicMock(side_effect=Exception('error'))):
ret = artifactory.downloaded(name, artifact)
self.assertEqual(ret['result'], False)
self.assertEqual(repr(ret['comment']), repr(Exception('error')))
if __name__ == '__main__':
from integration import run_tests
run_tests(ArtifactoryTestCase, needs_daemon=False)

View File

@ -0,0 +1,109 @@
# -*- coding: utf-8 -*-
'''
:codeauthor: :email:`Jayesh Kariya <jayeshk@saltstack.com>`
'''
# Import Python libs
from __future__ import absolute_import
# Import Salt Testing Libs
from salttesting import skipIf, TestCase
from salttesting.mock import (
NO_MOCK,
NO_MOCK_REASON,
MagicMock,
patch)
from salttesting.helpers import ensure_in_syspath
ensure_in_syspath('../../')
# Import Salt Libs
from salt.states import at
at.__salt__ = {}
at.__opts__ = {}
at.__grains__ = {}
@skipIf(NO_MOCK, NO_MOCK_REASON)
class AtTestCase(TestCase):
'''
Test cases for salt.states.at
'''
# 'present' function tests: 1
def test_present(self):
'''
Test to add a job to queue.
'''
name = 'jboss'
timespec = '9:09 11/04/15'
tag = 'love'
user = 'jam'
ret = {'name': name,
'result': True,
'changes': {},
'comment': ''}
mock = MagicMock(return_value=False)
with patch.dict(at.__opts__, {'test': False}):
with patch.dict(at.__grains__, {'os_family': 'Redhat'}):
with patch.dict(at.__salt__, {'cmd.run': mock}):
ret.update({'comment': False})
self.assertDictEqual(at.present(name, timespec, tag),
ret)
with patch.dict(at.__salt__, {'user.info': mock}):
comt = 'User: {0} is not exists'.format(user)
ret.update({'comment': comt, 'result': False})
self.assertDictEqual(at.present(name, timespec, tag, user),
ret)
with patch.dict(at.__opts__, {'test': True}):
comt = 'job {0} is add and will run on {1}'.format(name, timespec)
ret.update({'comment': comt, 'result': None})
self.assertDictEqual(at.present(name, timespec, tag, user), ret)
# 'absent' function tests: 1
def test_absent(self):
'''
Test to remove a job from queue
'''
name = 'jboss'
ret = {'name': name,
'result': None,
'changes': {},
'comment': ''}
with patch.dict(at.__opts__, {'test': True}):
ret.update({'comment': 'Remove jobs()'})
self.assertDictEqual(at.absent(name), ret)
with patch.dict(at.__opts__, {'test': False}):
comt = 'limit parameter not supported {0}'.format(name)
ret.update({'comment': comt, 'result': False})
self.assertDictEqual(at.absent(name), ret)
mock = MagicMock(return_value={'jobs': []})
mock_bool = MagicMock(return_value=False)
with patch.dict(at.__salt__, {'at.atq': mock,
'cmd.run': mock_bool}):
comt = 'No match jobs or time format error'
ret.update({'comment': comt, 'result': False, 'name': 'all'})
self.assertDictEqual(at.absent('all'), ret)
mock = MagicMock(return_value={'jobs': [{'job': 'rose'}]})
mock_bool = MagicMock(return_value=False)
with patch.dict(at.__salt__, {'at.atq': mock,
'cmd.run': mock_bool}):
comt = "Remove job(rose) from queue but (['rose']) fail"
ret.update({'comment': comt, 'result': True})
self.assertDictEqual(at.absent('all'), ret)
if __name__ == '__main__':
from integration import run_tests
run_tests(AtTestCase, needs_daemon=False)

View File

@ -0,0 +1,78 @@
# -*- coding: utf-8 -*-
'''
:codeauthor: :email:`Jayesh Kariya <jayeshk@saltstack.com>`
'''
# Import Python libs
from __future__ import absolute_import
# Import Salt Testing Libs
from salttesting import skipIf, TestCase
from salttesting.mock import (
NO_MOCK,
NO_MOCK_REASON,
MagicMock,
patch
)
from salttesting.helpers import ensure_in_syspath
ensure_in_syspath('../../')
# Import Salt Libs
from salt.states import augeas
augeas.__opts__ = {}
augeas.__salt__ = {}
@skipIf(NO_MOCK, NO_MOCK_REASON)
class AugeasTestCase(TestCase):
'''
Test cases for salt.states.augeas
'''
# 'change' function tests: 1
def test_change(self):
'''
Test to issue changes to Augeas, optionally for a specific context,
with a specific lens.
'''
name = 'zabbix'
context = '/files/etc/services'
changes = ['ins service-name after service-name[last()]',
'set service-name[last()] zabbix-agent']
ret = {'name': name,
'result': False,
'changes': {},
'comment': ''}
comt = ('\'changes\' must be specified as a list')
ret.update({'comment': comt})
self.assertDictEqual(augeas.change(name), ret)
comt = ('Executing commands in file "/files/etc/services":\n'
'ins service-name after service-name[last()]'
'\nset service-name[last()] zabbix-agent')
ret.update({'comment': comt, 'result': None})
with patch.dict(augeas.__opts__, {'test': True}):
self.assertDictEqual(augeas.change(name, context, changes), ret)
with patch.dict(augeas.__opts__, {'test': False}):
mock = MagicMock(return_value={'retval': False, 'error': 'error'})
with patch.dict(augeas.__salt__, {'augeas.execute': mock}):
ret.update({'comment': 'Error: error', 'result': False})
self.assertDictEqual(augeas.change(name, changes=changes), ret)
chang = ['ins service-name after service-name[last()]',
'set service-name[last()] zabbix-agent']
mock = MagicMock(return_value={'retval': True})
with patch.dict(augeas.__salt__, {'augeas.execute': mock}):
ret.update({'comment': 'Changes have been saved',
'result': True, 'changes': chang})
self.assertDictEqual(augeas.change(name, changes=changes), ret)
if __name__ == '__main__':
from integration import run_tests
run_tests(AugeasTestCase, needs_daemon=False)

View File

@ -0,0 +1,85 @@
# -*- coding: utf-8 -*-
'''
:codeauthor: :email:`Jayesh Kariya <jayeshk@saltstack.com>`
'''
# Import Python libs
from __future__ import absolute_import
# Import Salt Testing Libs
from salttesting import skipIf, TestCase
from salttesting.mock import (
NO_MOCK,
NO_MOCK_REASON,
MagicMock,
patch)
from salttesting.helpers import ensure_in_syspath
ensure_in_syspath('../../')
# Import Salt Libs
from salt.states import aws_sqs
aws_sqs.__salt__ = {}
aws_sqs.__opts__ = {}
@skipIf(NO_MOCK, NO_MOCK_REASON)
class AwsSqsTestCase(TestCase):
'''
Test cases for salt.states.aws_sqs
'''
# 'exists' function tests: 1
def test_exists(self):
'''
Test to ensure the SQS queue exists.
'''
name = 'myqueue'
region = 'eu-west-1'
ret = {'name': name,
'result': None,
'changes': {},
'comment': ''}
mock = MagicMock(side_effect=[False, True])
with patch.dict(aws_sqs.__salt__, {'aws_sqs.queue_exists': mock}):
comt = 'AWS SQS queue {0} is set to be created'.format(name)
ret.update({'comment': comt})
with patch.dict(aws_sqs.__opts__, {'test': True}):
self.assertDictEqual(aws_sqs.exists(name, region), ret)
comt = u'{0} exists in {1}'.format(name, region)
ret.update({'comment': comt, 'result': True})
self.assertDictEqual(aws_sqs.exists(name, region), ret)
# 'absent' function tests: 1
def test_absent(self):
'''
Test to remove the named SQS queue if it exists.
'''
name = 'myqueue'
region = 'eu-west-1'
ret = {'name': name,
'result': None,
'changes': {},
'comment': ''}
mock = MagicMock(side_effect=[True, False])
with patch.dict(aws_sqs.__salt__, {'aws_sqs.queue_exists': mock}):
comt = 'AWS SQS queue {0} is set to be removed'.format(name)
ret.update({'comment': comt})
with patch.dict(aws_sqs.__opts__, {'test': True}):
self.assertDictEqual(aws_sqs.absent(name, region), ret)
comt = u'{0} does not exist in {1}'.format(name, region)
ret.update({'comment': comt, 'result': True})
self.assertDictEqual(aws_sqs.absent(name, region), ret)
if __name__ == '__main__':
from integration import run_tests
run_tests(AwsSqsTestCase, needs_daemon=False)

View File

@ -0,0 +1,108 @@
# -*- coding: utf-8 -*-
'''
:codeauthor: :email:`Jayesh Kariya <jayeshk@saltstack.com>`
'''
# Import Python libs
from __future__ import absolute_import
import os
# Import Salt Testing Libs
from salttesting import skipIf, TestCase
from salttesting.mock import (
NO_MOCK,
NO_MOCK_REASON,
MagicMock,
patch)
from salttesting.helpers import ensure_in_syspath
ensure_in_syspath('../../')
# Import Salt Libs
from salt.states import blockdev
import salt.utils
blockdev.__salt__ = {}
blockdev.__opts__ = {}
@skipIf(NO_MOCK, NO_MOCK_REASON)
class BlockdevTestCase(TestCase):
'''
Test cases for salt.states.blockdev
'''
# 'tuned' function tests: 1
def test_tuned(self):
'''
Test to manage options of block device
'''
name = '/dev/vg/master-data'
ret = {'name': name,
'result': True,
'changes': {},
'comment': ''}
comt = ('Changes to {0} cannot be applied. '
'Not a block device. ').format(name)
with patch.dict(blockdev.__salt__, {'file.is_blkdev': False}):
ret.update({'comment': comt})
self.assertDictEqual(blockdev.tuned(name), ret)
comt = ('Changes to {0} will be applied '.format(name))
with patch.dict(blockdev.__salt__, {'file.is_blkdev': True}):
ret.update({'comment': comt, 'result': None})
with patch.dict(blockdev.__opts__, {'test': True}):
self.assertDictEqual(blockdev.tuned(name), ret)
# 'formatted' function tests: 1
def test_formatted(self):
'''
Test to manage filesystems of partitions.
'''
name = '/dev/vg/master-data'
ret = {'name': name,
'result': False,
'changes': {},
'comment': ''}
with patch.object(os.path, 'exists', MagicMock(side_effect=[False, True,
True, True,
True])):
comt = ('{0} does not exist'.format(name))
ret.update({'comment': comt})
self.assertDictEqual(blockdev.formatted(name), ret)
mock = MagicMock(return_value='ext4')
with patch.dict(blockdev.__salt__, {'cmd.run': mock}):
comt = ('{0} already formatted with '.format(name))
ret.update({'comment': comt, 'result': True})
self.assertDictEqual(blockdev.formatted(name, fs_type=''), ret)
ret.update({'comment': 'Invalid fs_type: ext4',
'result': False})
with patch.object(salt.utils, 'which',
MagicMock(return_value=False)):
self.assertDictEqual(blockdev.formatted(name), ret)
comt = ('Changes to {0} will be applied '.format(name))
ret.update({'comment': comt, 'result': None})
with patch.object(salt.utils, 'which',
MagicMock(return_value=True)):
with patch.dict(blockdev.__opts__, {'test': True}):
self.assertDictEqual(blockdev.formatted(name), ret)
comt = ('Failed to format {0}'.format(name))
ret.update({'comment': comt, 'result': False})
with patch.object(salt.utils, 'which',
MagicMock(return_value=True)):
with patch.dict(blockdev.__opts__, {'test': False}):
self.assertDictEqual(blockdev.formatted(name), ret)
if __name__ == '__main__':
from integration import run_tests
run_tests(BlockdevTestCase, needs_daemon=False)