Merge remote-tracking branch 'upstream/2015.5' into merge-forward-develop

Conflicts:
    doc/man/salt-call.1
    doc/man/salt-cloud.1
    doc/man/salt-cp.1
    doc/man/salt.7
    salt/cloud/__init__.py
    salt/fileclient.py
    salt/modules/file.py
    salt/modules/gpg.py
This commit is contained in:
Colton Myers 2015-06-29 16:49:40 -06:00
commit 99fc7ecb4b
19 changed files with 1002 additions and 312 deletions

View File

@ -11,6 +11,8 @@ There are a number of ways to contribute to Salt development.
For details on how to contribute documentation improvements please review
:ref:`Writing Salt Documentation <salt-docs>`.
.. _github-pull-request:
Sending a GitHub pull request
=============================
@ -41,7 +43,7 @@ Fork a Repo Guide_>`_ and is well worth reading.
isolated into separate branches.
If you're working on a fix, create your branch from the oldest release
branch having the bug. See :ref:`Which Salt Branch?`.
branch having the bug. See :ref:`Which Salt Branch? <which-salt-branch>`.
.. code-block:: bash
@ -155,13 +157,15 @@ Fork a Repo Guide_>`_ and is well worth reading.
Test progress and results can be found at http://jenkins.saltstack.com/.
.. _which-salt-branch:
Which Salt branch?
==================
GitHub will open pull requests against Salt's main branch, ``develop``, by
default. Ideally features should go into ``develop`` and bug fixes should go
into the oldest supported release branch affected by the bug. See
:ref:`Sending a GitHub pull request`.
:ref:`Sending a GitHub pull request <github-pull-request>`.
If you have a bug fix and have already forked your working branch from
``develop`` and do not know how to rebase your commits against another branch,
@ -281,6 +285,8 @@ format-patch`_ and send them to the `salt-users`_ mailing list. The contributor
will then get credit for the patch, and the Salt community will have an archive
of the patch and a place for discussion.
.. _backporting-pull-requests:
Backporting Pull Requests
=========================
@ -355,8 +361,8 @@ Issue and Pull Request Labeling System
======================================
SaltStack uses several labeling schemes to help facilitate code contributions
and bug resolution. See the :doc:`<labels-and-milestones>` documentation for
more information.
and bug resolution. See the :ref:`Labels and Milestones
<labels-and-milestones>` documentation for more information.
.. _`saltstack/salt`: https://github.com/saltstack/salt
.. _`GitHub Fork a Repo Guide`: https://help.github.com/articles/fork-a-repo

View File

@ -291,5 +291,5 @@ Issue and Pull Request Labeling System
--------------------------------------
SaltStack uses several labeling schemes to help facilitate code contributions
and bug resolution. See the :doc:`<labels-and-milestones>` documentation for
more information.
and bug resolution. See the :ref:`Labels and Milestones
<labels-and-milestones>` documentation for more information.

View File

@ -4,284 +4,292 @@
GitHub Labels and Milestones
============================
SaltStack uses several labeling schemes, as well as applying milestones, to triage incoming issues and pull requests in
the GitHub Issue Tracker. Most of the labels and milestones are used for internal tracking, but the following
definitions might prove useful for the community to discover the best issues to help resolve.
SaltStack uses several label categories, as well as milestones, to triage incoming issues and pull requests in the
GitHub issue tracker. Labels are used to sort issues by type, priority, severity, status, functional area, functional
group, and targeted release and pull requests by status, functional area, functional group, type of change, and test
status. Milestones are used to indicate whether an issue is fully triaged or is scheduled to be fixed by SaltStack in
an upcoming sprint.
Milestones
==========
Milestones are most often applied to issues, as a milestone is assigned to every issue that has been triaged. However,
milestones can also be applied to pull requests. SaltStack uses milestones to track bugs or features that should be
included in the next major feature release, or even the next bug-fix release, as well as what issues are ready to be
worked on or what might be blocked. All incoming issues must have a milestone associated with them.
All issues are assigned to a milestone, whereas pull requests are almost never assigned to a milestone as the mean
lifetime of pull requests is short enough that there is no need to track them temporally.
Approved
Used to indicate that this issue has all of the needed information and is ready to be worked on.
SaltStack uses milestones to indicate which issues are blocked on submitter or upstream actions, are approved, or are
scheduled to be fixed or implemented in an upcoming sprint. If an issue is not attached to a sprint milestone, you are
welcome to work on it at your own desire and convenience. If it is attached to a sprint milestone and you have already
begun working on it or have a solution in mind or have other ideas related to the issue, you are encouraged to
coordinate with the assignee via the GitHub issue tracker to create the best possible solution or implementation.
Blocked
Used to indicate that the issue is not ready to be worked on yet. This typically applies to issues that have been
labeled with “Info Needed”, “Question”, “Expected Behavior”, “Wont Fix for Now”, etc.
``Approved``
The issue has been validated and has all necessary information.
Dot or Bug-fix Release
Used to help filter/identify what issues must be fixed before the release such as 2014.7.4 or 2015.2.3. This
milestone is often used in conjunction with the ``Blocker`` label, but not always.
``Blocked``
The issue is waiting on actions by parties outside of SaltStack, such as receiving more information from the
submitter or resolution of an upstream issue. This milestone is usually applied in conjunction with the labels
``Info Needed``, ``Question``, ``Expected Behavior``, ``Won't Fix For Now``, or ``Upstream Bug``.
Feature Release
Similar to the Dot or Bug-fix Release milestone, but for upcoming feature releases such as Boron, Carbon, etc.
This milestone is often used in conjunction with the ``Blocker`` label, but not always.
``Under Review``
The issue is having further validation done by a SaltStack engineer.
``<Sprint>``
The issue is being actively worked on by a SaltStack engineer. Sprint milestones names are constructed from the
chemical symbol of the next release's codename and the number of sprints until that release is made. For example,
if the next release codename is ``Neon`` and there are five sprints until that release, the corresponding sprint
milestone will be called ``Ne 5``. See :doc:`<topics/releases/version_numbers>` for a discussion of Salt's release
codenames.
Labels
======
Labels are used to facilitate the resolution of new pull requests and open issues. Most labels are confined to being
applied to either issues or pull requests, though some labels may be applied to both.
Labels are used to sort and describe issues and pull requests. Some labels are usually reserved for one or the other,
though most labels may be applied to both.
Issue Labels
------------
New issues will receive at least one label and a milestone, and new pull requests will receive at least one label.
Except for the :ref:`functional area <functional-area-labels>` and :ref:`functional group <functional-group-labels>`
label categories, issues will generally receive only up to one label per category.
All incoming issues should be triaged with at least one label and a milestone. When a new issue comes in, it should be
determined if the issue is a bug or a feature request, and either of those labels should be applied accordingly. Bugs
and Feature Requests have differing labeling schemes, detailed below, where other labels are applied to them to further
help contributors find issues to fix or implement.
Type
----
There are some labels, such as ``Question`` or some of the "Status" labels that may be applied as "stand alone" labels
in which more information may be needed or a decision must be reached on how to proceed. (See the "Bug Status Labels"
section below.)
Issues are categorized into one of several types. Type labels are almost never used for pull requests. GitHub treats
pull requests like issues in many ways, so a pull request could be considered an issue with an implicit ``Pull Request``
type label applied.
Features
~~~~~~~~
``Feature``
The issue is a request for new functionality including changes, enhancements, refactors, etc.
The ``Feature`` label should be applied when a user is requesting entirely new functionality. This can include new
functions, modules, states, modular systems, flags for existing functions, etc. Features *do not* receive severity
or priority labels, as those labels are only used for bugs. However, they may receive "Functional Area" labels or "ZD".
``Bug``
The issue documents broken, incorrect, or confusing behavior. This label is always accompanied by a :ref:`severity
label <bug-severity-labels>`.
Feature request issues will be prioritized on an "as-needed" basis using milestones during SaltStack's feature release
and sprint planning processes.
``Duplicate``
The issue is a duplicate of another feature request or bug report.
Bugs
~~~~
``Upstream Bug``
The issue is a result of an upstream issue.
All bugs should have the ``Bug`` label as well as a severity, priority, functional area, and a status, as applicable.
``Question``
The issue is more of a question than a request for new features or a report of broken features, but can sometimes
lead to further discussion or changes of confusing or incongruous behavior or documentation.
Severity
^^^^^^^^
How severe is the bug? SaltStack uses four labels to determine the severity of a bug: ``Blocker``, ``Critical``,
``High``, and ``Medium``. This scale is intended to make the bug-triage process as objective as possible.
Blocker
Should be used sparingly to indicate must-have fixes for the impending release.
Critical
Applied to bugs that have data loss, crashes, hanging, unresponsive system, etc.
High Severity
Any bug report that contains incorrect functionality, bad functionality, a confusing user experience, etc.
Medium Severity
Applied to bugs that are about cosmetic items, spelling, spacing, colors, etc.
``Expected Behavior``
The issue is a bug report of intended functionality.
Priority
^^^^^^^^
--------
In addition to using a bug severity to classify issues, a priority is also assigned to each bug to give further
granularity in searching for bugs to fix. In this way, a bug's priority is defined as follows:
An issue's priority is relative to its :ref:`functional area <functional-area-labels>`. If a bug report, for example,
about ``gitfs`` indicates that all users of ``gitfs`` will encounter this bug, then a ``P1`` label will be applied, even
though users who are not using ``gitfs`` will not encounter the bug. If a feature is requested by many users, it may be
given a high priority.
P1
Very likely. Everyone will see the bug.
``P1``
The issue will be seen by all users.
P2
Somewhat likely. Most will see the bug, but a few will not.
``P2``
The issue will be seen by most users.
P3
Half will see the bug, about half will not.
``P3``
The issue will be seen by about half of users.
P4
Most will not see the bug. Usually a very specific use case or corner case.
``P4``
The issue will not be seen by most users. Usually the issue is a very specific use case or corner case.
.. note::
.. _bug-severity-labels:
A bug's priority is relative to its functional area. If a bug report, for example, about ``gitfs`` includes details
indicating that everyone who ``gitfs`` will run into this bug, then a ``P1`` label will be applied, even though
Salt users who are not enabling ``gitfs`` will see the bug.
Severity
--------
Functional Areas
^^^^^^^^^^^^^^^^
Severity labels are almost always only applied to issues labeled ``Bug``.
All bugs should receive a "Functional Area" label to indicate what region of Salt the bug is mainly seen in. This will
help internal developers as well as community members identify areas of expertise to find issues that can be fixed more
easily. Functional Area labels can also be applied to Feature Requests.
``Blocker``
The issue is blocking an impending release.
Functional Area Labels, in alphabetical order, include:
``Critical``
The issue causes data loss, crashes or hangs salt processes, makes the system unresponsive, etc.
* Core
* Documentation
* Execution Module
* File Servers
* Multi-Master
* Packaging
* Pillar
* Platform Mgmt.
* RAET
* Returners
* Salt-API
* Salt-Cloud
* Salt-SSH
* Salt-Syndic
* State Module
* Windows
* ZMQ
``High Severity``
The issue reports incorrect functionality, bad functionality, a confusing user experience, etc.
Bug Status Labels
^^^^^^^^^^^^^^^^^
``Medium Severity``
The issue reports cosmetic items, formatting, spelling, colors, etc.
Status lables are used to define and track the state a bug is in at any given time. Not all bugs will have a status
label, but if a SaltStack employee is able to apply a status label, he or she will. Status labels are somewhat unique
in the fact that they might be the only label on an issue, such as ``Pending Discussion``, ``Info Needed``, or
``Expected Behavior`` until further action can be taken.
.. _functional-area-labels:
Cannot Reproduce
Someone from the SaltStack team has tried to reproduce the bug with the given information but they are unable to
replicate the problem. More information will need to be provided from the original issue-filer before proceeding.
Functional Area
---------------
Confirmed
A SaltStack engineer has confirmed the reported bug and provided a simple way to reproduce the failure.
Many major components of Salt have corresponding GitHub labels. These labels are applied to all issues and pull
requests as is reasonably appropriate. They are useful in organizing issues and pull requests according to the source
code relevant to issues or the source code changed by pull requests.
Duplicate
The issue has been reported already in another report. A link to the other bug report must be provided. At that
point the new issue can be closed. Usually, the earliest bug on file is kept as that typically has the most
discussion revolving around the issue, though not always. (This can be a "stand-alone" label.)
* ``Execution Module``
* ``File Servers``
* ``Grains``
* ``Multi-Master``
* ``Packaging`` Related to packaging of Salt, not Salt's support for package management.
* ``Pillar``
* ``RAET``
* ``Returners``
* ``Runners``
* ``Salt-API``
* ``Salt-Cloud``
* ``Salt-SSH``
* ``Salt-Syndic``
* ``State Module``
* ``Tests``
* ``Transport``
* ``Windows``
* ``ZMQ``
Expected Behavior
The issue reported is expected behavior and nothing needs to be fixed. (This can be a "stand-alone" label.)
.. _functional-group-labels:
Fixed Pending Verification
The bug has been fixed and a link to the applicable pull request(s) has been provided, but confirmation is being
sought from the community member(s) involved in the bug to test and confirm the fix.
Functional Group
----------------
Info Needed
More information about the issue is needed before proceeding such as a versions report, a sample state, the command
the user was running, or the operating system the error was occurring on, etc. (This can be a "stand-alone" label.)
These labels sort issues and pull requests according to the internal SaltStack engineering teams.
Upstream Bug
The reported bug is something that cannot be fixed in the Salt code base but is instead a bug in another library
such a bug in ZMQ or Python. When an issue is labeled with ``Upstream Bug`` then a bug report in the upstream
project must be filed (or found if a report already exists) and a link to the report must be provided to the issue
in Salt for tracking purposes. (This can be a stand-alone label.)
``Core``
The issue or pull request relates to code that is central or existential to Salt itself.
Won't Fix for Now
The SaltStack team has acknowledged the issue at hand is legitimate, but made the call that its not something
theyre able or willing to fix at this time. These issues may be revisited in the future.
``Platform``
The issue or pull request relates to support and integration with various platforms like traditional operating
systems as well as containers, platform-based utilities like filesystems, command schedulers, etc., and
system-based applications like webservers, databases, etc.
Other
~~~~~
``RIoT``
The issue or pull request relates to support and integration with various abstract systems like cloud providers,
hypervisors, API-based services, etc.
There are a couple of other labels that are helpful in categorizing bugs that are not included in the categories above.
These labels can either stand on their own such as ``Question`` or can be applied to bugs or feature requests as
applicable.
``Console``
The issue or pull request relates to the SaltStack enterprise console.
Low Hanging Fruit
Applied to bugs that should be easy to fix. This is useful for new contributors to know where some simple things
are to get involved in contributing to salt.
``Documentation``
The issue or pull request relates to documentation.
Question
Used when the issue isnt a bug nor a feature, but the user has a question about expected behavior, how something
works, is misunderstanding a concept, etc. This label is typically applied on its own with ``Blocked`` milestone.
Status
------
Regression
Helps with additional filtering for bug fixing. If something previously worked and now does not work, as opposed to
something that never worked in the first place, the issue should be treated with greater urgency.
Status labels are used to define and track the state of issues and pull requests. Not all potential statuses correspond
to a label, but some statuses are common enough that labels have been created for them. If an issue has not been moved
beyond the ``Blocked`` milestone, it is very likely that it will only have a status label.
ZD
Stands for “Zendesk” and is used to help track bugs that customers are seeing as well as community members. Bugs
with this label should be treated with greater urgency.
``Bugfix - back-port``
The pull request needs to be back-ported to an older release branch. This is done by :ref:`recreating the pull
request <backporting-pull-requests>` against that branch. Once the back-port is completed, this label is replaced
with a ``Bugfix - [Done] back-ported`` label. Normally, new features should go into the develop and bug fixes into
the oldest supported release branch, see :ref:`<which-salt-branch>`.
Pull Request Labels
-------------------
``Bugfix - [Done] back-ported``
The pull request has been back-ported to an older branch.
SaltStack also applies various labels to incoming pull requests. These are mainly used to help SaltStack engineers
easily identify the nature the changes presented in a pull request and whether or not that pull request is ready to be
reviewed and merged into the Salt codebase.
``Cannot Reproduce``
The issue is a bug and has been reviewed by a SaltStack engineer, but it cannot be replicated with the provided
information and context. Those involved with the bug will need to work through additional ideas until the bug can
be isolated and verified.
``Confirmed``
The issue is a bug and has been confirmed by a SaltStack engineer, who often documents a minimal working example
that reproduces the bug.
``Fixed Pending Verification``
The issue is a bug and has been fixed by one or more pull requests, which should link to the issue. Closure of the
issue is contingent upon confirmation of resolution from the submitter. If the submitter reports a negative
confirmation, this label is removed. If no response is given after a few weeks, then the issue will be assumed
fixed and closed.
``Info Needed``
The issue needs more information before it can be verified and resolved. For a feature request this may include a
description of the use cases. Almost all bug reports need to include at least the versions of salt and its
dependencies, the system type and version, commands used, debug logs, error messages, and relevant configs.
``Pending Changes``
The pull request needs additional changes before it can be merged.
``Pending Discussion``
The issue or pull request needs more discussion before it can be closed or merged. The status of the issue or pull
request is not clear or apparent enough for definite action to be taken, or additional input from SaltStack, the
submitter, or another party has been requested.
If the issue is not a pull request, once the discussion has arrived at a cogent conclusion, this label will be
removed and the issue will be accepted. If it is a pull request, the results of the discussion may require
additional changes and thus, a ``Pending Changes`` label.
``Won't Fix for Now``
The issue is legitimate, but it is not something the SaltStack team is currently able or willing to fix or
implement. Issues having this label may be revisited in the future.
Type of Change
~~~~~~~~~~~~~~
A "* Change" label is applied to each incoming pull request. The type of change label that is applied to a pull request
is based on a scale that encompasses the number of lines affected by the change in conjunction with the area of code
the change touches (i.e. core code areas vs. execution or state modules).
Every pull request should receive a change label. These labels measure the quantity of change as well as the
significance of the change. The amount of change and the importance of the code area changed are considered, but often
the depth of secondary code review required and the potential repercussions of the change may also advise the label
choice.
The conditions given for these labels are recommendations, as the pull request reviewer will also consult their
intuition and experience regarding the magnitude of the impact of the proposed changes in the pull request.
Core code areas include: state compiler, crypto engine, master and minion and syndic daemons, transport, pillar
rendering, loader, transport layer, event system, salt.utils, client, cli, logging, netapi, runner engine, templating
engine, top file compilation, file client, file server, mine, salt-ssh, test runner, etc.
Core code areas include: state compiler, crypto engine, master and minion, transport, pillar rendering, loader,
transport layer, event system, salt.utils, client, cli, logging, netapi, runner engine, templating engine, top file
compilation, file client, file server, mine, salt-ssh, test runner, etc.
Non-core code usually constitutes the specific set of plugins for each of the several plugin layers of Salt: execution
modules, states, runners, returners, clouds, etc.
* Minor Change
``Minor Change``
* Less than 64 lines changed, or
* Less than 8 core lines changed
* Medium Change
``Medium Change``
* Less than 256 lines changed, or
* Less than 64 core lines changed
* Master Change
``Master Change``
* More than 256 lines changed, or
* More than 64 core lines changed
* Expert Change
``Expert Change``
* Needs specialized, in-depth review
Back-port Labels
~~~~~~~~~~~~~~~~
Test Status
-----------
There are two labels that are used to keep track of what pull requests need to be back-ported to an older release branch
and which pull requests have already been back-ported.
These labels relate to the status of the automated tests that run on pull requests. If the tests on a pull request fail
and are not overridden by one of these labels, the pull request submitter needs to update the code and/or tests so that
the tests pass and the pull request can be merged.
Bugfix - back-port
Indicates a pull request that needs to be back-ported. Once the back-port is completed, the back-porting pull request
is linked to the original pull request and this label is removed.
``Lint``
The pull request has passed all tests except for the code lint checker.
Bugfix - [Done] back-ported
Indicates a pull request that has been back-ported to another branch. The pull request that is responsible for the
backport should be linked to this original pull request.
``Tests Passed``
The pull request has passed all tests even though some test results are negative. Sometimes the automated testing
infrastructure will encounter internal errors unrelated to the code change in the pull request that cause test runs
to fail. These errors can be caused by cloud provider and network issues and also Jenkins issues like erroneously
accumulating workspace artifacts, resource exhaustion, and bugs that arise from long running Jenkins processes.
Testing Labels
~~~~~~~~~~~~~~
Other
-----
There are a couple of labels that the QA team uses to indicate the mergability of a pull request. If the pull request is
legitimately passing or failing tests, then one or more of these labels may be applied.
These labels indicate miscellaneous issue types or statuses that are common or important enough to be tracked and sorted
with labels.
Lint
If a pull request fails the test run, but the only failures are related pylint errors, this label will be applied to
indicate that pylint needs to be fixed before proceeding.
``Awesome``
The pull request implements an especially well crafted solution, or a very difficult but necessary change.
Pending Changes
Indicates that additional commits should be added to the original pull request before the pull request is merged
into the codebase. These changes are unrelated to fixing tests and are generally needed to round out any unfinished
pull requests.
``Low Hanging Fruit``
The issue is trivial or almost trivial to implement or fix. Issues having this label should be a good starting
place for new contributors to Salt.
Tests Passed
Sometimes the Jenkins test run encounters problems, either tests that are known to have reliability issues or a
test VM failed to build, but the problems are not related to the code changed in the pull request. This label is
used to indicate that someone has reviewed the test failures and has deemed the failures to be non-pertinent.
``Needs Testcase``
The issue or pull request relates to a feature that needs test coverage. The pull request containing the tests
should reference the issue or pull request having this label, whereupon the label should be removed.
Other Pull Request Labels
~~~~~~~~~~~~~~~~~~~~~~~~~
``Regression``
The issue is a bug that breaks functionality known to work in previous releases.
Awesome
Applied to pull requests that implemented a cool new feature or fixed a bug in an excellent way.
``Story``
The issue is used by a SaltStack engineer to track progress on multiple related issues in a single place.
Labels that Bridge Issues and Pull Requests
===========================================
``ZD``
The issue is related to a Zendesk customer support ticket.
Needs Testcase
Used by SaltStack's QA team to realize where pain points are and to bring special attention to where some test
coverage needs to occur, especially in areas that have regressed. This label can apply to issues or pull requests,
which can also be open or closed. Once tests are written, the pull request containing the tests should be linked to
the issue or pull request that originally had the ``Needs Testcase`` label. At this point, the ``Needs Testcase``
label must be removed to indicate that tests no longer need to be written.
Pending Discussion
If this label is applied to an issue, the issue may or may not be a bug. Enough information was provided about the
issue, but some other opinions on the issue are desirable before proceeding. (This can be a "stand-alone" label.)
If the label is applied to a pull request, this is used to signal that further discussion must occur before a
decision is made to either merge the pull request into the code base or to close it all together.
``<Release>``
The issue is scheduled to be implemented by ``<Release>``. See :doc:`<topics/releases/version_numbers>` for a
discussion of Salt's release codenames.

View File

@ -14,7 +14,7 @@
grouping="require_all"
restart_on="none"
type="path">
<service_fmri value='file:///opt/local/etc/salt/minion'/>
<service_fmri value="file:///opt/local/etc/salt/minion"/>
</dependency>
<dependency name="network"
@ -31,17 +31,17 @@
<service_fmri value="svc:/system/filesystem/local"/>
</dependency>
<method_context>
<method_environment>
<envvar name='PATH'
value='/usr/local/sbin:/usr/local/bin:/opt/local/sbin:/opt/local/bin:/usr/sbin:/usr/bin:/sbin'/>
</method_environment>
</method_context>
<exec_method type="method"
name="start"
exec="/opt/local/bin/salt-minion -c %{config_dir}"
timeout_seconds="60"/>
timeout_seconds="60">
<method_context>
<method_environment>
<envvar name="PATH"
value="/usr/local/sbin:/usr/local/bin:/opt/local/sbin:/opt/local/bin:/usr/sbin:/usr/bin:/sbin"/>
</method_environment>
</method_context>
</exec_method>
<exec_method type="method"
name="stop"

View File

@ -1365,6 +1365,9 @@ class Cloud(object):
except IOError:
main_cloud_config = {}
if main_cloud_config is None:
main_cloud_config = {}
profile_details = self.opts['profiles'][profile]
alias, driver = profile_details['provider'].split(':')
mapped_providers = self.map_providers_parallel()
@ -1540,9 +1543,13 @@ class Cloud(object):
# Mis-configured provider that got removed?
log.warn(
'The cloud driver, {0!r}, configured under the '
'{1!r} cloud provider alias was not loaded since '
'\'{2}()\' could not be found. Removing it from '
'the available providers list.'.format(
'{1!r} cloud provider alias, could not be loaded. '
'Please check your provider configuration files and '
'ensure all required dependencies are installed '
'for the {0!r} driver.\n'
'In rare cases, this could indicate the \'{2}()\' '
'function could not be found.\nRemoving {0!r} from '
'the available providers list'.format(
driver, alias, fun
)
)

View File

@ -80,19 +80,22 @@ def get_configured_provider():
'''
Return the first configured instance.
'''
warn_until(
'Beryllium',
'The digital_ocean driver is deprecated and will be removed in Salt Beryllium. '
'Please convert your digital ocean provider configs to use the digital_ocean_v2 '
'driver.'
)
return config.is_provider_configured(
configuration = config.is_provider_configured(
__opts__,
__active_provider_name__ or 'digital_ocean',
('personal_access_token',)
)
if configuration:
warn_until(
'Beryllium',
'The digital_ocean driver is deprecated and will be removed in Salt Beryllium. '
'Please convert your digital ocean provider configs to use the digital_ocean_v2 '
'driver.'
)
return configuration
def avail_locations(call=None):
'''

View File

@ -1348,14 +1348,13 @@ def prepend_root_dir(opts, path_options):
'root_dir' option.
'''
root_dir = os.path.abspath(opts['root_dir'])
root_opt = opts['root_dir'].rstrip(os.sep)
for path_option in path_options:
if path_option in opts:
if opts[path_option].startswith(opts['root_dir']):
opts[path_option] = opts[path_option][len(opts['root_dir']):]
opts[path_option] = salt.utils.path_join(
root_dir,
opts[path_option]
)
path = opts[path_option]
if path == root_opt or path.startswith(root_opt + os.sep):
path = path[len(root_opt):]
opts[path_option] = salt.utils.path_join(root_dir, path)
def insert_system_path(opts, paths):

View File

@ -366,11 +366,14 @@ class Client(object):
self.opts['cachedir'], 'localfiles', path.lstrip('|/'))
filesdest = os.path.join(
self.opts['cachedir'], 'files', saltenv, path.lstrip('|'))
extrndest = self._extrn_path(path, saltenv)
if os.path.exists(filesdest):
return salt.utils.url.escape(filesdest) if escaped else filesdest
elif os.path.exists(localsfilesdest):
return salt.utils.url.escape(localsfilesdest) if escaped else localsfilesdest
elif os.path.exists(extrndest):
return extrndest
return ''
@ -546,13 +549,7 @@ class Client(object):
netloc = salt.utils.sanitize_win_path_string(url_data.netloc)
else:
netloc = url_data.netloc
dest = salt.utils.path_join(
self.opts['cachedir'],
'extrn_files',
saltenv,
netloc,
url_data.path
)
dest = self._extrn_path(url, saltenv)
destdir = os.path.dirname(dest)
if not os.path.isdir(destdir):
os.makedirs(destdir)
@ -681,13 +678,7 @@ class Client(object):
return ''
if not dest:
# No destination passed, set the dest as an extrn_files cache
dest = salt.utils.path_join(
self.opts['cachedir'],
'extrn_files',
saltenv,
url_data.netloc,
url_data.path
)
dest = self._extrn_path(url, saltenv)
# If Salt generated the dest name, create any required dirs
makedirs = True
@ -701,6 +692,20 @@ class Client(object):
shutil.move(data['data'], dest)
return dest
def _extrn_path(self, url, saltenv):
'''
Return the extn_filepath for a given url
'''
url_data = urlparse(url)
return salt.utils.path_join(
self.opts['cachedir'],
'extrn_files',
saltenv,
url_data.netloc,
url_data.path
)
class LocalClient(Client):
'''

View File

@ -3144,8 +3144,61 @@ def get_managed(
# Copy the file to the minion and templatize it
sfn = ''
source_sum = {}
# if we have a source defined, lets figure out what the hash is
if source:
urlparsed_source = _urlparse(source)
if urlparsed_source.scheme == 'salt':
source_sum = __salt__['cp.hash_file'](source, saltenv)
if not source_sum:
return '', {}, 'Source file {0} not found'.format(source)
# if its a local file
elif urlparsed_source.scheme == 'file':
source_sum = get_hash(urlparsed_source.path)
elif source.startswith('/'):
source_sum = get_hash(source)
elif source_hash:
protos = ('salt', 'http', 'https', 'ftp', 'swift')
if _urlparse(source_hash).scheme in protos:
# The source_hash is a file on a server
hash_fn = __salt__['cp.cache_file'](source_hash, saltenv)
if not hash_fn:
return '', {}, 'Source hash file {0} not found'.format(
source_hash)
source_sum = extract_hash(hash_fn, '', name)
if source_sum is None:
return '', {}, ('Source hash file {0} contains an invalid '
'hash format, it must be in the format <hash type>=<hash>.'
).format(source_hash)
else:
# The source_hash is a hash string
comps = source_hash.split('=')
if len(comps) < 2:
return '', {}, ('Source hash file {0} contains an '
'invalid hash format, it must be in '
'the format <hash type>=<hash>'
).format(source_hash)
source_sum['hsum'] = comps[1].strip()
source_sum['hash_type'] = comps[0].strip()
else:
return '', {}, ('Unable to determine upstream hash of'
' source file {0}').format(source)
# if the file is a template we need to actually template the file to get
# a checksum, but we can cache the template itself, but only if there is
# a template source (it could be a templated contents)
if template and source:
sfn = __salt__['cp.cache_file'](source, saltenv)
# check if we have the template cached
template_dest = __salt__['cp.is_cached'](source, saltenv)
if template_dest:
comps = source_hash.split('=')
cached_template_sum = get_hash(template_dest, form=source_sum['hash_type'])
if cached_template_sum == source_sum['hsum']:
sfn = template_dest
# if we didn't have the template file, lets get it
if not sfn:
sfn = __salt__['cp.cache_file'](source, saltenv)
# exists doesn't play nice with sfn as bool
# but if cache failed, sfn == False
if not sfn or not os.path.exists(sfn):
@ -3184,40 +3237,7 @@ def get_managed(
else:
__clean_tmp(sfn)
return sfn, {}, data['data']
else:
# Copy the file down if there is a source
if source:
if _urlparse(source).scheme == 'salt':
source_sum = __salt__['cp.hash_file'](source, saltenv)
if not source_sum:
return '', {}, 'Source file {0!r} not found'.format(source)
elif source_hash:
protos = ['salt', 'http', 'https', 'ftp', 'swift', 's3', 'file']
if _urlparse(source_hash).scheme in protos:
# The source_hash is a file on a server
hash_fn = __salt__['cp.cache_file'](source_hash, saltenv)
if not hash_fn:
return '', {}, 'Source hash file {0} not found'.format(
source_hash)
source_sum = extract_hash(hash_fn, '', name)
if source_sum is None:
return '', {}, ('Source hash file {0} contains an invalid '
'hash format, it must be in the format <hash type>=<hash>.'
).format(source_hash)
else:
# The source_hash is a hash string
comps = source_hash.split('=')
if len(comps) < 2:
return '', {}, ('Source hash file {0} contains an '
'invalid hash format, it must be in '
'the format <hash type>=<hash>'
).format(source_hash)
source_sum['hsum'] = comps[1].strip()
source_sum['hash_type'] = comps[0].strip()
else:
return '', {}, ('Unable to determine upstream hash of'
' source file {0}').format(source)
return sfn, source_sum, ''

View File

@ -218,7 +218,6 @@ def list_keys(user=None, gnupghome=None):
salt '*' gpg.list_keys
'''
log.debug('GPG_1_3_1 {0}'.format(GPG_1_3_1))
_keys = []
for _key in _list_keys(user, gnupghome):
tmp = {}
@ -641,22 +640,36 @@ def import_key(user=None,
except IOError:
raise SaltInvocationError('filename does not exist.')
import_result = gpg.import_keys(text)
counts = import_result.counts
log.debug('imported_data {0}'.format(list(import_result.__dict__.keys())))
log.debug('imported_data {0}'.format(counts))
imported_data = gpg.import_keys(text)
if counts.get('imported') or counts.get('imported_rsa'):
ret['message'] = 'Successfully imported key(s).'
elif counts.get('unchanged'):
ret['message'] = 'Key(s) already exist in keychain.'
elif counts.get('not_imported'):
ret['res'] = False
ret['message'] = 'Unable to import key.'
elif not counts.get('count'):
ret['res'] = False
ret['message'] = 'Unable to import key.'
# include another check for Salt unit tests
gnupg_version = distutils.version.LooseVersion(gnupg.__version__)
if gnupg_version >= '1.3.1':
GPG_1_3_1 = True
if GPG_1_3_1:
counts = imported_data.counts
if counts.get('imported') or counts.get('imported_rsa'):
ret['message'] = 'Successfully imported key(s).'
elif counts.get('unchanged'):
ret['message'] = 'Key(s) already exist in keychain.'
elif counts.get('not_imported'):
ret['res'] = False
ret['message'] = 'Unable to import key.'
elif not counts.get('count'):
ret['res'] = False
ret['message'] = 'Unable to import key.'
else:
if imported_data.imported or imported_data.imported_rsa:
ret['message'] = 'Successfully imported key(s).'
elif imported_data.unchanged:
ret['message'] = 'Key(s) already exist in keychain.'
elif imported_data.not_imported:
ret['res'] = False
ret['message'] = 'Unable to import key.'
elif not imported_data.count:
ret['res'] = False
ret['message'] = 'Unable to import key.'
return ret

View File

@ -1164,3 +1164,30 @@ def default_route(family=None):
ret.append(route)
return ret
def get_route(ip):
'''
Return routing information for given destination ip
.. versionadded:: 2015.5.3
CLI Example::
salt '*' network.get_route 10.10.10.10
'''
if __grains__['kernel'] == 'Linux':
cmd = 'ip route get {0}'.format(ip)
out = __salt__['cmd.run'](cmd, python_shell=True)
regexp = re.compile(r'(via\s+(?P<gateway>[\w\.:]+))?\s+dev\s+(?P<interface>[\w\.\:]+)\s+.*src\s+(?P<source>[\w\.:]+)')
m = regexp.search(out.splitlines()[0])
ret = {
'destination': ip,
'gateway': m.group('gateway'),
'interface': m.group('interface'),
'source': m.group('source')}
return ret
else:
raise CommandExecutionError('Not yet supported on this platform')

View File

@ -119,10 +119,13 @@ def install(pkg=None,
elif pkgs:
cmd += ' "{0}"'.format('" "'.join(pkgs))
if env is None:
env = {}
if runas:
uid = salt.utils.get_uid(runas)
if uid:
env.update({'SUDO_UID': uid, 'SUDO_USER': ''})
env.update({'SUDO_UID': b'{0}'.format(uid), 'SUDO_USER': b''})
result = __salt__['cmd.run_all'](cmd, python_shell=False, cwd=dir, runas=runas, env=env)
@ -188,10 +191,13 @@ def uninstall(pkg,
'''
if env is None:
env = {}
if runas:
uid = salt.utils.get_uid(runas)
if uid:
env.update({'SUDO_UID': uid, 'SUDO_USER': ''})
env.update({'SUDO_UID': b'{0}'.format(uid), 'SUDO_USER': b''})
cmd = 'npm uninstall'
@ -245,10 +251,13 @@ def list_(pkg=None,
'''
if env is None:
env = {}
if runas:
uid = salt.utils.get_uid(runas)
if uid:
env.update({'SUDO_UID': uid, 'SUDO_USER': ''})
env.update({'SUDO_UID': b'{0}'.format(uid), 'SUDO_USER': b''})
cmd = 'npm list --silent --json'

View File

@ -268,7 +268,8 @@ class EventListener(object):
# request_obj -> list of (tag, future)
self.request_map = defaultdict(list)
self.timeout_map = {} # map of future -> timeout_callback
# map of future -> timeout_callback
self.timeout_map = {}
self.stream = zmqstream.ZMQStream(self.event.sub,
io_loop=tornado.ioloop.IOLoop.current())
@ -281,7 +282,14 @@ class EventListener(object):
if request not in self.request_map:
return
for tag, future in self.request_map[request]:
# timeout the future
self._timeout_future(tag, future)
# remove the timeout
if future in self.timeout_map:
tornado.ioloop.IOLoop.current().remove_timeout(self.timeout_map[future])
del self.timeout_map[future]
del self.request_map[request]
def get_event(self,
request,
@ -292,6 +300,13 @@ class EventListener(object):
'''
Get an event (async of course) return a future that will get it later
'''
# if the request finished, no reason to allow event fetching, since we
# can't send back to the client
if request._finished:
future = Future()
future.set_exception(TimeoutException())
return future
future = Future()
if callback is not None:
def handle_future(future):

View File

@ -1136,14 +1136,15 @@ def installed(
if modified_hold:
for i in modified_hold:
comment.append(i['comment'])
change_name = i['name']
if len(changes[change_name]['new']) > 0:
changes[change_name]['new'] += '\n'
changes[change_name]['new'] += '{0}'.format(i['changes']['new'])
if len(changes[change_name]['old']) > 0:
changes[change_name]['old'] += '\n'
changes[change_name]['old'] += '{0}'.format(i['changes']['old'])
if change_name in changes:
comment.append(i['comment'])
if len(changes[change_name]['new']) > 0:
changes[change_name]['new'] += '\n'
changes[change_name]['new'] += '{0}'.format(i['changes']['new'])
if len(changes[change_name]['old']) > 0:
changes[change_name]['old'] += '\n'
changes[change_name]['old'] += '{0}'.format(i['changes']['old'])
# Any requested packages that were not targeted for install or reinstall
if not_modified:

View File

@ -103,7 +103,7 @@ def top(**kwargs):
environment_field = __opts__['master_tops']['mongo'].get('environment_field', 'environment')
log.info('connecting to {0}:{1} for mongo ext_tops'.format(host, port))
conn = pymongo.Connection(host, port)
conn = pymongo.MongoClient(host, port)
log.debug('using database \'{0}\''.format(__opts__['mongo.db']))
mdb = conn[__opts__['mongo.db']]
@ -127,7 +127,7 @@ def top(**kwargs):
)
)
result = mdb[collection].find_one({id_field: minion_id}, fields=[states_field, environment_field])
result = mdb[collection].find_one({id_field: minion_id}, projection=[states_field, environment_field])
if result and states_field in result:
if environment_field in result:
environment = result[environment_field]

View File

@ -540,6 +540,7 @@ class TestWebhookSaltAPIHandler(SaltnadoTestCase):
self.assertIn('headers', event['data'])
self.assertEqual(event['data']['post'], {'foo': 'bar'})
# get an event future
self._finished = False # TODO: remove after some cleanup of the event listener
event = self.application.event_listener.get_event(self,
tag='salt/netapi/hook',
callback=verify_event,

View File

@ -37,7 +37,7 @@ RET = [{'created': '2014-07-25',
class Mockgnupg(object):
'''
Mock smtplib class
Mock gnupg class
'''
__version__ = '1.3.1'
fingerprint = u'F321F'
@ -54,7 +54,7 @@ class Mockgnupg(object):
class GPG(object):
'''
Mock smtplib class
Mock gnupg class
'''
def __init__(self, gnupghome='/tmp/salt/.gnupg',
homedir='/tmp/salt/.gnupg'):

View File

@ -0,0 +1,474 @@
# -*- 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 redismod
from datetime import datetime
# Globals
redismod.__grains__ = {}
redismod.__salt__ = {}
redismod.__context__ = {}
redismod.__opts__ = {}
class Mockredis(object):
'''
Mock redis class
'''
class ConnectionError(Exception):
'''
Mock ConnectionError class
'''
pass
redismod.redis = Mockredis
class MockConnect(object):
'''
Mock Connect class
'''
counter = 0
def __init__(self):
self.name = None
self.pattern = None
self.value = None
self.key = None
self.seconds = None
self.timestamp = None
self.field = None
self.start = None
self.stop = None
self.master_host = None
self.master_port = None
@staticmethod
def bgrewriteaof():
'''
Mock bgrewriteaof method
'''
return 'A'
@staticmethod
def bgsave():
'''
Mock bgsave method
'''
return 'A'
def config_get(self, pattern):
'''
Mock config_get method
'''
self.pattern = pattern
return 'A'
def config_set(self, name, value):
'''
Mock config_set method
'''
self.name = name
self.value = value
return 'A'
@staticmethod
def dbsize():
'''
Mock dbsize method
'''
return 'A'
@staticmethod
def delete():
'''
Mock delete method
'''
return 'A'
def exists(self, key):
'''
Mock exists method
'''
self.key = key
return 'A'
def expire(self, key, seconds):
'''
Mock expire method
'''
self.key = key
self.seconds = seconds
return 'A'
def expireat(self, key, timestamp):
'''
Mock expireat method
'''
self.key = key
self.timestamp = timestamp
return 'A'
@staticmethod
def flushall():
'''
Mock flushall method
'''
return 'A'
@staticmethod
def flushdb():
'''
Mock flushdb method
'''
return 'A'
def get(self, key):
'''
Mock get method
'''
self.key = key
return 'A'
def hget(self, key, field):
'''
Mock hget method
'''
self.key = key
self.field = field
return 'A'
def hgetall(self, key):
'''
Mock hgetall method
'''
self.key = key
return 'A'
@staticmethod
def info():
'''
Mock info method
'''
return 'A'
def keys(self, pattern):
'''
Mock keys method
'''
self.pattern = pattern
return 'A'
def type(self, key):
'''
Mock type method
'''
self.key = key
return 'A'
@staticmethod
def lastsave():
'''
Mock lastsave method
'''
return datetime.now()
def llen(self, key):
'''
Mock llen method
'''
self.key = key
return 'A'
def lrange(self, key, start, stop):
'''
Mock lrange method
'''
self.key = key
self.start = start
self.stop = stop
return 'A'
@staticmethod
def ping():
'''
Mock ping method
'''
MockConnect.counter = MockConnect.counter + 1
if MockConnect.counter == 1:
return 'A'
elif MockConnect.counter in (2, 3, 5):
raise Mockredis.ConnectionError('foo')
@staticmethod
def save():
'''
Mock save method
'''
return 'A'
def set(self, key, value):
'''
Mock set method
'''
self.key = key
self.value = value
return 'A'
@staticmethod
def shutdown():
'''
Mock shutdown method
'''
return 'A'
def slaveof(self, master_host, master_port):
'''
Mock slaveof method
'''
self.master_host = master_host
self.master_port = master_port
return 'A'
def smembers(self, key):
'''
Mock smembers method
'''
self.key = key
return 'A'
@staticmethod
def time():
'''
Mock time method
'''
return 'A'
def zcard(self, key):
'''
Mock zcard method
'''
self.key = key
return 'A'
def zrange(self, key, start, stop):
'''
Mock zrange method
'''
self.key = key
self.start = start
self.stop = stop
return 'A'
@skipIf(NO_MOCK, NO_MOCK_REASON)
@patch('salt.modules.redismod._connect', MagicMock(return_value=MockConnect()))
class RedismodTestCase(TestCase):
'''
Test cases for salt.modules.redismod
'''
def test_bgrewriteaof(self):
'''
Test to asynchronously rewrite the append-only file
'''
self.assertEqual(redismod.bgrewriteaof(), 'A')
def test_bgsave(self):
'''
Test to asynchronously save the dataset to disk
'''
self.assertEqual(redismod.bgsave(), 'A')
def test_config_get(self):
'''
Test to get redis server configuration values
'''
self.assertEqual(redismod.config_get('*'), 'A')
def test_config_set(self):
'''
Test to set redis server configuration values
'''
self.assertEqual(redismod.config_set('name', 'value'), 'A')
def test_dbsize(self):
'''
Test to return the number of keys in the selected database
'''
self.assertEqual(redismod.dbsize(), 'A')
def test_delete(self):
'''
Test to deletes the keys from redis, returns number of keys deleted
'''
self.assertEqual(redismod.delete(), 'A')
def test_exists(self):
'''
Test to return true if the key exists in redis
'''
self.assertEqual(redismod.exists('key'), 'A')
def test_expire(self):
'''
Test to set a keys time to live in seconds
'''
self.assertEqual(redismod.expire('key', 'seconds'), 'A')
def test_expireat(self):
'''
Test to set a keys expire at given UNIX time
'''
self.assertEqual(redismod.expireat('key', 'timestamp'), 'A')
def test_flushall(self):
'''
Test to remove all keys from all databases
'''
self.assertEqual(redismod.flushall(), 'A')
def test_flushdb(self):
'''
Test to remove all keys from the selected database
'''
self.assertEqual(redismod.flushdb(), 'A')
def test_get_key(self):
'''
Test to get redis key value
'''
self.assertEqual(redismod.get_key('key'), 'A')
def test_hget(self):
'''
Test to get specific field value from a redis hash, returns dict
'''
self.assertEqual(redismod.hget('key', 'field'), 'A')
def test_hgetall(self):
'''
Test to get all fields and values from a redis hash, returns dict
'''
self.assertEqual(redismod.hgetall('key'), 'A')
def test_info(self):
'''
Test to get information and statistics about the server
'''
self.assertEqual(redismod.info(), 'A')
def test_keys(self):
'''
Test to get redis keys, supports glob style patterns
'''
self.assertEqual(redismod.keys('pattern'), 'A')
def test_key_type(self):
'''
Test to get redis key type
'''
self.assertEqual(redismod.key_type('key'), 'A')
def test_lastsave(self):
'''
Test to get the UNIX time in seconds of the last successful
save to disk
'''
self.assertTrue(redismod.lastsave())
def test_llen(self):
'''
Test to get the length of a list in Redis
'''
self.assertEqual(redismod.llen('key'), 'A')
def test_lrange(self):
'''
Test to get a range of values from a list in Redis
'''
self.assertEqual(redismod.lrange('key', 'start', 'stop'), 'A')
def test_ping(self):
'''
Test to ping the server, returns False on connection errors
'''
self.assertEqual(redismod.ping(), 'A')
self.assertFalse(redismod.ping())
def test_save(self):
'''
Test to synchronously save the dataset to disk
'''
self.assertEqual(redismod.save(), 'A')
def test_set_key(self):
'''
Test to set redis key value
'''
self.assertEqual(redismod.set_key('key', 'value'), 'A')
def test_shutdown(self):
'''
Test to synchronously save the dataset to disk and then
shut down the server
'''
self.assertFalse(redismod.shutdown())
self.assertTrue(redismod.shutdown())
self.assertFalse(redismod.shutdown())
def test_slaveof(self):
'''
Test to make the server a slave of another instance, or
promote it as master
'''
self.assertEqual(redismod.slaveof('master_host', 'master_port'), 'A')
def test_smembers(self):
'''
Test to get members in a Redis set
'''
self.assertListEqual(redismod.smembers('key'), ['A'])
def test_time(self):
'''
Test to return the current server UNIX time in seconds
'''
self.assertEqual(redismod.time(), 'A')
def test_zcard(self):
'''
Test to get the length of a sorted set in Redis
'''
self.assertEqual(redismod.zcard('key'), 'A')
def test_zrange(self):
'''
Test to get a range of values from a sorted set in Redis by index
'''
self.assertEqual(redismod.zrange('key', 'start', 'stop'), 'A')
if __name__ == '__main__':
from integration import run_tests
run_tests(RedismodTestCase, needs_daemon=False)

View File

@ -0,0 +1,102 @@
# -*- 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 supervisord
supervisord.__salt__ = {}
supervisord.__opts__ = {}
@skipIf(NO_MOCK, NO_MOCK_REASON)
class SupervisordTestCase(TestCase):
'''
Test cases for salt.states.supervisord
'''
# 'running' function tests: 1
def test_running(self):
'''
Test to ensure the named service is running.
'''
name = 'wsgi_server'
ret = {'name': name,
'changes': {},
'result': True,
'comment': ''}
comt = ('Supervisord module not activated.'
' Do you need to install supervisord?')
ret.update({'comment': comt, 'result': False})
self.assertDictEqual(supervisord.running(name), ret)
mock = MagicMock(return_value={name: {'state': 'running'}})
with patch.dict(supervisord.__salt__, {'supervisord.status': mock}):
with patch.dict(supervisord.__opts__, {'test': True}):
comt = ('Service wsgi_server is already running')
ret.update({'comment': comt, 'result': True})
self.assertDictEqual(supervisord.running(name), ret)
with patch.dict(supervisord.__opts__, {'test': False}):
comt = ('Not starting already running service: wsgi_server')
ret.update({'comment': comt})
self.assertDictEqual(supervisord.running(name), ret)
# 'dead' function tests: 1
def test_dead(self):
'''
Test to ensure the named service is dead (not running).
'''
name = 'wsgi_server'
ret = {'name': name,
'changes': {},
'result': None,
'comment': ''}
with patch.dict(supervisord.__opts__, {'test': True}):
comt = ('Service {0} is set to be stopped'.format(name))
ret.update({'comment': comt})
self.assertDictEqual(supervisord.dead(name), ret)
# 'mod_watch' function tests: 1
def test_mod_watch(self):
'''
Test to always restart on watch.
'''
name = 'wsgi_server'
ret = {'name': name,
'changes': {},
'result': None,
'comment': ''}
comt = ('Supervisord module not activated.'
' Do you need to install supervisord?')
ret.update({'comment': comt, 'result': False})
self.assertDictEqual(supervisord.mod_watch(name), ret)
if __name__ == '__main__':
from integration import run_tests
run_tests(SupervisordTestCase, needs_daemon=False)