From ea27cefb101e68cf9ded0d9418c47da7bc2395e5 Mon Sep 17 00:00:00 2001 From: Jayesh Kariya Date: Fri, 5 Jun 2015 17:32:19 +0530 Subject: [PATCH 01/40] adding states/pyrax_queues unit test case. --- tests/unit/states/pyrax_queues_test.py | 94 ++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 tests/unit/states/pyrax_queues_test.py diff --git a/tests/unit/states/pyrax_queues_test.py b/tests/unit/states/pyrax_queues_test.py new file mode 100644 index 0000000000..145833863d --- /dev/null +++ b/tests/unit/states/pyrax_queues_test.py @@ -0,0 +1,94 @@ +# -*- coding: utf-8 -*- +''' + :codeauthor: :email:`Jayesh Kariya ` +''' +# Import Python libs +from __future__ import absolute_import + +# Import Salt Testing Libs +from salttesting import skipIf, TestCase +from salttesting.mock import ( + NO_MOCK, + NO_MOCK_REASON, + MagicMock, + patch +) + +from salttesting.helpers import ensure_in_syspath + +ensure_in_syspath('../../') + +# Import Salt Libs +from salt.states import pyrax_queues + +pyrax_queues.__opts__ = {} +pyrax_queues.__salt__ = {} + + +@skipIf(NO_MOCK, NO_MOCK_REASON) +class PyraxQueuesTestCase(TestCase): + ''' + Test cases for salt.states.pyrax_queues + ''' + # 'present' function tests: 1 + + def test_present(self): + ''' + Test to ensure the RackSpace queue exists. + ''' + name = 'myqueue' + provider = 'my-pyrax' + + ret = {'name': name, + 'changes': {}, + 'result': True, + 'comment': ''} + + mock_dct = MagicMock(side_effect=[{provider: {'salt': True}}, + {provider: {'salt': False}}, + {provider: {'salt': False}}, False]) + with patch.dict(pyrax_queues.__salt__, {'cloud.action': mock_dct}): + comt = ('{0} present.'.format(name)) + ret.update({'comment': comt}) + self.assertDictEqual(pyrax_queues.present(name, provider), ret) + + with patch.dict(pyrax_queues.__opts__, {'test': True}): + comt = ('Rackspace queue myqueue is set to be created.') + ret.update({'comment': comt, 'result': None}) + self.assertDictEqual(pyrax_queues.present(name, provider), ret) + + with patch.dict(pyrax_queues.__opts__, {'test': False}): + comt = ('Failed to create myqueue Rackspace queue.') + ret.update({'comment': comt, 'result': False}) + self.assertDictEqual(pyrax_queues.present(name, provider), ret) + + # 'absent' function tests: 1 + + def test_absent(self): + ''' + Test to ensure the named Rackspace queue is deleted. + ''' + name = 'myqueue' + provider = 'my-pyrax' + + ret = {'name': name, + 'changes': {}, + 'result': True, + 'comment': ''} + + mock_dct = MagicMock(side_effect=[{provider: {'salt': False}}, + {provider: {'salt': True}}]) + with patch.dict(pyrax_queues.__salt__, {'cloud.action': mock_dct}): + comt = ('myqueue does not exist.') + ret.update({'comment': comt}) + self.assertDictEqual(pyrax_queues.absent(name, provider), ret) + + with patch.dict(pyrax_queues.__opts__, {'test': True}): + comt = ('Rackspace queue myqueue is set to be removed.') + ret.update({'comment': comt, 'result': None}) + self.assertDictEqual(pyrax_queues.absent(name, provider), ret) + + +if __name__ == '__main__': + from integration import run_tests + run_tests(PyraxQueuesTestCase, needs_daemon=False) From 21b51abf25897a596ab836e8fd4dd52d911b1a1d Mon Sep 17 00:00:00 2001 From: Arthur Lutz Date: Fri, 5 Jun 2015 12:32:21 +0200 Subject: [PATCH 02/40] [doc] Alignement fix on external_auth documentation --- doc/topics/eauth/index.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/topics/eauth/index.rst b/doc/topics/eauth/index.rst index e1e9ec4844..cff16439f5 100644 --- a/doc/topics/eauth/index.rst +++ b/doc/topics/eauth/index.rst @@ -195,15 +195,15 @@ membership. Then the following LDAP quey is executed: external_auth: ldap: test_ldap_user: - - '*': - - test.ping + - '*': + - test.ping To configure an LDAP group, append a ``%`` to the ID: .. code-block:: yaml external_auth: - ldap: - test_ldap_group%: - - '*': - - test.echo \ No newline at end of file + ldap: + test_ldap_group%: + - '*': + - test.echo From 70028553c16f014b870615895fd033eddbc83d04 Mon Sep 17 00:00:00 2001 From: rallytime Date: Fri, 5 Jun 2015 11:21:26 -0600 Subject: [PATCH 03/40] yaml indentations should be 2 spaces --- doc/topics/eauth/index.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/topics/eauth/index.rst b/doc/topics/eauth/index.rst index cff16439f5..c1dcd052ef 100644 --- a/doc/topics/eauth/index.rst +++ b/doc/topics/eauth/index.rst @@ -195,15 +195,15 @@ membership. Then the following LDAP quey is executed: external_auth: ldap: test_ldap_user: - - '*': - - test.ping + - '*': + - test.ping To configure an LDAP group, append a ``%`` to the ID: .. code-block:: yaml external_auth: - ldap: - test_ldap_group%: - - '*': - - test.echo + ldap: + test_ldap_group%: + - '*': + - test.echo From 1944a743d7fd27f76bdd77b624af3d06b201d398 Mon Sep 17 00:00:00 2001 From: dkiser Date: Fri, 5 Jun 2015 14:13:25 -0700 Subject: [PATCH 04/40] fix for #24434 --- salt/minion.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/salt/minion.py b/salt/minion.py index af646c993c..488159ea09 100644 --- a/salt/minion.py +++ b/salt/minion.py @@ -795,7 +795,8 @@ class Minion(MinionBase): ' {0}'.format(opts['master'])) if opts['master_shuffle']: shuffle(opts['master']) - elif isinstance(opts['master'], str): + # if opts['master'] is a str and we have never created opts['master_list'] + elif isinstance(opts['master'], str) and ('master_list' not in opts): # We have a string, but a list was what was intended. Convert. # See issue 23611 for details opts['master'] = list(opts['master']) From 6e8cd44500afedde41bd614132d359d65f153914 Mon Sep 17 00:00:00 2001 From: Justin Findlay Date: Fri, 5 Jun 2015 16:21:12 -0600 Subject: [PATCH 05/40] fix typo in modules/mount.py Fixes #24296. --- salt/modules/mount.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/salt/modules/mount.py b/salt/modules/mount.py index 18aa2c0f5a..d71bb3b6c5 100644 --- a/salt/modules/mount.py +++ b/salt/modules/mount.py @@ -687,7 +687,7 @@ def mount(name, device, mkmnt=False, fstype='', opts='defaults', user=None): opts = opts.split(',') if not os.path.exists(name) and mkmnt: - __salt__['file.mkdir'](name=name, user=user) + __salt__['file.mkdir'](name, user=user) args = '' if opts is not None: From 19c912866d72f3d7df6cc9e9c88fc6db10982d9f Mon Sep 17 00:00:00 2001 From: Justin Findlay Date: Fri, 5 Jun 2015 16:52:02 -0600 Subject: [PATCH 06/40] catch exception from softwarerepositories Fixes #24318. --- salt/modules/aptpkg.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/salt/modules/aptpkg.py b/salt/modules/aptpkg.py index 33f85fed9b..b2bd8d44dc 100644 --- a/salt/modules/aptpkg.py +++ b/salt/modules/aptpkg.py @@ -1249,13 +1249,18 @@ def get_repo(repo, **kwargs): ppa_name, dist) else: if HAS_SOFTWAREPROPERTIES: - if hasattr(softwareproperties.ppa, 'PPAShortcutHandler'): - repo = softwareproperties.ppa.PPAShortcutHandler(repo).expand( - __grains__['lsb_distrib_codename'])[0] - else: - repo = softwareproperties.ppa.expand_ppa_line( - repo, - __grains__['lsb_distrib_codename'])[0] + try: + if hasattr(softwareproperties.ppa, 'PPAShortcutHandler'): + repo = softwareproperties.ppa.PPAShortcutHandler( + repo).expand(dist)[0] + else: + repo = softwareproperties.ppa.expand_ppa_line( + repo, + dist)[0] + except NameError as name_error: + raise CommandExecutionError( + 'Could not find ppa {0}: {1}'.format(repo, name_error) + ) else: repo = LP_SRC_FORMAT.format(owner_name, ppa_name, dist) From 2e0609f09e1b5f43efb452bb95d4c8f5cb0559dc Mon Sep 17 00:00:00 2001 From: Colton Myers Date: Fri, 5 Jun 2015 17:17:43 -0600 Subject: [PATCH 07/40] Fix for # in inner strings in yaml arguments Fixes #18045 The fix for #8585 should still be intact --- salt/utils/args.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/salt/utils/args.py b/salt/utils/args.py index 75d02c1edb..36f93024c9 100644 --- a/salt/utils/args.py +++ b/salt/utils/args.py @@ -106,9 +106,12 @@ def yamlify_arg(arg): import salt.utils.yamlloader as yamlloader original_arg = arg if '#' in arg: - # Don't yamlify this argument or the '#' and everything after - # it will be interpreted as a comment. - return arg + # Only yamlify if it parses into a non-string type, to prevent + # loss of content due to # as comment character + parsed_arg = yamlloader.load(arg, Loader=yamlloader.SaltYamlSafeLoader) + if isinstance(parsed_arg, string_types): + return arg + return parsed_arg if arg == 'None': arg = None else: From d45c4ed11f4fec91e399b9149715cec1bbfe12e4 Mon Sep 17 00:00:00 2001 From: Jacob Hammons Date: Fri, 5 Jun 2015 17:32:35 -0600 Subject: [PATCH 08/40] Bug fixes and build errors Refs #23211 Refs #24268 Refs #24235 Refs #24193 Refs #24172 Refs #19901 Refs #19801 --- doc/ref/cli/salt-call.rst | 8 +++++ doc/ref/cli/salt-cloud.rst | 5 --- doc/ref/configuration/master.rst | 12 ++++++++ doc/ref/configuration/minion.rst | 16 ++++++++++ doc/ref/file_server/index.rst | 15 +++++++++ doc/ref/modules/all/salt.modules.ipmi.rst | 2 +- doc/ref/states/all/index.rst | 2 ++ doc/ref/states/all/salt.states.ipmi.rst | 6 ++++ doc/ref/states/all/salt.states.tls.rst | 6 ++++ doc/topics/development/external_pillars.rst | 6 ++-- doc/topics/installation/windows.rst | 5 +-- doc/topics/troubleshooting/minion.rst | 2 ++ doc/topics/tutorials/pillar.rst | 12 ++------ doc/topics/tutorials/standalone_minion.rst | 10 +++++- doc/topics/tutorials/states_pt1.rst | 4 +-- salt/auth/mysql.py | 34 ++++++++++----------- salt/beacons/inotify.py | 34 +++++++++++---------- salt/modules/cassandra_cql.py | 2 ++ salt/modules/cmdmod.py | 34 ++++++++++----------- salt/modules/dockerio.py | 2 +- salt/modules/gpg.py | 3 -- salt/modules/nacl.py | 32 +++++++++++++------ salt/modules/puppet.py | 5 +-- salt/modules/random_org.py | 5 ++- salt/modules/state.py | 8 ++++- salt/modules/system_profiler.py | 8 ++--- salt/netapi/rest_cherrypy/app.py | 14 +++++---- salt/returners/django_return.py | 2 +- salt/roster/ansible.py | 1 + salt/runners/fileserver.py | 2 +- salt/runners/http.py | 6 ++-- salt/states/boto_elb.py | 8 ++--- salt/states/grafana.py | 2 +- salt/states/hipchat.py | 1 + salt/states/ipmi.py | 2 ++ salt/states/linux_acl.py | 6 ++-- salt/states/slack.py | 2 +- salt/states/win_servermanager.py | 17 ++++++----- salt/wheel/config.py | 25 ++++++++------- 39 files changed, 233 insertions(+), 133 deletions(-) create mode 100644 doc/ref/states/all/salt.states.ipmi.rst create mode 100644 doc/ref/states/all/salt.states.tls.rst diff --git a/doc/ref/cli/salt-call.rst b/doc/ref/cli/salt-call.rst index 82d4b8a988..c6d89af79e 100644 --- a/doc/ref/cli/salt-call.rst +++ b/doc/ref/cli/salt-call.rst @@ -15,6 +15,14 @@ Description The salt-call command is used to run module functions locally on a minion instead of executing them from the master. +salt-call is used to run a :ref:`Standalone Minion `, +and was originally created for :ref:`troubleshooting `. +Be aware that ``salt-call`` commands execute from the current user's shell +context, while ``salt`` commands execute from the system's default context. + +By default, the Salt Master is contacted to retrieve state files and other resources +during execution unless the ``--local`` option is specified.:w + Options ======= diff --git a/doc/ref/cli/salt-cloud.rst b/doc/ref/cli/salt-cloud.rst index 2c452e6759..863670e36b 100644 --- a/doc/ref/cli/salt-cloud.rst +++ b/doc/ref/cli/salt-cloud.rst @@ -87,11 +87,6 @@ Execution Options for this influx of vm creation. When creating large groups of VMs watch the cloud provider carefully. -.. option:: -Q, --query - - Execute a query and print out information about all cloud VMs. Can be used - in conjunction with -m to display only information about the specified map. - .. option:: -u, --update-bootstrap Update salt-bootstrap to the latest develop version on GitHub. diff --git a/doc/ref/configuration/master.rst b/doc/ref/configuration/master.rst index 4f1a56608e..2a755492a5 100644 --- a/doc/ref/configuration/master.rst +++ b/doc/ref/configuration/master.rst @@ -2432,3 +2432,15 @@ List of git repositories to include with the local repo. win_gitrepos: - 'https://github.com/saltstack/salt-winrepo.git' + +To specify a specific revision of the repository, preface the +repository location with a commit ID: + +.. code-block:: yaml + + win_gitrepos: + - ' https://github.com/saltstack/salt-winrepo.git' + +Replacing ```` with the ID from GitHub. Specifying a commit +ID is useful if you need to revert to a previous version if an error +is introduced in the latest version. diff --git a/doc/ref/configuration/minion.rst b/doc/ref/configuration/minion.rst index f4d64b49e0..3acca6b6b5 100644 --- a/doc/ref/configuration/minion.rst +++ b/doc/ref/configuration/minion.rst @@ -289,6 +289,22 @@ executed. By default this feature is disabled, to enable set cache_jobs to cache_jobs: False +.. conf_minion:: grains_cache + +``grains_cache`` +---------------- + +Default: ``False`` + +The minion can locally cache grain data instead of refreshing the data +each time the grain is referenced. By default this feature is disabled, +to enable set grains_cache to ``True``. + +.. code-block:: yaml + + cache_jobs: False + + .. conf_minion:: sock_dir ``sock_dir`` diff --git a/doc/ref/file_server/index.rst b/doc/ref/file_server/index.rst index 0b03f44e44..47ad2c10b5 100644 --- a/doc/ref/file_server/index.rst +++ b/doc/ref/file_server/index.rst @@ -24,6 +24,21 @@ The cp module is the home of minion side file server operations. The cp module is used by the Salt state system, salt-cp, and can be used to distribute files presented by the Salt file server. +Escaping Special Characters +``````````````````````````` + +The ``salt://`` url format can potentially contain a query string, for example +``salt://dir/file.txt?saltenv=base``. You can prevent the fileclient/fileserver from +interpreting ``?`` as the initial token of a query string by referencing the file +with ``salt://|`` rather than ``salt://``. + +.. code-block:: yaml + + /etc/marathon/conf/?checkpoint: + file.managed: + - source: salt://|hw/config/?checkpoint + - makedirs: True + Environments ```````````` diff --git a/doc/ref/modules/all/salt.modules.ipmi.rst b/doc/ref/modules/all/salt.modules.ipmi.rst index 423ec21c47..8b52e18822 100644 --- a/doc/ref/modules/all/salt.modules.ipmi.rst +++ b/doc/ref/modules/all/salt.modules.ipmi.rst @@ -3,4 +3,4 @@ salt.modules.ipmi ================= .. automodule:: salt.modules.ipmi - :members \ No newline at end of file + :members: \ No newline at end of file diff --git a/doc/ref/states/all/index.rst b/doc/ref/states/all/index.rst index 25b06de476..6f896f18ce 100644 --- a/doc/ref/states/all/index.rst +++ b/doc/ref/states/all/index.rst @@ -63,6 +63,7 @@ Full list of builtin state modules influxdb_database influxdb_user ini_manage + ipmi ipset iptables jboss7 @@ -142,6 +143,7 @@ Full list of builtin state modules sysrc test timezone + tls tomcat user vbox_guest diff --git a/doc/ref/states/all/salt.states.ipmi.rst b/doc/ref/states/all/salt.states.ipmi.rst new file mode 100644 index 0000000000..8d0f1cf2cc --- /dev/null +++ b/doc/ref/states/all/salt.states.ipmi.rst @@ -0,0 +1,6 @@ +================ +salt.states.ipmi +================ + +.. automodule:: salt.states.ipmi + :members: \ No newline at end of file diff --git a/doc/ref/states/all/salt.states.tls.rst b/doc/ref/states/all/salt.states.tls.rst new file mode 100644 index 0000000000..5ed041fec2 --- /dev/null +++ b/doc/ref/states/all/salt.states.tls.rst @@ -0,0 +1,6 @@ +=============== +salt.states.tls +=============== + +.. automodule:: salt.states.tls + :members: \ No newline at end of file diff --git a/doc/topics/development/external_pillars.rst b/doc/topics/development/external_pillars.rst index c06362edd8..d0e9eb3952 100644 --- a/doc/topics/development/external_pillars.rst +++ b/doc/topics/development/external_pillars.rst @@ -1,6 +1,8 @@ -=================== +.. _external-pillars: + +================ External Pillars -=================== +================ Salt provides a mechanism for generating pillar data by calling external pillar interfaces. This document will describe an outline of an ext_pillar diff --git a/doc/topics/installation/windows.rst b/doc/topics/installation/windows.rst index b5a30fa488..6ab4f306d8 100644 --- a/doc/topics/installation/windows.rst +++ b/doc/topics/installation/windows.rst @@ -43,8 +43,9 @@ minion exe>` should match the contents of the corresponding md5 file. * 2014.7.0 * Salt-Minion-2014.7.0-1-win32-Setup.exe | md5 * Salt-Minion-2014.7.0-AMD64-Setup.exe | md5 - .. note:: - The 2014.7.0 installers have been removed because of a regression. Please use the 2014.7.1 release instead. + .. note:: + + The 2014.7.0 installers have been removed because of a regression. Please use the 2014.7.1 release instead. * 2014.1.13 * `Salt-Minion-2014.1.13-x86-Setup.exe `__ | `md5 `__ diff --git a/doc/topics/troubleshooting/minion.rst b/doc/topics/troubleshooting/minion.rst index bd7d328372..d15f559bad 100644 --- a/doc/topics/troubleshooting/minion.rst +++ b/doc/topics/troubleshooting/minion.rst @@ -66,6 +66,8 @@ check that no additional access control system such as `SELinux`_ or .. _`SELinux`: https://en.wikipedia.org/wiki/Security-Enhanced_Linux .. _`AppArmor`: http://wiki.apparmor.net/index.php/Main_Page +.. _troubleshooting-minion-salt-call: + Using salt-call =============== diff --git a/doc/topics/tutorials/pillar.rst b/doc/topics/tutorials/pillar.rst index 51fb1acc65..bce8487d30 100644 --- a/doc/topics/tutorials/pillar.rst +++ b/doc/topics/tutorials/pillar.rst @@ -34,9 +34,9 @@ Variables: minions can be defined in pillar and then accessed inside sls formulas and template files. Arbitrary Data: - Pillar can contain any basic data structure, so a list of values, or a - key/value store can be defined making it easy to iterate over a group - of values in sls formulas + Pillar can contain any basic data structure in dictionary format, + so a key/value store can be defined making it easy to iterate over a group + of values in sls formulas. Pillar is therefore one of the most important systems when using Salt. This walkthrough is designed to get a simple Pillar up and running in a few minutes @@ -309,12 +309,6 @@ line: salt '*' state.sls my_sls_file pillar='{"hello": "world"}' -Lists can be passed in pillar as well: - -.. code-block:: bash - - salt '*' state.highstate pillar='["foo", "bar", "baz"]' - .. note:: If a key is passed on the command line that already exists on the minion, diff --git a/doc/topics/tutorials/standalone_minion.rst b/doc/topics/tutorials/standalone_minion.rst index 0ccffa1c85..5badda2f22 100644 --- a/doc/topics/tutorials/standalone_minion.rst +++ b/doc/topics/tutorials/standalone_minion.rst @@ -1,3 +1,5 @@ +.. _tutorial-standalone-minion: + ================= Standalone Minion ================= @@ -77,4 +79,10 @@ it unnecessary to change the configuration file: .. code-block:: bash - salt-call state.highstate --local \ No newline at end of file + salt-call state.highstate --local + +External Pillars +================ + +:ref:`External pillars ` are supported when running in masterless mode. + diff --git a/doc/topics/tutorials/states_pt1.rst b/doc/topics/tutorials/states_pt1.rst index ea11e0dcb3..bd520cc07a 100644 --- a/doc/topics/tutorials/states_pt1.rst +++ b/doc/topics/tutorials/states_pt1.rst @@ -178,8 +178,8 @@ and all changes made. salt-minion -l debug Run the minion in the foreground - By not starting the minion in daemon mode (:option:`-d `) one can view any output from the minion as it works: + By not starting the minion in daemon mode (:option:`-d `) + one can view any output from the minion as it works: .. code-block:: bash diff --git a/salt/auth/mysql.py b/salt/auth/mysql.py index 695d8f83cc..be367a374f 100644 --- a/salt/auth/mysql.py +++ b/salt/auth/mysql.py @@ -9,29 +9,29 @@ use an existing table that has a username and a password column. To get started, create a simple table that holds just a username and a password. The password field will hold a SHA256 checksum. - .. code-block:: sql +.. code-block:: sql - CREATE TABLE `users` ( - `id` int(11) NOT NULL AUTO_INCREMENT, - `username` varchar(25) DEFAULT NULL, - `password` varchar(70) DEFAULT NULL, - PRIMARY KEY (`id`) - ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1; + CREATE TABLE `users` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `username` varchar(25) DEFAULT NULL, + `password` varchar(70) DEFAULT NULL, + PRIMARY KEY (`id`) + ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1; To create a user within MySQL, execute the following statement. - .. code-block:: sql +.. code-block:: sql - INSERT INTO users VALUES (NULL, 'diana', SHA2('secret', 256)) + INSERT INTO users VALUES (NULL, 'diana', SHA2('secret', 256)) - .. code-block:: yaml +.. code-block:: yaml - mysql_auth: - hostname: localhost - database: SaltStack - username: root - password: letmein - auth_sql: 'SELECT username FROM users WHERE username = "{0}" AND password = SHA2("{1}", 256)' + mysql_auth: + hostname: localhost + database: SaltStack + username: root + password: letmein + auth_sql: 'SELECT username FROM users WHERE username = "{0}" AND password = SHA2("{1}", 256)' The `auth_sql` contains the SQL that will validate a user to ensure they are correctly authenticated. This is where you can specify other SQL queries to @@ -39,7 +39,7 @@ authenticate users. Enable MySQL authentication. - .. code-block:: yaml +.. code-block:: yaml external_auth: mysql: diff --git a/salt/beacons/inotify.py b/salt/beacons/inotify.py index 9eccd1b2bb..5d3290d1da 100644 --- a/salt/beacons/inotify.py +++ b/salt/beacons/inotify.py @@ -84,24 +84,26 @@ def beacon(config): The mask list can contain the following events (the default mask is create, delete, and modify): - * access File accessed - * attrib File metadata changed - * close_nowrite Unwritable file closed - * close_write Writable file closed - * create File created in watched directory - * delete File deleted from watched directory - * delete_self Watched file or directory deleted - * modify File modified - * moved_from File moved out of watched directory - * moved_to File moved into watched directory - * move_self Watched file moved - * open File opened + + * access File accessed + * attrib File metadata changed + * close_nowrite Unwritable file closed + * close_write Writable file closed + * create File created in watched directory + * delete File deleted from watched directory + * delete_self Watched file or directory deleted + * modify File modified + * moved_from File moved out of watched directory + * moved_to File moved into watched directory + * move_self Watched file moved + * open File opened The mask can also contain the following options: - * dont_follow Don't dereference symbolic links - * excl_unlink Omit events for children after they have been unlinked - * oneshot Remove watch after one event - * onlydir Operate only if name is directory + + * dont_follow Don't dereference symbolic links + * excl_unlink Omit events for children after they have been unlinked + * oneshot Remove watch after one event + * onlydir Operate only if name is directory recurse: Recursively watch files in the directory diff --git a/salt/modules/cassandra_cql.py b/salt/modules/cassandra_cql.py index a738bc2728..ce13a7b00e 100644 --- a/salt/modules/cassandra_cql.py +++ b/salt/modules/cassandra_cql.py @@ -647,6 +647,7 @@ def list_permissions(username=None, resource=None, resource_type='keyspace', per :rtype: dict .. code-block:: bash + salt 'minion1' cassandra_cql.list_permissions salt 'minion1' cassandra_cql.list_permissions username=joe resource=test_keyspace permission=select @@ -702,6 +703,7 @@ def grant_permission(username, resource=None, resource_type='keyspace', permissi :rtype: .. code-block:: bash + salt 'minion1' cassandra_cql.grant_permission salt 'minion1' cassandra_cql.grant_permission username=joe resource=test_keyspace permission=select diff --git a/salt/modules/cmdmod.py b/salt/modules/cmdmod.py index 430561dcd8..dcddb329e0 100644 --- a/salt/modules/cmdmod.py +++ b/salt/modules/cmdmod.py @@ -579,18 +579,18 @@ def run(cmd, Note that ``env`` represents the environment variables for the command, and should be formatted as a dict, or a YAML string which resolves to a dict. - ************************************************************************* - WARNING: This function does not process commands through a shell - unless the python_shell flag is set to True. This means that any - shell-specific functionality such as 'echo' or the use of pipes, - redirection or &&, should either be migrated to cmd.shell or - have the python_shell=True flag set here. + .. warning:: - The use of python_shell=True means that the shell will accept _any_ input - including potentially malicious commands such as 'good_command;rm -rf /'. - Be absolutely certain that you have sanitized your input prior to using - python_shell=True - ************************************************************************* + This function does not process commands through a shell + unless the python_shell flag is set to True. This means that any + shell-specific functionality such as 'echo' or the use of pipes, + redirection or &&, should either be migrated to cmd.shell or + have the python_shell=True flag set here. + + The use of python_shell=True means that the shell will accept _any_ input + including potentially malicious commands such as 'good_command;rm -rf /'. + Be absolutely certain that you have sanitized your input prior to using + python_shell=True CLI Example: @@ -707,12 +707,12 @@ def shell(cmd, .. versionadded:: 2015.5.0 - ************************************************************ - WARNING: This passes the cmd argument directly to the shell - without any further processing! Be absolutely sure that you - have properly santized the command passed to this function - and do not use untrusted inputs. - ************************************************************ + .. warning :: + + This passes the cmd argument directly to the shell + without any further processing! Be absolutely sure that you + have properly santized the command passed to this function + and do not use untrusted inputs. Note that ``env`` represents the environment variables for the command, and should be formatted as a dict, or a YAML string which resolves to a dict. diff --git a/salt/modules/dockerio.py b/salt/modules/dockerio.py index d476361d64..c85b5c36f8 100644 --- a/salt/modules/dockerio.py +++ b/salt/modules/dockerio.py @@ -1807,7 +1807,7 @@ def _run_wrapper(status, container, func, cmd, *args, **kwargs): def load(imagepath): ''' Load the specified file at imagepath into docker that was generated from - a docker save command + a docker save command e.g. `docker load < imagepath` imagepath diff --git a/salt/modules/gpg.py b/salt/modules/gpg.py index 025157a741..4301ec9dba 100644 --- a/salt/modules/gpg.py +++ b/salt/modules/gpg.py @@ -590,9 +590,7 @@ def import_key(user=None, .. code-block:: bash 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, @@ -749,7 +747,6 @@ def trust_key(keyid=None, salt '*' gpg.trust_key fingerprint='53C96788253E58416D20BCD352952C84C3252192' trust_level='not_trusted' salt '*' gpg.trust_key keys=3FAD9F1E trust_level='ultimately' user='username' - ''' ret = { 'res': True, diff --git a/salt/modules/nacl.py b/salt/modules/nacl.py index 1ed435932b..d7f941ab30 100644 --- a/salt/modules/nacl.py +++ b/salt/modules/nacl.py @@ -1,11 +1,11 @@ # -*- coding: utf-8 -*- ''' -:requires: libnacl -https://github.com/saltstack/libnacl - This module helps include encrypted passwords in pillars, grains and salt state files. -This is often usefull if you wish to store your pillars in source control or -share your pillar data with others that you trust. I dont advise making your pillars public + +:depends: libnacl, https://github.com/saltstack/libnacl + +This is often useful if you wish to store your pillars in source control or +share your pillar data with others that you trust. I don't advise making your pillars public regardless if they are encrypted or not. When generating keys and encrypting passwords use --local when using salt-call for extra @@ -14,20 +14,28 @@ security. Also consider using just the salt runner nacl when encrypting pillar p The nacl lib uses 32byte keys, these keys are base64 encoded to make your life more simple. To generate your `key` or `keyfile` you can use: +.. code-block:: bash + salt-call --local nacl.keygen keyfile=/root/.nacl -Now with your key, you can encrypt some data +Now with your key, you can encrypt some data: + +.. code-block:: bash salt-call --local nacl.enc mypass keyfile=/root/.nacl DRB7Q6/X5gGSRCTpZyxS6hXO5LnlJIIJ4ivbmUlbWj0llUA+uaVyvou3vJ4= -To decrypt the data +To decrypt the data: + +.. code-block:: bash salt-call --local nacl.dec data='DRB7Q6/X5gGSRCTpZyxS6hXO5LnlJIIJ4ivbmUlbWj0llUA+uaVyvou3vJ4=' keyfile=/root/.nacl mypass The following optional configurations can be defined in the -minion or master config. Avoide storeing the config in pillars! +minion or master config. Avoid storing the config in pillars! + +.. code-block:: yaml cat /etc/salt/master.d/nacl.conf nacl.config: @@ -36,15 +44,21 @@ minion or master config. Avoide storeing the config in pillars! When the key is defined in the master config you can use it from the nacl runner: +.. code-block:: bash + salt-run nacl.enc 'myotherpass' Now you can create a pillar with protected data like: +.. code-block:: yaml + pillarexample: user: root password: {{ salt.nacl.dec('DRB7Q6/X5gGSRCTpZyxS6hXO5LnlJIIJ4ivbmUlbWj0llUA+uaVyvou3vJ4=') }} -Or do somthing interesting with grains like: +Or do something interesting with grains like: + +.. code-block:: yaml salt-call nacl.enc minionname:dbrole AL24Z2C5OlkReer3DuQTFdrNLchLuz3NGIhGjZkLtKRYry/b/CksWM8O9yskLwH2AGVLoEXI5jAa diff --git a/salt/modules/puppet.py b/salt/modules/puppet.py index 0111635c79..3f60c1356e 100644 --- a/salt/modules/puppet.py +++ b/salt/modules/puppet.py @@ -225,11 +225,13 @@ def enable(): def disable(message=None): ''' .. versionadded:: 2014.7.0 + Disable the puppet agent message .. versionadded:: 2015.5.2 - disable message to send to puppet + + Disable message to send to puppet CLI Example: @@ -237,7 +239,6 @@ def disable(message=None): salt '*' puppet.disable salt '*' puppet.disable 'disabled for a good reason' - ''' _check_puppet() diff --git a/salt/modules/random_org.py b/salt/modules/random_org.py index 35b8d1b055..92433176ed 100644 --- a/salt/modules/random_org.py +++ b/salt/modules/random_org.py @@ -681,10 +681,9 @@ def generateBlobs(api_key=None, .. code-block:: bash - salt '*' get_intergers number=5 min=1 max=6 - - salt '*' get_intergers number=5 min=1 max=6 + salt '*' get_integers number=5 min=1 max=6 + salt '*' get_integers number=5 min=1 max=6 ''' ret = {'res': True} diff --git a/salt/modules/state.py b/salt/modules/state.py index 840613adf0..1fdcaaf051 100644 --- a/salt/modules/state.py +++ b/salt/modules/state.py @@ -1,6 +1,12 @@ # -*- coding: utf-8 -*- ''' -Control the state system on the minion +Control the state system on the minion. + +State Caching +------------- + +When a highstate is called, the minion automatically caches a copy of the last high data. +If you then run a highstate with cache=True it will use that cached highdata and won't hit the fileserver. ''' from __future__ import absolute_import diff --git a/salt/modules/system_profiler.py b/salt/modules/system_profiler.py index e9ae016cc9..5789f80dec 100644 --- a/salt/modules/system_profiler.py +++ b/salt/modules/system_profiler.py @@ -52,8 +52,7 @@ def _call_system_profiler(datatype): def receipts(): ''' Return the results of a call to - `system_profiler -xml -detail full - SPInstallHistoryDataType` + ``system_profiler -xml -detail full SPInstallHistoryDataType`` as a dictionary. Top-level keys of the dictionary are the names of each set of install receipts, since there can be multiple receipts with the same name. @@ -93,12 +92,11 @@ def receipts(): def applications(): ''' Return the results of a call to - `system_profiler -xml -detail full - SPApplicationsDataType` + ``system_profiler -xml -detail full SPApplicationsDataType`` as a dictionary. Top-level keys of the dictionary are the names of each set of install receipts, since there can be multiple receipts with the same name. - Contents of each key are a list of dicttionaries. + Contents of each key are a list of dictionaries. Note that this can take a long time depending on how many applications are installed on the target Mac. diff --git a/salt/netapi/rest_cherrypy/app.py b/salt/netapi/rest_cherrypy/app.py index 5931dbd93b..a3ec7a4958 100644 --- a/salt/netapi/rest_cherrypy/app.py +++ b/salt/netapi/rest_cherrypy/app.py @@ -7,16 +7,18 @@ A REST API for Salt .. py:currentmodule:: salt.netapi.rest_cherrypy.app -:depends: - CherryPy Python module. Versions 3.2.{2,3,4} are strongly - recommended due to a known `SSL error - `_ - introduced in version 3.2.5. The issue was reportedly resolved with - CherryPy milestone 3.3, but the patch was committed for version 3.6.1. +:depends: + - CherryPy Python module. Versions 3.2.{2,3,4} are strongly + recommended due to a known `SSL error + `_ + introduced in version 3.2.5. The issue was reportedly resolved with + CherryPy milestone 3.3, but the patch was committed for version 3.6.1. :optdepends: - ws4py Python module for websockets support. :client_libraries: - Java: https://github.com/SUSE/saltstack-netapi-client-java - Python: https://github.com/saltstack/pepper -:configuration: All authentication is done through Salt's :ref:`external auth +:configuration: + All authentication is done through Salt's :ref:`external auth ` system which requires additional configuration not described here. diff --git a/salt/returners/django_return.py b/salt/returners/django_return.py index 06a765ecb0..2c1eaf390a 100644 --- a/salt/returners/django_return.py +++ b/salt/returners/django_return.py @@ -16,7 +16,7 @@ them. An example Django module that registers a function called 'returner_callback' with this module's 'returner' function: - .. code-block:: python +.. code-block:: python import salt.returners.django_return from django.dispatch import receiver diff --git a/salt/roster/ansible.py b/salt/roster/ansible.py index 5a98ac509b..b1afccec65 100644 --- a/salt/roster/ansible.py +++ b/salt/roster/ansible.py @@ -84,6 +84,7 @@ There is also the option of specifying a dynamic inventory, and generating it on This is the format that an inventory script needs to output to work with ansible, and thus here. .. code-block:: bash + [~]# salt-ssh --roster-file /etc/salt/hosts salt.gtmanfred.com test.ping salt.gtmanfred.com: True diff --git a/salt/runners/fileserver.py b/salt/runners/fileserver.py index e08703dabc..7dfe56b833 100644 --- a/salt/runners/fileserver.py +++ b/salt/runners/fileserver.py @@ -349,7 +349,7 @@ def lock(backend=None, remote=None): .. note:: This will only operate on enabled backends (those configured in - :master_conf:`fileserver_backend`). + :conf_master:`fileserver_backend`). backend Only set the update lock for the specified backend(s). diff --git a/salt/runners/http.py b/salt/runners/http.py index ab55db6d9d..b4134faf34 100644 --- a/salt/runners/http.py +++ b/salt/runners/http.py @@ -3,7 +3,7 @@ Module for making various web calls. Primarily designed for webhooks and the like, but also useful for basic http testing. -.. versionadded:: 2015.5.0 +.. versionadded:: 2015.5 ''' from __future__ import absolute_import # Import Python libs @@ -19,7 +19,7 @@ def query(url, output=True, **kwargs): ''' Query a resource, and decode the return data - .. versionaddedd:: 2015.2 + .. versionadded:: 2015.5 CLI Example: @@ -44,7 +44,7 @@ def update_ca_bundle(target=None, source=None, merge_files=None): ''' Update the local CA bundle file from a URL - .. versionaddedd:: 2015.2 + .. versionadded:: 2015.5 CLI Example: diff --git a/salt/states/boto_elb.py b/salt/states/boto_elb.py index c3fe0488e4..6326db9ff5 100644 --- a/salt/states/boto_elb.py +++ b/salt/states/boto_elb.py @@ -234,10 +234,10 @@ def present( listeners A list of listener lists; example: - [ - ['443', 'HTTPS', 'arn:aws:iam::1111111:server-certificate/mycert'], - ['8443', '80', 'HTTPS', 'HTTP', 'arn:aws:iam::1111111:server-certificate/mycert'] - ] + [ + ['443', 'HTTPS', 'arn:aws:iam::1111111:server-certificate/mycert'], + ['8443', '80', 'HTTPS', 'HTTP', 'arn:aws:iam::1111111:server-certificate/mycert'] + ] subnets A list of subnet IDs in your VPC to attach to your LoadBalancer. diff --git a/salt/states/grafana.py b/salt/states/grafana.py index f11eb005d6..a8818e9ab8 100644 --- a/salt/states/grafana.py +++ b/salt/states/grafana.py @@ -164,7 +164,7 @@ elasticsearch profile via pillars: The behavior of this module is to create dashboards if they do not exist, to add rows if they do not exist in existing dashboards, and to update rows if they exist in dashboards. The module will not manage rows that are not defined, - allowing users to manage their own custom rows. +allowing users to manage their own custom rows. ''' from __future__ import absolute_import from salt.exceptions import SaltInvocationError diff --git a/salt/states/hipchat.py b/salt/states/hipchat.py index d43635ff04..31f1530a6b 100644 --- a/salt/states/hipchat.py +++ b/salt/states/hipchat.py @@ -73,6 +73,7 @@ def send_message(name, The message that is to be sent to the Hipchat room. The following parameters are optional: + api_key The api key for Hipchat to use for authentication, if not specified in the configuration options of master or minion. diff --git a/salt/states/ipmi.py b/salt/states/ipmi.py index cd182548ac..72d87b8824 100644 --- a/salt/states/ipmi.py +++ b/salt/states/ipmi.py @@ -163,8 +163,10 @@ def user_present(name, uid, password, channel=14, callback=False, callback User Restricted to Callback + False = User Privilege Limit is determined by the User Privilege Limit parameter privilege_level, for both callback and non-callback connections. + True = User Privilege Limit is determined by the privilege_level parameter for callback connections, but is restricted to Callback level for non-callback connections. Thus, a user can only initiate diff --git a/salt/states/linux_acl.py b/salt/states/linux_acl.py index 55c2ed57c5..792114662e 100644 --- a/salt/states/linux_acl.py +++ b/salt/states/linux_acl.py @@ -4,7 +4,8 @@ Linux File Access Control Lists Ensure a Linux ACL is present - .. code-block:: yaml +.. code-block:: yaml + root: acl.present: - name: /root @@ -14,7 +15,8 @@ Ensure a Linux ACL is present Ensure a Linux ACL does not exist - .. code-block:: yaml +.. code-block:: yaml + root: acl.absent: - name: /root diff --git a/salt/states/slack.py b/salt/states/slack.py index 594f1cb3b7..76ddfdb0e7 100644 --- a/salt/states/slack.py +++ b/salt/states/slack.py @@ -66,10 +66,10 @@ def post_message(name, The message that is to be sent to the Hipchat room. The following parameters are optional: + api_key The api key for Slack to use for authentication, if not specified in the configuration options of master or minion. - ''' ret = {'name': name, 'changes': {}, diff --git a/salt/states/win_servermanager.py b/salt/states/win_servermanager.py index 8ebbdedc90..c8dfdbf458 100644 --- a/salt/states/win_servermanager.py +++ b/salt/states/win_servermanager.py @@ -73,23 +73,26 @@ def installed(name, recurse=False, force=False): def removed(name): ''' Remove the windows feature + name: short name of the feature (the right column in win_servermanager.list_available) - Note: + .. note:: + Some features require a reboot after uninstallation. If so the feature will not be completly uninstalled until - the server is restarted. + the server is restarted. Example: - Run ``salt MinionName win_servermanager.list_installed`` to get a list of all features installed. Use the top + + Run ``salt MinionName win_servermanager.list_installed`` to get a list of all features installed. Use the top name listed for each feature, not the indented one. Do not use the role or feature names mentioned in the PKGMGR documentation. - .. code-block:: yaml - ISWebserverRole: - win_servermanager.removed: - - name: Web-Server + .. code-block:: yaml + ISWebserverRole: + win_servermanager.removed: + - name: Web-Server ''' ret = {'name': name, 'result': True, diff --git a/salt/wheel/config.py b/salt/wheel/config.py index bfc6095a09..8964cd5b26 100644 --- a/salt/wheel/config.py +++ b/salt/wheel/config.py @@ -52,19 +52,22 @@ def update_config(file_name, yaml_contents): specified by ``default_include``. This folder is named ``master.d`` by default. Please look at - http://docs.saltstack.com/en/latest/ref/configuration/master.html#include-configuration + :conf_master:`include-configuration` for more information. - Example low data:: - data = { - 'username': 'salt', - 'password': 'salt', - 'fun': 'config.update_config', - 'file_name': 'gui', - 'yaml_contents': {'id': 1}, - 'client': 'wheel', - 'eauth': 'pam', - } + Example low data: + + .. code-block:: yaml + + data = { + 'username': 'salt', + 'password': 'salt', + 'fun': 'config.update_config', + 'file_name': 'gui', + 'yaml_contents': {'id': 1}, + 'client': 'wheel', + 'eauth': 'pam', + } ''' file_name = '{0}{1}'.format(file_name, '.conf') dir_path = os.path.join(__opts__['config_dir'], From cb572f8c415ead164660814d3e8ed2d4648c42f5 Mon Sep 17 00:00:00 2001 From: Justin Findlay Date: Fri, 5 Jun 2015 19:25:49 -0600 Subject: [PATCH 09/40] add `env` parameter to npm.uninstall --- salt/modules/npm.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/salt/modules/npm.py b/salt/modules/npm.py index 27cb04b584..72740beb53 100644 --- a/salt/modules/npm.py +++ b/salt/modules/npm.py @@ -151,7 +151,8 @@ def install(pkg=None, def uninstall(pkg, dir=None, - runas=None): + runas=None, + env=None): ''' Uninstall an NPM package. @@ -167,6 +168,13 @@ def uninstall(pkg, runas The user to run NPM with + env + Environment variables to set when invoking npm. Uses the same ``env`` + format as the :py:func:`cmd.run ` execution + function. + + .. versionadded:: 2015.5.3 + CLI Example: .. code-block:: bash @@ -182,7 +190,7 @@ def uninstall(pkg, cmd += ' "{0}"'.format(pkg) - result = __salt__['cmd.run_all'](cmd, python_shell=False, cwd=dir, runas=runas) + result = __salt__['cmd.run_all'](cmd, python_shell=False, cwd=dir, runas=runas, env=env) if result['retcode'] != 0: log.error(result['stderr']) From 8140c9694988bbc053c41800918f5eac78ea4561 Mon Sep 17 00:00:00 2001 From: Justin Findlay Date: Fri, 5 Jun 2015 11:33:56 -0600 Subject: [PATCH 10/40] update npm's user info envs Proposed fix for #24231. --- salt/modules/npm.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/salt/modules/npm.py b/salt/modules/npm.py index 72740beb53..75a72cfd70 100644 --- a/salt/modules/npm.py +++ b/salt/modules/npm.py @@ -119,6 +119,11 @@ def install(pkg=None, elif pkgs: cmd += ' "{0}"'.format('" "'.join(pkgs)) + if runas: + uid = salt.utils.get_uid(runas) + if uid: + env.update({'SUDO_UID': uid, 'SUDO_USER': ''}) + result = __salt__['cmd.run_all'](cmd, python_shell=False, cwd=dir, runas=runas, env=env) if result['retcode'] != 0: @@ -183,6 +188,11 @@ def uninstall(pkg, ''' + if runas: + uid = salt.utils.get_uid(runas) + if uid: + env.update({'SUDO_UID': uid, 'SUDO_USER': ''}) + cmd = 'npm uninstall' if dir is None: @@ -235,6 +245,11 @@ def list_(pkg=None, ''' + if runas: + uid = salt.utils.get_uid(runas) + if uid: + env.update({'SUDO_UID': uid, 'SUDO_USER': ''}) + cmd = 'npm list --silent --json' if dir is None: From 6a11ec87b8aa39dc64ecf65b8d93db9e2efb6b1a Mon Sep 17 00:00:00 2001 From: Andreas Lutro Date: Sat, 6 Jun 2015 12:02:52 +0200 Subject: [PATCH 11/40] set up salt-ssh file logging --- salt/cli/ssh.py | 1 + 1 file changed, 1 insertion(+) diff --git a/salt/cli/ssh.py b/salt/cli/ssh.py index 5812300bb4..8e22b166c7 100644 --- a/salt/cli/ssh.py +++ b/salt/cli/ssh.py @@ -13,6 +13,7 @@ class SaltSSH(parsers.SaltSSHOptionParser): def run(self): self.parse_args() + self.setup_logfile_logger() ssh = salt.client.ssh.SSH(self.config) ssh.run() From 37e8827ce8ff6a1f39e737009bab4189c9d8626f Mon Sep 17 00:00:00 2001 From: Ivan Vari Date: Sat, 6 Jun 2015 23:03:14 +1200 Subject: [PATCH 12/40] ensure {} output is not treated as change in module.py state, fixes #24233 --- salt/states/module.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/salt/states/module.py b/salt/states/module.py index 69d3964392..63a0f25fff 100644 --- a/salt/states/module.py +++ b/salt/states/module.py @@ -209,7 +209,7 @@ def run(name, **kwargs): ret['result'] = False return ret else: - if mret is not None: + if mret is not None or mret is not {}: ret['changes']['ret'] = mret if 'returner' in kwargs: From 10359594597cd7cf8ce6d1b4e188427e1812bfb8 Mon Sep 17 00:00:00 2001 From: Jacob Hammons Date: Sat, 6 Jun 2015 12:38:59 -0600 Subject: [PATCH 13/40] Appended .0 to version added --- salt/runners/http.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/salt/runners/http.py b/salt/runners/http.py index b4134faf34..f67066d97c 100644 --- a/salt/runners/http.py +++ b/salt/runners/http.py @@ -3,7 +3,7 @@ Module for making various web calls. Primarily designed for webhooks and the like, but also useful for basic http testing. -.. versionadded:: 2015.5 +.. versionadded:: 2015.5.0 ''' from __future__ import absolute_import # Import Python libs @@ -19,7 +19,7 @@ def query(url, output=True, **kwargs): ''' Query a resource, and decode the return data - .. versionadded:: 2015.5 + .. versionadded:: 2015.5.0 CLI Example: @@ -44,7 +44,7 @@ def update_ca_bundle(target=None, source=None, merge_files=None): ''' Update the local CA bundle file from a URL - .. versionadded:: 2015.5 + .. versionadded:: 2015.5.0 CLI Example: From 3613cc9659aa9fe452dd0b440c8d3ccceef63733 Mon Sep 17 00:00:00 2001 From: Niels Abspoel Date: Thu, 4 Jun 2015 21:02:05 +0200 Subject: [PATCH 14/40] added random integer module to mod_random.py fixes #24407 this will help solve it --- salt/modules/mod_random.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/salt/modules/mod_random.py b/salt/modules/mod_random.py index 28fcd25e91..6fdc4c58c6 100644 --- a/salt/modules/mod_random.py +++ b/salt/modules/mod_random.py @@ -7,6 +7,7 @@ Provides access to randomness generators. from __future__ import absolute_import # Import python libs import hashlib +import random # Import salt libs import salt.utils.pycrypto @@ -118,3 +119,21 @@ def shadow_hash(crypt_salt=None, password=None, algorithm='sha512'): salt '*' random.shadow_hash 'My5alT' 'MyP@asswd' md5 ''' return salt.utils.pycrypto.gen_hash(crypt_salt, password, algorithm) + +def rand_int(start=1, end=10): + ''' + .. versionadded: 2015.5.1 + + Returns a random integer number between the start and end number. + + start : 1 + Any valid integer number + + end : 10 + Any valid integer number + + .. code-block:: bash + + salt '*' random.rand_int 1 10 + ''' + return random.randint(start, end) From 4219b404ad33b4ba7e6b14a73414ea2d39f22249 Mon Sep 17 00:00:00 2001 From: Niels Abspoel Date: Thu, 4 Jun 2015 22:42:59 +0200 Subject: [PATCH 15/40] Fix lint error and update versionadded to 2015.5.3 --- salt/modules/mod_random.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/salt/modules/mod_random.py b/salt/modules/mod_random.py index 6fdc4c58c6..420bf253b0 100644 --- a/salt/modules/mod_random.py +++ b/salt/modules/mod_random.py @@ -120,9 +120,10 @@ def shadow_hash(crypt_salt=None, password=None, algorithm='sha512'): ''' return salt.utils.pycrypto.gen_hash(crypt_salt, password, algorithm) + def rand_int(start=1, end=10): ''' - .. versionadded: 2015.5.1 + .. versionadded: 2015.5.3 Returns a random integer number between the start and end number. From a793c192a66f3f7f123d15d3519eed864820c188 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Hertzog?= Date: Fri, 5 Jun 2015 18:25:46 +0200 Subject: [PATCH 16/40] Avoid extraneous newline character added in last environment variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The print statement used to dump the environment associated to the 'runas' user adds a trailing newline at the end of the string. This newline is kept and injected in the value of the last environment variable. Most of the time, it is innocuous but in some cases it can have serious consequences. In my case, the last variable was HOME and the trailing newline broke the command that salt was executing because it was not able to create a file in the home directory (which was non-existing). Sponsored-By: Offensive Security Signed-off-by: Raphaƫl Hertzog --- salt/modules/cmdmod.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/salt/modules/cmdmod.py b/salt/modules/cmdmod.py index 430561dcd8..7bf752d42f 100644 --- a/salt/modules/cmdmod.py +++ b/salt/modules/cmdmod.py @@ -270,8 +270,8 @@ def _run(cmd, # Getting the environment for the runas user # There must be a better way to do this. py_code = ( - 'import os, itertools; ' - 'print \"\\0\".join(itertools.chain(*os.environ.items()))' + 'import sys, os, itertools; ' + 'sys.stdout.write(\"\\0\".join(itertools.chain(*os.environ.items())))' ) if __grains__['os'] in ['MacOS', 'Darwin']: env_cmd = ('sudo', '-i', '-u', runas, '--', From 7d6b60c79df83dfe7895034465ec271e3155f74b Mon Sep 17 00:00:00 2001 From: Alexander Schwartz Date: Sun, 7 Jun 2015 13:14:26 +0200 Subject: [PATCH 17/40] change "path" to "name" for "file" operations Path is no supported parameter for any file operation (maybe it has been in the past) --- doc/ref/states/requisites.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/ref/states/requisites.rst b/doc/ref/states/requisites.rst index dd3d460511..d534d78ddf 100644 --- a/doc/ref/states/requisites.rst +++ b/doc/ref/states/requisites.rst @@ -508,7 +508,7 @@ at the end of a state run, after all states have completed. configure-apache2: file.managed: - - path: /etc/apache2/apache2.conf + - name: /etc/apache2/apache2.conf - source: salt://apache2/apache2.conf This example will cause apache2 to be restarted when the apache2.conf file is @@ -522,7 +522,7 @@ changed, but the apache2 restart will happen at the end of the state run. configure-apache2: file.managed: - - path: /etc/apache2/apache2.conf + - name: /etc/apache2/apache2.conf - source: salt://apache2/apache2.conf - listen_in: - service: apache2 @@ -547,7 +547,7 @@ same privileges as the salt-minion. comment-repo: file.replace: - - path: /etc/yum.repos.d/fedora.repo + - name: /etc/yum.repos.d/fedora.repo - pattern: ^enabled=0 - repl: enabled=1 - check_cmd: From 1280054bce253faeb5bf68ec473d217e366cdb4b Mon Sep 17 00:00:00 2001 From: Elias Probst Date: Sun, 7 Jun 2015 15:59:27 +0200 Subject: [PATCH 18/40] =?UTF-8?q?Fix=20typo=20(licnese=20=E2=86=92=20licen?= =?UTF-8?q?se).?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- salt/states/powerpath.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/salt/states/powerpath.py b/salt/states/powerpath.py index 12ebd2a195..6d1dacf5f8 100644 --- a/salt/states/powerpath.py +++ b/salt/states/powerpath.py @@ -19,7 +19,7 @@ def license_present(name): on the host. name - The licnese key to ensure is present + The license key to ensure is present ''' ret = {'name': name, 'changes': {}, @@ -61,7 +61,7 @@ def license_absent(name): on the host. name - The licnese key to ensure is absent + The license key to ensure is absent ''' ret = {'name': name, 'changes': {}, From dca33f11124818615e7104388393e3ca5bbb7b60 Mon Sep 17 00:00:00 2001 From: Aneesh Agrawal Date: Sun, 7 Jun 2015 23:36:05 -0400 Subject: [PATCH 19/40] Fix pacman.list_upgrades for new python_shell default. 2015.5 sets the default for python_shell to False, so the pipe used in pacman.list_upgrades no longer works. The egrep invocation after the pipe has the effect of skipping the first output line, which is an informational message. Instead of piping to egrep, we simply skip the first line of output when parsing for the available upgrades. --- salt/modules/pacman.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/salt/modules/pacman.py b/salt/modules/pacman.py index fb5773910e..089c6a863b 100644 --- a/salt/modules/pacman.py +++ b/salt/modules/pacman.py @@ -126,10 +126,7 @@ def list_upgrades(refresh=False): if refresh: options.append('-y') - cmd = ( - 'pacman {0} | egrep -v ' - r'"^\s|^:"' - ).format(' '.join(options)) + cmd = ('pacman {0}').format(' '.join(options)) call = __salt__['cmd.run_all'](cmd, output_loglevel='trace') @@ -145,7 +142,9 @@ def list_upgrades(refresh=False): else: out = call['stdout'] - for line in out.splitlines(): + output = iter(out.splitlines()) + output.next() # Skip informational output line + for line in output: comps = line.split(' ') if len(comps) < 2: continue From 980e1cb4dccb41266288bde83a1eb345cd38eaea Mon Sep 17 00:00:00 2001 From: Aneesh Agrawal Date: Sun, 7 Jun 2015 23:54:16 -0400 Subject: [PATCH 20/40] Lint fix. --- salt/modules/pacman.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/salt/modules/pacman.py b/salt/modules/pacman.py index 089c6a863b..2c40479bc8 100644 --- a/salt/modules/pacman.py +++ b/salt/modules/pacman.py @@ -143,7 +143,7 @@ def list_upgrades(refresh=False): out = call['stdout'] output = iter(out.splitlines()) - output.next() # Skip informational output line + output.next() # Skip informational output line for line in output: comps = line.split(' ') if len(comps) < 2: From 7d96f27f91f6addc8e7aaa42ede62d0e0f5c689a Mon Sep 17 00:00:00 2001 From: Jayesh Kariya Date: Mon, 8 Jun 2015 17:47:04 +0530 Subject: [PATCH 21/40] adding states/rabbitmq_user unit test case. --- tests/unit/states/rabbitmq_user_test.py | 113 ++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 tests/unit/states/rabbitmq_user_test.py diff --git a/tests/unit/states/rabbitmq_user_test.py b/tests/unit/states/rabbitmq_user_test.py new file mode 100644 index 0000000000..6d3c417896 --- /dev/null +++ b/tests/unit/states/rabbitmq_user_test.py @@ -0,0 +1,113 @@ +# -*- coding: utf-8 -*- +''' + :codeauthor: :email:`Jayesh Kariya ` +''' +# Import Python libs +from __future__ import absolute_import + +# Import Salt Testing Libs +from salttesting import skipIf, TestCase +from salttesting.mock import ( + NO_MOCK, + NO_MOCK_REASON, + MagicMock, + patch +) + +from salttesting.helpers import ensure_in_syspath + +ensure_in_syspath('../../') + +# Import Salt Libs +from salt.states import rabbitmq_user + +rabbitmq_user.__opts__ = {} +rabbitmq_user.__salt__ = {} + + +@skipIf(NO_MOCK, NO_MOCK_REASON) +class RabbitmqUserTestCase(TestCase): + ''' + Test cases for salt.states.rabbitmq_user + ''' + # 'present' function tests: 1 + + def test_present(self): + ''' + Test to ensure the RabbitMQ user exists. + ''' + name = 'foo' + passwd = 'password' + tag = 'user' + perms = [{'/': ['.*', '.*']}] + + ret = {'name': name, + 'changes': {}, + 'result': True, + 'comment': ''} + + mock = MagicMock(side_effect=[True, False, True, True, + True, True, True]) + mock_dct = MagicMock(return_value={name: set(tag)}) + mock_pr = MagicMock(return_value=perms) + mock_add = MagicMock(return_value={'Added': name}) + with patch.dict(rabbitmq_user.__salt__, + {'rabbitmq.user_exists': mock, + 'rabbitmq.list_users': mock_dct, + 'rabbitmq.list_user_permissions': mock_pr, + 'rabbitmq.set_user_tags': mock_add}): + comt = ('User foo already presents') + ret.update({'comment': comt}) + self.assertDictEqual(rabbitmq_user.present(name), ret) + + with patch.dict(rabbitmq_user.__opts__, {'test': True}): + comt = ('User foo is set to be created') + ret.update({'comment': comt, 'result': None}) + self.assertDictEqual(rabbitmq_user.present(name), ret) + + comt = ("User foo's password is set to be updated") + ret.update({'comment': comt}) + self.assertDictEqual(rabbitmq_user.present(name, + password=passwd, + force=True), ret) + + comt = ("User foo's password is set to be removed") + ret.update({'comment': comt}) + self.assertDictEqual(rabbitmq_user.present(name, force=True), + ret) + + comt = ('Tags for user foo is set to be changed') + ret.update({'comment': comt}) + self.assertDictEqual(rabbitmq_user.present(name, tags=tag), ret) + + comt = ('Permissions for user foo is set to be changed') + ret.update({'comment': comt}) + self.assertDictEqual(rabbitmq_user.present(name, perms=perms), + ret) + + with patch.dict(rabbitmq_user.__opts__, {'test': False}): + ret.update({'comment': name, 'result': True, + 'changes': {'new': 'Set tags: user\n', 'old': ''}}) + self.assertDictEqual(rabbitmq_user.present(name, tags=tag), ret) + + # 'absent' function tests: 1 + + def test_absent(self): + ''' + Test to ensure the named user is absent. + ''' + name = 'foo' + + ret = {'name': name, + 'changes': {}, + 'result': True, + 'comment': 'User {0} is not present'.format(name)} + + mock = MagicMock(return_value=False) + with patch.dict(rabbitmq_user.__salt__, {'rabbitmq.user_exists': mock}): + self.assertDictEqual(rabbitmq_user.absent(name), ret) + + +if __name__ == '__main__': + from integration import run_tests + run_tests(RabbitmqUserTestCase, needs_daemon=False) From 3ad77143a88bfd1e3ccabcd29b05798a7621f045 Mon Sep 17 00:00:00 2001 From: Jayesh Kariya Date: Mon, 8 Jun 2015 18:23:15 +0530 Subject: [PATCH 22/40] adding states/rabbitmq_vhost unit test case. --- tests/unit/states/rabbitmq_vhost_test.py | 83 ++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 tests/unit/states/rabbitmq_vhost_test.py diff --git a/tests/unit/states/rabbitmq_vhost_test.py b/tests/unit/states/rabbitmq_vhost_test.py new file mode 100644 index 0000000000..fe9f2b00d9 --- /dev/null +++ b/tests/unit/states/rabbitmq_vhost_test.py @@ -0,0 +1,83 @@ +# -*- coding: utf-8 -*- +''' + :codeauthor: :email:`Jayesh Kariya ` +''' +# Import Python libs +from __future__ import absolute_import + +# Import Salt Testing Libs +from salttesting import skipIf, TestCase +from salttesting.mock import ( + NO_MOCK, + NO_MOCK_REASON, + MagicMock, + patch +) + +from salttesting.helpers import ensure_in_syspath + +ensure_in_syspath('../../') + +# Import Salt Libs +from salt.states import rabbitmq_vhost + +rabbitmq_vhost.__opts__ = {} +rabbitmq_vhost.__salt__ = {} + + +@skipIf(NO_MOCK, NO_MOCK_REASON) +class RabbitmqVhostTestCase(TestCase): + ''' + Test cases for salt.states.rabbitmq_vhost + ''' + # 'present' function tests: 1 + + def test_present(self): + ''' + Test to ensure the RabbitMQ VHost exists. + ''' + name = 'virtual_host' + owner = 'rabbit_user' + + ret = {'name': name, + 'changes': {}, + 'result': True, + 'comment': ''} + + mock_t = MagicMock(side_effect=[True, False]) + mock_lst = MagicMock(return_value=[[owner, None, None, None]]) + with patch.dict(rabbitmq_vhost.__salt__, + {'rabbitmq.vhost_exists': mock_t, + 'rabbitmq.list_permissions': mock_lst}): + comt = ('Nothing to do') + ret.update({'comment': comt}) + self.assertDictEqual(rabbitmq_vhost.present(name, owner=owner), ret) + + with patch.dict(rabbitmq_vhost.__opts__, {'test': True}): + comt = ('Creating VHost virtual_host') + ret.update({'comment': comt, 'result': None}) + self.assertDictEqual(rabbitmq_vhost.present(name, owner=owner), + ret) + + # 'absent' function tests: 1 + + def test_absent(self): + ''' + Test to ensure the named user is absent. + ''' + name = 'myqueue' + + ret = {'name': name, + 'changes': {}, + 'result': True, + 'comment': 'Virtual Host {0} is not present'.format(name)} + + mock = MagicMock(return_value=False) + with patch.dict(rabbitmq_vhost.__salt__, + {'rabbitmq.vhost_exists': mock}): + self.assertDictEqual(rabbitmq_vhost.absent(name), ret) + + +if __name__ == '__main__': + from integration import run_tests + run_tests(RabbitmqVhostTestCase, needs_daemon=False) From 79d343a62be01b10bae66cc1d5526341c3e9e76c Mon Sep 17 00:00:00 2001 From: Jayesh Kariya Date: Mon, 8 Jun 2015 18:24:24 +0530 Subject: [PATCH 23/40] adding states/rbenv unit test case. --- tests/unit/states/rbenv_test.py | 135 ++++++++++++++++++++++++++++++++ 1 file changed, 135 insertions(+) create mode 100644 tests/unit/states/rbenv_test.py diff --git a/tests/unit/states/rbenv_test.py b/tests/unit/states/rbenv_test.py new file mode 100644 index 0000000000..56ef9714f0 --- /dev/null +++ b/tests/unit/states/rbenv_test.py @@ -0,0 +1,135 @@ +# -*- coding: utf-8 -*- +''' + :codeauthor: :email:`Jayesh Kariya ` +''' +# Import Python libs +from __future__ import absolute_import + +# Import Salt Testing Libs +from salttesting import skipIf, TestCase +from salttesting.mock import ( + NO_MOCK, + NO_MOCK_REASON, + MagicMock, + patch +) + +from salttesting.helpers import ensure_in_syspath + +ensure_in_syspath('../../') + +# Import Salt Libs +from salt.states import rbenv + +rbenv.__opts__ = {} +rbenv.__salt__ = {} + + +@skipIf(NO_MOCK, NO_MOCK_REASON) +class RbenvTestCase(TestCase): + ''' + Test cases for salt.states.rbenv + ''' + # 'installed' function tests: 1 + + def test_installed(self): + ''' + Test to verify that the specified ruby is installed with rbenv. + ''' + name = 'rbenv-deps' + + ret = {'name': name, + 'changes': {}, + 'result': True, + 'comment': ''} + + mock_t = MagicMock(side_effect=[False, True, True]) + mock_f = MagicMock(return_value=False) + mock_def = MagicMock(return_value='2.7') + mock_ver = MagicMock(return_value=['2.7']) + with patch.dict(rbenv.__salt__, + {'rbenv.is_installed': mock_f, + 'rbenv.install': mock_t, + 'rbenv.default': mock_def, + 'rbenv.versions': mock_ver, + 'rbenv.install_ruby': mock_t}): + with patch.dict(rbenv.__opts__, {'test': True}): + comt = ('Ruby rbenv-deps is set to be installed') + ret.update({'comment': comt, 'result': None}) + self.assertDictEqual(rbenv.installed(name), ret) + + with patch.dict(rbenv.__opts__, {'test': False}): + comt = ('Rbenv failed to install') + ret.update({'comment': comt, 'result': False}) + self.assertDictEqual(rbenv.installed(name), ret) + + comt = ('Successfully installed ruby') + ret.update({'comment': comt, 'result': True, 'default': False, + 'changes': {name: 'Installed'}}) + self.assertDictEqual(rbenv.installed(name), ret) + + # 'absent' function tests: 1 + + def test_absent(self): + ''' + Test to verify that the specified ruby is not installed with rbenv. + ''' + name = 'myqueue' + + ret = {'name': name, + 'changes': {}, + 'result': True, + 'comment': ''} + + mock = MagicMock(side_effect=[False, True]) + mock_def = MagicMock(return_value='2.7') + mock_ver = MagicMock(return_value=['2.7']) + with patch.dict(rbenv.__salt__, + {'rbenv.is_installed': mock, + 'rbenv.default': mock_def, + 'rbenv.versions': mock_ver}): + with patch.dict(rbenv.__opts__, {'test': True}): + comt = ('Ruby myqueue is set to be uninstalled') + ret.update({'comment': comt, 'result': None}) + self.assertDictEqual(rbenv.absent(name), ret) + + with patch.dict(rbenv.__opts__, {'test': False}): + comt = ('Rbenv not installed, myqueue not either') + ret.update({'comment': comt, 'result': True}) + self.assertDictEqual(rbenv.absent(name), ret) + + comt = ('Ruby myqueue is already absent') + ret.update({'comment': comt, 'result': True}) + self.assertDictEqual(rbenv.absent(name), ret) + + # 'install_rbenv' function tests: 1 + + def test_install_rbenv(self): + ''' + Test to install rbenv if not installed. + ''' + name = 'myqueue' + + ret = {'name': name, + 'changes': {}, + 'result': True, + 'comment': ''} + + with patch.dict(rbenv.__opts__, {'test': True}): + comt = ('Rbenv is set to be installed') + ret.update({'comment': comt, 'result': None}) + self.assertDictEqual(rbenv.install_rbenv(name), ret) + + with patch.dict(rbenv.__opts__, {'test': False}): + mock = MagicMock(side_effect=[False, True]) + with patch.dict(rbenv.__salt__, + {'rbenv.is_installed': mock, + 'rbenv.install': mock}): + comt = ('Rbenv installed') + ret.update({'comment': comt, 'result': True}) + self.assertDictEqual(rbenv.install_rbenv(name), ret) + + +if __name__ == '__main__': + from integration import run_tests + run_tests(RbenvTestCase, needs_daemon=False) From d992ef4777e7e0ad5f2f7926a2680bd045962d3d Mon Sep 17 00:00:00 2001 From: rallytime Date: Mon, 8 Jun 2015 08:45:59 -0600 Subject: [PATCH 24/40] Added "CLI Example" to make failing test happy on 2015.5 --- salt/modules/mod_random.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/salt/modules/mod_random.py b/salt/modules/mod_random.py index 420bf253b0..d1d0c7c3c6 100644 --- a/salt/modules/mod_random.py +++ b/salt/modules/mod_random.py @@ -123,16 +123,18 @@ def shadow_hash(crypt_salt=None, password=None, algorithm='sha512'): def rand_int(start=1, end=10): ''' - .. versionadded: 2015.5.3 - Returns a random integer number between the start and end number. + .. versionadded: 2015.5.3 + start : 1 Any valid integer number end : 10 Any valid integer number + CLI Example: + .. code-block:: bash salt '*' random.rand_int 1 10 From b685ebc104545a9b0b49910026056d1fc39b9655 Mon Sep 17 00:00:00 2001 From: rallytime Date: Mon, 8 Jun 2015 10:22:50 -0600 Subject: [PATCH 25/40] Add vSphere deprecation warnings to 2015.5 --- doc/topics/cloud/index.rst | 1 + salt/cloud/clouds/vsphere.py | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/doc/topics/cloud/index.rst b/doc/topics/cloud/index.rst index 36c522702f..c8be6d4b7f 100644 --- a/doc/topics/cloud/index.rst +++ b/doc/topics/cloud/index.rst @@ -173,6 +173,7 @@ Cloud Provider Specifics Getting Started With Rackspace Getting Started With SoftLayer Getting Started With Vexxhost + Getting Started With vSphere diff --git a/salt/cloud/clouds/vsphere.py b/salt/cloud/clouds/vsphere.py index 8e73a28a7f..242a244d08 100644 --- a/salt/cloud/clouds/vsphere.py +++ b/salt/cloud/clouds/vsphere.py @@ -3,7 +3,15 @@ vSphere Cloud Module ==================== -.. versionadded:: 2014.7.0 +.. note:: + + .. deprecated:: Carbon + + The :py:func:`vsphere ` cloud driver has been + deprecated in favor of the :py:func:`vmware ` + cloud driver and will be removed in Salt Carbon. Please refer to + :doc:`Getting started with VMware ` to get started + and convert your vsphere provider configurations to use the vmware driver. The vSphere cloud module is used to control access to VMWare vSphere. @@ -76,6 +84,7 @@ import time import salt.utils.cloud import salt.utils.xmlutil from salt.exceptions import SaltCloudSystemExit +from salt.utils import warn_until # Import salt cloud libs import salt.config as config @@ -110,6 +119,11 @@ def get_configured_provider(): ''' Return the first configured instance. ''' + warn_until( + 'Carbon', + 'The vsphere driver is deprecated in favor of the vmware driver and will be removed ' + 'in Salt Carbon. Please convert your vsphere provider configs to use the vmware driver.' + ) return config.is_provider_configured( __opts__, __active_provider_name__ or 'vsphere', From d876535d716f8c147cfbde7ae0eb7cdb8c3a21c7 Mon Sep 17 00:00:00 2001 From: rallytime Date: Mon, 8 Jun 2015 10:23:47 -0600 Subject: [PATCH 26/40] Add Getting Started with VSphere doc to 2015.5 --- doc/topics/cloud/vsphere.rst | 121 +++++++++++++++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 doc/topics/cloud/vsphere.rst diff --git a/doc/topics/cloud/vsphere.rst b/doc/topics/cloud/vsphere.rst new file mode 100644 index 0000000000..4f3368d141 --- /dev/null +++ b/doc/topics/cloud/vsphere.rst @@ -0,0 +1,121 @@ +============================ +Getting Started With vSphere +============================ + +.. note:: + + .. deprecated:: Carbon + + The :py:func:`vsphere ` cloud driver has been + deprecated in favor of the :py:func:`vmware ` + cloud driver and will be removed in Salt Carbon. Please refer to + :doc:`Getting started with VMware ` instead to get + started with the configuration. + +VMware vSphere is a management platform for virtual infrastructure and cloud +computing. + + +Dependencies +============ +The vSphere module for Salt Cloud requires the PySphere package, which is +available at PyPI: + +https://pypi.python.org/pypi/pysphere + +This package can be installed using `pip` or `easy_install`: + +.. code-block:: bash + + # pip install pysphere + # easy_install pysphere + + +Configuration +============= +Set up the cloud config at ``/etc/salt/cloud.providers`` or in the +``/etc/salt/cloud.providers.d/`` directory: + +.. code-block:: yaml + + my-vsphere-config: + provider: vsphere + # Set the vSphere access credentials + user: marco + password: polo + # Set the URL of your vSphere server + url: 'vsphere.example.com' + + +Profiles +======== + +Cloud Profiles +~~~~~~~~~~~~~~ +vSphere uses a Managed Object Reference to identify objects located in vCenter. +The MOR ID's are used when configuring a vSphere cloud profile. Use the +following reference when locating the MOR's for the cloud profile. + +http://kb.vmware.com/selfservice/microsites/search.do?cmd=displayKC&docType=kc&externalId=1017126&sliceId=1&docTypeID=DT_KB_1_1&dialogID=520386078&stateId=1%200%20520388386 + +Set up an initial profile at ``/etc/salt/cloud.profiles`` or in the +``/etc/salt/cloud.profiles.d`` directory: + +.. code-block:: yaml + + vsphere-centos: + provider: my-vsphere-config + image: centos + # Optional + datastore: datastore-15 + resourcepool: resgroup-8 + folder: salt-cloud + host: host-9 + template: False + + +provider +-------- +Enter the name that was specified when the cloud provider profile was created. + +image +----- +Images available to build an instance can be found using the `--list-images` +option: + +.. code-block:: bash + + # salt-cloud --list-images my-vsphere-config + +datastore +--------- +The MOR of the datastore where the virtual machine should be located. If not +specified, the current datastore is used. + +resourcepool +------------ +The MOR of the resourcepool to be used for the new vm. If not set, it will use +the same resourcepool as the original vm. + +folder +------ +Name of the folder that will contain the new VM. If not set, the VM will be +added to the folder the original VM belongs to. + +host +---- +The MOR of the host where the vm should be registered. + + If not specified: + * if resourcepool is not specified, the current host is used. + * if resourcepool is specified, and the target pool represents a + stand-alone host, the host is used. + * if resourcepool is specified, and the target pool represents a + DRS-enabled cluster, a host selected by DRS is used. + * if resourcepool is specified, and the target pool represents a + cluster without DRS enabled, an InvalidArgument exception will be thrown. + +template +-------- +Specifies whether or not the new virtual machine should be marked as a +template. Default is False. From 1c0fca2b9de96b70f1f89ed7d7e7b48f8768f2ed Mon Sep 17 00:00:00 2001 From: rallytime Date: Mon, 8 Jun 2015 10:43:10 -0600 Subject: [PATCH 27/40] Backport #24450 to 2015.5 Backport #24450 to 2015.5 --- salt/cli/batch.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/salt/cli/batch.py b/salt/cli/batch.py index ea319c4c7a..87e0f65c37 100644 --- a/salt/cli/batch.py +++ b/salt/cli/batch.py @@ -139,10 +139,10 @@ class Batch(object): for ping_ret in self.ping_gen: if ping_ret is None: break - if ping_ret not in self.minions: - self.minions.append(ping_ret) - to_run.append(ping_ret) - + m = next(ping_ret.iterkeys()) + if m not in self.minions: + self.minions.append(m) + to_run.append(m) for queue in iters: try: # Gather returns until we get to the bottom From 2be0180e5e606cf428fe4367ea560730372ab2e4 Mon Sep 17 00:00:00 2001 From: Jeff Quast Date: Mon, 8 Jun 2015 14:42:42 -0700 Subject: [PATCH 28/40] bugfix use of 'iteritem' in 2014.7 branch --- salt/states/rabbitmq_vhost.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/salt/states/rabbitmq_vhost.py b/salt/states/rabbitmq_vhost.py index 1a53606b41..007836ab77 100644 --- a/salt/states/rabbitmq_vhost.py +++ b/salt/states/rabbitmq_vhost.py @@ -98,7 +98,7 @@ def present(name, if vhost_exists: owner_perms = __salt__['rabbitmq.list_permissions'](name, runas=runas) - for eowner, eperms in owner_perms.iteritem(): + for eowner, eperms in owner_perms.iteritems(): if eowner == owner and eperms == [conf, write, read]: ret['comment'] = 'Nothing to do' return ret From ddc63f0f307d96d33d61b7abb39a2988c8709e6d Mon Sep 17 00:00:00 2001 From: Brandon Matthews Date: Fri, 5 Jun 2015 13:31:33 -0700 Subject: [PATCH 29/40] Fix volume handling when creating containers Fixes #24455 --- salt/modules/dockerio.py | 63 +++++++++----- salt/states/dockerio.py | 178 ++++++++++++++++++++++++++++----------- 2 files changed, 174 insertions(+), 67 deletions(-) diff --git a/salt/modules/dockerio.py b/salt/modules/dockerio.py index d476361d64..fd25893fb0 100644 --- a/salt/modules/dockerio.py +++ b/salt/modules/dockerio.py @@ -563,7 +563,8 @@ def create_container(image, volumes_from=None, name=None, cpu_shares=None, - cpuset=None): + cpuset=None, + binds=None): ''' Create a new container @@ -582,10 +583,26 @@ def create_container(image, ports port redirections ``({'222': {}})`` volumes - list of volume mappings:: + list of volume mappings in either local volume, bound volume, or read-only + bound volume form:: - (['/mountpoint/in/container:/guest/foo', '/same/path/mounted/point']) + (['/var/lib/mysql/', '/usr/local/etc/ssl:/etc/ssl', '/etc/passwd:/etc/passwd:ro']) + binds + complete dictionary of bound volume mappings:: + { '/usr/local/etc/ssl/certs/internal.crt': { + 'bind': '/etc/ssl/certs/com.example.internal.crt', + 'ro': True + }, + '/var/lib/mysql': { + 'bind': '/var/lib/mysql/', + 'ro': False + } + } + + This dictionary is suitable for feeding directly into the Docker API, and all + keys are required. + (see http://docker-py.readthedocs.org/en/latest/volumes/) tty attach ttys, Default is ``False`` stdin_open @@ -606,21 +623,28 @@ def create_container(image, ''' status = base_status.copy() client = _get_client() + + # In order to permit specification of bind volumes in the volumes field, + # we'll look through it for bind-style specs and move them. This is purely + # for CLI convenience and backwards-compatibility, as states.dockerio + # should parse volumes before this, and the binds argument duplicates this. + # N.B. this duplicates code in states.dockerio._parse_volumes() + if isinstance(volumes, list): + for volume in volumes: + if ':' in volume: + volspec = volume.split(':') + source = volspec[0] + target = volspec[1] + ro = False + try: + if len(volspec) > 2: + ro = volspec[2] == "ro" + except IndexError: + pass + binds[source] = {'bind': target, 'ro': ro} + volumes.remove(volume) + try: - mountpoints = {} - binds = {} - # create empty mountpoints for them to be - # editable - # either we have a list of guest or host:guest - if isinstance(volumes, list): - for mountpoint in volumes: - mounted = mountpoint - if ':' in mountpoint: - parts = mountpoint.split(':') - mountpoint = parts[1] - mounted = parts[0] - mountpoints[mountpoint] = {} - binds[mounted] = mountpoint container_info = client.create_container( image=image, command=command, @@ -633,11 +657,12 @@ def create_container(image, ports=ports, environment=environment, dns=dns, - volumes=mountpoints, + volumes=volumes, volumes_from=volumes_from, name=name, cpu_shares=cpu_shares, - cpuset=cpuset + cpuset=cpuset, + host_config=docker.utils.create_host_config(binds=binds) ) container = container_info['Id'] callback = _valid diff --git a/salt/states/dockerio.py b/salt/states/dockerio.py index b45b83eb52..0dca477220 100644 --- a/salt/states/dockerio.py +++ b/salt/states/dockerio.py @@ -184,6 +184,102 @@ def _invalid(exec_status=None, name='', comment='', changes=None): result=False) +def _parse_volumes(volumes): + ''' + Parse a given volumes state specification for later use in + modules.docker.create_container(). This produces a dict that can be directly + consumed by the Docker API /containers/create. + + Note: this only really exists for backwards-compatibility, and because + modules.dockerio.start() currently takes a binds argument. + + volumes + A structure containing information about the volumes to be included in the + container that will be created, either: + - a bare dictionary + - a list of dictionaries and lists + + .. code-block:: yaml + + # bare dict style + - volumes: + /usr/local/etc/ssl/certs/example.crt: + bind: /etc/ssl/certs/com.example.internal.crt + ro: True + /var/run: + bind: /var/run/host/ + ro: False + + # list of dicts style: + - volumes: + - /usr/local/etc/ssl/certs/example.crt: + bind: /etc/ssl/certs/com.example.internal.crt + ro: True + - /var/run: /var/run/host/ # read-write bound volume + - /var/lib/mysql # un-bound, container-only volume + + note: bind mounts specified like "/etc/timezone:/tmp/host_tz" will fall + through this parser. + + Returns a dict of volume specifications: + + .. code-block:: yaml + + { + 'bindvols': { + '/usr/local/etc/ssl/certs/example.crt': { + 'bind': '/etc/ssl/certs/com.example.internal.crt', + 'ro': True + }, + '/var/run/': { + 'bind': '/var/run/host', + 'ro': False + }, + }, + 'contvols': [ '/var/lib/mysql/' ] + } + + ''' + bindvolumes = {} + contvolumes = [] + if isinstance(volumes, dict): + # If volumes as a whole is a dict, then there's no way to specify a non-bound volume + # so we exit early and assume the dict is properly formed. + bindvolumes = volumes + if isinstance(volumes, list): + for vol in volumes: + if isinstance(vol, dict): + for volsource, voldef in vol.items(): + if isinstance(voldef, dict): + target = voldef['bind'] + read_only = voldef.get('ro', False) + else: + target = str(voldef) + read_only = False + source = volsource + else: # isinstance(vol, dict) + if ':' in vol: + volspec = vol.split(':') + source = volspec[0] + target = volspec[1] + read_only = False + try: + if len(volspec) > 2: + read_only = volspec[2] == "ro" + except IndexError: + pass + else: + contvolumes.append(str(vol)) + continue + bindvolumes[source] = { + 'bind': target, + 'ro': read_only + } + result = {'bindvols': bindvolumes, 'contvols': contvolumes} + log.trace("Finished parsing volumes, with result: " + str(result)) + return result + + def mod_watch(name, sfun=None, *args, **kw): if sfun == 'built': # Needs to refresh the image @@ -479,7 +575,7 @@ def installed(name, - a port to map - a mapping of mapping portInHost : PortInContainer volumes - List of volumes + List of volumes (see notes for the running function) For other parameters, see absolutely first the salt.modules.dockerio execution module and the docker-py python bindings for docker @@ -502,7 +598,7 @@ def installed(name, # if container exists but is not started, try to start it if already_exists: return _valid(comment='image {0!r} already exists'.format(name)) - dports, dvolumes, denvironment = {}, [], {} + dports, denvironment = {}, {} if not ports: ports = [] if not volumes: @@ -521,15 +617,13 @@ def installed(name, else: for k in p: dports[str(p)] = {} - for p in volumes: - vals = [] - if not isinstance(p, dict): - vals.append('{0}'.format(p)) - else: - for k in p: - vals.append('{0}:{1}'.format(k, p[k])) - dvolumes.extend(vals) + + parsed_volumes = _parse_volumes(volumes) + bindvolumes = parsed_volumes['bindvols'] + contvolumes = parsed_volumes['contvols'] + a, kw = [image], dict( + binds=bindvolumes, command=command, hostname=hostname, user=user, @@ -540,7 +634,7 @@ def installed(name, ports=dports, environment=denvironment, dns=dns, - volumes=dvolumes, + volumes=contvolumes, volumes_from=volumes_from, name=name, cpu_shares=cpu_shares, @@ -799,44 +893,47 @@ def running(name, volumes List of volumes to mount or create in the container (like ``-v`` of ``docker run`` command), mapping host directory to container directory. - To create a volume in the container: + + To specify a volume in the container in terse list format: .. code-block:: yaml - volumes: - - "/var/log/service" + - "/var/log/service" # container-only volume + - "/srv/timezone:/etc/timezone" # bound volume + - "/usr/local/etc/passwd:/etc/passwd:ro" # read-only bound volume - For read-write mounting, use the short form (note that the notion of + You can also use the short dictionary form (note that the notion of source:target from docker is preserved): .. code-block:: yaml - volumes: - - /var/log/service: /var/log/service + - /var/log/service: /var/log/service # mandatory read-write implied - Or, to specify read-only mounting, use the extended form: + Or, alternatively, to specify read-only mounting, use the extended form: .. code-block:: yaml - volumes: - /home/user1: - bind: /mnt/vol2 - ro: true + bind: /mnt/vol2 + ro: True - /var/www: - bind: /mnt/vol1 - ro: false + bind: /mnt/vol1 + ro: False - Or (mostly for backwards compatibility) a dict style + Or (for backwards compatibility) another dict style: .. code-block:: yaml - volumes: - /home/user1: - bind: /mnt/vol2 - ro: true - /var/www: - bind: /mnt/vol1 - ro: false + /home/user1: + bind: /mnt/vol2 + ro: True + /var/www: + bind: /mnt/vol1 + ro: False volumes_from List of containers to share volumes with @@ -934,27 +1031,6 @@ def running(name, if isinstance(var, dict): for key in var: denvironment[six.text_type(key)] = six.text_type(var[key]) - if isinstance(volumes, dict): - bindvolumes = volumes - if isinstance(volumes, list): - for vol in volumes: - if isinstance(vol, dict): - # get source as the dict key - source = list(vol.keys())[0] - # then find target - if isinstance(vol[source], dict): - target = vol[source]['bind'] - read_only = vol[source].get('ro', False) - else: - target = str(vol[source]) - read_only = False - bindvolumes[source] = { - 'bind': target, - 'ro': read_only - } - else: - # assume just an own volumes - contvolumes.append(str(vol)) if isinstance(ports, dict): bindports = ports # in dict form all ports bind, so no need for exposeports @@ -976,6 +1052,11 @@ def running(name, else: #assume just a port to expose exposeports.append(str(port)) + + parsed_volumes = _parse_volumes(volumes) + bindvolumes = parsed_volumes['bindvols'] + contvolumes = parsed_volumes['contvols'] + if not already_exists: args, kwargs = [image], dict( command=command, @@ -988,6 +1069,7 @@ def running(name, ports=exposeports, environment=denvironment, dns=dns, + binds=bindvolumes, volumes=contvolumes, name=name, cpu_shares=cpu_shares, From d1d85dd685070cc9441d5956fedb4c8852cb974d Mon Sep 17 00:00:00 2001 From: Brandon Matthews Date: Fri, 5 Jun 2015 13:59:24 -0700 Subject: [PATCH 30/40] Add logging --- salt/modules/dockerio.py | 2 ++ salt/states/dockerio.py | 1 + 2 files changed, 3 insertions(+) diff --git a/salt/modules/dockerio.py b/salt/modules/dockerio.py index fd25893fb0..af7ee72f4c 100644 --- a/salt/modules/dockerio.py +++ b/salt/modules/dockerio.py @@ -621,6 +621,7 @@ def create_container(image, salt '*' docker.create_container o/ubuntu volumes="['/s','/m:/f']" ''' + log.trace("modules.dockerio.create_container() called for image " + image) status = base_status.copy() client = _get_client() @@ -664,6 +665,7 @@ def create_container(image, cpuset=cpuset, host_config=docker.utils.create_host_config(binds=binds) ) + log.trace("docker.client.create_container returned: " + str(container_info)) container = container_info['Id'] callback = _valid comment = 'Container created' diff --git a/salt/states/dockerio.py b/salt/states/dockerio.py index 0dca477220..a680e7744f 100644 --- a/salt/states/dockerio.py +++ b/salt/states/dockerio.py @@ -240,6 +240,7 @@ def _parse_volumes(volumes): } ''' + log.trace("Parsing given volumes dict: " + str(volumes)) bindvolumes = {} contvolumes = [] if isinstance(volumes, dict): From db4e3dc69bb06af4e0d6b52cd1f0421ba6a9526a Mon Sep 17 00:00:00 2001 From: Brandon Matthews Date: Fri, 5 Jun 2015 14:44:45 -0700 Subject: [PATCH 31/40] Let's raise an exception if create fails --- salt/modules/dockerio.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/salt/modules/dockerio.py b/salt/modules/dockerio.py index af7ee72f4c..080c733107 100644 --- a/salt/modules/dockerio.py +++ b/salt/modules/dockerio.py @@ -675,8 +675,9 @@ def create_container(image, } __salt__['mine.send']('docker.get_containers', host=True) return callback(status, id_=container, comment=comment, out=out) - except Exception: + except Exception, e: _invalid(status, id_=image, out=traceback.format_exc()) + raise e __salt__['mine.send']('docker.get_containers', host=True) return status From 078b33eaaf456ea98a619b1ea1c59fafd4b87bdc Mon Sep 17 00:00:00 2001 From: Colton Myers Date: Mon, 8 Jun 2015 17:38:11 -0600 Subject: [PATCH 32/40] Add xml library to the thin --- salt/utils/thin.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/salt/utils/thin.py b/salt/utils/thin.py index 489640676f..e7b4cb8447 100644 --- a/salt/utils/thin.py +++ b/salt/utils/thin.py @@ -30,6 +30,12 @@ try: except ImportError: # Older jinja does not need markupsafe HAS_MARKUPSAFE = False + +try: + import xml + HAS_XML = True +except ImportError: + HAS_XML = False # pylint: enable=import-error,no-name-in-module try: @@ -115,6 +121,10 @@ def gen_thin(cachedir, extra_mods='', overwrite=False, so_mods=''): if HAS_SSL_MATCH_HOSTNAME: tops.append(os.path.dirname(os.path.dirname(ssl_match_hostname.__file__))) + if HAS_XML: + # For openSUSE, which apparently doesn't include the whole stdlib + tops.append(os.path.dirname(xml.__file__)) + for mod in [m for m in extra_mods.split(',') if m]: if mod not in locals() and mod not in globals(): try: From e78aea9b01bb90a2faae353e8ec08b3d0337c4ed Mon Sep 17 00:00:00 2001 From: Steve Weber Date: Mon, 8 Jun 2015 23:01:41 -0400 Subject: [PATCH 33/40] more small fixes to the ipmi docs more small fixes to the ipmi docs --- salt/modules/ipmi.py | 71 +++++++++++++++++++++++++------------------- 1 file changed, 41 insertions(+), 30 deletions(-) diff --git a/salt/modules/ipmi.py b/salt/modules/ipmi.py index 53816b3466..c2522c81d1 100644 --- a/salt/modules/ipmi.py +++ b/salt/modules/ipmi.py @@ -279,8 +279,11 @@ def get_channel_access(channel=14, read_mode='non_volatile', **kwargs): - api_port=623 - api_kg=None - :return: A Python dict with the following keys/values: + return + A Python dict with the following keys/values: + .. code-block:: python + { alerting: per_msg_auth: @@ -322,14 +325,17 @@ def get_channel_info(channel=14, **kwargs): - api_port=623 - api_kg=None - :return: - session_support: - no_session: channel is session-less - single: channel is single-session - multi: channel is multi-session - auto: channel is session-based (channel could alternate between - single- and multi-session operation, as can occur with a - serial/modem channel that supports connection mode auto-detect) + return + channel session supports: + + .. code-block:: none + + - no_session: channel is session-less + - single: channel is single-session + - multi: channel is multi-session + - auto: channel is session-based (channel could alternate between + single- and multi-session operation, as can occur with a + serial/modem channel that supports connection mode auto-detect) CLI Examples: @@ -419,19 +425,20 @@ def get_user_access(uid, channel=14, **kwargs): - api_port=623 - api_kg=None - :return: - channel_info: - - max_user_count = maximum number of user IDs on this channel - - enabled_users = count of User ID slots presently in use - - users_with_fixed_names = count of user IDs with fixed names - access: - - callback - - link_auth - - ipmi_msg - - privilege_level: [reserved, callback, user, operator - administrator, proprietary, no_access] + return + .. code-block:: none + channel_info: + - max_user_count = maximum number of user IDs on this channel + - enabled_users = count of User ID slots presently in use + - users_with_fixed_names = count of user IDs with fixed names + access: + - callback + - link_auth + - ipmi_msg + - privilege_level: [reserved, callback, user, operator + administrator, proprietary, no_access] CLI Examples: @@ -770,16 +777,20 @@ def get_user(uid, channel=14, **kwargs): - api_port=623 - api_kg=None - :return: - 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] + return + + .. code-block:: none + + 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] + CLI Examples: .. code-block:: bash From 641371284446ec1fa9668322072ed79a2dadfbda Mon Sep 17 00:00:00 2001 From: Steve Weber Date: Mon, 8 Jun 2015 23:32:05 -0400 Subject: [PATCH 34/40] lint lint --- salt/modules/ipmi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/salt/modules/ipmi.py b/salt/modules/ipmi.py index c2522c81d1..4f820cf397 100644 --- a/salt/modules/ipmi.py +++ b/salt/modules/ipmi.py @@ -778,7 +778,7 @@ def get_user(uid, channel=14, **kwargs): - api_kg=None return - + .. code-block:: none name: (str) From 5de741d6265a27cc86aca767797a866402d537ea Mon Sep 17 00:00:00 2001 From: Elias Probst Date: Sun, 7 Jun 2015 16:39:34 +0200 Subject: [PATCH 35/40] 'docker.running' needs now the 'image' param. --- salt/states/dockerio.py | 1 + 1 file changed, 1 insertion(+) diff --git a/salt/states/dockerio.py b/salt/states/dockerio.py index b45b83eb52..0765a80a20 100644 --- a/salt/states/dockerio.py +++ b/salt/states/dockerio.py @@ -74,6 +74,7 @@ Available Functions my_service: docker.running: - container: mysuperdocker + - image: corp/mysuperdocker_img - port_bindings: "5000/tcp": HostIp: "" From cf501cf60db412fb09a5422b3caae9fef34e222d Mon Sep 17 00:00:00 2001 From: Jayesh Kariya Date: Tue, 9 Jun 2015 18:10:37 +0530 Subject: [PATCH 36/40] resolved error. --- tests/unit/states/rabbitmq_vhost_test.py | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/tests/unit/states/rabbitmq_vhost_test.py b/tests/unit/states/rabbitmq_vhost_test.py index fe9f2b00d9..1b3d333db6 100644 --- a/tests/unit/states/rabbitmq_vhost_test.py +++ b/tests/unit/states/rabbitmq_vhost_test.py @@ -37,27 +37,19 @@ class RabbitmqVhostTestCase(TestCase): Test to ensure the RabbitMQ VHost exists. ''' name = 'virtual_host' - owner = 'rabbit_user' ret = {'name': name, 'changes': {}, 'result': True, 'comment': ''} - mock_t = MagicMock(side_effect=[True, False]) - mock_lst = MagicMock(return_value=[[owner, None, None, None]]) + mock = MagicMock(return_value=False) with patch.dict(rabbitmq_vhost.__salt__, - {'rabbitmq.vhost_exists': mock_t, - 'rabbitmq.list_permissions': mock_lst}): - comt = ('Nothing to do') - ret.update({'comment': comt}) - self.assertDictEqual(rabbitmq_vhost.present(name, owner=owner), ret) - + {'rabbitmq.vhost_exists': mock}): with patch.dict(rabbitmq_vhost.__opts__, {'test': True}): comt = ('Creating VHost virtual_host') ret.update({'comment': comt, 'result': None}) - self.assertDictEqual(rabbitmq_vhost.present(name, owner=owner), - ret) + self.assertDictEqual(rabbitmq_vhost.present(name), ret) # 'absent' function tests: 1 From 01c99ad7677991cee541f2e9da7a0751674d0fbb Mon Sep 17 00:00:00 2001 From: Jayesh Kariya Date: Tue, 9 Jun 2015 18:12:53 +0530 Subject: [PATCH 37/40] any() takes list oy tuple. --- salt/states/rabbitmq_vhost.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/salt/states/rabbitmq_vhost.py b/salt/states/rabbitmq_vhost.py index fa963138c6..f08dfe9799 100644 --- a/salt/states/rabbitmq_vhost.py +++ b/salt/states/rabbitmq_vhost.py @@ -81,7 +81,7 @@ def present(name, 'information or see #6961.' ) - if any(user, owner, conf, write, read): + if any((user, owner, conf, write, read)): salt.utils.warn_until( 'Beryllium', 'Passed \'owner\', \'user\', \'conf\', \'write\' or \'read\' ' From 31889e38eb33d61d6811a756695e5bda9ef835b0 Mon Sep 17 00:00:00 2001 From: Jayesh Kariya Date: Tue, 9 Jun 2015 19:44:16 +0530 Subject: [PATCH 38/40] cosmetic change. --- tests/unit/states/rabbitmq_vhost_test.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tests/unit/states/rabbitmq_vhost_test.py b/tests/unit/states/rabbitmq_vhost_test.py index 1b3d333db6..73ca4ca321 100644 --- a/tests/unit/states/rabbitmq_vhost_test.py +++ b/tests/unit/states/rabbitmq_vhost_test.py @@ -40,15 +40,13 @@ class RabbitmqVhostTestCase(TestCase): ret = {'name': name, 'changes': {}, - 'result': True, - 'comment': ''} + 'result': None, + 'comment': 'Creating VHost virtual_host'} mock = MagicMock(return_value=False) with patch.dict(rabbitmq_vhost.__salt__, {'rabbitmq.vhost_exists': mock}): with patch.dict(rabbitmq_vhost.__opts__, {'test': True}): - comt = ('Creating VHost virtual_host') - ret.update({'comment': comt, 'result': None}) self.assertDictEqual(rabbitmq_vhost.present(name), ret) # 'absent' function tests: 1 From 52a694b9acc081993b610c35b84cf7acaefe3611 Mon Sep 17 00:00:00 2001 From: Colton Myers Date: Tue, 9 Jun 2015 12:45:31 -0600 Subject: [PATCH 39/40] Python 3 compat --- salt/modules/dockerio.py | 2 +- salt/modules/pacman.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/salt/modules/dockerio.py b/salt/modules/dockerio.py index 609b1e50c2..d366c9458f 100644 --- a/salt/modules/dockerio.py +++ b/salt/modules/dockerio.py @@ -687,7 +687,7 @@ def create_container(image, } __salt__['mine.send']('docker.get_containers', host=True) return callback(status, id_=container, comment=comment, out=out) - except Exception, e: + except Exception as e: _invalid(status, id_=image, out=traceback.format_exc()) raise e __salt__['mine.send']('docker.get_containers', host=True) diff --git a/salt/modules/pacman.py b/salt/modules/pacman.py index 21ae2061b2..deafd9f5b8 100644 --- a/salt/modules/pacman.py +++ b/salt/modules/pacman.py @@ -145,7 +145,7 @@ def list_upgrades(refresh=False): out = call['stdout'] output = iter(out.splitlines()) - output.next() # Skip informational output line + next(output) # Skip informational output line for line in output: comps = line.split(' ') if len(comps) < 2: From 6e87ad383a997b68269a569f57a4ab885858eb11 Mon Sep 17 00:00:00 2001 From: Colton Myers Date: Tue, 9 Jun 2015 12:45:36 -0600 Subject: [PATCH 40/40] lint --- salt/utils/args.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/salt/utils/args.py b/salt/utils/args.py index bbd0db4123..c657104608 100644 --- a/salt/utils/args.py +++ b/salt/utils/args.py @@ -114,7 +114,7 @@ def yamlify_arg(arg): # Only yamlify if it parses into a non-string type, to prevent # loss of content due to # as comment character parsed_arg = yamlloader.load(arg, Loader=yamlloader.SaltYamlSafeLoader) - if isinstance(parsed_arg, string_types): + if isinstance(parsed_arg, six.string_types): return arg return parsed_arg if arg == 'None':