mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Merge remote-tracking branch 'upstream/2015.5' into merge-forward-2015.8
Conflicts: doc/conf.py doc/topics/cloud/gce.rst salt/cli/api.py salt/cli/call.py salt/cli/cp.py salt/cli/key.py salt/cli/run.py salt/cli/salt.py salt/modules/dockerio.py salt/states/dockerio.py
This commit is contained in:
commit
2c2a5f85ac
33 changed files with 314 additions and 152 deletions
|
@ -28,6 +28,9 @@
|
|||
# The level of messages to send to the console.
|
||||
# One of 'garbage', 'trace', 'debug', info', 'warning', 'error', 'critical'.
|
||||
#
|
||||
# The following log levels are considered INSECURE and may log sensitive data:
|
||||
# ['garbage', 'trace', 'debug']
|
||||
#
|
||||
# Default: 'info'
|
||||
#
|
||||
#log_level: info
|
||||
|
|
|
@ -692,6 +692,10 @@
|
|||
|
||||
# The level of messages to send to the console.
|
||||
# One of 'garbage', 'trace', 'debug', info', 'warning', 'error', 'critical'.
|
||||
#
|
||||
# The following log levels are considered INSECURE and may log sensitive data:
|
||||
# ['garbage', 'trace', 'debug']
|
||||
#
|
||||
#log_level: warning
|
||||
|
||||
# The level of messages to send to the log file.
|
||||
|
|
|
@ -511,6 +511,10 @@
|
|||
|
||||
# The level of messages to send to the console.
|
||||
# One of 'garbage', 'trace', 'debug', info', 'warning', 'error', 'critical'.
|
||||
#
|
||||
# The following log levels are considered INSECURE and may log sensitive data:
|
||||
# ['garbage', 'trace', 'debug']
|
||||
#
|
||||
# Default: 'warning'
|
||||
#log_level: warning
|
||||
|
||||
|
|
17
doc/faq.rst
17
doc/faq.rst
|
@ -1,3 +1,5 @@
|
|||
.. _faq:
|
||||
|
||||
Frequently Asked Questions
|
||||
==========================
|
||||
|
||||
|
@ -301,3 +303,18 @@ More information about salting the Salt master can be found in the salt-formula
|
|||
for salt itself:
|
||||
|
||||
https://github.com/saltstack-formulas/salt-formula
|
||||
|
||||
.. _faq-grain-security:
|
||||
|
||||
Is Targeting using Grain Data Secure?
|
||||
=====================================
|
||||
|
||||
Because grains can be set by users that have access to the minion configuration
|
||||
files on the local system, grains are considered less secure than other
|
||||
identifiers in Salt. Use caution when targeting sensitive operations or setting
|
||||
pillar values based on grain data.
|
||||
|
||||
When possible, you should target sensitive operations and data using the Minion
|
||||
ID. If the Minion ID of a system changes, the Salt Minion's public key must be
|
||||
re-accepted by an administrator on the Salt Master, making it less vulnerable
|
||||
to impersonation attacks.
|
||||
|
|
|
@ -238,15 +238,6 @@ The ``__virtual__`` function is used to return either a
|
|||
False is returned then the module is not loaded, if a string is returned then
|
||||
the module is loaded with the name of the string.
|
||||
|
||||
.. note::
|
||||
|
||||
Optionally, modules may additionally return a list of reasons that a module could
|
||||
not be loaded. For example, if a dependency for 'my_mod' was not met, a
|
||||
__virtual__ function could do as follows:
|
||||
|
||||
return False, ['My Module must be installed before this module can be
|
||||
used.']
|
||||
|
||||
This means that the package manager modules can be presented as the ``pkg`` module
|
||||
regardless of what the actual module is named.
|
||||
|
||||
|
@ -265,6 +256,16 @@ function. Some examples:
|
|||
Modules which return a string from ``__virtual__`` that is already used by a module that
|
||||
ships with Salt will _override_ the stock module.
|
||||
|
||||
Returning Error Information from ``__virtual__``
|
||||
------------------------------------------------
|
||||
|
||||
Optionally, modules may additionally return a list of reasons that a module could
|
||||
not be loaded. For example, if a dependency for 'my_mod' was not met, a
|
||||
__virtual__ function could do as follows:
|
||||
|
||||
return False, ['My Module must be installed before this module can be
|
||||
used.']
|
||||
|
||||
|
||||
Documentation
|
||||
=============
|
||||
|
|
|
@ -60,6 +60,7 @@ Google Compute Engine Setup
|
|||
*If you are using ``libcloud >= 0.17.0`` it is recommended that you use the ``JSON
|
||||
format`` file you downloaded above and skip to the "Configuration" section below, using
|
||||
the JSON file **_in place of 'NEW.pem'_** in the documentation.
|
||||
|
||||
If you are using an older version of libcloud or are unsure of the version you
|
||||
have, please follow the instructions below to generate and format a new P12 key.*
|
||||
|
||||
|
@ -78,35 +79,31 @@ Google Compute Engine Setup
|
|||
|
||||
|
||||
|
||||
Configuration
|
||||
=============
|
||||
Provider Configuration
|
||||
======================
|
||||
|
||||
Set up the cloud config at ``/etc/salt/cloud``:
|
||||
Set up the provider cloud config at ``/etc/salt/cloud.providers`` or
|
||||
``/etc/salt/cloud.providers.d/*.conf``:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
# Note: This example is for /etc/salt/cloud
|
||||
gce-config:
|
||||
# Set up the Project name and Service Account authorization
|
||||
project: "your-project-id"
|
||||
service_account_email_address: "123-a5gt@developer.gserviceaccount.com"
|
||||
service_account_private_key: "/path/to/your/NEW.pem"
|
||||
|
||||
providers:
|
||||
gce-config:
|
||||
# Set up the Project name and Service Account authorization
|
||||
#
|
||||
project: "your-project-id"
|
||||
service_account_email_address: "123-a5gt@developer.gserviceaccount.com"
|
||||
service_account_private_key: "/path/to/your/NEW.pem"
|
||||
# Set up the location of the salt master
|
||||
minion:
|
||||
master: saltmaster.example.com
|
||||
|
||||
# Set up the location of the salt master
|
||||
#
|
||||
minion:
|
||||
master: saltmaster.example.com
|
||||
# Set up grains information, which will be common for all nodes
|
||||
# using this provider
|
||||
grains:
|
||||
node_type: broker
|
||||
release: 1.0.1
|
||||
|
||||
# Set up grains information, which will be common for all nodes
|
||||
# using this provider
|
||||
grains:
|
||||
node_type: broker
|
||||
release: 1.0.1
|
||||
|
||||
driver: gce
|
||||
driver: gce
|
||||
|
||||
.. note::
|
||||
|
||||
|
@ -122,13 +119,14 @@ Set up the cloud config at ``/etc/salt/cloud``:
|
|||
provides the underlying functionality to connect to a cloud host, while cloud profiles continue
|
||||
to use ``provider`` to refer to provider configurations that you define.
|
||||
|
||||
Cloud Profiles
|
||||
==============
|
||||
Set up an initial profile at ``/etc/salt/cloud.profiles``:
|
||||
Profile Configuration
|
||||
=====================
|
||||
Set up an initial profile at ``/etc/salt/cloud.profiles`` or
|
||||
``/etc/salt/cloud.profiles.d/*.conf``:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
all_settings:
|
||||
my-gce-profile:
|
||||
image: centos-6
|
||||
size: n1-standard-1
|
||||
location: europe-west1-b
|
||||
|
@ -145,18 +143,18 @@ The profile can be realized now with a salt command:
|
|||
|
||||
.. code-block:: bash
|
||||
|
||||
salt-cloud -p all_settings gce-instance
|
||||
salt-cloud -p my-gce-profile gce-instance
|
||||
|
||||
This will create an salt minion instance named ``gce-instance`` in GCE. If
|
||||
the command was executed on the salt-master, its Salt key will automatically
|
||||
be signed on the master.
|
||||
|
||||
Once the instance has been created with salt-minion installed, connectivity to
|
||||
Once the instance has been created with a salt-minion installed, connectivity to
|
||||
it can be verified with Salt:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
salt 'ami.example.com' test.ping
|
||||
salt gce-instance test.ping
|
||||
|
||||
|
||||
GCE Specific Settings
|
||||
|
@ -167,7 +165,7 @@ typically also include a hard-coded default.
|
|||
|
||||
.. code-block:: yaml
|
||||
|
||||
all_settings:
|
||||
my-gce-profile:
|
||||
|
||||
# Image is used to define what Operating System image should be used
|
||||
# to for the instance. Examples are Debian 7 (wheezy) and CentOS 6.
|
||||
|
@ -239,11 +237,12 @@ typically also include a hard-coded default.
|
|||
|
||||
GCE instances do not allow remote access to the root user by default.
|
||||
Instead, another user must be used to run the deploy script using sudo.
|
||||
Append something like this to ``/etc/salt/cloud.profiles``:
|
||||
Append something like this to ``/etc/salt/cloud.profiles`` or
|
||||
``/etc/salt/cloud.profiles.d/*.conf``:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
all_settings:
|
||||
my-gce-profile:
|
||||
...
|
||||
|
||||
# SSH to GCE instances as gceuser
|
||||
|
@ -259,7 +258,7 @@ the metadata setting too:
|
|||
|
||||
.. code-block:: yaml
|
||||
|
||||
all_settings:
|
||||
my-gce-profile:
|
||||
...
|
||||
|
||||
metadata: '{"one": "1", "2": "two",
|
||||
|
@ -432,7 +431,7 @@ Specify the network name to view information about the network.
|
|||
salt-cloud -f show_network gce name=mynet
|
||||
|
||||
Create address
|
||||
---------------
|
||||
--------------
|
||||
Create a new named static IP address in a region.
|
||||
|
||||
.. code-block:: bash
|
||||
|
@ -440,7 +439,7 @@ Create a new named static IP address in a region.
|
|||
salt-cloud -f create_address gce name=my-fixed-ip region=us-central1
|
||||
|
||||
Delete address
|
||||
---------------
|
||||
--------------
|
||||
Delete an existing named fixed IP address.
|
||||
|
||||
.. code-block:: bash
|
||||
|
@ -448,7 +447,7 @@ Delete an existing named fixed IP address.
|
|||
salt-cloud -f delete_address gce name=my-fixed-ip region=us-central1
|
||||
|
||||
Show address
|
||||
---------------
|
||||
------------
|
||||
View details on a named address.
|
||||
|
||||
.. code-block:: bash
|
||||
|
|
|
@ -64,6 +64,87 @@ installer:
|
|||
Salt-Minion-0.17.0-Setup-amd64.exe /S /master=yoursaltmaster /minion-name=yourminionname
|
||||
|
||||
|
||||
Running the Salt Minion on Windows as an Unprivileged User
|
||||
==========================================================
|
||||
|
||||
Notes:
|
||||
- These instructions were tested with Windows Server 2008 R2
|
||||
- They are generalizable to any version of Windows that supports a salt-minion
|
||||
|
||||
A. Create the Unprivileged User that the Salt Minion will Run As
|
||||
----------------------------------------------------------------
|
||||
|
||||
1. Click "Start", "Control Panel", "User Accounts"
|
||||
|
||||
2. Click "Add or remove user accounts"
|
||||
|
||||
3. Click "Create new account"
|
||||
|
||||
4. Enter "salt-user" (or a name of your preference) in the "New account name" field
|
||||
|
||||
5. Select the "Standard user" radio button
|
||||
|
||||
6. Click the "Create Account" button
|
||||
|
||||
7. Click on the newly created user account
|
||||
|
||||
8. Click the "Create a password" link
|
||||
|
||||
9. In the "New password" and "Confirm new password" fields, provide a password (e.g "SuperSecretMinionPassword4Me!")
|
||||
|
||||
10. In the "Type a password hint" field, provide appropriate text (e.g. "My Salt Password")
|
||||
|
||||
11. Click the "Create password" button
|
||||
|
||||
12. Close the "Change an Account" window
|
||||
|
||||
|
||||
B. Add the New User to the Access Control List for the Salt Folder
|
||||
------------------------------------------------------------------
|
||||
|
||||
1. In a File Explorer window, browse to the path where Salt is installed (the default path is C:\Salt)
|
||||
|
||||
2. Right-click on the "Salt" folder and select "Properties"
|
||||
|
||||
3. Click on the "Security" tab
|
||||
|
||||
4. Click the "Edit" button
|
||||
|
||||
5. Click the "Add" button
|
||||
|
||||
6. Type the name of your designated Salt user and click the "OK" button
|
||||
|
||||
7. Check the box to "Allow" the "Modify" permission
|
||||
|
||||
8. Click the "OK" button
|
||||
|
||||
9. Click the "OK" button to close the "Salt Properties" window
|
||||
|
||||
|
||||
C. Update the Windows Service User for the "salt-minion" Service
|
||||
----------------------------------------------------------------
|
||||
|
||||
1. Click "Start", "Administrative Tools", "Services"
|
||||
|
||||
2. In the list of Services, Right-Click on "salt-minion" and select "Properties"
|
||||
|
||||
3. Click the "Log On" tab
|
||||
|
||||
4. Click the "This account" radio button
|
||||
|
||||
5. Provide the account credentials created in section A
|
||||
|
||||
6. Click the "OK" button
|
||||
|
||||
7. Click the "OK" button to the prompt confirming that the user "has been granted the Log On As A Service right"
|
||||
|
||||
8. Click the "OK" button to the prompt confirming that "The new logon name will not take effect until you stop and restart the service"
|
||||
|
||||
9. Right-Click on "salt-minion" and select "Stop"
|
||||
|
||||
10. Right-Click on "salt-minion" and select "Start"
|
||||
|
||||
|
||||
Setting up a Windows build environment
|
||||
======================================
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ Release notes
|
|||
See the :doc:`version numbers</topics/releases/version_numbers>` page for more
|
||||
information about the version numbering scheme.
|
||||
|
||||
Latest Stable Release
|
||||
Latest Branch Release
|
||||
=====================
|
||||
|
||||
|current_release_doc|
|
||||
|
|
|
@ -16,6 +16,7 @@ import logging
|
|||
import salt.utils.parsers as parsers
|
||||
import salt.version
|
||||
import salt.syspaths as syspaths
|
||||
from salt.utils.verify import verify_log
|
||||
|
||||
# Import 3rd-party libs
|
||||
import salt.ext.six as six
|
||||
|
@ -48,6 +49,7 @@ class SaltAPI(six.with_metaclass(parsers.OptionParserMeta, # pylint: disable=W0
|
|||
import salt.client.netapi
|
||||
self.parse_args()
|
||||
self.setup_logfile_logger()
|
||||
verify_log(self.config)
|
||||
self.daemonize_if_required()
|
||||
client = salt.client.netapi.NetapiClient(self.config)
|
||||
self.set_pidfile()
|
||||
|
|
|
@ -4,6 +4,7 @@ from __future__ import absolute_import
|
|||
import os
|
||||
|
||||
from salt.utils import parsers
|
||||
from salt.utils.verify import verify_log
|
||||
from salt.config import _expand_glob_path
|
||||
import salt.cli.caller
|
||||
import salt.defaults.exitcodes
|
||||
|
@ -37,6 +38,7 @@ class SaltCall(parsers.SaltCallOptionParser):
|
|||
|
||||
# Setup file logging!
|
||||
self.setup_logfile_logger()
|
||||
verify_log(self.config)
|
||||
|
||||
caller = salt.cli.caller.Caller.factory(self.config)
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ import sys
|
|||
# Import salt libs
|
||||
import salt.client
|
||||
from salt.utils import parsers, print_cli
|
||||
from salt.utils.verify import verify_log
|
||||
import salt.output
|
||||
|
||||
|
||||
|
@ -31,6 +32,7 @@ class SaltCPCli(parsers.SaltCPOptionParser):
|
|||
|
||||
# Setup file logging!
|
||||
self.setup_logfile_logger()
|
||||
verify_log(self.config)
|
||||
|
||||
cp_ = SaltCP(self.config)
|
||||
cp_.run()
|
||||
|
|
|
@ -8,6 +8,7 @@ from __future__ import absolute_import
|
|||
import os
|
||||
import sys
|
||||
import warnings
|
||||
from salt.utils.verify import verify_log
|
||||
|
||||
# All salt related deprecation warnings should be shown once each!
|
||||
warnings.filterwarnings(
|
||||
|
@ -115,6 +116,7 @@ class Master(parsers.MasterOptionParser):
|
|||
sys.exit(err.errno)
|
||||
|
||||
self.setup_logfile_logger()
|
||||
verify_log(self.config)
|
||||
logger.info('Setting up the Salt Master')
|
||||
|
||||
# TODO: AIO core is separate from transport
|
||||
|
@ -226,6 +228,7 @@ class Minion(parsers.MinionOptionParser): # pylint: disable=no-init
|
|||
sys.exit(err.errno)
|
||||
|
||||
self.setup_logfile_logger()
|
||||
verify_log(self.config)
|
||||
logger.info(
|
||||
'Setting up the Salt Minion "{0}"'.format(
|
||||
self.config['id']
|
||||
|
@ -393,6 +396,7 @@ class ProxyMinion(parsers.ProxyMinionOptionParser): # pylint: disable=no-init
|
|||
sys.exit(err.errno)
|
||||
|
||||
self.setup_logfile_logger()
|
||||
verify_log(self.config)
|
||||
logger.info(
|
||||
'Setting up a Salt Proxy Minion "{0}"'.format(
|
||||
self.config['id']
|
||||
|
@ -490,6 +494,7 @@ class Syndic(parsers.SyndicOptionParser):
|
|||
sys.exit(err.errno)
|
||||
|
||||
self.setup_logfile_logger()
|
||||
verify_log(self.config)
|
||||
logger.info(
|
||||
'Setting up the Salt Syndic Minion "{0}"'.format(
|
||||
self.config['id']
|
||||
|
|
|
@ -3,7 +3,7 @@ from __future__ import print_function
|
|||
from __future__ import absolute_import
|
||||
|
||||
from salt.utils import parsers
|
||||
from salt.utils.verify import check_user
|
||||
from salt.utils.verify import check_user, verify_log
|
||||
|
||||
|
||||
class SaltKey(parsers.SaltKeyOptionParser):
|
||||
|
@ -22,6 +22,7 @@ class SaltKey(parsers.SaltKeyOptionParser):
|
|||
multi = True
|
||||
|
||||
self.setup_logfile_logger()
|
||||
verify_log(self.config)
|
||||
|
||||
if multi:
|
||||
key = salt.key.MultiKeyCLI(self.config)
|
||||
|
|
|
@ -5,7 +5,7 @@ from __future__ import absolute_import
|
|||
from salt.utils import parsers
|
||||
from salt.utils import activate_profile
|
||||
from salt.utils import output_profile
|
||||
from salt.utils.verify import check_user
|
||||
from salt.utils.verify import check_user, verify_log
|
||||
from salt.exceptions import SaltClientError
|
||||
import salt.defaults.exitcodes # pylint: disable=W0611
|
||||
|
||||
|
@ -24,6 +24,7 @@ class SaltRun(parsers.SaltRunOptionParser):
|
|||
|
||||
# Setup file logging!
|
||||
self.setup_logfile_logger()
|
||||
verify_log(self.config)
|
||||
profiling_enabled = self.options.profiling_enabled
|
||||
|
||||
runner = salt.runner.Runner(self.config)
|
||||
|
|
|
@ -9,6 +9,7 @@ import sys
|
|||
import salt.utils.job
|
||||
from salt.ext.six import string_types
|
||||
from salt.utils import parsers, print_cli
|
||||
from salt.utils.verify import verify_log
|
||||
from salt.exceptions import (
|
||||
SaltClientError,
|
||||
SaltInvocationError,
|
||||
|
@ -34,6 +35,7 @@ class SaltCMD(parsers.SaltCMDOptionParser):
|
|||
|
||||
# Setup file logging!
|
||||
self.setup_logfile_logger()
|
||||
verify_log(self.config)
|
||||
|
||||
try:
|
||||
# We don't need to bail on config file permission errors
|
||||
|
|
|
@ -4,6 +4,7 @@ from __future__ import print_function
|
|||
from __future__ import absolute_import
|
||||
import salt.client.ssh
|
||||
from salt.utils import parsers
|
||||
from salt.utils.verify import verify_log
|
||||
|
||||
|
||||
class SaltSSH(parsers.SaltSSHOptionParser):
|
||||
|
@ -14,6 +15,7 @@ class SaltSSH(parsers.SaltSSHOptionParser):
|
|||
def run(self):
|
||||
self.parse_args()
|
||||
self.setup_logfile_logger()
|
||||
verify_log(self.config)
|
||||
|
||||
ssh = salt.client.ssh.SSH(self.config)
|
||||
ssh.run()
|
||||
|
|
|
@ -25,7 +25,7 @@ import salt.defaults.exitcodes
|
|||
import salt.output
|
||||
import salt.utils
|
||||
from salt.utils import parsers
|
||||
from salt.utils.verify import check_user, verify_env, verify_files
|
||||
from salt.utils.verify import check_user, verify_env, verify_files, verify_log
|
||||
|
||||
# Import salt.cloud libs
|
||||
import salt.cloud
|
||||
|
@ -77,6 +77,7 @@ class SaltCloud(parsers.SaltCloudParser):
|
|||
|
||||
# Setup log file logging
|
||||
self.setup_logfile_logger()
|
||||
verify_log(self.config)
|
||||
|
||||
if self.options.update_bootstrap:
|
||||
ret = salt.utils.cloud.update_bootstrap(self.config)
|
||||
|
|
|
@ -3027,6 +3027,11 @@ def list_nodes_full(location=None, call=None):
|
|||
get_location(vm_) for vm_ in six.itervalues(__opts__['profiles'])
|
||||
if _vm_provider_driver(vm_)
|
||||
)
|
||||
# If there aren't any profiles defined for EC2, check
|
||||
# the provider config file, or use the default location.
|
||||
if not locations:
|
||||
locations = [get_location()]
|
||||
|
||||
for loc in locations:
|
||||
ret.update(_list_nodes_full(loc))
|
||||
return ret
|
||||
|
|
|
@ -119,7 +119,7 @@ list_nodes = namespaced_function(list_nodes, globals())
|
|||
list_nodes_full = namespaced_function(list_nodes_full, globals())
|
||||
list_nodes_select = namespaced_function(list_nodes_select, globals())
|
||||
|
||||
GCE_VM_NAME_REGEX = re.compile(r'(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?)')
|
||||
GCE_VM_NAME_REGEX = re.compile(r'^(?:[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?)$')
|
||||
|
||||
|
||||
# Only load in this module if the GCE configurations are in place
|
||||
|
@ -2041,9 +2041,8 @@ def create(vm_=None, call=None):
|
|||
|
||||
if not GCE_VM_NAME_REGEX.match(vm_['name']):
|
||||
raise SaltCloudSystemExit(
|
||||
'The allowed VM names must match the following regular expression: {0}'.format(
|
||||
GCE_VM_NAME_REGEX.pattern
|
||||
)
|
||||
'VM names must start with a letter, only contain letters, numbers, or dashes '
|
||||
'and cannot end in a dash.'
|
||||
)
|
||||
|
||||
try:
|
||||
|
|
|
@ -492,7 +492,7 @@ def list_nodes_full(mask='mask[id]', call=None):
|
|||
)
|
||||
|
||||
ret = {}
|
||||
conn = get_conn(service='Account')
|
||||
conn = get_conn(service='SoftLayer_Account')
|
||||
response = conn.getVirtualGuests()
|
||||
for node_id in response:
|
||||
ret[node_id['hostname']] = node_id
|
||||
|
@ -605,5 +605,5 @@ def list_vlans(call=None):
|
|||
'The list_vlans function must be called with -f or --function.'
|
||||
)
|
||||
|
||||
conn = get_conn(service='Account')
|
||||
conn = get_conn(service='SoftLayer_Account')
|
||||
return conn.getNetworkVlans()
|
||||
|
|
|
@ -424,7 +424,7 @@ def list_nodes_full(mask='mask[id, hostname, primaryIpAddress, \
|
|||
)
|
||||
|
||||
ret = {}
|
||||
conn = get_conn(service='Account')
|
||||
conn = get_conn(service='SoftLayer_Account')
|
||||
response = conn.getHardware(mask=mask)
|
||||
|
||||
for node in response:
|
||||
|
@ -544,7 +544,7 @@ def list_vlans(call=None):
|
|||
'The list_vlans function must be called with -f or --function.'
|
||||
)
|
||||
|
||||
conn = get_conn(service='Account')
|
||||
conn = get_conn(service='SoftLayer_Account')
|
||||
return conn.getNetworkVlans()
|
||||
|
||||
|
||||
|
|
|
@ -1487,8 +1487,8 @@ def build(path=None,
|
|||
|
||||
except Exception:
|
||||
_invalid(status,
|
||||
out=traceback.format_exc(),
|
||||
comment='Unexpected error while building an image')
|
||||
out=traceback.format_exc(),
|
||||
comment='Unexpected error while building an image')
|
||||
return status
|
||||
|
||||
return status
|
||||
|
@ -1863,16 +1863,13 @@ def _run_wrapper(status, container, func, cmd, *args, **kwargs):
|
|||
comment = 'Executed {0}'.format(full_cmd)
|
||||
try:
|
||||
ret = __salt__[func](full_cmd, *args, **kwargs)
|
||||
if ((isinstance(ret, dict) and
|
||||
('retcode' in ret) and
|
||||
(ret['retcode'] != 0))
|
||||
or (func == 'cmd.retcode' and ret != 0)):
|
||||
return _invalid(status, id_=container, out=ret,
|
||||
comment=comment)
|
||||
_valid(status, id_=container, out=ret, comment=comment,)
|
||||
if ((isinstance(ret, dict) and ('retcode' in ret) and (ret['retcode'] != 0))
|
||||
or (func == 'cmd.retcode' and ret != 0)):
|
||||
_invalid(status, id_=container, out=ret, comment=comment)
|
||||
else:
|
||||
_valid(status, id_=container, out=ret, comment=comment)
|
||||
except Exception:
|
||||
_invalid(status, id_=container,
|
||||
comment=comment, out=traceback.format_exc())
|
||||
_invalid(status, id_=container, comment=comment, out=traceback.format_exc())
|
||||
return status
|
||||
|
||||
|
||||
|
@ -1897,9 +1894,7 @@ def load(imagepath):
|
|||
try:
|
||||
dockercmd = ['docker', 'load', '-i', imagepath]
|
||||
ret = __salt__['cmd.run'](dockercmd, python_shell=False)
|
||||
if ((isinstance(ret, dict) and
|
||||
('retcode' in ret) and
|
||||
(ret['retcode'] != 0))):
|
||||
if isinstance(ret, dict) and ('retcode' in ret) and (ret['retcode'] != 0):
|
||||
return _invalid(status, id_=None,
|
||||
out=ret,
|
||||
comment='Command to load image {0} failed.'.format(imagepath))
|
||||
|
@ -1907,12 +1902,12 @@ def load(imagepath):
|
|||
_valid(status, id_=None, out=ret, comment='Image load success')
|
||||
except Exception:
|
||||
_invalid(status, id_=None,
|
||||
comment="Image not loaded.",
|
||||
out=traceback.format_exc())
|
||||
comment="Image not loaded.",
|
||||
out=traceback.format_exc())
|
||||
else:
|
||||
_invalid(status, id_=None,
|
||||
comment='Image file {0} could not be found.'.format(imagepath),
|
||||
out=traceback.format_exc())
|
||||
comment='Image file {0} could not be found.'.format(imagepath),
|
||||
out=traceback.format_exc())
|
||||
|
||||
return status
|
||||
|
||||
|
@ -1943,16 +1938,14 @@ def save(image, filename):
|
|||
ok = True
|
||||
except Exception:
|
||||
_invalid(status, id_=image,
|
||||
comment="docker image {0} could not be found.".format(image),
|
||||
out=traceback.format_exc())
|
||||
comment="docker image {0} could not be found.".format(image),
|
||||
out=traceback.format_exc())
|
||||
|
||||
if ok:
|
||||
try:
|
||||
dockercmd = ['docker', 'save', '-o', filename, image]
|
||||
ret = __salt__['cmd.run'](dockercmd)
|
||||
if ((isinstance(ret, dict) and
|
||||
('retcode' in ret) and
|
||||
(ret['retcode'] != 0))):
|
||||
if isinstance(ret, dict) and ('retcode' in ret) and (ret['retcode'] != 0):
|
||||
return _invalid(status,
|
||||
id_=image,
|
||||
out=ret,
|
||||
|
@ -2097,9 +2090,7 @@ def retcode(container, cmd):
|
|||
command to execute
|
||||
|
||||
.. note::
|
||||
The return is a bit different as we use the docker struct.
|
||||
Output of the command is in 'out' and result is ``False`` if
|
||||
command failed to execute.
|
||||
The return is True or False depending on the commands success.
|
||||
|
||||
.. warning::
|
||||
Be advised that this function allows for raw shell access to the named
|
||||
|
@ -2114,7 +2105,7 @@ def retcode(container, cmd):
|
|||
'''
|
||||
status = base_status.copy()
|
||||
return _run_wrapper(
|
||||
status, container, 'cmd.retcode', cmd)
|
||||
status, container, 'cmd.retcode', cmd)['status']
|
||||
|
||||
|
||||
def get_container_root(container):
|
||||
|
|
|
@ -199,19 +199,25 @@ def read_value(hive, key, vname=None):
|
|||
ret['vname'] = '(Default)'
|
||||
|
||||
registry = Registry()
|
||||
hive = registry.hkeys[hive]
|
||||
hkey = registry.hkeys[hive]
|
||||
|
||||
try:
|
||||
handle = _winreg.OpenKey(hive, key)
|
||||
vdata, vtype = _winreg.QueryValueEx(handle, vname)
|
||||
if vdata:
|
||||
ret['vdata'] = vdata
|
||||
ret['vtype'] = registry.vtype_reverse[vtype]
|
||||
else:
|
||||
ret['comment'] = 'Empty Value'
|
||||
handle = _winreg.OpenKey(hkey, key)
|
||||
try:
|
||||
vdata, vtype = _winreg.QueryValueEx(handle, vname)
|
||||
if vdata or vdata in [0, '']:
|
||||
ret['vtype'] = registry.vtype_reverse[vtype]
|
||||
ret['vdata'] = vdata
|
||||
else:
|
||||
ret['comment'] = 'Empty Value'
|
||||
except WindowsError as exc: # pylint: disable=E0602
|
||||
ret['vdata'] = ('(value not set)')
|
||||
ret['vtype'] = 'REG_SZ'
|
||||
ret['success'] = True
|
||||
except WindowsError as exc: # pylint: disable=E0602
|
||||
log.debug(exc)
|
||||
ret['comment'] = '{0}'.format(exc)
|
||||
log.debug('Cannot find key: {0}\\{1}'.format(hive, key))
|
||||
ret['comment'] = 'Cannot find key: {0}\\{1}'.format(hive, key)
|
||||
ret['success'] = False
|
||||
|
||||
return ret
|
||||
|
@ -312,7 +318,7 @@ def set_value(hive, key, vname=None, vdata=None, vtype='REG_SZ', reflection=True
|
|||
_winreg.CloseKey(handle)
|
||||
return True
|
||||
except (WindowsError, ValueError) as exc: # pylint: disable=E0602
|
||||
log.error(exc)
|
||||
log.error(exc, exc_info=True)
|
||||
return False
|
||||
|
||||
|
||||
|
@ -434,7 +440,7 @@ def delete_key(hkey, path, key=None, reflection=True, force=False):
|
|||
_winreg.DeleteKey(hive, key)
|
||||
return True
|
||||
except WindowsError as exc: # pylint: disable=E0602
|
||||
log.error(exc)
|
||||
log.error(exc, exc_info=True)
|
||||
return False
|
||||
|
||||
|
||||
|
@ -504,7 +510,7 @@ def delete_key_recursive(hive, key):
|
|||
_winreg.DeleteKey(hkey, keypath)
|
||||
ret['Deleted'].append(r'{0}\{1}'.format(hive, keypath))
|
||||
except WindowsError as exc: # pylint: disable=E0602
|
||||
log.error(exc)
|
||||
log.error(exc, exc_info=True)
|
||||
ret['Failed'].append(r'{0}\{1} {2}'.format(hive, key, exc))
|
||||
|
||||
# Delete the key now that all the subkeys are deleted
|
||||
|
@ -512,7 +518,7 @@ def delete_key_recursive(hive, key):
|
|||
_winreg.DeleteKey(hkey, key)
|
||||
ret['Deleted'].append(r'{0}\{1}'.format(hive, key))
|
||||
except WindowsError as exc: # pylint: disable=E0602
|
||||
log.error(exc)
|
||||
log.error(exc, exc_info=True)
|
||||
ret['Failed'].append(r'{0}\{1} {2}'.format(hive, key, exc))
|
||||
|
||||
return ret
|
||||
|
@ -561,5 +567,5 @@ def delete_value(hive, key, vname=None, reflection=True):
|
|||
return True
|
||||
except WindowsError as exc: # pylint: disable=E0602
|
||||
_winreg.CloseKey(handle)
|
||||
log.error(exc)
|
||||
log.error(exc, exc_info=True)
|
||||
return False
|
||||
|
|
|
@ -452,7 +452,8 @@ def sync_log_handlers(saltenv=None, refresh=True):
|
|||
def sync_all(saltenv=None, refresh=True):
|
||||
'''
|
||||
Sync down all of the dynamic modules from the file server for a specific
|
||||
environment
|
||||
environment. This function synchronizes custom modules, states, beacons,
|
||||
grains, returners, outputters, renderers, and utils.
|
||||
|
||||
refresh : True
|
||||
Also refresh the execution modules available to the minion.
|
||||
|
|
|
@ -73,7 +73,7 @@ def get_path():
|
|||
|
||||
salt '*' win_path.get_path
|
||||
'''
|
||||
ret = __salt__['reg.read_key']('HKEY_LOCAL_MACHINE',
|
||||
ret = __salt__['reg.read_value']('HKEY_LOCAL_MACHINE',
|
||||
'SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment',
|
||||
'PATH')
|
||||
if isinstance(ret, dict):
|
||||
|
@ -155,8 +155,8 @@ def add(path, index=0):
|
|||
regedit = __salt__['reg.set_value'](
|
||||
'HKEY_LOCAL_MACHINE',
|
||||
'SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment',
|
||||
';'.join(sysPath),
|
||||
'PATH',
|
||||
';'.join(sysPath),
|
||||
'REG_EXPAND_SZ'
|
||||
)
|
||||
|
||||
|
@ -197,8 +197,8 @@ def remove(path):
|
|||
regedit = __salt__['reg.set_value'](
|
||||
'HKEY_LOCAL_MACHINE',
|
||||
'SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment',
|
||||
';'.join(sysPath),
|
||||
'PATH',
|
||||
';'.join(sysPath),
|
||||
'REG_EXPAND_SZ'
|
||||
)
|
||||
if regedit:
|
||||
|
|
|
@ -300,8 +300,8 @@ def _parse_volumes(volumes):
|
|||
contvolumes.append(str(vol))
|
||||
continue
|
||||
bindvolumes[source] = {
|
||||
'bind': target,
|
||||
'ro': read_only
|
||||
'bind': target,
|
||||
'ro': read_only
|
||||
}
|
||||
result = {'bindvols': bindvolumes, 'contvols': contvolumes}
|
||||
log.trace("Finished parsing volumes, with result: " + str(result))
|
||||
|
@ -507,9 +507,9 @@ def loaded(name, tag='latest', source=None, source_hash='', force=False):
|
|||
|
||||
tmp_filename = salt.utils.mkstemp()
|
||||
__salt__['state.single']('file.managed',
|
||||
name=tmp_filename,
|
||||
source=source,
|
||||
source_hash=source_hash)
|
||||
name=tmp_filename,
|
||||
source=source,
|
||||
source_hash=source_hash)
|
||||
changes = {}
|
||||
|
||||
if image_infos['status']:
|
||||
|
@ -517,9 +517,8 @@ def loaded(name, tag='latest', source=None, source_hash='', force=False):
|
|||
remove_image = __salt__['docker.remove_image']
|
||||
remove_info = remove_image(image_name)
|
||||
if not remove_info['status']:
|
||||
return _invalid(
|
||||
name=name,
|
||||
comment='Image could not be removed: {0}'.format(image_name))
|
||||
return _invalid(name=name,
|
||||
comment='Image could not be removed: {0}'.format(name))
|
||||
|
||||
load = __salt__['docker.load']
|
||||
returned = load(tmp_filename)
|
||||
|
@ -757,23 +756,23 @@ def absent(name):
|
|||
is_gone = __salt__['docker.exists'](cid)
|
||||
if is_gone:
|
||||
return _valid(comment=('Container {0!r}'
|
||||
' was stopped and destroyed, '.format(cid)),
|
||||
changes={name: True})
|
||||
' was stopped and destroyed, '.format(cid)),
|
||||
changes={name: True})
|
||||
else:
|
||||
return _valid(comment=('Container {0!r}'
|
||||
' was stopped but could not be destroyed,'.format(cid)),
|
||||
changes={name: True})
|
||||
' was stopped but could not be destroyed,'.format(cid)),
|
||||
changes={name: True})
|
||||
else:
|
||||
__salt__['docker.remove_container'](cid)
|
||||
is_gone = __salt__['docker.exists'](cid)
|
||||
if is_gone:
|
||||
return _valid(comment=('Container {0!r}'
|
||||
' is stopped and was destroyed, '.format(cid)),
|
||||
changes={name: True})
|
||||
'is stopped and was destroyed, '.format(cid)),
|
||||
changes={name: True})
|
||||
else:
|
||||
return _valid(comment=('Container {0!r}'
|
||||
' is stopped but could not be destroyed,'.format(cid)),
|
||||
changes={name: True})
|
||||
' is stopped but could not be destroyed,'.format(cid)),
|
||||
changes={name: True})
|
||||
else:
|
||||
return _valid(comment="Container {0!r} not found".format(name))
|
||||
|
||||
|
@ -862,7 +861,7 @@ def run(name,
|
|||
if not onlyif:
|
||||
return valid(comment='onlyif execution failed')
|
||||
elif isinstance(onlyif, string_types):
|
||||
if retcode(cid, onlyif) != 0:
|
||||
if not __salt__['cmd.retcode'](onlyif) == 0:
|
||||
return valid(comment='onlyif execution failed')
|
||||
|
||||
if unless is not None:
|
||||
|
@ -870,7 +869,7 @@ def run(name,
|
|||
if unless:
|
||||
return valid(comment='unless execution succeeded')
|
||||
elif isinstance(unless, string_types):
|
||||
if retcode(cid, unless) == 0:
|
||||
if __salt__['cmd.retcode'](unless) == 0:
|
||||
return valid(comment='unless execution succeeded')
|
||||
|
||||
if docked_onlyif is not None:
|
||||
|
@ -878,7 +877,7 @@ def run(name,
|
|||
if not docked_onlyif:
|
||||
return valid(comment='docked_onlyif execution failed')
|
||||
elif isinstance(docked_onlyif, string_types):
|
||||
if retcode(cid, docked_onlyif) != 0:
|
||||
if not retcode(cid, docked_onlyif):
|
||||
return valid(comment='docked_onlyif execution failed')
|
||||
|
||||
if docked_unless is not None:
|
||||
|
@ -886,7 +885,7 @@ def run(name,
|
|||
if docked_unless:
|
||||
return valid(comment='docked_unless execution succeeded')
|
||||
elif isinstance(docked_unless, string_types):
|
||||
if retcode(cid, docked_unless) == 0:
|
||||
if retcode(cid, docked_unless):
|
||||
return valid(comment='docked_unless execution succeeded')
|
||||
|
||||
if __opts__['test']:
|
||||
|
@ -1266,9 +1265,8 @@ def running(name,
|
|||
if is_running:
|
||||
changes.append('Container {0!r} started.\n'.format(name))
|
||||
else:
|
||||
return _invalid(comment=(
|
||||
'Container {0!r} cannot be started\n{1!s}'
|
||||
.format(name, started['out'],)))
|
||||
return _invalid(comment=('Container {0!r} cannot be started\n{1!s}'
|
||||
.format(name, started['out'],)))
|
||||
else:
|
||||
changes.append('Container {0!r} started.\n'.format(name))
|
||||
return _valid(comment='\n'.join(changes), changes={name: True})
|
||||
|
|
|
@ -1445,6 +1445,8 @@ def managed(name,
|
|||
if ret['changes']:
|
||||
ret['result'] = None
|
||||
ret['comment'] = 'The file {0} is set to be changed'.format(name)
|
||||
if not show_diff:
|
||||
ret['changes']['diff'] = '<show_diff=False>'
|
||||
else:
|
||||
ret['result'] = True
|
||||
ret['comment'] = 'The file {0} is in the correct state'.format(name)
|
||||
|
@ -3825,11 +3827,16 @@ def copy(
|
|||
)
|
||||
|
||||
if __opts__['test']:
|
||||
ret['comment'] = 'File "{0}" is set to be copied to "{1}"'.format(
|
||||
source,
|
||||
name
|
||||
)
|
||||
ret['result'] = None
|
||||
if changed:
|
||||
ret['comment'] = 'File "{0}" is set to be copied to "{1}"'.format(
|
||||
source,
|
||||
name
|
||||
)
|
||||
ret['result'] = None
|
||||
else:
|
||||
ret['comment'] = ('The target file "{0}" exists and will not be '
|
||||
'overwritten'.format(name))
|
||||
ret['result'] = True
|
||||
return ret
|
||||
|
||||
if not changed:
|
||||
|
@ -4248,10 +4255,10 @@ def serialize(name,
|
|||
if os.path.isfile(name):
|
||||
if formatter == 'yaml':
|
||||
with salt.utils.fopen(name, 'r') as fhr:
|
||||
existing_data = yaml.safe_load(fhr.read())
|
||||
existing_data = yaml.safe_load(fhr)
|
||||
elif formatter == 'json':
|
||||
with salt.utils.fopen(name, 'r') as fhr:
|
||||
existing_data = json.load(fhr.read())
|
||||
existing_data = json.load(fhr)
|
||||
else:
|
||||
return {'changes': {},
|
||||
'comment': ('{0} format is not supported for merging'
|
||||
|
|
|
@ -186,7 +186,7 @@ def present(name, value=None, vname=None, vdata=None, vtype='REG_SZ', reflection
|
|||
# This is for backwards compatibility
|
||||
# If 'value' is passed a value, vdata becomes value and the vname is
|
||||
# obtained from the key path
|
||||
if value:
|
||||
if value or value in [0, '']:
|
||||
hive, key, vname = _parse_key_value(name)
|
||||
vdata = value
|
||||
ret['comment'] = 'State file is using deprecated syntax. Please update.'
|
||||
|
@ -208,7 +208,7 @@ def present(name, value=None, vname=None, vdata=None, vtype='REG_SZ', reflection
|
|||
|
||||
add_change = {'Key': r'{0}\{1}'.format(hive, key),
|
||||
'Entry': '{0}'.format(vname if vname else '(Default)'),
|
||||
'Value': '{0}'.format(vdata if vdata else '(Empty String)')}
|
||||
'Value': '{0}'.format(vdata)}
|
||||
|
||||
# Check for test option
|
||||
if __opts__['test']:
|
||||
|
@ -256,9 +256,15 @@ def absent(name, vname=None):
|
|||
hive, key = _parse_key(name)
|
||||
|
||||
# Determine what to do
|
||||
if not __salt__['reg.read_value'](hive, key, vname)['success']:
|
||||
hive, key, vname = _parse_key_value(name)
|
||||
if not __salt__['reg.read_value'](hive, key, vname)['success']:
|
||||
reg_check = __salt__['reg.read_value'](hive, key, vname)
|
||||
if not reg_check['success'] or reg_check['vdata'] == '(value not set)':
|
||||
if not vname:
|
||||
hive, key, vname = _parse_key_value(name)
|
||||
reg_check = __salt__['reg.read_value'](hive, key, vname)
|
||||
if not reg_check['success'] or reg_check['vdata'] == '(value not set)':
|
||||
ret['comment'] = '{0} is already absent'.format(name)
|
||||
return ret
|
||||
else:
|
||||
ret['comment'] = '{0} is already absent'.format(name)
|
||||
return ret
|
||||
|
||||
|
@ -275,11 +281,10 @@ def absent(name, vname=None):
|
|||
ret['result'] = __salt__['reg.delete_value'](hive, key, vname)
|
||||
if not ret['result']:
|
||||
ret['changes'] = {}
|
||||
ret['comment'] = r'Failed to remove {0} from {1}\{2}'.format(name, hive,
|
||||
key)
|
||||
ret['comment'] = r'Failed to remove {0} from {1}'.format(key, hive)
|
||||
else:
|
||||
ret['changes'] = {'reg': {'Removed': remove_change}}
|
||||
ret['comment'] = r'Removed {0} from {1}\{2}'.format(name, hive, key)
|
||||
ret['comment'] = r'Removed {0} from {1}'.format(key, hive)
|
||||
|
||||
return ret
|
||||
|
||||
|
|
|
@ -954,6 +954,9 @@ def deploy_windows(host,
|
|||
newtimeout = timeout - (time.mktime(time.localtime()) - starttime)
|
||||
|
||||
smb_conn = salt.utils.smb.get_conn(host, username, password)
|
||||
if smb_conn is False:
|
||||
log.error('Please install impacket to enable SMB functionality')
|
||||
return False
|
||||
|
||||
creds = "-U '{0}%{1}' //{2}".format(
|
||||
username, password, host)
|
||||
|
|
|
@ -47,6 +47,9 @@ def get_conn(host=None, username=None, password=None):
|
|||
'''
|
||||
Get an SMB connection
|
||||
'''
|
||||
if not HAS_IMPACKET:
|
||||
return False
|
||||
|
||||
conn = impacket.smbconnection.SMBConnection(
|
||||
remoteName='*SMBSERVER',
|
||||
remoteHost=host,
|
||||
|
@ -65,6 +68,9 @@ def mkdirs(path, share='C$', conn=None, host=None, username=None, password=None)
|
|||
if conn is None:
|
||||
conn = get_conn(host, username, password)
|
||||
|
||||
if conn is False:
|
||||
return False
|
||||
|
||||
comps = path.split('/')
|
||||
pos = 1
|
||||
for comp in comps:
|
||||
|
@ -85,5 +91,8 @@ def put_str(content, path, share='C$', conn=None, host=None, username=None, pass
|
|||
if conn is None:
|
||||
conn = get_conn(host, username, password)
|
||||
|
||||
if conn is False:
|
||||
return False
|
||||
|
||||
fh_ = StrHandle(content)
|
||||
conn.putFile(share, path, fh_.string)
|
||||
|
|
|
@ -510,3 +510,11 @@ def safe_py_code(code):
|
|||
if code.count(bad):
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def verify_log(opts):
|
||||
'''
|
||||
If an insecre logging configuration is found, show a warning
|
||||
'''
|
||||
if opts.get('log_level') in ('garbage', 'trace', 'debug'):
|
||||
log.warn('Insecure logging configuration detected! Sensitive data may be logged.')
|
||||
|
|
|
@ -70,7 +70,7 @@ class WinPathTestCase(TestCase):
|
|||
Test to Returns the system path
|
||||
'''
|
||||
mock = MagicMock(return_value={'vdata': 'c:\\salt'})
|
||||
with patch.dict(win_path.__salt__, {'reg.read_key': mock}):
|
||||
with patch.dict(win_path.__salt__, {'reg.read_value': mock}):
|
||||
self.assertListEqual(win_path.get_path(), ['c:\\salt'])
|
||||
|
||||
def test_exists(self):
|
||||
|
|
|
@ -80,34 +80,37 @@ class RegTestCase(TestCase):
|
|||
'''
|
||||
Test to remove a registry entry.
|
||||
'''
|
||||
name = 'HKEY_CURRENT_USER\\SOFTWARE\\Salt'
|
||||
hive = 'HKEY_CURRENT_USER'
|
||||
key = 'SOFTWARE\\Salt'
|
||||
name = hive + '\\' + key
|
||||
vname = 'version'
|
||||
vdata = '0.15.3'
|
||||
|
||||
ret = {'name': name,
|
||||
'changes': {},
|
||||
'result': True,
|
||||
'comment': '{0} is already absent'.format(name)}
|
||||
|
||||
mock_read = MagicMock(side_effect=[{'success': False},
|
||||
{'success': False},
|
||||
{'success': True},
|
||||
{'success': True}])
|
||||
mock_read_true = MagicMock(return_value={'success': True, 'vdata': vdata})
|
||||
mock_read_false = MagicMock(return_value={'success': False, 'vdata': False})
|
||||
|
||||
mock_t = MagicMock(return_value=True)
|
||||
with patch.dict(reg.__salt__, {'reg.read_value': mock_read,
|
||||
with patch.dict(reg.__salt__, {'reg.read_value': mock_read_false,
|
||||
'reg.delete_value': mock_t}):
|
||||
self.assertDictEqual(reg.absent(name, vname), ret)
|
||||
|
||||
with patch.dict(reg.__salt__, {'reg.read_value': mock_read_true}):
|
||||
with patch.dict(reg.__opts__, {'test': True}):
|
||||
ret.update({'comment': '', 'result': None,
|
||||
'changes': {'reg': {'Will remove': {'Entry': vname,
|
||||
'Key': name}}}})
|
||||
'changes': {'reg': {'Will remove': {'Entry': vname, 'Key': name}}}})
|
||||
self.assertDictEqual(reg.absent(name, vname), ret)
|
||||
|
||||
with patch.dict(reg.__salt__, {'reg.read_value': mock_read_true,
|
||||
'reg.delete_value': mock_t}):
|
||||
with patch.dict(reg.__opts__, {'test': False}):
|
||||
ret.update({'result': True,
|
||||
'changes': {'reg': {'Removed': {'Entry': vname,
|
||||
'Key': name}}},
|
||||
'comment': 'Removed {0} from {0}'.format(name)})
|
||||
'changes': {'reg': {'Removed': {'Entry': vname, 'Key': name}}},
|
||||
'comment': 'Removed {0} from {1}'.format(key, hive)})
|
||||
self.assertDictEqual(reg.absent(name, vname), ret)
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue