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

Merge forward from 2015.8 to develop
This commit is contained in:
Justin Findlay 2015-09-18 13:55:49 -06:00
commit c9255f2bbd
88 changed files with 954 additions and 710 deletions

View File

@ -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

View File

@ -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.

View 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

View File

@ -25,7 +25,8 @@ Salt Table of Contents
topics/highavailability/index
topics/topology/index
topics/proxyminion/index
topics/transports/raet/index
topics/spm/index
topics/transports/index
topics/windows/index
topics/cloud/index
topics/netapi/index

View File

@ -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.

View File

@ -1,4 +1,4 @@
.. _spm:
.. _spm-cli:
=======
``spm``

View File

@ -198,7 +198,7 @@ need to be changed to the ownership of the new user.
.. conf_minion:: sudo_user
``sudo_user``
--------
-------------
Default: ``''``

View File

@ -33,3 +33,4 @@ Reference
beacons/all/index
engines/all/index
sdb/all/index
serializers/all/index

View File

@ -65,6 +65,7 @@ Full list of builtin execution modules
cpan
cron
cyg
cytest
daemontools
darwin_pkgutil
darwin_sysctl

View File

@ -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
=============

View File

@ -34,6 +34,7 @@ Full list of runner modules
queue
reactor
sdb
ssh
search
spacewalk
ssh

View File

@ -13,13 +13,14 @@ at https://cloud.google.com.
Dependencies
============
* Libcloud >= 0.14.0-beta3
* PyCrypto >= 2.1.
* LibCloud >= 0.14.1
* A Google Cloud Platform account with Compute Engine enabled
* A registered Service Account for authorization
* Oh, and obviously you'll need `salt <https://github.com/saltstack/salt>`_
.. _gce_setup:
Google Compute Engine Setup
===========================
#. Sign up for Google Cloud Platform
@ -49,17 +50,20 @@ Google Compute Engine Setup
To set up authorization, navigate to *APIs & auth* section and then the
*Credentials* link and click the *CREATE NEW CLIENT ID* button. Select
*Service Account* and click the *Create Client ID* button. This will
automatically download a ``.json`` file which can be ignored.
automatically download a ``.json`` file, which may or may not be used
in later steps, depending on your version of ``libcloud``.
Look for a new *Service Account* section in the page and record the generated email
address for the matching key/fingerprint. The email address will be used
in the ``service_account_email_address`` of the ``/etc/salt/cloud`` file.
Look for a new *Service Account* section in the page and record the generated
email address for the matching key/fingerprint. The email address will be used
in the ``service_account_email_address`` of the ``/etc/salt/cloud.providers``
or the ``/etc/salt/cloud.providers.d/*.conf`` file.
#. Key Format
*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 ``libcloud >= 0.17.0`` it is recommended that you use the ``JSON
format`` file you downloaded above and skip to the `Provider 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 +82,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 +122,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 +146,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 +168,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 +240,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 +261,7 @@ the metadata setting too:
.. code-block:: yaml
all_settings:
my-gce-profile:
...
metadata: '{"one": "1", "2": "two",
@ -432,7 +434,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 +442,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 +450,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

View File

@ -41,7 +41,7 @@ To install using the SaltStack yum repository:
Versions 6 / 7:
.. code-block:: config
.. code-block:: cfg
####################
# Enable SaltStack's package repository
@ -54,7 +54,7 @@ To install using the SaltStack yum repository:
Version 5:
.. code-block:: config
.. code-block:: cfg
####################
# Enable SaltStack's package repository

View File

@ -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
======================================

View File

@ -1,8 +1,8 @@
.. _proxy-minion:
===============================
Salt Proxy Minion Documentation
===============================
=================
Salt Proxy Minion
=================
Proxy minions are a developing Salt feature that enables controlling devices
that, for whatever reason, cannot run a standard salt-minion. Examples include
@ -507,3 +507,8 @@ And then in salt.proxy.rest_sample.py we find
return False
.. toctree::
:maxdepth: 2
:glob:
demo

View File

@ -0,0 +1,8 @@
===========================
Salt 2015.8.1 Release Notes
===========================
Version 2015.8.1 is a bugfix release for :doc:`2015.8.0
</topics/releases/2015.8.0>`.
Changes:

View File

@ -1,3 +1,5 @@
:orphan:
===================================
Salt Release Notes - Codename Boron
===================================

View File

@ -1,3 +1,5 @@
:orphan:
.. _proxy-2015.8.0:
=========================

View File

@ -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|

View File

@ -1,3 +1,5 @@
:orphan:
===========================================
Installing/Testing a Salt Release Candidate
===========================================

View File

@ -1,3 +1,5 @@
:orphan:
===============
Version Numbers
===============

View File

@ -333,3 +333,9 @@ The files in this type of package are configuration files for Salt, which
normally live in the ``/etc/salt/`` directory. Configuration files for packages
other than Salt can and should be handled with a Salt State (using a ``formula``
type of package).
.. toctree::
:maxdepth: 2
:glob:
dev

View File

@ -141,4 +141,6 @@ http://curvecp.org/
Programming Intro
=================
:ref:`Raet Programming Introduction <raet-programming>`
.. toctree:
programming_intro

View File

@ -39,6 +39,7 @@ Advanced Topics
:maxdepth: 2
walkthrough
rooted
minionfs
esky
multimaster
@ -50,6 +51,7 @@ Advanced Topics
writing_tests
http
lxc
stormpath
Salt Virt
==========

View File

@ -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()

View File

@ -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
@ -42,6 +43,7 @@ class SaltCall(parsers.SaltCallOptionParser):
# Setup file logging!
self.setup_logfile_logger()
verify_log(self.config)
caller = salt.cli.caller.Caller.factory(self.config)

View File

@ -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()

View File

@ -7,6 +7,7 @@ Make me some salt!
from __future__ import absolute_import
import os
import warnings
from salt.utils.verify import verify_log
# All salt related deprecation warnings should be shown once each!
warnings.filterwarnings(
@ -114,6 +115,7 @@ class Master(parsers.MasterOptionParser):
self.shutdown(err.errno)
self.setup_logfile_logger()
verify_log(self.config)
logger.info('Setting up the Salt Master')
# TODO: AIO core is separate from transport
@ -232,6 +234,7 @@ class Minion(parsers.MinionOptionParser): # pylint: disable=no-init
self.shutdown(err.errno)
self.setup_logfile_logger()
verify_log(self.config)
logger.info(
'Setting up the Salt Minion "{0}"'.format(
self.config['id']
@ -408,6 +411,7 @@ class ProxyMinion(parsers.ProxyMinionOptionParser): # pylint: disable=no-init
self.shutdown(err.errno)
self.setup_logfile_logger()
verify_log(self.config)
logger.info(
'Setting up a Salt Proxy Minion "{0}"'.format(
self.config['id']
@ -507,6 +511,7 @@ class Syndic(parsers.SyndicOptionParser):
self.shutdown(err.errno)
self.setup_logfile_logger()
verify_log(self.config)
logger.info(
'Setting up the Salt Syndic Minion "{0}"'.format(
self.config['id']

View File

@ -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)

View File

@ -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)

View File

@ -10,6 +10,7 @@ import salt.utils.job
from salt.ext.six import string_types
from salt.utils import parsers, print_cli
from salt.utils.args import yamlify_arg
from salt.utils.verify import verify_log
from salt.exceptions import (
SaltClientError,
SaltInvocationError,
@ -35,6 +36,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

View File

@ -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()

View File

@ -228,7 +228,7 @@ class CloudClient(object):
if a.get('provider', '')]
if providers:
_providers = opts.get('providers', {})
for provider in six.iterkeys(_providers):
for provider in _providers.keys():
if provider not in providers:
_providers.pop(provider)
return opts

View File

@ -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
@ -80,6 +80,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)

View File

@ -176,57 +176,10 @@ def list_nodes(call=None):
raise SaltCloudSystemExit(
'The list_nodes function must be called with -f or --function.'
)
fetch = True
page = 1
ret = {}
while fetch:
items = query(method='droplets', command='?page=' + str(page) + '&per_page=200')
for node in items['droplets']:
networks = node['networks']
v4s = networks.get('v4')
v6s = networks.get('v6')
public_ips = []
private_ips = []
if v4s:
for item in v4s:
ip_type = item.get('type')
ip_address = item.get('ip_address')
if ip_type == 'public':
public_ips.append(ip_address)
if ip_type == 'private':
private_ips.append(ip_address)
if v6s:
for item in v6s:
ip_type = item.get('type')
ip_address = item.get('ip_address')
if ip_type == 'public':
public_ips.append(ip_address)
if ip_type == 'private':
private_ips.append(ip_address)
ret[node['name']] = {
'id': node['id'],
'image': node['image']['name'],
'name': node['name'],
'private_ips': private_ips,
'public_ips': public_ips,
'size': node['size_slug'],
'state': str(node['status']),
}
page += 1
try:
fetch = 'next' in items['links']['pages']
except KeyError:
fetch = False
return ret
return _list_nodes()
def list_nodes_full(call=None, forOutput=True):
def list_nodes_full(call=None, for_output=True):
'''
Return a list of the VMs that are on the provider
'''
@ -234,26 +187,7 @@ def list_nodes_full(call=None, forOutput=True):
raise SaltCloudSystemExit(
'The list_nodes_full function must be called with -f or --function.'
)
fetch = True
page = 1
ret = {}
while fetch:
items = query(method='droplets', command='?page=' + str(page) + '&per_page=200')
for node in items['droplets']:
ret[node['name']] = {}
for item in six.iterkeys(node):
value = node[item]
if value is not None and forOutput:
value = str(value)
ret[node['name']][item] = value
page += 1
try:
fetch = 'next' in items['links']['pages']
except KeyError:
fetch = False
return ret
return _list_nodes(full=True, for_output=for_output)
def list_nodes_select(call=None):
@ -601,7 +535,7 @@ def _get_node(name):
attempts = 10
while attempts >= 0:
try:
return list_nodes_full(forOutput=False)[name]
return list_nodes_full(for_output=False)[name]
except KeyError:
attempts -= 1
log.debug(
@ -855,3 +789,85 @@ def show_pricing(kwargs=None, call=None):
ret['_raw'] = raw
return {profile['profile']: ret}
def _list_nodes(full=False, for_output=False):
'''
Helper function to format and parse node data.
'''
fetch = True
page = 1
ret = {}
while fetch:
items = query(method='droplets',
command='?page=' + str(page) + '&per_page=200')
for node in items['droplets']:
name = node['name']
ret[name] = {}
if full:
ret[name] = _get_full_output(node, for_output=for_output)
else:
public_ips, private_ips = _get_ips(node['networks'])
ret[name] = {
'id': node['id'],
'image': node['image']['name'],
'name': name,
'private_ips': private_ips,
'public_ips': public_ips,
'size': node['size_slug'],
'state': str(node['status']),
}
page += 1
try:
fetch = 'next' in items['links']['pages']
except KeyError:
fetch = False
return ret
def _get_full_output(node, for_output=False):
'''
Helper function for _list_nodes to loop through all node information.
Returns a dictionary containing the full information of a node.
'''
ret = {}
for item in six.iterkeys(node):
value = node[item]
if value is not None and for_output:
value = str(value)
ret[item] = value
return ret
def _get_ips(networks):
'''
Helper function for list_nodes. Returns public and private ip lists based on a
given network dictionary.
'''
v4s = networks.get('v4')
v6s = networks.get('v6')
public_ips = []
private_ips = []
if v4s:
for item in v4s:
ip_type = item.get('type')
ip_address = item.get('ip_address')
if ip_type == 'public':
public_ips.append(ip_address)
if ip_type == 'private':
private_ips.append(ip_address)
if v6s:
for item in v6s:
ip_type = item.get('type')
ip_address = item.get('ip_address')
if ip_type == 'public':
public_ips.append(ip_address)
if ip_type == 'private':
private_ips.append(ip_address)
return public_ips, private_ips

View File

@ -3025,6 +3025,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

View File

@ -17,30 +17,12 @@ limitations under the License.
Google Compute Engine Module
============================
The Google Compute Engine module. This module interfaces with Google Compute
Engine. To authenticate to GCE, you will need to create a Service Account.
The Google Compute Engine module. This module interfaces with Google Compute
Engine (GCE). To authenticate to GCE, you will need to create a Service Account.
To set up Service Account Authentication, follow the :ref:`gce_setup` instructions.
Setting up Service Account Authentication:
- Go to the Cloud Console at: https://cloud.google.com/console.
- Create or navigate to your desired Project.
- Make sure Google Compute Engine service is enabled under the Services
section.
- Go to "APIs and auth" section, and then the "Credentials" link.
- Click the "CREATE NEW CLIENT ID" button.
- Select "Service Account" and click "Create Client ID" button.
- This will automatically download a .json file; ignore it.
- Look for a new "Service Account" section in the page, click on the "Generate New P12 key" button
- Copy the Email Address for inclusion in your /etc/salt/cloud file
in the 'service_account_email_address' setting.
- Download the Private Key
- The key that you download is a PKCS12 key. It needs to be converted to
the PEM format.
- Convert the key using OpenSSL (the default password is 'notasecret'):
C{openssl pkcs12 -in PRIVKEY.p12 -passin pass:notasecret \
-nodes -nocerts | openssl rsa -out ~/PRIVKEY.pem}
- Add the full path name of the converted private key to your
/etc/salt/cloud file as 'service_account_private_key' setting.
- Consider using a more secure location for your private key.
Example Provider Configuration
------------------------------
.. code-block:: yaml
@ -60,7 +42,6 @@ Setting up Service Account Authentication:
:maintainer: Eric Johnson <erjohnso@google.com>
:depends: libcloud >= 0.14.1
:depends: pycrypto >= 2.1
'''
# pylint: disable=invalid-name,function-redefined
@ -119,7 +100,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 +2022,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:

View File

@ -558,7 +558,7 @@ def create_config(kwargs=None, call=None):
def create_disk_from_distro(vm_, linode_id, swap_size=None):
'''
r'''
Creates the disk for the Linode from the distribution.
vm_
@ -601,7 +601,7 @@ def create_disk_from_distro(vm_, linode_id, swap_size=None):
def create_swap_disk(vm_, linode_id, swap_size=None):
'''
r'''
Creates the disk for the specified Linode.
vm_
@ -630,7 +630,7 @@ def create_swap_disk(vm_, linode_id, swap_size=None):
def create_private_ip(vm_, linode_id):
'''
r'''
Creates a private IP for the specified Linode.
vm_
@ -747,7 +747,7 @@ def get_datacenter_id(location):
def get_disk_size(vm_, swap):
'''
r'''
Returns the size of of the root disk in MB.
vm_
@ -761,7 +761,7 @@ def get_disk_size(vm_, swap):
def get_distribution_id(vm_):
'''
r'''
Returns the distribution ID for a VM
vm_
@ -890,7 +890,7 @@ def get_linode_id_from_name(name):
def get_password(vm_):
'''
r'''
Return the password to use for a VM.
vm_
@ -946,7 +946,7 @@ def get_private_ip(vm_):
def get_pub_key(vm_):
'''
r'''
Return the SSH pubkey.
vm_
@ -958,7 +958,7 @@ def get_pub_key(vm_):
def get_swap_size(vm_):
'''
r'''
Returns the amoutn of swap space to be used in MB.
vm_
@ -970,7 +970,7 @@ def get_swap_size(vm_):
def get_vm_size(vm_):
'''
r'''
Returns the VM's size.
vm_

View File

@ -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()

View File

@ -426,7 +426,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:
@ -546,7 +546,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()

View File

@ -38,7 +38,7 @@ import salt.utils.rsax931
import salt.utils.verify
import salt.version
from salt.exceptions import (
AuthenticationError, SaltClientError, SaltReqTimeoutError
AuthenticationError, SaltClientError, SaltReqTimeoutError, SaltSystemExit
)
import tornado.gen
@ -551,7 +551,7 @@ class AsyncAuth(object):
'Salt Minion.\nThe master public key can be found '
'at:\n{1}'.format(salt.version.__version__, m_pub_fn)
)
sys.exit(42)
raise SaltSystemExit('Invalid master key')
if self.opts.get('syndic_master', False): # Is syndic
syndic_finger = self.opts.get('syndic_finger', self.opts.get('master_finger', False))
if syndic_finger:

View File

@ -902,14 +902,22 @@ def add_pool_member(hostname, username, password, name, member):
'''
A function to connect to a bigip device and add a new member to an existing pool.
Parameters:
hostname: The host/address of the bigip device
username: The iControl REST username
password: The iControl REST password
name: The name of the pool to modify
member: The name of the member to add
i.e. 10.1.1.2:80
hostname
The host/address of the bigip device
username
The iControl REST username
password
The iControl REST password
name
The name of the pool to modify
member
The name of the member to add
i.e. 10.1.1.2:80
CLI Example:
.. code-block:: bash
salt '*' bigip.add_pool_members bigip admin admin my-pool 10.2.2.1:80
'''

View File

@ -1024,6 +1024,7 @@ def create_internet_gateway(internet_gateway_name=None, vpc_id=None,
returns False if the internet gateways was not created.
.. versionadded:: 2015.8.0
CLI Example:
.. code-block:: bash

View File

@ -1489,8 +1489,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
@ -1865,16 +1865,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
@ -1899,9 +1896,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))
@ -1909,12 +1904,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
@ -1945,16 +1940,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,
@ -2099,9 +2092,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
@ -2116,7 +2107,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):

View File

@ -114,6 +114,7 @@ The following options can be set in the :ref:`minion config
- nsenter
- lxc-attach
- docker-exec
See :ref:`Executing Commands Within a Running Container <docker-execution-driver>`.
Functions

View File

@ -1042,24 +1042,24 @@ def comment_line(path,
Comment or Uncomment a line in a text file.
:param path: string
The full path to the text file.
The full path to the text file.
:param regex: string
A regex expression that begins with ``^`` that will find the line you wish
to comment. Can be as simple as ``^color =``
A regex expression that begins with ``^`` that will find the line you wish
to comment. Can be as simple as ``^color =``
:param char: string
The character used to comment a line in the type of file you're referencing.
Default is ``#``
The character used to comment a line in the type of file you're referencing.
Default is ``#``
:param cmnt: boolean
True to comment the line. False to uncomment the line. Default is True.
True to comment the line. False to uncomment the line. Default is True.
:param backup: string
The file extension to give the backup file. Default is ``.bak``
The file extension to give the backup file. Default is ``.bak``
:return: boolean
Returns True if successful, False if not
Returns True if successful, False if not
CLI Example:
@ -1080,7 +1080,7 @@ def comment_line(path,
.. code-block:: bash
salt '*' file.comment_line 'C:\salt\conf\minion' '^log_level: (warning|info|debug)' '#' False '.bk'
salt '*' file.comment_line 'C:\salt\conf\minion' '^log_level: (warning|info|debug)' '#' False '.bk'
'''
# Get the regex for comment or uncomment
if cmnt:

View File

@ -885,7 +885,7 @@ def config_get_regexp(key,
ignore_retcode=False,
**kwargs):
r'''
.. versionaded:: 2015.8.0
.. versionadded:: 2015.8.0
Get the value of a key or keys in the git configuration file using regexes
for more flexible matching. The return data is a dictionary mapping keys to

View File

@ -221,6 +221,7 @@ def image_create(name, location=None, profile=None, visibility=None,
CLI Example, old format:
.. code-block:: bash
salt '*' glance.image_create name=f16-jeos is_public=true \\
disk_format=qcow2 container_format=ovf \\
copy_from=http://berrange.fedorapeople.org/\
@ -228,6 +229,8 @@ def image_create(name, location=None, profile=None, visibility=None,
CLI Example, new format resembling Glance API v2:
.. code-block:: bash
salt '*' glance.image_create name=f16-jeos visibility=public \\
disk_format=qcow2 container_format=ovf \\
copy_from=http://berrange.fedorapeople.org/\
@ -452,9 +455,9 @@ def image_update(id=None, name=None, profile=None, **kwargs): # pylint: disable
'''
Update properties of given image.
Known to work for:
- min_ram (in MB)
- protected (bool)
- visibility ('public' or 'private')
- min_ram (in MB)
- protected (bool)
- visibility ('public' or 'private')
'''
if id:
image = image_show(id=id)

View File

@ -623,7 +623,7 @@ def import_key(user=None,
text=None,
filename=None,
gnupghome=None):
'''
r'''
Import a key from text or file
user
@ -645,6 +645,7 @@ def import_key(user=None,
salt '*' gpg.import_key text='-----BEGIN PGP PUBLIC KEY BLOCK-----\n ... -----END PGP PUBLIC KEY BLOCK-----'
salt '*' gpg.import_key filename='/path/to/public-key-file'
'''
ret = {
'res': True,

View File

@ -81,7 +81,7 @@ def trigger_event(event=None, **kwargs):
CLI Example:
.. code-block:: yaml
TBA
'''
res = {'result': False, 'message': 'Something went wrong'}

View File

@ -193,7 +193,8 @@ def set_channel_access(channel=14, access_update_mode='non_volatile',
Set channel access
:param channel: number [1:7]
:param access_update_mode: one of
:param access_update_mode:
- 'dont_change' = don't set or change Channel Access
- 'non_volatile' = set non-volatile Channel Access
- 'volatile' = set volatile (active) setting of Channel Access
@ -683,21 +684,24 @@ def set_bootdev(bootdev='default', persist=False, uefiboot=False, **kwargs):
Set boot device to use on next reboot
:param bootdev:
*network -- Request network boot
*hd -- Boot from hard drive
*safe -- Boot from hard drive, requesting 'safe mode'
*optical -- boot from CD/DVD/BD drive
*setup -- Boot into setup utility
*default -- remove any IPMI directed boot device
request
- network: Request network boot
- hd: Boot from hard drive
- safe: Boot from hard drive, requesting 'safe mode'
- optical: boot from CD/DVD/BD drive
- setup: Boot into setup utility
- default: remove any IPMI directed boot device
request
:param persist: If true, ask that system firmware use this device
beyond next boot. Be aware many systems do not honor
this
:param uefiboot: If true, request UEFI boot explicitly. Strictly
speaking, the spec sugests that if not set, the system
should BIOS boot and offers no "don't care" option.
In practice, this flag not being set does not preclude
UEFI boot on any system I've encountered.
:param kwargs:
- api_host=127.0.0.1
- api_user=admin
@ -811,6 +815,7 @@ def get_users(channel=14, **kwargs):
get list of users and access information
:param channel: number [1:7]
:param kwargs:
- api_host=127.0.0.1
- api_user=admin
@ -819,15 +824,15 @@ def get_users(channel=14, **kwargs):
- api_kg=None
:return:
name: (str)
uid: (int)
channel: (int)
access:
- name: (str)
- uid: (int)
- channel: (int)
- access:
- callback (bool)
- link_auth (bool)
- ipmi_msg (bool)
- privilege_level: (str)[callback, user, operatorm administrator,
proprietary, no_access]
proprietary, no_access]
CLI Examples:

View File

@ -279,10 +279,10 @@ def list_sets(family='ipv4'):
def check_set(set=None, family='ipv4'):
'''
.. versionadded:: 2014.7.0
Check that given ipset set exists.
.. versionadded:: 2014.7.0
CLI Example:
.. code-block:: bash
@ -395,7 +395,7 @@ def check(set=None, entry=None, family='ipv4'):
An entry in the ipset. This parameter can be a single IP address, a
range of IP addresses, or a subnet block. Example:
.. code-block::
.. code-block:: cfg
192.168.0.1
192.168.0.2-192.168.0.19

View File

@ -314,7 +314,10 @@ def create_simple_binding(jboss_config, binding_name, value, profile=None):
.. code-block:: bash
salt '*' jboss7.create_simple_binding '{"cli_path": "integration.modules.sysmod.SysModuleTest.test_valid_docs", "controller": "10.11.12.13:9999", "cli_user": "jbossadm", "cli_password": "jbossadm"}' my_binding_name my_binding_value
salt '*' jboss7.create_simple_binding \\
'{"cli_path": "integration.modules.sysmod.SysModuleTest.test_valid_docs", \\
"controller": "10.11.12.13:9999", "cli_user": "jbossadm", "cli_password": "jbossadm"}' \\
my_binding_name my_binding_value
'''
log.debug("======================== MODULE FUNCTION: jboss7.create_simple_binding, binding_name=%s, value=%s, profile=%s", binding_name, value, profile)
if profile is None:

View File

@ -2,21 +2,22 @@
'''
Manage Kerberos KDC
:configuration: In order to manage your KDC you will need to generate a keytab
that can authenticate without requireing a password.
:configuration:
In order to manage your KDC you will need to generate a keytab
that can authenticate without requiring a password.
.. code-block:: bash
.. code-block:: bash
# ktadd -k /root/secure.keytab kadmin/admin kadmin/changepw
# ktadd -k /root/secure.keytab kadmin/admin kadmin/changepw
On the KDC minion you will need to add the following to the minion
configuration file so Salt knows what keytab to use and what principal to
authenticate as.
.. code-block:: yaml
.. code-block:: yaml
auth_keytab: /root/auth.keytab
auth_principal: kadmin/admin
auth_keytab: /root/auth.keytab
auth_principal: kadmin/admin
'''
# Import python libs

View File

@ -424,7 +424,7 @@ def last(attrs=None, where=None):
def listening_ports(attrs=None, where=None):
'''
r'''
Return listening_ports_ information from osquery
CLI Example:
@ -437,7 +437,7 @@ def listening_ports(attrs=None, where=None):
def logged_in_users(attrs=None, where=None):
'''
r'''
Return logged_in_users_ information from osquery
CLI Example:
@ -450,7 +450,7 @@ def logged_in_users(attrs=None, where=None):
def mounts(attrs=None, where=None):
'''
r'''
Return mounts_ information from osquery
CLI Example:

View File

@ -150,7 +150,7 @@ def obfuscate(*args):
Here are some examples:
* ``'secret password'`` becomes ``'<str>'``
* ``['secret', 1]`` becomes ``['<str>', '<int>']
* ``['secret', 1]`` becomes ``['<str>', '<int>']``
* ``{'login': 'somelogin', 'pwd': 'secret'}`` becomes
``{'login': '<str>', 'pwd': '<str>'}``

View File

@ -58,10 +58,10 @@ def post_message(user=None,
:param user: The user or group to send to, must be key of user or group not email address.
:param message: The message to send to the PushOver user or group.
:param title: Specify who the message is from.
:param priority The priority of the message, defaults to 0.
:param expire The message should expire after N number of seconds.
:param retry The number of times the message should be retried.
:param sound The sound to associate with the message.
:param priority: The priority of the message, defaults to 0.
:param expire: The message should expire after N number of seconds.
:param retry: The number of times the message should be retried.
:param sound: The sound to associate with the message.
:param api_version: The PushOver API version, if not specified in the configuration.
:param token: The PushOver token, if not specified in the configuration.
:return: Boolean if message was sent successfully.

View File

@ -667,6 +667,7 @@ def generateBlobs(api_key=None,
**kwargs):
'''
List all Slack users.
:param api_key: The Random.org api key.
:param api_version: The Random.org api version.
:param format: Specifies the format in which the

View File

@ -108,20 +108,19 @@ def __virtual__():
def read_key(hkey, path, key=None):
'''
*** Incorrect Usage ***
The name of this function is misleading and will be changed to reflect
proper usage in the Boron release of Salt. The path option will be removed
and the key will be the actual key. See the following issue:
.. important::
The name of this function is misleading and will be changed to reflect
proper usage in the Boron release of Salt. The path option will be removed
and the key will be the actual key. See the following issue:
https://github.com/saltstack/salt/issues/25618
https://github.com/saltstack/salt/issues/25618
In order to not break existing state files this function will call the
read_value function if a key is passed. Key will be passed as the value
name. If key is not passed, this function will return the default value for
the key.
In order to not break existing state files this function will call the
read_value function if a key is passed. Key will be passed as the value
name. If key is not passed, this function will return the default value for
the key.
In the Boron release this function will be removed in favor of read_value.
***
In the Boron release this function will be removed in favor of read_value.
Read registry key value
@ -199,19 +198,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
@ -219,20 +224,19 @@ def read_value(hive, key, vname=None):
def set_key(hkey, path, value, key=None, vtype='REG_DWORD', reflection=True):
'''
*** Incorrect Usage ***
The name of this function is misleading and will be changed to reflect
proper usage in the Boron release of Salt. The path option will be removed
and the key will be the actual key. See the following issue:
.. important ::
The name of this function is misleading and will be changed to reflect
proper usage in the Boron release of Salt. The path option will be removed
and the key will be the actual key. See the following issue:
https://github.com/saltstack/salt/issues/25618
https://github.com/saltstack/salt/issues/25618
In order to not break existing state files this function will call the
set_value function if a key is passed. Key will be passed as the value
name. If key is not passed, this function will return the default value for
the key.
In order to not break existing state files this function will call the
set_value function if a key is passed. Key will be passed as the value
name. If key is not passed, this function will return the default value for
the key.
In the Boron release this function will be removed in favor of set_value.
***
In the Boron release this function will be removed in favor of set_value.
Set a registry key
@ -312,27 +316,26 @@ 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
def create_key(hkey, path, key=None, value=None, reflection=True):
'''
*** Incorrect Usage ***
The name of this function is misleading and will be changed to reflect
proper usage in the Boron release of Salt. The path option will be removed
and the key will be the actual key. See the following issue:
.. important ::
The name of this function is misleading and will be changed to reflect
proper usage in the Boron release of Salt. The path option will be removed
and the key will be the actual key. See the following issue:
https://github.com/saltstack/salt/issues/25618
https://github.com/saltstack/salt/issues/25618
In order to not break existing state files this function will call the
set_value function if key is passed. Key will be passed as the value name.
If key is not passed, this function will return the default value for the
key.
In order to not break existing state files this function will call the
set_value function if key is passed. Key will be passed as the value name.
If key is not passed, this function will return the default value for the
key.
In the Boron release path will be removed and key will be the path. You will
not pass value.
***
In the Boron release path will be removed and key will be the path. You will
not pass value.
Create a registry key
@ -357,21 +360,20 @@ def create_key(hkey, path, key=None, value=None, reflection=True):
def delete_key(hkey, path, key=None, reflection=True, force=False):
'''
*** Incorrect Usage ***
The name of this function is misleading and will be changed to reflect
proper usage in the Boron release of Salt. The path option will be removed
and the key will be the actual key. See the following issue:
.. important::
The name of this function is misleading and will be changed to reflect
proper usage in the Boron release of Salt. The path option will be removed
and the key will be the actual key. See the following issue:
https://github.com/saltstack/salt/issues/25618
https://github.com/saltstack/salt/issues/25618
In order to not break existing state files this function will call the
delete_value function if a key is passed. Key will be passed as the value
name. If key is not passed, this function will return the default value for
the key.
In order to not break existing state files this function will call the
delete_value function if a key is passed. Key will be passed as the value
name. If key is not passed, this function will return the default value for
the key.
In the Boron release path will be removed and key will be the path.
reflection will also be removed.
***
In the Boron release path will be removed and key will be the path.
reflection will also be removed.
Delete a registry key
@ -434,7 +436,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 +506,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 +514,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 +563,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

View File

@ -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 and pillar data available to the minion.

View File

@ -57,19 +57,23 @@ def splay(fun, *args, **kwargs):
Splay a salt function call execution time across minions over
a number of seconds (default: 600)
NOTE: You *probably* want to use --async here and look up the job results later.
If you're dead set on getting the output from the CLI command, then make
sure to set the timeout (with the -t flag) to something greater than the
splaytime (max splaytime + time to execute job).
Otherwise, it's very likely that the cli will time out before the job returns.
.. note::
You *probably* want to use --async here and look up the job results later.
If you're dead set on getting the output from the CLI command, then make
sure to set the timeout (with the -t flag) to something greater than the
splaytime (max splaytime + time to execute job).
Otherwise, it's very likely that the cli will time out before the job returns.
CLI Example:
# With default splaytime
salt --async '*' splay.splay pkg.install cowsay version=3.03-8.el6
CLI Examples:
# With specified splaytime (5 minutes) and timeout with 10 second buffer
.. code-block:: bash
salt --async '*' splay.splay pkg.install cowsay version=3.03-8.el6
.. code-block:: bash
# With specified splaytime (5 minutes) and timeout with 10 second buffer
salt -t 310 '*' splay.splay 300 pkg.version cowsay
'''
if fun == 'sudo.salt_call':

View File

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
'''
r'''
A salt module for SSL/TLS.
Can create a Certificate Authority (CA)
or use Self-Signed certificates.
@ -891,9 +891,9 @@ def create_csr(ca_name,
for the given req. source with a DNS: prefix. To be thorough, you
may want to include both DNS: and IP: entries if you are using
subjectAltNames for destinations for your TLS connections.
e.g.:
requests to https://1.2.3.4 will fail from python's
requests library w/out the second entry in the above list
e.g.:
requests to https://1.2.3.4 will fail from python's
requests library w/out the second entry in the above list
.. versionadded:: 2015.8.0
@ -901,17 +901,19 @@ def create_csr(ca_name,
Specify the general certificate type. Can be either `server` or
`client`. Indicates the set of common extensions added to the CSR.
server: {
'basicConstraints': 'CA:FALSE',
'extendedKeyUsage': 'serverAuth',
'keyUsage': 'digitalSignature, keyEncipherment'
}
.. code-block:: cfg
client: {
'basicConstraints': 'CA:FALSE',
'extendedKeyUsage': 'clientAuth',
'keyUsage': 'nonRepudiation, digitalSignature, keyEncipherment'
}
server: {
'basicConstraints': 'CA:FALSE',
'extendedKeyUsage': 'serverAuth',
'keyUsage': 'digitalSignature, keyEncipherment'
}
client: {
'basicConstraints': 'CA:FALSE',
'extendedKeyUsage': 'clientAuth',
'keyUsage': 'nonRepudiation, digitalSignature, keyEncipherment'
}
type_ext
boolean. Whether or not to extend the filename with CN_[cert_type]

View File

@ -1,8 +1,10 @@
# -*- coding: utf-8 -*-
'''
Interface to Red Hat tuned-adm module
:maintainer: Syed Ali <alicsyed@gmail.com>
:maturity: new
:depends: cmd.run
:depends: tuned-adm
:platform: Linux
'''

View File

@ -349,7 +349,7 @@ def get(path, objectType):
def add_ace(path, objectType, user, permission, acetype, propagation):
'''
r'''
add an ace to an object
path: path to the object (i.e. c:\\temp\\file, HKEY_LOCAL_MACHINE\\SOFTWARE\\KEY, etc)
@ -424,7 +424,7 @@ def add_ace(path, objectType, user, permission, acetype, propagation):
def rm_ace(path, objectType, user, permission, acetype, propagation):
'''
r'''
remove an ace to an object
path: path to the object (i.e. c:\\temp\\file, HKEY_LOCAL_MACHINE\\SOFTWARE\\KEY, etc)

View File

@ -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:

View File

@ -501,11 +501,15 @@ def install(name=None, refresh=False, pkgs=None, saltenv='base', **kwargs):
If the package is installed by ``pkg.install``:
.. code-block:: cfg
{'<package>': {'old': '<old-version>',
'new': '<new-version>'}}
If the package is already installed:
.. code-block:: cfg
{'<package>': {'current': '<current-version>'}}
The following example will refresh the winrepo and install a single package,

View File

@ -246,7 +246,6 @@ def restart(name):
def create_win_salt_restart_task():
'''
Create a task in Windows task scheduler to enable restarting the salt-minion
CLI Example:
@ -395,7 +394,7 @@ def create(name,
obj=None,
password=None,
**kwargs):
'''
r'''
Create the named service.
.. versionadded:: 2015.8.0

View File

@ -11,7 +11,8 @@ Module for managing Windows Users
- win32security
- win32ts
NOTE: This currently only works with local user accounts, not domain accounts
.. note::
This currently only works with local user accounts, not domain accounts
'''
from __future__ import absolute_import
@ -69,36 +70,36 @@ def add(name,
Add a user to the minion.
:param str name:
User name
User name
:param str password:
User's password in plain text.
User's password in plain text.
:param str fullname:
The user's full name.
The user's full name.
:param str description:
A brief description of the user account.
A brief description of the user account.
:param list groups:
A list of groups to add the user to.
A list of groups to add the user to.
:param str home:
The path to the user's home directory.
The path to the user's home directory.
:param str homedrive:
The drive letter to assign to the home directory. Must be the Drive Letter
followed by a colon. ie: U:
The drive letter to assign to the home directory. Must be the Drive Letter
followed by a colon. ie: U:
:param str profile:
An explicit path to a profile. Can be a UNC or a folder on the system. If
left blank, windows uses it's default profile directory.
An explicit path to a profile. Can be a UNC or a folder on the system. If
left blank, windows uses it's default profile directory.
:param str logonscript:
Path to a login script to run when the user logs on.
Path to a login script to run when the user logs on.
:return:
True if successful. False is unsuccessful.
True if successful. False is unsuccessful.
:rtype: bool
CLI Example:
@ -154,32 +155,32 @@ def update(name,
.. versionadded:: 2015.8.0
:param str name:
The user name to update.
The user name to update.
:param str password:
New user password in plain text.
New user password in plain text.
:param str fullname:
The user's full name.
The user's full name.
:param str description:
A brief description of the user account.
A brief description of the user account.
:param str home:
The path to the user's home directory.
The path to the user's home directory.
:param str homedrive:
The drive letter to assign to the home directory. Must be the Drive Letter
followed by a colon. ie: U:
The drive letter to assign to the home directory. Must be the Drive Letter
followed by a colon. ie: U:
:param str logonscript:
The path to the logon script.
The path to the logon script.
:param str profile:
The path to the user's profile directory.
The path to the user's profile directory.
:return:
True if successful. False is unsuccessful.
True if successful. False is unsuccessful.
:rtype: bool
CLI Example:
@ -240,18 +241,18 @@ def delete(name,
Remove a user from the minion
:param str name:
The name of the user to delete
The name of the user to delete
:param bool purge:
Boolean value indicating that the user profile should also be removed when
the user account is deleted. If set to True the profile will be removed.
Boolean value indicating that the user profile should also be removed when
the user account is deleted. If set to True the profile will be removed.
:param bool force:
Boolean value indicating that the user account should be deleted even if the
user is logged in. True will log the user out and delete user.
Boolean value indicating that the user account should be deleted even if the
user is logged in. True will log the user out and delete user.
:return:
True if successful
True if successful
:rtype: bool
CLI Example:
@ -342,10 +343,10 @@ def getUserSid(username):
Get the Security ID for the user
:param str username:
user name for which to look up the SID
user name for which to look up the SID
:return:
Returns the user SID
Returns the user SID
:rtype: str
CLI Example:
@ -367,13 +368,13 @@ def setpassword(name, password):
Set the user's password
:param str name:
user name for which to set the password
user name for which to set the password
:param str password:
the new password
the new password
:return:
True if successful. False is unsuccessful.
True if successful. False is unsuccessful.
:rtype: bool
CLI Example:
@ -390,13 +391,13 @@ def addgroup(name, group):
Add user to a group
:param str name:
user name to add to the group
user name to add to the group
:param str group:
name of the group to which to add the user
name of the group to which to add the user
:return:
True if successful. False is unsuccessful.
True if successful. False is unsuccessful.
:rtype: bool
CLI Example:
@ -425,13 +426,13 @@ def removegroup(name, group):
Remove user from a group
:param str name:
user name to remove from the group
user name to remove from the group
:param str group:
name of the group from which to remove the user
name of the group from which to remove the user
:return:
True if successful. False is unsuccessful.
True if successful. False is unsuccessful.
:rtype: bool
CLI Example:
@ -463,16 +464,16 @@ def chhome(name, home, persist=False):
to the new home directory if the old home directory exist.
:param str name:
name of the user whose home directory you wish to change
name of the user whose home directory you wish to change
:param str home:
new location of the home directory
new location of the home directory
:param bool persist:
True to move the contents of the existing home directory to the new location
True to move the contents of the existing home directory to the new location
:return:
True if successful. False is unsuccessful.
True if successful. False is unsuccessful.
:rtype: bool
CLI Example:
@ -509,10 +510,10 @@ def chprofile(name, profile):
Change the profile directory of the user
:param str name:
name of the user whose profile you wish to change
name of the user whose profile you wish to change
:param str profile:
new location of the profile
new location of the profile
:return:
True if successful. False is unsuccessful.
@ -532,13 +533,13 @@ def chfullname(name, fullname):
Change the full name of the user
:param str name:
user name for which to change the full name
user name for which to change the full name
:param str fullname:
the new value for the full name
the new value for the full name
:return:
True if successful. False is unsuccessful.
True if successful. False is unsuccessful.
:rtype: bool
CLI Example:
@ -556,18 +557,18 @@ def chgroups(name, groups, append=True):
member of only the specified groups
:param str name:
user name for which to change groups
user name for which to change groups
:param groups:
a single group or a list of groups to assign to the user
:type: list, str
a single group or a list of groups to assign to the user
:type groups: list, str
:param bool append:
True adds the passed groups to the user's current groups
False sets the user's groups to the passed groups only
True adds the passed groups to the user's current groups
False sets the user's groups to the passed groups only
:return:
True if successful. False is unsuccessful.
True if successful. False is unsuccessful.
:rtype: bool
CLI Example:
@ -609,23 +610,23 @@ def info(name):
Return user information
:param str name:
Username for which to display information
Username for which to display information
:returns:
A dictionary containing user information
- fullname
- username
- SID
- passwd (will always return None)
- comment (same as description, left here for backwards compatibility)
- description
- active
- logonscript
- profile
- home
- homedrive
- groups
- gid
A dictionary containing user information
- fullname
- username
- SID
- passwd (will always return None)
- comment (same as description, left here for backwards compatibility)
- description
- active
- logonscript
- profile
- home
- homedrive
- groups
- gid
:rtype: dict
CLI Example:
@ -687,10 +688,10 @@ def list_groups(name):
Return a list of groups the named user belongs to
:param str name:
user name for which to list groups
user name for which to list groups
:return:
list of groups to which the user belongs
list of groups to which the user belongs
:rtype: list
CLI Example:
@ -715,11 +716,11 @@ def getent(refresh=False):
Return the list of all info for all users
:param bool refresh:
Refresh the cached user information. Default is False. Useful when used from
within a state function.
Refresh the cached user information. Default is False. Useful when used from
within a state function.
:return:
A dictionary containing information about all users on the system
A dictionary containing information about all users on the system
:rtype: dict
CLI Example:
@ -755,7 +756,7 @@ def list_users():
Return a list of users on Windows
:return:
list of users on the system
list of users on the system
:rtype: list
CLI Example:
@ -790,13 +791,13 @@ def rename(name, new_name):
Change the username for a named user
:param str name:
user name to change
user name to change
:param str new_name:
the new name for the current user
the new name for the current user
:return:
True if successful. False is unsuccessful.
True if successful. False is unsuccessful.
:rtype: bool
CLI Example:

View File

@ -261,46 +261,50 @@ def list_update(name=None,
"""
Returns details for all updates that match the search criteria
:param name: str
The name of the update you're searching for. This can be the GUID
(preferred), a KB number, or the full name of the update. Run list_updates
to get the GUID for the update you're looking for.
:param str name:
The name of the update you're searching for. This can be the GUID
(preferred), a KB number, or the full name of the update. Run list_updates
to get the GUID for the update you're looking for.
:param download: bool
:param bool download:
Download the update returned by this function. Run this function first
to see if the update exists, then set download=True to download the
update.
:param install: bool
:param bool install:
Install the update returned by this function. Run this function first
to see if the update exists, then set install=True to install the
update. This will override download=True
:return: dict
Returns a dict containing a list of updates that match the name if
download and install are both set to False. Should usually be a single
update, but can return multiple if a partial name is given. If download or
install is set to true it will return the results of
win_wua.download_updates::
:return:
Returns a dict containing a list of updates that match the name if
download and install are both set to False. Should usually be a single
update, but can return multiple if a partial name is given. If download or
install is set to true it will return the results of
win_wua.download_updates:
List of Updates:
{'<GUID>': {'Title': <title>,
'KB': <KB>,
'GUID': <the globally unique identifier for the update>
'Description': <description>,
'Downloaded': <has the update been downloaded>,
'Installed': <has the update been installed>,
'Mandatory': <is the update mandatory>,
'UserInput': <is user input required>,
'EULAAccepted': <has the EULA been accepted>,
'Severity': <update severity>,
'NeedsReboot': <is the update installed and awaiting reboot>,
'RebootBehavior': <will the update require a reboot>,
'Categories': [ '<category 1>',
'<category 2>',
...]
}
}
.. code-block:: cfg
List of Updates:
{'<GUID>': {'Title': <title>,
'KB': <KB>,
'GUID': <the globally unique identifier for the update>
'Description': <description>,
'Downloaded': <has the update been downloaded>,
'Installed': <has the update been installed>,
'Mandatory': <is the update mandatory>,
'UserInput': <is user input required>,
'EULAAccepted': <has the EULA been accepted>,
'Severity': <update severity>,
'NeedsReboot': <is the update installed and awaiting reboot>,
'RebootBehavior': <will the update require a reboot>,
'Categories': [ '<category 1>',
'<category 2>',
...]
}
}
:return type: dict
CLI Examples:
@ -392,31 +396,31 @@ def list_updates(software=True,
"""
Returns a detailed list of available updates or a summary
:param software: bool
:param bool software:
Include software updates in the results (default is True)
:param drivers: bool
:param bool drivers:
Include driver updates in the results (default is False)
:param summary: bool
:param bool summary:
True: Return a summary of updates available for each category.\
False (default): Return a detailed list of available updates.
:param installed: bool
:param bool installed:
Include installed updates in the results (default if False)
:param download: bool
:param bool download:
(Overrides reporting functionality) Download the list of updates
returned by this function. Run this function first to see what will be
installed, then set download=True to download the updates.
:param install: bool
:param bool install:
(Overrides reporting functionality) Install the list of updates
returned by this function. Run this function first to see what will be
installed, then set install=True to install the updates. This will
override download=True
:param categories: list
:param list categories:
Specify the categories to list. Must be passed as a list. All
categories returned by default.
@ -436,7 +440,7 @@ def list_updates(software=True,
* Windows 8.1 and later drivers
* Windows Defender
:param severities: list
:param list severities:
Specify the severities to include. Must be passed as a list. All
severities returned by default.
@ -446,36 +450,39 @@ def list_updates(software=True,
* Important
:return:
Returns a dict containing either a summary or a list of updates::
Returns a dict containing either a summary or a list of updates:
List of Updates:
{'<GUID>': {'Title': <title>,
'KB': <KB>,
'GUID': <the globally uinique identifier for the update>
'Description': <description>,
'Downloaded': <has the update been downloaded>,
'Installed': <has the update been installed>,
'Mandatory': <is the update mandatory>,
'UserInput': <is user input required>,
'EULAAccepted': <has the EULA been accepted>,
'Severity': <update severity>,
'NeedsReboot': <is the update installed and awaiting reboot>,
'RebootBehavior': <will the update require a reboot>,
'Categories': [ '<category 1>',
'<category 2>',
...]
}
}
.. code-block:: cfg
Summary of Updates:
{'Total': <total number of updates returned>,
'Available': <updates that are not downloaded or installed>,
'Downloaded': <updates that are downloaded but not installed>,
'Installed': <updates installed (usually 0 unless installed=True)>,
'Categories': { <category 1>: <total for that category>,
<category 2>: <total for category 2>,
... }
}
List of Updates:
{'<GUID>': {'Title': <title>,
'KB': <KB>,
'GUID': <the globally uinique identifier for the update>
'Description': <description>,
'Downloaded': <has the update been downloaded>,
'Installed': <has the update been installed>,
'Mandatory': <is the update mandatory>,
'UserInput': <is user input required>,
'EULAAccepted': <has the EULA been accepted>,
'Severity': <update severity>,
'NeedsReboot': <is the update installed and awaiting reboot>,
'RebootBehavior': <will the update require a reboot>,
'Categories': [ '<category 1>',
'<category 2>',
...]
}
}
Summary of Updates:
{'Total': <total number of updates returned>,
'Available': <updates that are not downloaded or installed>,
'Downloaded': <updates that are downloaded but not installed>,
'Installed': <updates installed (usually 0 unless installed=True)>,
'Categories': { <category 1>: <total for that category>,
<category 2>: <total for category 2>,
... }
}
:return type: dict
CLI Examples:
@ -934,26 +941,26 @@ def set_wu_settings(level=None,
Change Windows Update settings. If no parameters are passed, the current
value will be returned.
:param level: int
:param int level:
Number from 1 to 4 indicating the update level:
1. Never check for updates
2. Check for updates but let me choose whether to download and install them
3. Download updates but let me choose whether to install them
4. Install updates automatically
:param recommended: bool
:param bool recommended:
Boolean value that indicates whether to include optional or recommended
updates when a search for updates and installation of updates is
performed.
:param featured: bool
:param bool featured:
Boolean value that indicates whether to display notifications for
featured updates.
:param elevated: bool
:param bool elevated:
Boolean value that indicates whether non-administrators can perform some
update-related actions without administrator approval.
:param msupdate: bool
:param bool msupdate:
Boolean value that indicates whether to turn on Microsoft Update for
other Microsoft products
:param day: str
:param str day:
Days of the week on which Automatic Updates installs or uninstalls
updates.
Accepted values:
@ -964,7 +971,7 @@ def set_wu_settings(level=None,
- Thursday
- Friday
- Saturday
:param time: str
:param str time:
Time at which Automatic Updates installs or uninstalls updates. Must be
in the ##:## 24hr format, eg. 3:00 PM would be 15:00
@ -1118,39 +1125,39 @@ def get_wu_settings():
Get current Windows Update settings.
:return:
Featured Updates:
Boolean value that indicates whether to display notifications for
featured updates.
Group Policy Required (Read-only):
Boolean value that indicates whether Group Policy requires the Automatic
Updates service.
Microsoft Update:
Boolean value that indicates whether to turn on Microsoft Update for
other Microsoft Products
Needs Reboot:
Boolean value that indicates whether the machine is in a reboot pending
state.
Non Admins Elevated:
Boolean value that indicates whether non-administrators can perform some
update-related actions without administrator approval.
Notification Level:
Number 1 to 4 indicating the update level:
1. Never check for updates
2. Check for updates but let me choose whether to download and install them
3. Download updates but let me choose whether to install them
4. Install updates automatically
Read Only (Read-only):
Boolean value that indicates whether the Automatic Update
settings are read-only.
Recommended Updates:
Boolean value that indicates whether to include optional or recommended
updates when a search for updates and installation of updates is
performed.
Scheduled Day:
Days of the week on which Automatic Updates installs or uninstalls
updates.
Scheduled Time:
Time at which Automatic Updates installs or uninstalls updates.
Featured Updates:
Boolean value that indicates whether to display notifications for
featured updates.
Group Policy Required (Read-only):
Boolean value that indicates whether Group Policy requires the Automatic
Updates service.
Microsoft Update:
Boolean value that indicates whether to turn on Microsoft Update for
other Microsoft Products
Needs Reboot:
Boolean value that indicates whether the machine is in a reboot pending
state.
Non Admins Elevated:
Boolean value that indicates whether non-administrators can perform some
update-related actions without administrator approval.
Notification Level:
Number 1 to 4 indicating the update level:
1. Never check for updates
2. Check for updates but let me choose whether to download and install them
3. Download updates but let me choose whether to install them
4. Install updates automatically
Read Only (Read-only):
Boolean value that indicates whether the Automatic Update
settings are read-only.
Recommended Updates:
Boolean value that indicates whether to include optional or recommended
updates when a search for updates and installation of updates is
performed.
Scheduled Day:
Days of the week on which Automatic Updates installs or uninstalls
updates.
Scheduled Time:
Time at which Automatic Updates installs or uninstalls updates.
CLI Examples:

View File

@ -1921,21 +1921,21 @@ class WebsocketEndpoint(object):
.. http:get:: /ws/(token)
:query format_events: The event stream will undergo server-side
formatting if the ``format_events`` URL parameter is included
in the request. This can be useful to avoid formatting on the
client-side:
:query format_events: The event stream will undergo server-side
formatting if the ``format_events`` URL parameter is included
in the request. This can be useful to avoid formatting on the
client-side:
.. code-block:: bash
.. code-block:: bash
curl -NsS <...snip...> localhost:8000/ws?format_events
curl -NsS <...snip...> localhost:8000/ws?format_events
:reqheader X-Auth-Token: an authentication token from
:py:class:`~Login`.
:reqheader X-Auth-Token: an authentication token from
:py:class:`~Login`.
:status 101: switching to the websockets protocol
:status 401: |401|
:status 406: |406|
:status 101: switching to the websockets protocol
:status 401: |401|
:status 406: |406|
**Example request:**

View File

@ -108,10 +108,14 @@ class AsyncRemotePillar(object):
'cmd': '_pillar'}
if self.ext:
load['ext'] = self.ext
ret_pillar = yield self.channel.crypted_transfer_decode_dictentry(
load,
dictkey='pillar',
)
try:
ret_pillar = yield self.channel.crypted_transfer_decode_dictentry(
load,
dictkey='pillar',
)
except:
log.exception('Exception getting pillar:')
raise SaltClientError('Exception getting pillar.')
if not isinstance(ret_pillar, dict):
msg = ('Got a bad pillar from master, type {0}, expecting dict: '

View File

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2014 Floris Bruynooghe <flub@devork.be>
'''
r'''
Use remote Mercurial repository as a Pillar source.
.. versionadded:: 2015.8.0

View File

@ -20,66 +20,72 @@ Return data to a cassandra server
IP address. No assumption or default will be used for the cluster IPs.
The cluster IPs will be tried in the order listed. The port, username,
and password values shown below will be the assumed defaults if you do
not provide values.::
not provide values.:
cassandra:
cluster:
- 192.168.50.11
- 192.168.50.12
- 192.168.50.13
port: 9042
username: salt
password: salt
.. code-block:: yaml
Use the following cassandra database schema::
cassandra:
cluster:
- 192.168.50.11
- 192.168.50.12
- 192.168.50.13
port: 9042
username: salt
password: salt
CREATE KEYSPACE IF NOT EXISTS salt
WITH replication = {'class': 'SimpleStrategy', 'replication_factor' : 1};
Use the following cassandra database schema:
CREATE USER IF NOT EXISTS salt WITH PASSWORD 'salt' NOSUPERUSER;
.. code-block:: sql
GRANT ALL ON KEYSPACE salt TO salt;
CREATE KEYSPACE IF NOT EXISTS salt
WITH replication = {'class': 'SimpleStrategy', 'replication_factor' : 1};
USE salt;
CREATE USER IF NOT EXISTS salt WITH PASSWORD 'salt' NOSUPERUSER;
CREATE TABLE IF NOT EXISTS salt.salt_returns (
jid text,
minion_id text,
fun text,
alter_time timestamp,
full_ret text,
return text,
success boolean,
PRIMARY KEY (jid, minion_id, fun)
) WITH CLUSTERING ORDER BY (minion_id ASC, fun ASC);
CREATE INDEX IF NOT EXISTS salt_returns_minion_id ON salt.salt_returns (minion_id);
CREATE INDEX IF NOT EXISTS salt_returns_fun ON salt.salt_returns (fun);
GRANT ALL ON KEYSPACE salt TO salt;
CREATE TABLE IF NOT EXISTS salt.jids (
jid text PRIMARY KEY,
load text
);
USE salt;
CREATE TABLE IF NOT EXISTS salt.minions (
minion_id text PRIMARY KEY,
last_fun text
);
CREATE INDEX IF NOT EXISTS minions_last_fun ON salt.minions (last_fun);
CREATE TABLE IF NOT EXISTS salt.salt_returns (
jid text,
minion_id text,
fun text,
alter_time timestamp,
full_ret text,
return text,
success boolean,
PRIMARY KEY (jid, minion_id, fun)
) WITH CLUSTERING ORDER BY (minion_id ASC, fun ASC);
CREATE INDEX IF NOT EXISTS salt_returns_minion_id ON salt.salt_returns (minion_id);
CREATE INDEX IF NOT EXISTS salt_returns_fun ON salt.salt_returns (fun);
CREATE TABLE IF NOT EXISTS salt.salt_events (
id timeuuid,
tag text,
alter_time timestamp,
data text,
master_id text,
PRIMARY KEY (id, tag)
) WITH CLUSTERING ORDER BY (tag ASC);
CREATE INDEX tag ON salt.salt_events (tag);
CREATE TABLE IF NOT EXISTS salt.jids (
jid text PRIMARY KEY,
load text
);
CREATE TABLE IF NOT EXISTS salt.minions (
minion_id text PRIMARY KEY,
last_fun text
);
CREATE INDEX IF NOT EXISTS minions_last_fun ON salt.minions (last_fun);
CREATE TABLE IF NOT EXISTS salt.salt_events (
id timeuuid,
tag text,
alter_time timestamp,
data text,
master_id text,
PRIMARY KEY (id, tag)
) WITH CLUSTERING ORDER BY (tag ASC);
CREATE INDEX tag ON salt.salt_events (tag);
Required python modules: cassandra-driver
To use the cassandra returner, append '--return cassandra' to the salt command. ex:
To use the cassandra returner, append '--return cassandra' to the salt command. ex:
.. code-block:: bash
salt '*' test.ping --return cassandra
'''

View File

@ -23,7 +23,7 @@ def cmd(
Execute a single command via the salt-ssh subsystem and return all
routines at once
.. versionaddedd:: 2015.2
.. versionadded:: 2015.2
A wrapper around the :py:meth:`SSHClient.cmd
<salt.client.ssh.client.SSHClient.cmd>` method.

View File

@ -176,7 +176,7 @@ def event(tagmatch='*',
.. seealso::
See :glob:`tests/eventlisten.sh` for an example of usage within a shell
See :blob:`tests/eventlisten.sh` for an example of usage within a shell
script.
'''
statemod = salt.loader.raw_mod(__opts__, 'state', None)

View File

@ -1,39 +1,40 @@
# -*- coding: utf-8 -*-
'''
Connection module for Amazon Cloud Formation
Connection module for Amazon Cloud Formation
.. versionadded:: 2015.8.0
.. versionadded:: 2015.8.0
:configuration: This module accepts explicit AWS credentials but can also utilize
IAM roles assigned to the instance trough Instance Profiles. Dynamic
:depends: boto
:configuration: This module accepts explicit AWS credentials but can also utilize
IAM roles assigned to the instance through Instance Profiles. Dynamic
credentials are then automatically obtained from AWS API and no further
configuration is necessary. More Information available at::
http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html
configuration is necessary. More Information available at
http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html
If IAM roles are not used you need to specify them either in a pillar or
in the minion's config file::
in the minion's config file:
.. code-block:: yaml
keyid: GKTADJGHEIQSXMKKRBJ08H
key: askdjghsdfjkghWupUjasdflkdfklgjsdfjajkghs
.. code-block:: yaml
stack-present:
boto_cfn.present:
- name: mystack
- template_body: salt://base/mytemplate.json
- disable_rollback: true
- region: eu-west-1
- keyid: 'AKIAJHTMIQ2ASDFLASDF'
- key: 'fdkjsafkljsASSADFalkfjasdf'
stack-present:
boto_cfn.present:
- name: mystack
- template_body: salt://base/mytemplate.json
- disable_rollback: true
- region: eu-west-1
- keyid: 'AKIAJHTMIQ2ASDFLASDF'
- key: 'fdkjsafkljsASSADFalkfjasdf'
.. code-block:: yaml
stack-absent:
boto_cfn.absent:
- name: mystack
:depends: boto
stack-absent:
boto_cfn.absent:
- name: mystack
'''
from __future__ import absolute_import
@ -116,6 +117,8 @@ def present(name, template_body=None, template_url=None, parameters=None, notifi
profile (dict) - A dict with region, key and keyid, or a pillar key (string) that contains a dict with region, key
and keyid.
.. _ sns_console: https://console.aws.amazon.com/sns
'''
ret = {'name': name, 'result': True, 'comment': '', 'changes': {}}

View File

@ -38,43 +38,41 @@ pillars or minion config:
.. code-block:: yaml
Ensure DynamoDB table does not exist:
boto_dynamodb.absent:
- table_name: new_table
- keyid: GKTADJGHEIQSXMKKRBJ08H
- key: askdjghsdfjkghWupUjasdflkdfklgjsdfjajkghs
- region: us-east-1
Ensure DynamoDB table exists:
boto_dynamodb.present:
- table_name: new_table
- read_capacity_units: 1
- write_capacity_units: 2
- hash_key: primary_id
- hash_key_data_type: N
- range_key: start_timestamp
- range_key_data_type: N
- keyid: GKTADJGHEIQSXMKKRBJ08H
- key: askdjghsdfjkghWupUjasdflkdfklgjsdfjajkghs
- region: us-east-1
- local_indexes:
- index:
- name: "primary_id_end_timestamp_index"
- hash_key: primary_id
- hash_key_data_type: N
- range_key: end_timestamp
- range_key_data_type: N
- global_indexes:
- index:
- name: "name_end_timestamp_index"
- hash_key: name
- hash_key_data_type: S
- range_key: end_timestamp
- range_key_data_type: N
- read_capacity_units: 3
- write_capacity_units: 4
Ensure DynamoDB table does not exist:
boto_dynamodb.absent:
- table_name: new_table
- keyid: GKTADJGHEIQSXMKKRBJ08H
- key: askdjghsdfjkghWupUjasdflkdfklgjsdfjajkghs
- region: us-east-1
Ensure DynamoDB table exists:
boto_dynamodb.present:
- table_name: new_table
- read_capacity_units: 1
- write_capacity_units: 2
- hash_key: primary_id
- hash_key_data_type: N
- range_key: start_timestamp
- range_key_data_type: N
- keyid: GKTADJGHEIQSXMKKRBJ08H
- key: askdjghsdfjkghWupUjasdflkdfklgjsdfjajkghs
- region: us-east-1
- local_indexes:
- index:
- name: "primary_id_end_timestamp_index"
- hash_key: primary_id
- hash_key_data_type: N
- range_key: end_timestamp
- range_key_data_type: N
- global_indexes:
- index:
- name: "name_end_timestamp_index"
- hash_key: name
- hash_key_data_type: S
- range_key: end_timestamp
- range_key_data_type: N
- read_capacity_units: 3
- write_capacity_units: 4
'''
# Import Python libs
from __future__ import absolute_import

View File

@ -374,12 +374,12 @@ def register_instances(name, instances, region=None, key=None, keyid=None,
.. code-block:: yaml
add-instances:
boto_elb.register_instances:
- name: myloadbalancer
- instances:
- instance-id1
- instance-id2
add-instances:
boto_elb.register_instances:
- name: myloadbalancer
- instances:
- instance-id1
- instance-id2
'''
ret = {'name': name, 'result': None, 'comment': '', 'changes': {}}
ret['name'] = name

View File

@ -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})

View File

@ -1464,6 +1464,8 @@ def managed(name,
ret['comment'] = 'The file {0} is set to be changed'.format(name)
if show_diff and 'diff' in ret['pchanges']:
ret['changes']['diff'] = ret['pchanges']['diff']
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)

View File

@ -7,7 +7,7 @@ Schedules and users can be referenced by pagerduty ID, or by name, or by email a
For example:
.. code-block:: yaml
.. code-block:: yaml
ensure test escalation policy:
pagerduty_escalation_policy.present:

View File

@ -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

View File

@ -1,5 +1,7 @@
# -*- coding: utf-8 -*-
'''
Interface to Red Hat tuned-adm module
:maintainer: Syed Ali <alicsyed@gmail.com>
:maturity: new
:depends: cmd.run

View File

@ -984,6 +984,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)

View File

@ -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)

View File

@ -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.')

View File

@ -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):

View File

@ -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)