From b17d3e3575c9e9886155b511b0ec248f2a0d0dbf63fcbee34e49744779e0648f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?= Date: Fri, 26 Jan 2018 13:46:21 +0000 Subject: [PATCH] Accepting request 569868 from systemsmanagement:saltstack:testing - Fix the usage of custom macros on the spec file. - Fix RES7: different dependency names for python-PyYAML and python-MarkupSafe - Build both python2 and python3 binaries together. - Bugfix: errors in external pillar causes crash instead of report of them (bsc#1068446) - Fix 'user.present' when 'gid_from_name' is set but group does not exist. - Added: * bugfix-the-logic-according-to-the-exact-described-pu.patch * return-error-when-gid_from_name-and-group-does-not-e.patch - Fix "No service execution module loaded" issue (bsc#1065792) - Set SHELL environment variable Added: * fix-bsc-1065792.patch * set-shell-environment-variable-64.patch - Removed unnecessary logging on shutdown (bsc#1050003) - Renamed patch that adds grain fqdns Changed: * catching-error-when-pidfile-cannot-be-deleted Removed: * fix-for-pidfile-removal-logging Renamed: * add-fqdns-grains -> feat-add-grain-for-all-fqdns OBS-URL: https://build.opensuse.org/request/show/569868 OBS-URL: https://build.opensuse.org/package/show/systemsmanagement:saltstack/salt?expand=0&rev=107 --- ...beacons-sources-config-pillar-grains.patch | 26 ++ ...ve-syslogging-by-watchdog-cronjob-58.patch | 26 ++ ...turn-a-string-list-on-unknown-job-ta.patch | 5 +- ...-according-to-the-exact-described-pu.patch | 316 +++++++++++++++ ...error-when-pidfile-cannot-be-deleted.patch | 115 ++++++ ...ads-bytes-from-the-wire-and-write-th.patch | 117 ++++++ ...-version-parameter-for-setup.py-scri.patch | 5 +- fake-fix.patch | 0 feat-add-grain-for-all-fqdns.patch | 119 ++++++ fix-bsc-1065792.patch | 25 ++ ...lete_deployment-in-kubernetes-module.patch | 253 ++++++++++++ fix-for-wrong-version-processing.patch | 162 ++++++++ fix-salt-master-for-old-psutil.patch | 26 ++ html.tar.bz2 | 4 +- ...s_count_max-minion-configuration-par.patch | 5 +- ...rameter-for-returned-attribute-selec.patch | 7 +- ...ng-minion-option-documentation-fixes.patch | 5 +- older-logrotate-need-su-directive.patch | 25 ++ ...ility-fix-got-bytes-instead-of-strin.patch | 25 ++ ...n-gid_from_name-and-group-does-not-e.patch | 123 ++++++ run-salt-api-as-user-salt-bsc-1064520.patch | 5 +- run-salt-master-as-dedicated-salt-user.patch | 5 +- salt-2017.7.2.tar.gz | 3 - salt.changes | 124 ++++++ salt.spec | 369 ++++++++++++++---- set-shell-environment-variable-64.patch | 25 ++ split-only-strings-if-they-are-such.patch | 50 +++ update-documentation.sh | 52 ++- ...the-user-home-directory-instead-usin.patch | 5 +- v2017.7.2.tar.gz | 3 + zyppnotify | 59 --- 31 files changed, 1921 insertions(+), 168 deletions(-) create mode 100644 activate-all-beacons-sources-config-pillar-grains.patch create mode 100644 avoid-excessive-syslogging-by-watchdog-cronjob-58.patch create mode 100644 bugfix-the-logic-according-to-the-exact-described-pu.patch create mode 100644 catching-error-when-pidfile-cannot-be-deleted.patch create mode 100644 cherrypy-read-reads-bytes-from-the-wire-and-write-th.patch create mode 100644 fake-fix.patch create mode 100644 feat-add-grain-for-all-fqdns.patch create mode 100644 fix-bsc-1065792.patch create mode 100644 fix-for-delete_deployment-in-kubernetes-module.patch create mode 100644 fix-for-wrong-version-processing.patch create mode 100644 fix-salt-master-for-old-psutil.patch create mode 100644 older-logrotate-need-su-directive.patch create mode 100644 python3-compatibility-fix-got-bytes-instead-of-strin.patch create mode 100644 return-error-when-gid_from_name-and-group-does-not-e.patch delete mode 100644 salt-2017.7.2.tar.gz create mode 100644 set-shell-environment-variable-64.patch create mode 100644 split-only-strings-if-they-are-such.patch create mode 100644 v2017.7.2.tar.gz delete mode 100644 zyppnotify diff --git a/activate-all-beacons-sources-config-pillar-grains.patch b/activate-all-beacons-sources-config-pillar-grains.patch new file mode 100644 index 0000000..bb6b711 --- /dev/null +++ b/activate-all-beacons-sources-config-pillar-grains.patch @@ -0,0 +1,26 @@ +From 2a88378d88c2f56b152ef048214728995476244a Mon Sep 17 00:00:00 2001 +From: Bo Maryniuk +Date: Tue, 17 Oct 2017 16:52:33 +0200 +Subject: [PATCH] Activate all beacons sources: config/pillar/grains + +--- + salt/minion.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/salt/minion.py b/salt/minion.py +index 33cbb8fa0a..10b608cc7a 100644 +--- a/salt/minion.py ++++ b/salt/minion.py +@@ -404,7 +404,7 @@ class MinionBase(object): + the pillar or grains changed + ''' + if 'config.merge' in functions: +- b_conf = functions['config.merge']('beacons', self.opts['beacons'], omit_opts=True) ++ b_conf = functions['config.merge']('beacons', self.opts['beacons']) + if b_conf: + return self.beacons.process(b_conf, self.opts['grains']) # pylint: disable=no-member + return [] +-- +2.15.1 + + diff --git a/avoid-excessive-syslogging-by-watchdog-cronjob-58.patch b/avoid-excessive-syslogging-by-watchdog-cronjob-58.patch new file mode 100644 index 0000000..37a800f --- /dev/null +++ b/avoid-excessive-syslogging-by-watchdog-cronjob-58.patch @@ -0,0 +1,26 @@ +From a94f7d5739fd38529ebf23a89e6afc164739dd8d Mon Sep 17 00:00:00 2001 +From: Hubert Mantel +Date: Mon, 27 Nov 2017 13:55:13 +0100 +Subject: [PATCH] avoid excessive syslogging by watchdog cronjob (#58) + +--- + pkg/suse/salt-minion | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/pkg/suse/salt-minion b/pkg/suse/salt-minion +index 2e418094ed..73a91ebd62 100755 +--- a/pkg/suse/salt-minion ++++ b/pkg/suse/salt-minion +@@ -55,7 +55,7 @@ WATCHDOG_CRON="/etc/cron.d/salt-minion" + + set_watchdog() { + if [ ! -f $WATCHDOG_CRON ]; then +- echo -e '* * * * * root /usr/bin/salt-daemon-watcher --with-init\n' > $WATCHDOG_CRON ++ echo -e '-* * * * * root /usr/bin/salt-daemon-watcher --with-init\n' > $WATCHDOG_CRON + # Kick the watcher for 1 minute immediately, because cron will wake up only afterwards + /usr/bin/salt-daemon-watcher --with-init & disown + fi +-- +2.15.1 + + diff --git a/bugfix-always-return-a-string-list-on-unknown-job-ta.patch b/bugfix-always-return-a-string-list-on-unknown-job-ta.patch index ca1a3e3..a59fb1e 100644 --- a/bugfix-always-return-a-string-list-on-unknown-job-ta.patch +++ b/bugfix-always-return-a-string-list-on-unknown-job-ta.patch @@ -1,7 +1,7 @@ From 49a4e807fb1cb844cec7b7c11b37f6c276f899e4 Mon Sep 17 00:00:00 2001 From: Bo Maryniuk Date: Mon, 9 Oct 2017 17:57:48 +0200 -Subject: [PATCH 5/6] Bugfix: always return a string "list" on unknown job +Subject: [PATCH] Bugfix: always return a string "list" on unknown job target type. --- @@ -64,5 +64,6 @@ index 3f4ef296a2..4dbf0d2c6f 100644 if 'metadata' in job: -- -2.14.2 +2.15.1 + diff --git a/bugfix-the-logic-according-to-the-exact-described-pu.patch b/bugfix-the-logic-according-to-the-exact-described-pu.patch new file mode 100644 index 0000000..eaf6132 --- /dev/null +++ b/bugfix-the-logic-according-to-the-exact-described-pu.patch @@ -0,0 +1,316 @@ +From 0e1cac43dd8211186d6794602f6da77f612850a7 Mon Sep 17 00:00:00 2001 +From: Bo Maryniuk +Date: Tue, 21 Nov 2017 12:53:11 +0100 +Subject: [PATCH] Bugfix the logic according to the exact described + purpose of the function. + +Rename function from ambiguous name + +Fix and clarify docstring. + +Remove unused variable (no exception, within the try/finally block) + +Bugfix: do not pull '_errors' from unchecked objects + +Bugfix: unit test mistakenly expects pillar errors as a string, while it is a list + +Fix unit test: wrong error types in side effect + +Add unit test for _get_pillar_errors when external and internal pillars are clean + +Add unit test for _get_pillar_errors when external pillar has errors and internal is clean + +Add unit test for _get_pillar_errors when both external and internal pillars contains errors + +Add unit test for _get_pillar_errors when external pillar is clean and internal contains errors + +Use variable, instead of direct value +--- + salt/modules/state.py | 82 +++++++++++++++++++--------------------- + tests/unit/modules/test_state.py | 75 +++++++++++++++++++++++++++++++----- + 2 files changed, 103 insertions(+), 54 deletions(-) + +diff --git a/salt/modules/state.py b/salt/modules/state.py +index fa5b997ef7..31ffc25dfe 100644 +--- a/salt/modules/state.py ++++ b/salt/modules/state.py +@@ -99,17 +99,16 @@ def _set_retcode(ret, highstate=None): + __context__['retcode'] = 2 + + +-def _check_pillar(kwargs, pillar=None): ++def _get_pillar_errors(kwargs, pillar=None): + ''' +- Check the pillar for errors, refuse to run the state if there are errors +- in the pillar and return the pillar errors ++ Checks all pillars (external and internal) for errors. ++ Return an error message, if anywhere or None. ++ ++ :param kwargs: dictionary of options ++ :param pillar: external pillar ++ :return: None or an error message + ''' +- if kwargs.get('force'): +- return True +- pillar_dict = pillar if pillar is not None else __pillar__ +- if '_errors' in pillar_dict: +- return False +- return True ++ return None if kwargs.get('force') else (pillar or {}).get('_errors', __pillar__.get('_errors')) or None + + + def _wait(jid): +@@ -411,10 +410,10 @@ def template(tem, queue=False, **kwargs): + context=__context__, + initial_pillar=_get_initial_pillar(opts)) + +- if not _check_pillar(kwargs, st_.opts['pillar']): ++ errors = _get_pillar_errors(kwargs, pillar=st_.opts['pillar']) ++ if errors: + __context__['retcode'] = 5 +- raise CommandExecutionError('Pillar failed to render', +- info=st_.opts['pillar']['_errors']) ++ raise CommandExecutionError('Pillar failed to render', info=errors) + + if not tem.endswith('.sls'): + tem = '{sls}.sls'.format(sls=tem) +@@ -872,11 +871,10 @@ def highstate(test=None, queue=False, **kwargs): + mocked=kwargs.get('mock', False), + initial_pillar=_get_initial_pillar(opts)) + +- if not _check_pillar(kwargs, st_.opts['pillar']): ++ errors = _get_pillar_errors(kwargs, st_.opts['pillar']) ++ if errors: + __context__['retcode'] = 5 +- err = ['Pillar failed to render with the following messages:'] +- err += __pillar__['_errors'] +- return err ++ return ['Pillar failed to render with the following messages:'] + errors + + st_.push_active() + ret = {} +@@ -1071,11 +1069,10 @@ def sls(mods, test=None, exclude=None, queue=False, **kwargs): + mocked=kwargs.get('mock', False), + initial_pillar=_get_initial_pillar(opts)) + +- if not _check_pillar(kwargs, st_.opts['pillar']): ++ errors = _get_pillar_errors(kwargs, pillar=st_.opts['pillar']) ++ if errors: + __context__['retcode'] = 5 +- err = ['Pillar failed to render with the following messages:'] +- err += __pillar__['_errors'] +- return err ++ return ['Pillar failed to render with the following messages:'] + errors + + orchestration_jid = kwargs.get('orchestration_jid') + umask = os.umask(0o77) +@@ -1090,7 +1087,6 @@ def sls(mods, test=None, exclude=None, queue=False, **kwargs): + mods = mods.split(',') + + st_.push_active() +- ret = {} + try: + high_, errors = st_.render_highstate({opts['environment']: mods}) + +@@ -1197,11 +1193,10 @@ def top(topfn, test=None, queue=False, **kwargs): + pillar_enc=pillar_enc, + context=__context__, + initial_pillar=_get_initial_pillar(opts)) +- if not _check_pillar(kwargs, st_.opts['pillar']): ++ errors = _get_pillar_errors(kwargs, pillar=st_.opts['pillar']) ++ if errors: + __context__['retcode'] = 5 +- err = ['Pillar failed to render with the following messages:'] +- err += __pillar__['_errors'] +- return err ++ return ['Pillar failed to render with the following messages:'] + errors + + st_.push_active() + st_.opts['state_top'] = salt.utils.url.create(topfn) +@@ -1259,10 +1254,10 @@ def show_highstate(queue=False, **kwargs): + pillar_enc=pillar_enc, + initial_pillar=_get_initial_pillar(opts)) + +- if not _check_pillar(kwargs, st_.opts['pillar']): ++ errors = _get_pillar_errors(kwargs, pillar=st_.opts['pillar']) ++ if errors: + __context__['retcode'] = 5 +- raise CommandExecutionError('Pillar failed to render', +- info=st_.opts['pillar']['_errors']) ++ raise CommandExecutionError('Pillar failed to render', info=errors) + + st_.push_active() + try: +@@ -1293,10 +1288,10 @@ def show_lowstate(queue=False, **kwargs): + st_ = salt.state.HighState(opts, + initial_pillar=_get_initial_pillar(opts)) + +- if not _check_pillar(kwargs, st_.opts['pillar']): ++ errors = _get_pillar_errors(kwargs, pillar=st_.opts['pillar']) ++ if errors: + __context__['retcode'] = 5 +- raise CommandExecutionError('Pillar failed to render', +- info=st_.opts['pillar']['_errors']) ++ raise CommandExecutionError('Pillar failed to render', info=errors) + + st_.push_active() + try: +@@ -1394,11 +1389,10 @@ def sls_id(id_, mods, test=None, queue=False, **kwargs): + st_ = salt.state.HighState(opts, + initial_pillar=_get_initial_pillar(opts)) + +- if not _check_pillar(kwargs, st_.opts['pillar']): ++ errors = _get_pillar_errors(kwargs, pillar=st_.opts['pillar']) ++ if errors: + __context__['retcode'] = 5 +- err = ['Pillar failed to render with the following messages:'] +- err += __pillar__['_errors'] +- return err ++ return ['Pillar failed to render with the following messages:'] + errors + + if isinstance(mods, six.string_types): + split_mods = mods.split(',') +@@ -1474,10 +1468,10 @@ def show_low_sls(mods, test=None, queue=False, **kwargs): + + st_ = salt.state.HighState(opts, initial_pillar=_get_initial_pillar(opts)) + +- if not _check_pillar(kwargs, st_.opts['pillar']): ++ errors = _get_pillar_errors(kwargs, pillar=st_.opts['pillar']) ++ if errors: + __context__['retcode'] = 5 +- raise CommandExecutionError('Pillar failed to render', +- info=st_.opts['pillar']['_errors']) ++ raise CommandExecutionError('Pillar failed to render', info=errors) + + if isinstance(mods, six.string_types): + mods = mods.split(',') +@@ -1561,10 +1555,10 @@ def show_sls(mods, test=None, queue=False, **kwargs): + pillar_enc=pillar_enc, + initial_pillar=_get_initial_pillar(opts)) + +- if not _check_pillar(kwargs, st_.opts['pillar']): ++ errors = _get_pillar_errors(kwargs, pillar=st_.opts['pillar']) ++ if errors: + __context__['retcode'] = 5 +- raise CommandExecutionError('Pillar failed to render', +- info=st_.opts['pillar']['_errors']) ++ raise CommandExecutionError('Pillar failed to render', info=errors) + + if isinstance(mods, six.string_types): + mods = mods.split(',') +@@ -1610,10 +1604,10 @@ def show_top(queue=False, **kwargs): + + st_ = salt.state.HighState(opts, initial_pillar=_get_initial_pillar(opts)) + +- if not _check_pillar(kwargs, st_.opts['pillar']): ++ errors = _get_pillar_errors(kwargs, pillar=st_.opts['pillar']) ++ if errors: + __context__['retcode'] = 5 +- raise CommandExecutionError('Pillar failed to render', +- info=st_.opts['pillar']['_errors']) ++ raise CommandExecutionError('Pillar failed to render', info=errors) + + errors = [] + top_ = st_.get_top() +diff --git a/tests/unit/modules/test_state.py b/tests/unit/modules/test_state.py +index 7f4f361c26..e5d10493da 100644 +--- a/tests/unit/modules/test_state.py ++++ b/tests/unit/modules/test_state.py +@@ -695,9 +695,9 @@ class StateTestCase(TestCase, LoaderModuleMockMixin): + with patch.object(state, '_check_queue', mock): + self.assertEqual(state.top("reverse_top.sls"), "A") + +- mock = MagicMock(side_effect=[False, True, True]) +- with patch.object(state, '_check_pillar', mock): +- with patch.dict(state.__pillar__, {"_errors": "E"}): ++ mock = MagicMock(side_effect=[['E'], None, None]) ++ with patch.object(state, '_get_pillar_errors', mock): ++ with patch.dict(state.__pillar__, {"_errors": ['E']}): + self.assertListEqual(state.top("reverse_top.sls"), ret) + + with patch.dict(state.__opts__, {"test": "A"}): +@@ -854,14 +854,10 @@ class StateTestCase(TestCase, LoaderModuleMockMixin): + True), + ["A"]) + +- mock = MagicMock(side_effect=[False, +- True, +- True, +- True, +- True]) +- with patch.object(state, '_check_pillar', mock): ++ mock = MagicMock(side_effect=[['E', '1'], None, None, None, None]) ++ with patch.object(state, '_get_pillar_errors', mock): + with patch.dict(state.__context__, {"retcode": 5}): +- with patch.dict(state.__pillar__, {"_errors": "E1"}): ++ with patch.dict(state.__pillar__, {"_errors": ['E', '1']}): + self.assertListEqual(state.sls("core,edit.vim dev", + None, + None, +@@ -979,3 +975,62 @@ class StateTestCase(TestCase, LoaderModuleMockMixin): + with patch('salt.utils.fopen', mock_open()): + self.assertTrue(state.pkg("/tmp/state_pkg.tgz", + 0, "md5")) ++ ++ def test_get_pillar_errors_CC(self): ++ ''' ++ Test _get_pillar_errors function. ++ CC: External clean, Internal clean ++ :return: ++ ''' ++ for int_pillar, ext_pillar in [({'foo': 'bar'}, {'fred': 'baz'}), ++ ({'foo': 'bar'}, None), ++ ({}, {'fred': 'baz'})]: ++ with patch('salt.modules.state.__pillar__', int_pillar): ++ for opts, res in [({'force': True}, None), ++ ({'force': False}, None), ++ ({}, None)]: ++ assert res == state._get_pillar_errors(kwargs=opts, pillar=ext_pillar) ++ ++ def test_get_pillar_errors_EC(self): ++ ''' ++ Test _get_pillar_errors function. ++ EC: External erroneous, Internal clean ++ :return: ++ ''' ++ errors = ['failure', 'everywhere'] ++ for int_pillar, ext_pillar in [({'foo': 'bar'}, {'fred': 'baz', '_errors': errors}), ++ ({}, {'fred': 'baz', '_errors': errors})]: ++ with patch('salt.modules.state.__pillar__', int_pillar): ++ for opts, res in [({'force': True}, None), ++ ({'force': False}, errors), ++ ({}, errors)]: ++ assert res == state._get_pillar_errors(kwargs=opts, pillar=ext_pillar) ++ ++ def test_get_pillar_errors_EE(self): ++ ''' ++ Test _get_pillar_errors function. ++ CC: External erroneous, Internal erroneous ++ :return: ++ ''' ++ errors = ['failure', 'everywhere'] ++ for int_pillar, ext_pillar in [({'foo': 'bar', '_errors': errors}, {'fred': 'baz', '_errors': errors})]: ++ with patch('salt.modules.state.__pillar__', int_pillar): ++ for opts, res in [({'force': True}, None), ++ ({'force': False}, errors), ++ ({}, errors)]: ++ assert res == state._get_pillar_errors(kwargs=opts, pillar=ext_pillar) ++ ++ def test_get_pillar_errors_CE(self): ++ ''' ++ Test _get_pillar_errors function. ++ CC: External clean, Internal erroneous ++ :return: ++ ''' ++ errors = ['failure', 'everywhere'] ++ for int_pillar, ext_pillar in [({'foo': 'bar', '_errors': errors}, {'fred': 'baz'}), ++ ({'foo': 'bar', '_errors': errors}, None)]: ++ with patch('salt.modules.state.__pillar__', int_pillar): ++ for opts, res in [({'force': True}, None), ++ ({'force': False}, errors), ++ ({}, errors)]: ++ assert res == state._get_pillar_errors(kwargs=opts, pillar=ext_pillar) +-- +2.15.1 + + diff --git a/catching-error-when-pidfile-cannot-be-deleted.patch b/catching-error-when-pidfile-cannot-be-deleted.patch new file mode 100644 index 0000000..fd00ab9 --- /dev/null +++ b/catching-error-when-pidfile-cannot-be-deleted.patch @@ -0,0 +1,115 @@ +From 16dc0e5ef2c86a315a0d09fb186dd1616df1444e Mon Sep 17 00:00:00 2001 +From: Jochen Breuer +Date: Wed, 6 Sep 2017 10:16:51 +0200 +Subject: [PATCH] Catching error when PIDfile cannot be deleted + +Usually the PIDfile is locate in /run. If Salt is not started with root +permissions, it is not able to delete the PIDfile in /run. It should +be safe to just ignore this error, since Salt overwrites the PIDfile on +the next start. +--- + salt/utils/parsers.py | 8 +++++- + tests/unit/utils/test_parsers.py | 54 ++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 61 insertions(+), 1 deletion(-) + +diff --git a/salt/utils/parsers.py b/salt/utils/parsers.py +index 925ec9f4e4..d8c5068874 100644 +--- a/salt/utils/parsers.py ++++ b/salt/utils/parsers.py +@@ -966,7 +966,13 @@ class DaemonMixIn(six.with_metaclass(MixInMeta, object)): + # We've loaded and merged options into the configuration, it's safe + # to query about the pidfile + if self.check_pidfile(): +- os.unlink(self.config['pidfile']) ++ try: ++ os.unlink(self.config['pidfile']) ++ except OSError as err: ++ # This happens when running salt-master as a non-root user ++ # and can be ignored, since salt-master is able to ++ # overwrite the PIDfile on the next start. ++ pass + + def set_pidfile(self): + from salt.utils.process import set_pidfile +diff --git a/tests/unit/utils/test_parsers.py b/tests/unit/utils/test_parsers.py +index 43488e894c..8168b3e6e3 100644 +--- a/tests/unit/utils/test_parsers.py ++++ b/tests/unit/utils/test_parsers.py +@@ -5,6 +5,7 @@ + + # Import python libs + from __future__ import absolute_import ++import logging + + # Import Salt Testing Libs + from tests.support.unit import skipIf, TestCase +@@ -21,6 +22,7 @@ import salt.utils.parsers + import salt.log.setup as log + import salt.config + import salt.syspaths ++from salt.utils.parsers import DaemonMixIn + + + class ErrorMock(object): # pylint: disable=too-few-public-methods +@@ -958,5 +960,57 @@ class SaltAPIParserTestCase(LogSettingsParserTests): + self.addCleanup(delattr, self, 'parser') + + ++@skipIf(NO_MOCK, NO_MOCK_REASON) ++class DaemonMixInTestCase(TestCase): ++ ''' ++ Tests the PIDfile deletion in the DaemonMixIn. ++ ''' ++ ++ def setUp(self): ++ ''' ++ Setting up ++ ''' ++ # Set PID ++ self.pid = '/some/fake.pid' ++ ++ # Setup mixin ++ self.mixin = salt.utils.parsers.DaemonMixIn() ++ self.mixin.config = {} ++ self.mixin.config['pidfile'] = self.pid ++ ++ # logger ++ self.logger = logging.getLogger('salt.utils.parsers') ++ ++ def test_pid_file_deletion(self): ++ ''' ++ PIDfile deletion without exception. ++ ''' ++ with patch('os.unlink', MagicMock()) as os_unlink: ++ with patch('os.path.isfile', MagicMock(return_value=True)): ++ with patch.object(self.logger, 'info') as mock_logger: ++ self.mixin._mixin_before_exit() ++ assert mock_logger.call_count == 0 ++ assert os_unlink.call_count == 1 ++ ++ + # Hide the class from unittest framework when it searches for TestCase classes in the module + del LogSettingsParserTests ++ ++ ++if __name__ == '__main__': ++ from integration import run_tests # pylint: disable=import-error,wrong-import-position ++ run_tests(MasterOptionParserTestCase, ++ MinionOptionParserTestCase, ++ ProxyMinionOptionParserTestCase, ++ SyndicOptionParserTestCase, ++ SaltCMDOptionParserTestCase, ++ SaltCPOptionParserTestCase, ++ SaltKeyOptionParserTestCase, ++ SaltCallOptionParserTestCase, ++ SaltRunOptionParserTestCase, ++ SaltSSHOptionParserTestCase, ++ SaltCloudParserTestCase, ++ SPMParserTestCase, ++ SaltAPIParserTestCase, ++ DaemonMixInTestCase, ++ needs_daemon=False) +-- +2.13.6 + + diff --git a/cherrypy-read-reads-bytes-from-the-wire-and-write-th.patch b/cherrypy-read-reads-bytes-from-the-wire-and-write-th.patch new file mode 100644 index 0000000..146d5d6 --- /dev/null +++ b/cherrypy-read-reads-bytes-from-the-wire-and-write-th.patch @@ -0,0 +1,117 @@ +From b31d8f3898149209097e01bbeefbfb70b5a0c395 Mon Sep 17 00:00:00 2001 +From: Michael Calmer +Date: Fri, 15 Dec 2017 09:53:10 +0100 +Subject: [PATCH] cherrypy read() reads bytes from the wire and write + them into contents var + +adapt tests to reflect reality + +When CherryPy run with python3 it reads "bytes" from the wire. +In case of python2 BytesIO == StringIO, so nothing should change. + +This change will do the same to make unit tests reflect reality. +--- + salt/netapi/rest_cherrypy/app.py | 25 +++++++------------------ + tests/support/cptestcase.py | 6 ++++-- + 2 files changed, 11 insertions(+), 20 deletions(-) + +diff --git a/salt/netapi/rest_cherrypy/app.py b/salt/netapi/rest_cherrypy/app.py +index 4099416a28..67e0bad07a 100644 +--- a/salt/netapi/rest_cherrypy/app.py ++++ b/salt/netapi/rest_cherrypy/app.py +@@ -505,6 +505,7 @@ import salt + import salt.auth + import salt.utils + import salt.utils.event ++from salt.ext.six import BytesIO + + # Import salt-api libs + import salt.netapi +@@ -830,18 +831,6 @@ def urlencoded_processor(entity): + + :param entity: raw POST data + ''' +- if six.PY3: +- # https://github.com/cherrypy/cherrypy/pull/1572 +- contents = six.StringIO() +- entity.fp.read(fp_out=contents) +- contents.seek(0) +- body_str = contents.read() +- body_bytes = salt.utils.to_bytes(body_str) +- body_bytes = six.BytesIO(body_bytes) +- body_bytes.seek(0) +- # Patch fp +- entity.fp = body_bytes +- del contents + # First call out to CherryPy's default processor + cherrypy._cpreqbody.process_urlencoded(entity) + cherrypy._cpreqbody.process_urlencoded(entity) +@@ -860,10 +849,10 @@ def json_processor(entity): + body = entity.fp.read() + else: + # https://github.com/cherrypy/cherrypy/pull/1572 +- contents = six.StringIO() ++ contents = BytesIO() + body = entity.fp.read(fp_out=contents) + contents.seek(0) +- body = contents.read() ++ body = salt.utils.to_unicode(contents.read()) + del contents + try: + cherrypy.serving.request.unserialized_data = json.loads(body) +@@ -884,10 +873,10 @@ def yaml_processor(entity): + body = entity.fp.read() + else: + # https://github.com/cherrypy/cherrypy/pull/1572 +- contents = six.StringIO() ++ contents = BytesIO() + body = entity.fp.read(fp_out=contents) + contents.seek(0) +- body = contents.read() ++ body = salt.utils.to_unicode(contents.read()) + try: + cherrypy.serving.request.unserialized_data = yaml.safe_load(body) + except ValueError: +@@ -910,10 +899,10 @@ def text_processor(entity): + body = entity.fp.read() + else: + # https://github.com/cherrypy/cherrypy/pull/1572 +- contents = six.StringIO() ++ contents = BytesIO() + body = entity.fp.read(fp_out=contents) + contents.seek(0) +- body = contents.read() ++ body = salt.utils.to_unicode(contents.read()) + try: + cherrypy.serving.request.unserialized_data = json.loads(body) + except ValueError: +diff --git a/tests/support/cptestcase.py b/tests/support/cptestcase.py +index ea2845f46d..75785b8eb1 100644 +--- a/tests/support/cptestcase.py ++++ b/tests/support/cptestcase.py +@@ -38,9 +38,11 @@ from tests.support.case import TestCase + # pylint: disable=import-error + import cherrypy # pylint: disable=3rd-party-module-not-gated + import salt.ext.six as six +-from salt.ext.six.moves import StringIO ++from salt.ext.six import BytesIO + # pylint: enable=import-error + ++import salt.utils ++ + # Not strictly speaking mandatory but just makes sense + cherrypy.config.update({'environment': "test_suite"}) + +@@ -92,7 +94,7 @@ class BaseCherryPyTestCase(TestCase): + fd = None + if body is not None: + h['content-length'] = '{0}'.format(len(body)) +- fd = StringIO(body) ++ fd = BytesIO(salt.utils.to_bytes(body)) + + if headers is not None: + h.update(headers) +-- +2.15.1 + + diff --git a/enable-with-salt-version-parameter-for-setup.py-scri.patch b/enable-with-salt-version-parameter-for-setup.py-scri.patch index 6836189..279351f 100644 --- a/enable-with-salt-version-parameter-for-setup.py-scri.patch +++ b/enable-with-salt-version-parameter-for-setup.py-scri.patch @@ -2,7 +2,7 @@ From 1949261a504fd01e057b41126d78f142f4977204 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?= Date: Fri, 6 Oct 2017 17:12:15 +0100 -Subject: [PATCH 6/6] Enable '--with-salt-version' parameter for setup.py +Subject: [PATCH] Enable '--with-salt-version' parameter for setup.py script --- @@ -71,5 +71,6 @@ index effdc2f230..519f753401 100755 self.salt_version = __version__ # pylint: disable=undefined-variable self.description = 'Portable, distributed, remote execution and configuration management system' -- -2.14.2 +2.15.1 + diff --git a/fake-fix.patch b/fake-fix.patch new file mode 100644 index 0000000..473a0f4 diff --git a/feat-add-grain-for-all-fqdns.patch b/feat-add-grain-for-all-fqdns.patch new file mode 100644 index 0000000..06da256 --- /dev/null +++ b/feat-add-grain-for-all-fqdns.patch @@ -0,0 +1,119 @@ +From ba9f26cf00b0a767b7b25f156553a9e783aa895d Mon Sep 17 00:00:00 2001 +From: Michele Bologna +Date: Thu, 14 Dec 2017 18:20:02 +0100 +Subject: [PATCH] Feat: add grain for all FQDNs + +This PR adds a grain named fqdns to the grains. +fqdns represents all the FQDNs known for the system on all available interfaces (excluding lo). + +Note: hostname != FQDN + +hostname is the UNIX name of the machine. A machine can have one and only one hostname. +FQDN is host.domain that resolves to an IP address that the machines is answering to. +A machine can have 1+ FQDNs. + +Upstream PR: +https://github.com/saltstack/salt/pull/45060 +--- + salt/grains/core.py | 27 +++++++++++++++++++++++++++ + tests/integration/modules/test_grains.py | 1 + + tests/unit/grains/test_core.py | 28 ++++++++++++++++++++++++++++ + 3 files changed, 56 insertions(+) + +diff --git a/salt/grains/core.py b/salt/grains/core.py +index a7e1a22d2a..04b73f9120 100644 +--- a/salt/grains/core.py ++++ b/salt/grains/core.py +@@ -1756,6 +1756,33 @@ def append_domain(): + return grain + + ++def fqdns(): ++ ''' ++ Return all known FQDNs for the system by enumerating all interfaces and ++ then trying to reverse resolve them (excluding 'lo' interface). ++ ''' ++ # Provides: ++ # fqdns ++ ++ grains = {} ++ fqdns = set() ++ ++ addresses = salt.utils.network.ip_addrs(include_loopback=False, ++ interface_data=_INTERFACES) ++ addresses.extend(salt.utils.network.ip_addrs6(include_loopback=False, ++ interface_data=_INTERFACES)) ++ ++ for ip in addresses: ++ try: ++ fqdns.add(socket.gethostbyaddr(ip)[0]) ++ except (socket.error, socket.herror, ++ socket.gaierror, socket.timeout) as e: ++ log.error("Exception during resolving address: " + str(e)) ++ ++ grains['fqdns'] = list(fqdns) ++ return grains ++ ++ + def ip_fqdn(): + ''' + Return ip address and FQDN grains +diff --git a/tests/integration/modules/test_grains.py b/tests/integration/modules/test_grains.py +index 7d46315e42..1db90ab532 100644 +--- a/tests/integration/modules/test_grains.py ++++ b/tests/integration/modules/test_grains.py +@@ -51,6 +51,7 @@ class TestModulesGrains(ModuleCase): + 'cpuarch', + 'domain', + 'fqdn', ++ 'fqdns', + 'gid', + 'groupname', + 'host', +diff --git a/tests/unit/grains/test_core.py b/tests/unit/grains/test_core.py +index 6ee4257863..4f1412de76 100644 +--- a/tests/unit/grains/test_core.py ++++ b/tests/unit/grains/test_core.py +@@ -6,6 +6,7 @@ + # Import Python libs + from __future__ import absolute_import + import os ++import socket + + # Import Salt Testing Libs + from tests.support.mixins import LoaderModuleMockMixin +@@ -462,3 +463,30 @@ PATCHLEVEL = 3 + self.assertEqual(os_grains.get('osrelease'), os_release_map['osrelease']) + self.assertListEqual(list(os_grains.get('osrelease_info')), os_release_map['osrelease_info']) + self.assertEqual(os_grains.get('osmajorrelease'), os_release_map['osmajorrelease']) ++ ++ @skipIf(not salt.utils.is_linux(), 'System is not Linux') ++ def test_fqdns_return(self): ++ ''' ++ test the return for a dns grain. test for issue: ++ https://github.com/saltstack/salt/issues/41230 ++ ''' ++ reverse_resolv_mock = [('foo.bar.baz', [], ['1.2.3.4']), ++ ('rinzler.evil-corp.com', [], ['5.6.7.8']), ++ ('foo.bar.baz', [], ['fe80::a8b2:93ff:fe00:0']), ++ ('bluesniff.foo.bar', [], ['fe80::a8b2:93ff:dead:beef'])] ++ ret = {'fqdns': ['rinzler.evil-corp.com', 'foo.bar.baz', 'bluesniff.foo.bar']} ++ self._run_fqdns_test(reverse_resolv_mock, ret) ++ ++ def _run_fqdns_test(self, reverse_resolv_mock, ret): ++ with patch.object(salt.utils, 'is_windows', MagicMock(return_value=False)): ++ with patch('salt.utils.network.ip_addrs', ++ MagicMock(return_value=['1.2.3.4', '5.6.7.8'])),\ ++ patch('salt.utils.network.ip_addrs6', ++ MagicMock(return_value=['fe80::a8b2:93ff:fe00:0', 'fe80::a8b2:93ff:dead:beef'])): ++ with patch.object(socket, 'gethostbyaddr', side_effect=reverse_resolv_mock): ++ fqdns = core.fqdns() ++ self.assertEqual(fqdns, ret) ++ ++if __name__ == '__main__': ++ from integration import run_tests ++ run_tests(CoreGrainsTestCase, needs_daemon=False) +-- +2.13.6 + + diff --git a/fix-bsc-1065792.patch b/fix-bsc-1065792.patch new file mode 100644 index 0000000..f4888dc --- /dev/null +++ b/fix-bsc-1065792.patch @@ -0,0 +1,25 @@ +From e6b1c05fb9e38e54ad30a540a32cd8491fee286b Mon Sep 17 00:00:00 2001 +From: Bo Maryniuk +Date: Thu, 14 Dec 2017 16:21:40 +0100 +Subject: [PATCH] Fix bsc#1065792 + +--- + salt/states/service.py | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/salt/states/service.py b/salt/states/service.py +index ff5300df6a..eaa9474f78 100644 +--- a/salt/states/service.py ++++ b/salt/states/service.py +@@ -80,6 +80,7 @@ def __virtual__(): + Only make these states available if a service provider has been detected or + assigned for this minion + ''' ++ __salt__._load_all() + if 'service.start' in __salt__: + return __virtualname__ + else: +-- +2.15.1 + + diff --git a/fix-for-delete_deployment-in-kubernetes-module.patch b/fix-for-delete_deployment-in-kubernetes-module.patch new file mode 100644 index 0000000..97f9afa --- /dev/null +++ b/fix-for-delete_deployment-in-kubernetes-module.patch @@ -0,0 +1,253 @@ +From 01c4d8875a8be8b0707b0088ccf186c4cd137448 Mon Sep 17 00:00:00 2001 +From: Jochen Breuer +Date: Wed, 23 Aug 2017 21:31:28 +0200 +Subject: [PATCH] Fix for delete_deployment in Kubernetes module + +The Kubernetes module function delete_deployment() uses +api_instance.delete_namespaced_deployment() from the Kubernetes lib. This +method from the Kubernetes lib returns immediately without giving a success +or failure indication, which lets Salt mark the job as failed even though we +don't know if it failed or not. + +To actually get a result I've implemented a polling via show_deployment() to +check if the deployment got removed. + +If a time limit is hit, we are returning with an error, otherwise it is a +success. + +Since Windows has no signal.alarm implementation, we are here falling back to +loop counting. +--- + salt/exceptions.py | 6 ++ + salt/modules/kubernetes.py | 44 +++++++++++- + tests/unit/modules/test_kubernetes.py | 126 ++++++++++++++++++++++++++++++++++ + 3 files changed, 175 insertions(+), 1 deletion(-) + create mode 100644 tests/unit/modules/test_kubernetes.py + +diff --git a/salt/exceptions.py b/salt/exceptions.py +index 256537dd77..00111df104 100644 +--- a/salt/exceptions.py ++++ b/salt/exceptions.py +@@ -265,6 +265,12 @@ class SaltCacheError(SaltException): + ''' + + ++class TimeoutError(SaltException): ++ ''' ++ Thrown when an opration cannot be completet within a given time limit. ++ ''' ++ ++ + class SaltReqTimeoutError(SaltException): + ''' + Thrown when a salt master request call fails to return within the timeout +diff --git a/salt/modules/kubernetes.py b/salt/modules/kubernetes.py +index 2e17b11444..890659c1c8 100644 +--- a/salt/modules/kubernetes.py ++++ b/salt/modules/kubernetes.py +@@ -40,11 +40,15 @@ import base64 + import logging + import yaml + import tempfile ++import signal ++from time import sleep ++from contextlib import contextmanager + + from salt.exceptions import CommandExecutionError + from salt.ext.six import iteritems + import salt.utils + import salt.utils.templates ++from salt.ext.six.moves import range # pylint: disable=import-error + + try: + import kubernetes # pylint: disable=import-self +@@ -78,6 +82,21 @@ def __virtual__(): + return False, 'python kubernetes library not found' + + ++if not salt.utils.is_windows(): ++ @contextmanager ++ def _time_limit(seconds): ++ def signal_handler(signum, frame): ++ raise TimeoutException ++ signal.signal(signal.SIGALRM, signal_handler) ++ signal.alarm(seconds) ++ try: ++ yield ++ finally: ++ signal.alarm(0) ++ ++ POLLING_TIME_LIMIT = 30 ++ ++ + # pylint: disable=no-member + def _setup_conn(**kwargs): + ''' +@@ -692,7 +711,30 @@ def delete_deployment(name, namespace='default', **kwargs): + name=name, + namespace=namespace, + body=body) +- return api_response.to_dict() ++ mutable_api_response = api_response.to_dict() ++ if not salt.utils.is_windows(): ++ try: ++ with _time_limit(POLLING_TIME_LIMIT): ++ while show_deployment(name, namespace) is not None: ++ sleep(1) ++ else: # pylint: disable=useless-else-on-loop ++ mutable_api_response['code'] = 200 ++ except TimeoutException: ++ pass ++ else: ++ # Windows has not signal.alarm implementation, so we are just falling ++ # back to loop-counting. ++ for i in range(60): ++ if show_deployment(name, namespace) is None: ++ mutable_api_response['code'] = 200 ++ break ++ else: ++ sleep(1) ++ if mutable_api_response['code'] != 200: ++ log.warning('Reached polling time limit. Deployment is not yet ' ++ 'deleted, but we are backing off. Sorry, but you\'ll ' ++ 'have to check manually.') ++ return mutable_api_response + except (ApiException, HTTPError) as exc: + if isinstance(exc, ApiException) and exc.status == 404: + return None +diff --git a/tests/unit/modules/test_kubernetes.py b/tests/unit/modules/test_kubernetes.py +new file mode 100644 +index 0000000000..493822a93c +--- /dev/null ++++ b/tests/unit/modules/test_kubernetes.py +@@ -0,0 +1,126 @@ ++# -*- coding: utf-8 -*- ++''' ++ :codeauthor: :email:`Jochen Breuer ` ++''' ++ ++# Import Python Libs ++from __future__ import absolute_import ++ ++# Import Salt Testing Libs ++from salttesting import TestCase, skipIf ++from salttesting.mock import ( ++ Mock, ++ patch, ++ NO_MOCK, ++ NO_MOCK_REASON ++) ++ ++try: ++ from salt.modules import kubernetes ++except ImportError: ++ kubernetes = False ++ ++# Globals ++kubernetes.__salt__ = dict() ++kubernetes.__grains__ = dict() ++kubernetes.__context__ = dict() ++ ++ ++@skipIf(NO_MOCK, NO_MOCK_REASON) ++@skipIf(kubernetes is False, "Probably Kubernetes client lib is not installed. \ ++ Skipping test_kubernetes.py") ++class KubernetesTestCase(TestCase): ++ ''' ++ Test cases for salt.modules.kubernetes ++ ''' ++ ++ def test_nodes(self): ++ ''' ++ Test node listing. ++ :return: ++ ''' ++ with patch('salt.modules.kubernetes.kubernetes') as mock_kubernetes_lib: ++ with patch.dict(kubernetes.__salt__, {'config.option': Mock(return_value="")}): ++ mock_kubernetes_lib.client.CoreV1Api.return_value = Mock( ++ **{"list_node.return_value.to_dict.return_value": ++ {'items': [{'metadata': {'name': 'mock_node_name'}}]}} ++ ) ++ self.assertEqual(kubernetes.nodes(), ['mock_node_name']) ++ self.assertTrue(kubernetes.kubernetes.client.CoreV1Api().list_node().to_dict.called) ++ ++ def test_deployments(self): ++ ''' ++ Tests deployment listing. ++ :return: ++ ''' ++ with patch('salt.modules.kubernetes.kubernetes') as mock_kubernetes_lib: ++ with patch.dict(kubernetes.__salt__, {'config.option': Mock(return_value="")}): ++ mock_kubernetes_lib.client.ExtensionsV1beta1Api.return_value = Mock( ++ **{"list_namespaced_deployment.return_value.to_dict.return_value": ++ {'items': [{'metadata': {'name': 'mock_deployment_name'}}]}} ++ ) ++ self.assertEqual(kubernetes.deployments(), ['mock_deployment_name']) ++ self.assertTrue( ++ kubernetes.kubernetes.client.ExtensionsV1beta1Api().list_namespaced_deployment().to_dict.called) ++ ++ def test_services(self): ++ ''' ++ Tests services listing. ++ :return: ++ ''' ++ with patch('salt.modules.kubernetes.kubernetes') as mock_kubernetes_lib: ++ with patch.dict(kubernetes.__salt__, {'config.option': Mock(return_value="")}): ++ mock_kubernetes_lib.client.CoreV1Api.return_value = Mock( ++ **{"list_namespaced_service.return_value.to_dict.return_value": ++ {'items': [{'metadata': {'name': 'mock_service_name'}}]}} ++ ) ++ self.assertEqual(kubernetes.services(), ['mock_service_name']) ++ self.assertTrue(kubernetes.kubernetes.client.CoreV1Api().list_namespaced_service().to_dict.called) ++ ++ def test_pods(self): ++ ''' ++ Tests pods listing. ++ :return: ++ ''' ++ with patch('salt.modules.kubernetes.kubernetes') as mock_kubernetes_lib: ++ with patch.dict(kubernetes.__salt__, {'config.option': Mock(return_value="")}): ++ mock_kubernetes_lib.client.CoreV1Api.return_value = Mock( ++ **{"list_namespaced_pod.return_value.to_dict.return_value": ++ {'items': [{'metadata': {'name': 'mock_pod_name'}}]}} ++ ) ++ self.assertEqual(kubernetes.pods(), ['mock_pod_name']) ++ self.assertTrue(kubernetes.kubernetes.client.CoreV1Api(). ++ list_namespaced_pod().to_dict.called) ++ ++ def test_delete_deployments(self): ++ ''' ++ Tests deployment deletion ++ :return: ++ ''' ++ with patch('salt.modules.kubernetes.kubernetes') as mock_kubernetes_lib: ++ with patch('salt.modules.kubernetes.show_deployment', Mock(return_value=None)): ++ with patch.dict(kubernetes.__salt__, {'config.option': Mock(return_value="")}): ++ mock_kubernetes_lib.client.V1DeleteOptions = Mock(return_value="") ++ mock_kubernetes_lib.client.ExtensionsV1beta1Api.return_value = Mock( ++ **{"delete_namespaced_deployment.return_value.to_dict.return_value": {'code': ''}} ++ ) ++ self.assertEqual(kubernetes.delete_deployment("test"), {'code': 200}) ++ self.assertTrue( ++ kubernetes.kubernetes.client.ExtensionsV1beta1Api(). ++ delete_namespaced_deployment().to_dict.called) ++ ++ def test_create_deployments(self): ++ ''' ++ Tests deployment creation. ++ :return: ++ ''' ++ with patch('salt.modules.kubernetes.kubernetes') as mock_kubernetes_lib: ++ with patch.dict(kubernetes.__salt__, {'config.option': Mock(return_value="")}): ++ mock_kubernetes_lib.client.ExtensionsV1beta1Api.return_value = Mock( ++ **{"create_namespaced_deployment.return_value.to_dict.return_value": {}} ++ ) ++ self.assertEqual(kubernetes.create_deployment("test", "default", {}, {}, ++ None, None, None), {}) ++ self.assertTrue( ++ kubernetes.kubernetes.client.ExtensionsV1beta1Api(). ++ create_namespaced_deployment().to_dict.called) +-- +2.15.1 + + diff --git a/fix-for-wrong-version-processing.patch b/fix-for-wrong-version-processing.patch new file mode 100644 index 0000000..7840bc3 --- /dev/null +++ b/fix-for-wrong-version-processing.patch @@ -0,0 +1,162 @@ +From 914cabfacd9c1209e3f0e7a613e8cc0d1617580b Mon Sep 17 00:00:00 2001 +From: Jochen Breuer +Date: Mon, 11 Dec 2017 09:49:10 +0100 +Subject: [PATCH] Fix for wrong version processing + +Since version and epoch seem to be split by default now, the yum pkg info +processing should have changed. + +* Fixes the version info processing for pkg installation. +* Test for installation with and without diff_attr. +--- + salt/modules/yumpkg.py | 28 +++++++++------ + tests/unit/modules/test_yumpkg.py | 72 +++++++++++++++++++++++++++++++++++++++ + 2 files changed, 90 insertions(+), 10 deletions(-) + +diff --git a/salt/modules/yumpkg.py b/salt/modules/yumpkg.py +index 8b63bff4a3..027d680bff 100644 +--- a/salt/modules/yumpkg.py ++++ b/salt/modules/yumpkg.py +@@ -588,7 +588,6 @@ def version_cmp(pkg1, pkg2, ignore_epoch=False): + + salt '*' pkg.version_cmp '0.2-001' '0.2.0.1-002' + ''' +- + return __salt__['lowpkg.version_cmp'](pkg1, pkg2, ignore_epoch=ignore_epoch) + + +@@ -1440,18 +1439,20 @@ def install(name=None, + else: + pkgstr = pkgpath + +- # Lambda to trim the epoch from the currently-installed version if +- # no epoch is specified in the specified version +- norm_epoch = lambda x, y: x.split(':', 1)[-1] \ +- if ':' not in y \ +- else x + cver = old_as_list.get(pkgname, []) + if reinstall and cver: + for ver in cver: +- ver = norm_epoch(ver, version_num) ++ if diff_attr: ++ # Since diff_attr was provided, the version info ++ # is a dict. ++ ver2 = ver['version'] ++ else: ++ # No diff_attr was provided, so version is directly ++ # in ver. ++ ver2 = ver + if salt.utils.compare_versions(ver1=version_num, + oper='==', +- ver2=ver, ++ ver2=ver2, + cmp_func=version_cmp): + # This version is already installed, so we need to + # reinstall. +@@ -1462,10 +1463,17 @@ def install(name=None, + to_install.append((pkgname, pkgstr)) + else: + for ver in cver: +- ver = norm_epoch(ver, version_num) ++ if diff_attr: ++ # Since diff_attr was provided, the version info ++ # is a dict. ++ ver2 = ver['version'] ++ else: ++ # No diff_attr was provided, so version is directly ++ # in ver. ++ ver2 = ver + if salt.utils.compare_versions(ver1=version_num, + oper='>=', +- ver2=ver, ++ ver2=ver2, + cmp_func=version_cmp): + to_install.append((pkgname, pkgstr)) + break +diff --git a/tests/unit/modules/test_yumpkg.py b/tests/unit/modules/test_yumpkg.py +index cf754d6289..c5e8d746d5 100644 +--- a/tests/unit/modules/test_yumpkg.py ++++ b/tests/unit/modules/test_yumpkg.py +@@ -27,6 +27,78 @@ class YumTestCase(TestCase, LoaderModuleMockMixin): + def setup_loader_modules(self): + return {yumpkg: {'rpm': None}} + ++ def test_install_pkg(self): ++ ''' ++ Test package installation. ++ ++ :return: ++ ''' ++ def _add_data(data, key, value): ++ data.setdefault(key, []).append(value) ++ ++ rpm_out = [ ++ 'python-urlgrabber_|-(none)_|-3.10_|-8.el7_|-noarch_|-(none)_|-1487838471', ++ 'alsa-lib_|-(none)_|-1.1.1_|-1.el7_|-x86_64_|-(none)_|-1487838475', ++ 'gnupg2_|-(none)_|-2.0.22_|-4.el7_|-x86_64_|-(none)_|-1487838477', ++ 'rpm-python_|-(none)_|-4.11.3_|-21.el7_|-x86_64_|-(none)_|-1487838477', ++ 'pygpgme_|-(none)_|-0.3_|-9.el7_|-x86_64_|-(none)_|-1487838478', ++ 'yum_|-(none)_|-3.4.3_|-150.el7.centos_|-noarch_|-(none)_|-1487838479', ++ 'lzo_|-(none)_|-2.06_|-8.el7_|-x86_64_|-(none)_|-1487838479', ++ 'qrencode-libs_|-(none)_|-3.4.1_|-3.el7_|-x86_64_|-(none)_|-1487838480', ++ 'ustr_|-(none)_|-1.0.4_|-16.el7_|-x86_64_|-(none)_|-1487838480', ++ 'shadow-utils_|-2_|-4.1.5.1_|-24.el7_|-x86_64_|-(none)_|-1487838481', ++ 'util-linux_|-(none)_|-2.23.2_|-33.el7_|-x86_64_|-(none)_|-1487838484', ++ 'openssh_|-(none)_|-6.6.1p1_|-33.el7_3_|-x86_64_|-(none)_|-1487838485', ++ 'virt-what_|-(none)_|-1.13_|-8.el7_|-x86_64_|-(none)_|-1487838486', ++ ] ++ with patch.dict(yumpkg.__grains__, {'osarch': 'x86_64', 'os': 'RedHat'}), \ ++ patch.dict(yumpkg.__salt__, {'cmd.run': MagicMock(return_value=os.linesep.join(rpm_out))}), \ ++ patch.dict(yumpkg.__salt__, {'cmd.run_all': MagicMock(return_value={'retcode': 0})}), \ ++ patch.dict(yumpkg.__salt__, {'pkg_resource.add_pkg': _add_data}), \ ++ patch.dict(yumpkg.__salt__, {'pkg_resource.parse_targets': MagicMock(return_value=({'python-urlgrabber': '0.0.1'} , 'repository'))}), \ ++ patch.dict(yumpkg.__salt__, {'pkg_resource.format_pkg_list': pkg_resource.format_pkg_list}), \ ++ patch.dict(yumpkg.__salt__, {'config.get': MagicMock()}), \ ++ patch.dict(yumpkg.__salt__, {'lowpkg.version_cmp': MagicMock(return_value=-1)}): ++ pkgs = yumpkg.install(name='python-urlgrabber') ++ self.assertEqual(pkgs, {}) ++ ++ ++ def test_install_pkg_with_diff_attr(self): ++ ''' ++ Test package installation with diff_attr. ++ ++ :return: ++ ''' ++ def _add_data(data, key, value): ++ data.setdefault(key, []).append(value) ++ ++ rpm_out = [ ++ 'python-urlgrabber_|-(none)_|-3.10_|-8.el7_|-noarch_|-(none)_|-1487838471', ++ 'alsa-lib_|-(none)_|-1.1.1_|-1.el7_|-x86_64_|-(none)_|-1487838475', ++ 'gnupg2_|-(none)_|-2.0.22_|-4.el7_|-x86_64_|-(none)_|-1487838477', ++ 'rpm-python_|-(none)_|-4.11.3_|-21.el7_|-x86_64_|-(none)_|-1487838477', ++ 'pygpgme_|-(none)_|-0.3_|-9.el7_|-x86_64_|-(none)_|-1487838478', ++ 'yum_|-(none)_|-3.4.3_|-150.el7.centos_|-noarch_|-(none)_|-1487838479', ++ 'lzo_|-(none)_|-2.06_|-8.el7_|-x86_64_|-(none)_|-1487838479', ++ 'qrencode-libs_|-(none)_|-3.4.1_|-3.el7_|-x86_64_|-(none)_|-1487838480', ++ 'ustr_|-(none)_|-1.0.4_|-16.el7_|-x86_64_|-(none)_|-1487838480', ++ 'shadow-utils_|-2_|-4.1.5.1_|-24.el7_|-x86_64_|-(none)_|-1487838481', ++ 'util-linux_|-(none)_|-2.23.2_|-33.el7_|-x86_64_|-(none)_|-1487838484', ++ 'openssh_|-(none)_|-6.6.1p1_|-33.el7_3_|-x86_64_|-(none)_|-1487838485', ++ 'virt-what_|-(none)_|-1.13_|-8.el7_|-x86_64_|-(none)_|-1487838486', ++ ] ++ with patch.dict(yumpkg.__grains__, {'osarch': 'x86_64', 'os': 'RedHat'}), \ ++ patch.dict(yumpkg.__salt__, {'cmd.run': MagicMock(return_value=os.linesep.join(rpm_out))}), \ ++ patch.dict(yumpkg.__salt__, {'cmd.run_all': MagicMock(return_value={'retcode': 0})}), \ ++ patch.dict(yumpkg.__salt__, {'pkg_resource.add_pkg': _add_data}), \ ++ patch.dict(yumpkg.__salt__, {'pkg_resource.parse_targets': MagicMock(return_value=({'python-urlgrabber': '0.0.1'} , 'repository'))}), \ ++ patch.dict(yumpkg.__salt__, {'pkg_resource.format_pkg_list': pkg_resource.format_pkg_list}), \ ++ patch.dict(yumpkg.__salt__, {'config.get': MagicMock()}), \ ++ patch.dict(yumpkg.__salt__, {'lowpkg.version_cmp': MagicMock(return_value=-1)}): ++ pkgs = yumpkg.install(name='python-urlgrabber', diff_attr=['version', 'epoch', 'release', 'arch']) ++ self.assertEqual(pkgs, {}) ++ ++ + def test_list_pkgs(self): + ''' + Test packages listing. +-- +2.15.1 + + diff --git a/fix-salt-master-for-old-psutil.patch b/fix-salt-master-for-old-psutil.patch new file mode 100644 index 0000000..0951685 --- /dev/null +++ b/fix-salt-master-for-old-psutil.patch @@ -0,0 +1,26 @@ +From e9635560f2b0a213518c5023e0b6fb4a11e5570d Mon Sep 17 00:00:00 2001 +From: Mihai Dinca +Date: Fri, 8 Dec 2017 13:34:06 +0100 +Subject: [PATCH] Fix salt-master for old psutil + +--- + salt/utils/psutil_compat.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/salt/utils/psutil_compat.py b/salt/utils/psutil_compat.py +index a32712860a..dee563455b 100644 +--- a/salt/utils/psutil_compat.py ++++ b/salt/utils/psutil_compat.py +@@ -26,7 +26,7 @@ else: + # Psuedo "from psutil import *" + _globals = globals() + for attr in psutil.__all__: +- _temp = __import__('psutil', globals(), locals(), [attr], -1) ++ _temp = __import__('psutil', globals(), locals(), [attr], -1 if six.PY2 else 0) + try: + _globals[attr] = getattr(_temp, attr) + except AttributeError: +-- +2.15.1 + + diff --git a/html.tar.bz2 b/html.tar.bz2 index f5421d4..e7d375f 100644 --- a/html.tar.bz2 +++ b/html.tar.bz2 @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4033a19f562875d4124d5f18fffb485cbbb1a256996b4a8019ac4f32064657be -size 6413238 +oid sha256:6b82846ed4005af7655290cd9bdc62c1d4912d4809acaca2ff37ebff0960b18c +size 1250836 diff --git a/introduce-process_count_max-minion-configuration-par.patch b/introduce-process_count_max-minion-configuration-par.patch index 8c500c9..22e1657 100644 --- a/introduce-process_count_max-minion-configuration-par.patch +++ b/introduce-process_count_max-minion-configuration-par.patch @@ -1,7 +1,7 @@ From cb472e1f0fc18a554e0de9e3fe6bbe16557957ee Mon Sep 17 00:00:00 2001 From: Silvio Moioli Date: Wed, 20 Sep 2017 14:33:33 +0200 -Subject: [PATCH 4/6] Introduce process_count_max minion configuration +Subject: [PATCH] Introduce process_count_max minion configuration parameter This allows users to limit the number of processes or threads a minion @@ -206,5 +206,6 @@ index 535dfeedfc..6c9dca13cd 100644 + finally: + minion.destroy() -- -2.14.2 +2.15.1 + diff --git a/list_pkgs-add-parameter-for-returned-attribute-selec.patch b/list_pkgs-add-parameter-for-returned-attribute-selec.patch index bd43879..96707a5 100644 --- a/list_pkgs-add-parameter-for-returned-attribute-selec.patch +++ b/list_pkgs-add-parameter-for-returned-attribute-selec.patch @@ -1,8 +1,8 @@ From ca7031e5223bb3bd35c31211d29177f05ed5e304 Mon Sep 17 00:00:00 2001 From: Silvio Moioli Date: Thu, 13 Jul 2017 15:59:01 +0200 -Subject: [PATCH 1/6] list_pkgs: add parameter for returned attribute selection - (bsc#1052264) +Subject: [PATCH] list_pkgs: add parameter for returned attribute + selection (bsc#1052264) zypper.list_pkgs: * It adds a new optional parameter to list_pkg in the zypper module to return more data than the version (original reason is that for SUSE Manager integration we also need arch and install_date). Format is the same of existing method info_installed. @@ -787,5 +787,6 @@ index f3403e6e1c..41f3845646 100644 def test_list_patches(self): ''' -- -2.14.2 +2.15.1 + diff --git a/multiprocessing-minion-option-documentation-fixes.patch b/multiprocessing-minion-option-documentation-fixes.patch index 0ef47a2..2990dbb 100644 --- a/multiprocessing-minion-option-documentation-fixes.patch +++ b/multiprocessing-minion-option-documentation-fixes.patch @@ -1,7 +1,7 @@ From 461654496d36a264903057a8255aec4eb700e506 Mon Sep 17 00:00:00 2001 From: Silvio Moioli Date: Wed, 20 Sep 2017 14:32:47 +0200 -Subject: [PATCH 3/6] multiprocessing minion option: documentation fixes +Subject: [PATCH] multiprocessing minion option: documentation fixes --- doc/man/salt.7 | 1 + @@ -42,5 +42,6 @@ index e0f349931c..5c92b932ab 100644 -- -2.14.2 +2.15.1 + diff --git a/older-logrotate-need-su-directive.patch b/older-logrotate-need-su-directive.patch new file mode 100644 index 0000000..db3105c --- /dev/null +++ b/older-logrotate-need-su-directive.patch @@ -0,0 +1,25 @@ +From d68365a35dd00cced7cdc6eff2ad8a3b823c26f6 Mon Sep 17 00:00:00 2001 +From: Michael Calmer +Date: Thu, 7 Dec 2017 17:30:31 +0100 +Subject: [PATCH] older logrotate need su directive + +--- + pkg/suse/salt-common.logrotate | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/pkg/suse/salt-common.logrotate b/pkg/suse/salt-common.logrotate +index 0d99d1b801..625670942c 100644 +--- a/pkg/suse/salt-common.logrotate ++++ b/pkg/suse/salt-common.logrotate +@@ -8,6 +8,7 @@ + } + + /var/log/salt/minion { ++ su root root + weekly + missingok + rotate 7 +-- +2.15.1 + + diff --git a/python3-compatibility-fix-got-bytes-instead-of-strin.patch b/python3-compatibility-fix-got-bytes-instead-of-strin.patch new file mode 100644 index 0000000..73ebae6 --- /dev/null +++ b/python3-compatibility-fix-got-bytes-instead-of-strin.patch @@ -0,0 +1,25 @@ +From d21ea1062f1cd8da0e604288b369c7ff38919c78 Mon Sep 17 00:00:00 2001 +From: Michael Calmer +Date: Tue, 19 Dec 2017 17:07:19 +0100 +Subject: [PATCH] python3 compatibility fix - got bytes instead of string + +--- + salt/netapi/rest_cherrypy/tools/websockets.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/salt/netapi/rest_cherrypy/tools/websockets.py b/salt/netapi/rest_cherrypy/tools/websockets.py +index fe4f9def85..44c5e2fa05 100644 +--- a/salt/netapi/rest_cherrypy/tools/websockets.py ++++ b/salt/netapi/rest_cherrypy/tools/websockets.py +@@ -54,6 +54,6 @@ class SynchronizingWebsocket(WebSocket): + This ensures completion of the underlying websocket connection + and can be used to synchronize parallel senders. + ''' +- if message.data == 'websocket client ready': ++ if message.data.decode('utf-8') == 'websocket client ready': + self.pipe.send(message) + self.send('server received message', False) +-- +2.13.6 + + diff --git a/return-error-when-gid_from_name-and-group-does-not-e.patch b/return-error-when-gid_from_name-and-group-does-not-e.patch new file mode 100644 index 0000000..410f3e9 --- /dev/null +++ b/return-error-when-gid_from_name-and-group-does-not-e.patch @@ -0,0 +1,123 @@ +From 5384cb815764af43f287bcb6ed49a9a68d5cd5c0 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?= + +Date: Wed, 10 Jan 2018 11:59:33 +0000 +Subject: [PATCH] Return error when gid_from_name and group does not + exist. + +Fixes #45345 + +Ensure empty string gid is set to None + +Make pylint happy + +Fix integration tests for 'user.present' state. + +Update documentation for 'gid_from_name' parameter + +Refactor to prevent logical bug when gid is 0 +--- + salt/states/user.py | 7 +++++- + tests/integration/states/test_user.py | 42 +++++++++++++++++++++++------------ + 2 files changed, 34 insertions(+), 15 deletions(-) + +diff --git a/salt/states/user.py b/salt/states/user.py +index 8a731cc2a1..737c39f4b4 100644 +--- a/salt/states/user.py ++++ b/salt/states/user.py +@@ -240,7 +240,8 @@ def present(name, + + gid_from_name + If True, the default group id will be set to the id of the group with +- the same name as the user, Default is ``False``. ++ the same name as the user. If the group does not exist the state will ++ fail. Default is ``False``. + + groups + A list of groups to assign the user to, pass a list object. If a group +@@ -455,6 +456,10 @@ def present(name, + + if gid_from_name: + gid = __salt__['file.group_to_gid'](name) ++ if gid == '': ++ ret['comment'] = 'Default group with name "{0}" is not present'.format(name) ++ ret['result'] = False ++ return ret + + changes = _changes(name, + uid, +diff --git a/tests/integration/states/test_user.py b/tests/integration/states/test_user.py +index 1317f12f97..ae9774a241 100644 +--- a/tests/integration/states/test_user.py ++++ b/tests/integration/states/test_user.py +@@ -97,15 +97,25 @@ class UserTest(ModuleCase, SaltReturnAssertsMixin): + home=HOMEDIR) + self.assertSaltTrueReturn(ret) + +- def test_user_present_nondefault(self): ++ @requires_system_grains ++ def test_user_present_nondefault(self, grains=None): + ''' + This is a DESTRUCTIVE TEST it creates a new user on the on the minion. + ''' + ret = self.run_state('user.present', name=self.user_name, + home=self.user_home) + self.assertSaltTrueReturn(ret) ++ ret = self.run_function('user.info', [self.user_name]) ++ self.assertReturnNonEmptySaltType(ret) ++ group_name = grp.getgrgid(ret['gid']).gr_name + if not salt.utils.is_darwin(): + self.assertTrue(os.path.isdir(self.user_home)) ++ if grains['os_family'] in ('Suse',): ++ self.assertEqual(group_name, 'users') ++ elif grains['os_family'] == 'MacOS': ++ self.assertEqual(group_name, 'staff') ++ else: ++ self.assertEqual(group_name, self.user_name) + + @requires_system_grains + def test_user_present_gid_from_name_default(self, grains=None): +@@ -120,22 +130,26 @@ class UserTest(ModuleCase, SaltReturnAssertsMixin): + # user + gid_from_name = False if grains['os_family'] == 'MacOS' else True + +- ret = self.run_state('user.present', name=self.user_name, ++ ret_user_present = self.run_state('user.present', name=self.user_name, + gid_from_name=gid_from_name, home=self.user_home) +- self.assertSaltTrueReturn(ret) + +- ret = self.run_function('user.info', [self.user_name]) +- self.assertReturnNonEmptySaltType(ret) +- group_name = grp.getgrgid(ret['gid']).gr_name +- +- if not salt.utils.is_darwin(): +- self.assertTrue(os.path.isdir(self.user_home)) +- if grains['os_family'] in ('Suse',): +- self.assertEqual(group_name, 'users') +- elif grains['os_family'] == 'MacOS': +- self.assertEqual(group_name, 'staff') ++ if gid_from_name: ++ self.assertSaltFalseReturn(ret_user_present) ++ ret_user_present = ret_user_present[next(iter(ret_user_present))] ++ self.assertTrue('is not present' in ret_user_present['comment']) + else: +- self.assertEqual(group_name, self.user_name) ++ self.assertSaltTrueReturn(ret_user_present) ++ ret_user_info = self.run_function('user.info', [self.user_name]) ++ self.assertReturnNonEmptySaltType(ret_user_info) ++ group_name = grp.getgrgid(ret_user_info['gid']).gr_name ++ if not salt.utils.is_darwin(): ++ self.assertTrue(os.path.isdir(self.user_home)) ++ if grains['os_family'] in ('Suse',): ++ self.assertEqual(group_name, 'users') ++ elif grains['os_family'] == 'MacOS': ++ self.assertEqual(group_name, 'staff') ++ else: ++ self.assertEqual(group_name, self.user_name) + + def test_user_present_gid_from_name(self): + ''' +-- +2.15.1 + + diff --git a/run-salt-api-as-user-salt-bsc-1064520.patch b/run-salt-api-as-user-salt-bsc-1064520.patch index 959a81d..0cc5bde 100644 --- a/run-salt-api-as-user-salt-bsc-1064520.patch +++ b/run-salt-api-as-user-salt-bsc-1064520.patch @@ -1,7 +1,7 @@ From 8f81bee8d8929cc4cd30dabc7cbc92d2cba9760e Mon Sep 17 00:00:00 2001 From: Christian Lanig Date: Mon, 27 Nov 2017 13:10:26 +0100 -Subject: [PATCH 2/2] Run salt-api as user salt (bsc#1064520) +Subject: [PATCH] Run salt-api as user salt (bsc#1064520) --- pkg/salt-api.service | 1 + @@ -20,5 +20,6 @@ index 7ca582dfb4..bf513e4dbd 100644 ExecStart=/usr/bin/salt-api TimeoutStopSec=3 -- -2.14.2 +2.15.1 + diff --git a/run-salt-master-as-dedicated-salt-user.patch b/run-salt-master-as-dedicated-salt-user.patch index e6e11e7..65da8fe 100644 --- a/run-salt-master-as-dedicated-salt-user.patch +++ b/run-salt-master-as-dedicated-salt-user.patch @@ -1,7 +1,7 @@ From 3902fe4183d169808b9d248b9b963926035ba954 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Klaus=20K=C3=A4mpf?= Date: Wed, 20 Jan 2016 11:01:06 +0100 -Subject: [PATCH 1/2] Run salt master as dedicated salt user +Subject: [PATCH] Run salt master as dedicated salt user * Minion runs always as a root --- @@ -42,5 +42,6 @@ index 3cd002308e..0d99d1b801 100644 missingok rotate 7 -- -2.14.2 +2.15.1 + diff --git a/salt-2017.7.2.tar.gz b/salt-2017.7.2.tar.gz deleted file mode 100644 index 11d023e..0000000 --- a/salt-2017.7.2.tar.gz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:ff3bc7de5abf01b8acbd144db5811b00867179b2353f5c6f7f19241e2eff2840 -size 11471191 diff --git a/salt.changes b/salt.changes index 1bad4b1..7fdfb14 100644 --- a/salt.changes +++ b/salt.changes @@ -1,3 +1,127 @@ +------------------------------------------------------------------- +Thu Jan 25 13:04:24 UTC 2018 - pablo.suarezhernandez@suse.com + +- Fix the usage of custom macros on the spec file. + +------------------------------------------------------------------- +Thu Jan 25 10:49:53 UTC 2018 - bmaryniuk@suse.com + +- Fix RES7: different dependency names for python-PyYAML + and python-MarkupSafe + +------------------------------------------------------------------- +Wed Jan 24 15:04:42 UTC 2018 - bmaryniuk@suse.com + +- Build both python2 and python3 binaries together. + +------------------------------------------------------------------- +Wed Jan 17 11:26:54 UTC 2018 - pablo.suarezhernandez@suse.com + +- Bugfix: errors in external pillar causes crash instead of report + of them (bsc#1068446) +- Fix 'user.present' when 'gid_from_name' is set but group does + not exist. + +- Added: + * bugfix-the-logic-according-to-the-exact-described-pu.patch + * return-error-when-gid_from_name-and-group-does-not-e.patch + +------------------------------------------------------------------- +Thu Jan 11 15:57:11 UTC 2018 - jrenner@suse.com + +- Fix "No service execution module loaded" issue (bsc#1065792) +- Set SHELL environment variable + + Added: + * fix-bsc-1065792.patch + * set-shell-environment-variable-64.patch + +------------------------------------------------------------------- +Fri Jan 05 15:24:30 UTC 2018 - jbreuer@suse.de + +- Removed unnecessary logging on shutdown (bsc#1050003) +- Renamed patch that adds grain fqdns + + Changed: + * catching-error-when-pidfile-cannot-be-deleted + + Removed: + * fix-for-pidfile-removal-logging + + Renamed: + * add-fqdns-grains -> feat-add-grain-for-all-fqdns + +------------------------------------------------------------------- +Thu Dec 28 10:37:10 UTC 2017 - michele.bologna@suse.com + +- Add fqdns to grains (bsc#1063419) + Added: + * add-fqdns-grains.patch + +------------------------------------------------------------------- +Tue Dec 19 16:15:14 UTC 2017 - mc@suse.com + +- Fixing cherrypy websocket with python3 + Added: + * python3-compatibility-fix-got-bytes-instead-of-strin.patch + +------------------------------------------------------------------- +Mon Dec 18 15:28:26 UTC 2017 - mihai.dinca@suse.com + +- Various-bug-fixes +- Python3 bugfix for cherrypy read() +- Fix for logging on salt-master exit in rare cases (pid-file removal) +- Added: + * cherrypy-read-reads-bytes-from-the-wire-and-write-th.patch + * fix-for-pidfile-removal-logging.patch + * split-only-strings-if-they-are-such.patch + +------------------------------------------------------------------- +Thu Dec 14 09:18:02 UTC 2017 - mihai.dinca@suse.com + +- Fix salt-master for old psutil version +- Added: + * fix-salt-master-for-old-psutil.patch + +------------------------------------------------------------------- +Wed Dec 13 16:23:38 UTC 2017 - mihai.dinca@suse.com + +- Put back accidentally removed patches +- Added: + * avoid-excessive-syslogging-by-watchdog-cronjob-58.patch + * catching-error-when-pidfile-cannot-be-deleted.patch + +------------------------------------------------------------------- +Wed Dec 13 16:22:25 UTC 2017 - mihai.dinca@suse.com + +- Fix for delete_deployment in Kubernetes module (bsc#1059291) + +- Added: + * fix-for-delete_deployment-in-kubernetes-module.patch + +------------------------------------------------------------------- +Wed Dec 13 16:15:53 UTC 2017 - mihai.dinca@suse.com + +- Older logrotate need su directive + * Added: + older-logrotate-need-su-directive.patch + +------------------------------------------------------------------- +Wed Dec 13 16:10:32 UTC 2017 - mihai.dinca@suse.com + +- Fix bsc#1041993 already included in 2017.7.2 +- Removed: + * removes-beacon-configuration-deprecation-warning-48.patch + +------------------------------------------------------------------- +Wed Dec 13 16:09:41 UTC 2017 - mihai.dinca@suse.com + +- Fixed beacons failure when pillar-based suppressing config-based. + (bsc#1060230) + +- Added: + * activate-all-beacons-sources-config-pillar-grains.patch + ------------------------------------------------------------------- Thu Dec 7 11:19:12 UTC 2017 - dimstar@opensuse.org diff --git a/salt.spec b/salt.spec index 7acd1cf..0269c7c 100644 --- a/salt.spec +++ b/salt.spec @@ -15,6 +15,22 @@ # Please submit bugfixes or comments via http://bugs.opensuse.org/ # +%if 0%{?suse_version} >= 1320 +# SLE15 +%global build_py3 1 +%global build_py2 1 +%global default_py3 1 +%else +%if 0%{?suse_version} == 1315 +# SLE12 +%global build_py3 1 +%global build_py2 1 +%else +# RES7 +%global build_py2 1 +%endif +%endif +%define pythonX %{?default_py3: python3}%{!?default_py3: python2} %if 0%{?suse_version} > 1210 || 0%{?rhel} >= 7 || 0%{?fedora} %bcond_without systemd @@ -42,26 +58,196 @@ Summary: A parallel remote execution system License: Apache-2.0 Group: System/Management Url: http://saltstack.org/ -# Git: https://github.com/openSUSE/salt.git -Source0: salt-2017.7.2.tar.gz +Source: https://github.com/saltstack/salt/archive/v%{version}.tar.gz Source1: README.SUSE Source2: salt-tmpfiles.d Source3: html.tar.bz2 Source4: update-documentation.sh Source5: travis.yml -Source6: zyppnotify -Patch1: list_pkgs-add-parameter-for-returned-attribute-selec.patch -Patch2: use-home-to-get-the-user-home-directory-instead-usin.patch -Patch3: multiprocessing-minion-option-documentation-fixes.patch -Patch4: introduce-process_count_max-minion-configuration-par.patch -Patch5: bugfix-always-return-a-string-list-on-unknown-job-ta.patch -Patch6: enable-with-salt-version-parameter-for-setup.py-scri.patch -Patch7: run-salt-master-as-dedicated-salt-user.patch -Patch8: run-salt-api-as-user-salt-bsc-1064520.patch +Patch1: list_pkgs-add-parameter-for-returned-attribute-selec.patch +Patch2: use-home-to-get-the-user-home-directory-instead-usin.patch +Patch3: multiprocessing-minion-option-documentation-fixes.patch +Patch4: introduce-process_count_max-minion-configuration-par.patch +Patch5: bugfix-always-return-a-string-list-on-unknown-job-ta.patch +Patch6: enable-with-salt-version-parameter-for-setup.py-scri.patch +Patch7: run-salt-master-as-dedicated-salt-user.patch +Patch8: run-salt-api-as-user-salt-bsc-1064520.patch +Patch9: activate-all-beacons-sources-config-pillar-grains.patch +Patch10: fix-for-delete_deployment-in-kubernetes-module.patch +Patch11: catching-error-when-pidfile-cannot-be-deleted.patch +Patch12: avoid-excessive-syslogging-by-watchdog-cronjob-58.patch +Patch13: fix-for-wrong-version-processing.patch +Patch14: older-logrotate-need-su-directive.patch +Patch15: fix-salt-master-for-old-psutil.patch +Patch16: split-only-strings-if-they-are-such.patch +Patch17: cherrypy-read-reads-bytes-from-the-wire-and-write-th.patch +Patch19: python3-compatibility-fix-got-bytes-instead-of-strin.patch +Patch20: feat-add-grain-for-all-fqdns.patch +Patch21: fix-bsc-1065792.patch +Patch22: set-shell-environment-variable-64.patch +Patch23: bugfix-the-logic-according-to-the-exact-described-pu.patch +Patch24: return-error-when-gid_from_name-and-group-does-not-e.patch BuildRoot: %{_tmppath}/%{name}-%{version}-build BuildRequires: logrotate +%if 0%{?suse_version} > 1020 +BuildRequires: fdupes +%endif + +Requires: %{pythonX}-%{name} = %{version}-%{release} + +Requires(pre): %{_sbindir}/groupadd +Requires(pre): %{_sbindir}/useradd + +%if 0%{?suse_version} +Requires(pre): %fillup_prereq +Requires(pre): pwdutils +%endif + +%if 0%{?suse_version} +Requires(pre): dbus-1 +%else +Requires(pre): dbus +%endif + +Requires: logrotate +Requires: procps + +%if %{with systemd} +BuildRequires: systemd +%{?systemd_requires} +%else +%if 0%{?suse_version} +Requires(pre): %insserv_prereq +%endif +%endif + +%if %{with fish_completion} +%define fish_dir %{_datadir}/fish/ +%define fish_completions_dir %{_datadir}/fish/completions/ +%endif + +%if %{with bash_completion} +%if 0%{?suse_version} >= 1140 +BuildRequires: bash-completion +%else +BuildRequires: bash +%endif +%endif + +%if %{with zsh_completion} +BuildRequires: zsh +%endif + +%if 0%{?rhel} +BuildRequires: yum +%endif + +%description +Salt is a distributed remote execution system used to execute commands and +query data. It was developed in order to bring the best solutions found in +the world of remote execution together and make them better, faster and more +malleable. Salt accomplishes this via its ability to handle larger loads of +information, and not just dozens, but hundreds or even thousands of individual +servers, handle them quickly and through a simple and manageable interface. + +%if 0%{?build_py2} +%package -n python2-salt +Summary: python2 library for salt +Group: System/Management +Requires: %{name} = %{version}-%{release} +BuildRequires: python >= 2.7 +BuildRequires: python-devel >= 2.7 +# requirements/base.txt +%if 0%{?rhel} +BuildRequires: python-jinja2 +BuildRequires: python-yaml +BuildRequires: python-markupsafe +%else +BuildRequires: python-Jinja2 +BuildRequires: python-PyYAML +BuildRequires: python-MarkupSafe +%endif + +BuildRequires: python-futures >= 2.0 +BuildRequires: python-msgpack-python > 0.3 +BuildRequires: python-psutil +BuildRequires: python-requests >= 1.0.0 +BuildRequires: python-tornado >= 4.2.1 + +# requirements/zeromq.txt +BuildRequires: python-pycrypto >= 2.6.1 +BuildRequires: python-pyzmq >= 2.2.0 +%if %{with test} +# requirements/dev_python27.txt +BuildRequires: python-boto >= 2.32.1 +BuildRequires: python-mock +BuildRequires: python-moto >= 0.3.6 +BuildRequires: python-pip +BuildRequires: python-salt-testing >= 2015.2.16 +BuildRequires: python-unittest2 +BuildRequires: python-xml +%endif +%if %{with builddocs} +BuildRequires: python-sphinx +%endif +Requires: python >= 2.7 +# +%if ! 0%{?suse_version} > 1110 +Requires: python-certifi +%endif +# requirements/base.txt +%if 0%{?rhel} +Requires: python-jinja2 +Requires: python-yaml +Requires: python-markupsafe +Requires: yum +%if 0%{?rhel} == 6 +Requires: yum-plugin-security +%endif +%else +Requires: python-Jinja2 +Requires: python-PyYAML +Requires: python-MarkupSafe +%endif + +Requires: python-futures >= 2.0 +Requires: python-msgpack-python > 0.3 +Requires: python-psutil +Requires: python-requests >= 1.0.0 +Requires: python-tornado >= 4.2.1 +%if 0%{?suse_version} +# required for zypper.py +Requires: rpm-python +Requires(pre): libzypp(plugin:system) >= 0 +Requires: zypp-plugin-python +# requirements/opt.txt (not all) +# Suggests: python-MySQL-python ## Disabled for now, originally Recommended +Suggests: python-timelib +Suggests: python-gnupg +# requirements/zeromq.txt +%endif +Requires: python-pycrypto >= 2.6.1 +Requires: python-pyzmq >= 2.2.0 +# +%if 0%{?suse_version} +# python-xml is part of python-base in all rhel versions +Requires: python-xml +Suggests: python-Mako +Recommends: python-netaddr +%endif + +%description -n python2-salt +Python2 specific files for salt + +%endif + +%if 0%{?build_py3} +%package -n python3-salt +Summary: python3 library for salt +Group: System/Management +Requires: %{name} = %{version}-%{release} BuildRequires: python-rpm-macros BuildRequires: python3 BuildRequires: python3-devel @@ -94,26 +280,6 @@ BuildRequires: python3-xml %if %{with builddocs} BuildRequires: python3-sphinx %endif -%if 0%{?suse_version} > 1020 -BuildRequires: fdupes -%endif - -Requires(pre): %{_sbindir}/groupadd -Requires(pre): %{_sbindir}/useradd - -%if 0%{?suse_version} -Requires(pre): %fillup_prereq -Requires(pre): pwdutils -%endif - -%if 0%{?suse_version} -Requires(pre): dbus-1 -%else -Requires(pre): dbus -%endif - -Requires: logrotate -Requires: procps Requires: python3 # %if ! 0%{?suse_version} > 1110 @@ -156,50 +322,21 @@ Suggests: python3-Mako Recommends: python3-netaddr %endif -%if %{with systemd} -BuildRequires: systemd -%{?systemd_requires} -%else -%if 0%{?suse_version} -Requires(pre): %insserv_prereq -%endif -%endif +%description -n python3-salt +Python3 specific files for salt -%if %{with fish_completion} -%define fish_dir %{_datadir}/fish/ -%define fish_completions_dir %{_datadir}/fish/completions/ %endif -%if %{with bash_completion} -%if 0%{?suse_version} >= 1140 -BuildRequires: bash-completion -%else -BuildRequires: bash -%endif -%endif - -%if %{with zsh_completion} -BuildRequires: zsh -%endif - -%if 0%{?rhel} -BuildRequires: yum -%endif - -%description -Salt is a distributed remote execution system used to execute commands and -query data. It was developed in order to bring the best solutions found in -the world of remote execution together and make them better, faster and more -malleable. Salt accomplishes this via its ability to handle larger loads of -information, and not just dozens, but hundreds or even thousands of individual -servers, handle them quickly and through a simple and manageable interface. - %package api Summary: The api for Salt a parallel remote execution system Group: System/Management Requires: %{name} = %{version}-%{release} Requires: %{name}-master = %{version}-%{release} +%if 0%{?default_py3} Requires: python3-CherryPy >= 3.2.2 +%else +Requires: python-CherryPy >= 3.2.2 +%endif %description api salt-api is a modular interface on top of Salt that can provide a variety of entry points into a running Salt system. @@ -397,7 +534,6 @@ Zsh command line completion support for %{name}. %setup -q -n salt-%{version} cp %{S:1} . cp %{S:5} ./.travis.yml -cp %{S:6} ./zyppnotify %patch1 -p1 %patch2 -p1 %patch3 -p1 @@ -406,10 +542,33 @@ cp %{S:6} ./zyppnotify %patch6 -p1 %patch7 -p1 %patch8 -p1 +%patch9 -p1 +%patch10 -p1 +%patch11 -p1 +%patch12 -p1 +%patch13 -p1 +%patch14 -p1 +%patch15 -p1 +%patch16 -p1 +%patch17 -p1 +%patch19 -p1 +%patch20 -p1 +%patch21 -p1 +%patch22 -p1 +%patch23 -p1 +%patch24 -p1 %build +%if 0%{?build_py2} +%{__python} setup.py --with-salt-version=%{version} --salt-transport=both build +cp ./build/lib/salt/_version.py ./salt +mv build _build.python2 +%endif +%if 0%{?build_py3} %{__python3} setup.py --with-salt-version=%{version} --salt-transport=both build cp ./build/lib/salt/_version.py ./salt +mv build _build.python3 +%endif %if %{with docs} && %{without builddocs} # extract docs from the tarball @@ -425,7 +584,28 @@ cd doc && make html && rm _build/html/.buildinfo && rm _build/html/_images/proxy %endif %install +%if 0%{?build_py2} +mv _build.python2 build +%{__python} setup.py --salt-transport=both install --prefix=%{_prefix} --root=%{buildroot} +mv build _build.python2 +%endif +%if 0%{?build_py3} +mv _build.python3 build %{__python3} setup.py --salt-transport=both install --prefix=%{_prefix} --root=%{buildroot} +mv build _build.python3 +%endif + +%if 0%{?default_py3} +DEF_PYPATH=_build.python3/scripts-*/ +%else +DEF_PYPATH=_build.python2/scripts-*/ +%endif + +rm -f %{buildroot}%{_bindir}/* +for script in $DEF_PYPATH/*; do + install -m 0755 $script %{buildroot}%{_bindir} +done + ## create missing directories install -Dd -m 0750 %{buildroot}%{_sysconfdir}/salt/master.d install -Dd -m 0750 %{buildroot}%{_sysconfdir}/salt/minion.d @@ -468,24 +648,24 @@ install -Dd -m 0750 %{buildroot}%{_sysconfdir}/salt/pki/minion ## Install Zypper plugins only on SUSE machines %if 0%{?suse_version} install -Dd -m 0750 %{buildroot}%{_prefix}/lib/zypp/plugins/commit -%{__install} zyppnotify %{buildroot}%{_prefix}/lib/zypp/plugins/commit/zyppnotify +%{__install} scripts/suse/zypper/plugins/commit/zyppnotify %{buildroot}%{_prefix}/lib/zypp/plugins/commit/zyppnotify %endif # Install Yum plugins only on RH machines %if 0%{?fedora} || 0%{?rhel} install -Dd %{buildroot}%{_prefix}/share/yum-plugins install -Dd %{buildroot}/etc/yum/pluginconf.d -%{__install} scripts/yum/plugins/yumnotify.py %{buildroot}%{_prefix}/share/yum-plugins -%{__install} scripts/yum/plugins/yumnotify.conf %{buildroot}/etc/yum/pluginconf.d +%{__install} scripts/suse/yum/plugins/yumnotify.py %{buildroot}%{_prefix}/share/yum-plugins +%{__install} scripts/suse/yum/plugins/yumnotify.conf %{buildroot}/etc/yum/pluginconf.d %endif ## install init and systemd scripts %if %{with systemd} -install -Dpm 0644 pkg/salt-master.service %{buildroot}%{_unitdir}/salt-master.service +install -Dpm 0644 pkg/suse/salt-master.service %{buildroot}%{_unitdir}/salt-master.service %if 0%{?suse_version} install -Dpm 0644 pkg/suse/salt-minion.service %{buildroot}%{_unitdir}/salt-minion.service %else -install -Dpm 0644 pkg/salt-minion.service.rhel7 %{buildroot}%{_unitdir}/salt-minion.service +install -Dpm 0644 pkg/suse/salt-minion.service.rhel7 %{buildroot}%{_unitdir}/salt-minion.service %endif install -Dpm 0644 pkg/salt-syndic.service %{buildroot}%{_unitdir}/salt-syndic.service install -Dpm 0644 pkg/suse/salt-api.service %{buildroot}%{_unitdir}/salt-api.service @@ -510,7 +690,7 @@ ln -sf %{_initddir}/salt-api %{buildroot}%{_sbindir}/rcsalt-api ## Install sysV salt-minion watchdog for SLES11 and RHEL6 %if 0%{?rhel} == 6 || 0%{?suse_version} == 1110 -install -Dpm 0755 scripts/watchdog/salt-daemon-watcher %{buildroot}%{_bindir}/salt-daemon-watcher +install -Dpm 0755 scripts/suse/watchdog/salt-daemon-watcher %{buildroot}%{_bindir}/salt-daemon-watcher %endif # @@ -523,8 +703,12 @@ install -Dpm 0640 conf/cloud %{buildroot}%{_sysconfdir}/salt/cloud install -Dpm 0640 conf/cloud.profiles %{buildroot}%{_sysconfdir}/salt/cloud.profiles install -Dpm 0640 conf/cloud.providers %{buildroot}%{_sysconfdir}/salt/cloud.providers # -## install logrotate file +## install logrotate file (for RHEL6 we use without sudo) +%if 0%{?rhel} > 6 || 0%{?suse_version} +install -Dpm 0644 pkg/suse/salt-common.logrotate %{buildroot}%{_sysconfdir}/logrotate.d/salt +%else install -Dpm 0644 pkg/salt-common.logrotate %{buildroot}%{_sysconfdir}/logrotate.d/salt +%endif # ## install SuSEfirewall2 rules install -Dpm 0644 pkg/suse/salt.SuSEfirewall2 %{buildroot}%{_sysconfdir}/sysconfig/SuSEfirewall2.d/services/salt @@ -544,12 +728,21 @@ install -Dpm 0644 pkg/fish-completions/* %{buildroot}%{fish_completions_dir} %if 0%{?suse_version} > 1020 %fdupes %{buildroot}%{_docdir} +%if 0%{?build_py2} +%fdupes %{buildroot}%{python_sitelib} +%endif +%if 0%{?build_py3} %fdupes %{buildroot}%{python3_sitelib} %endif +%endif %check %if %{with test} -python3 setup.py test --runtests-opts=-u +%if 0%{?default_py3} +%{__python3} setup.py test --runtests-opts=-u +%else +%{__python} setup.py test --runtests-opts=-u +%endif %endif %pre @@ -711,7 +904,7 @@ if [ $1 -eq 2 ] ; then true fi %if %{with systemd} -if [ `rpm -q systemd --queryformat="%%{VERSION}"` -lt 228 ]; then +if [ `rpm -q systemd --queryformat="%{VERSION}"` -lt 228 ]; then # On systemd < 228 the 'TasksTask' attribute is not available. # Removing TasksMax from salt-master.service on SLE12SP1 LTSS (bsc#985112) sed -i '/TasksMax=infinity/d' %{_unitdir}/salt-master.service @@ -873,8 +1066,13 @@ fi %config(noreplace) %attr(0640, root, salt) %{_sysconfdir}/salt/cloud.profiles %config(noreplace) %attr(0640, root, salt) %{_sysconfdir}/salt/cloud.providers %dir %attr(0750, root, salt) %{_localstatedir}/cache/salt/cloud +%if 0%{?default_py3} %{python3_sitelib}/salt/cloud/deploy/bootstrap-salt.sh %attr(755,root,root)%{python3_sitelib}/salt/cloud/deploy/bootstrap-salt.sh +%else +%{python_sitelib}/salt/cloud/deploy/bootstrap-salt.sh +%attr(755,root,root)%{python_sitelib}/salt/cloud/deploy/bootstrap-salt.sh +%endif %{_mandir}/man1/salt-cloud.1.* %files ssh @@ -985,9 +1183,6 @@ fi %{_mandir}/man1/salt-call.1.gz %{_mandir}/man1/spm.1.gz %config(noreplace) %{_sysconfdir}/logrotate.d/salt -%{python3_sitelib}/* -%exclude %{python3_sitelib}/salt/cloud/deploy/*.sh -%attr(755,root,root)%{python3_sitelib}/salt/cloud/deploy/*.sh %doc LICENSE AUTHORS README.rst HACKING.rst README.SUSE # %dir %attr(0750, root, salt) %{_sysconfdir}/salt @@ -1001,6 +1196,20 @@ fi %endif %{_mandir}/man1/salt.1.* +%if 0%{?build_py2} +%files -n python2-salt +%defattr(-,root,root,-) +%{python_sitelib}/* +%exclude %{python_sitelib}/salt/cloud/deploy/*.sh +%endif + +%if 0%{?build_py3} +%files -n python3-salt +%defattr(-,root,root,-) +%{python3_sitelib}/* +%exclude %{python3_sitelib}/salt/cloud/deploy/*.sh +%endif + %if %{with docs} %files doc %defattr(-,root,root) @@ -1030,3 +1239,5 @@ fi %endif %changelog + + diff --git a/set-shell-environment-variable-64.patch b/set-shell-environment-variable-64.patch new file mode 100644 index 0000000..44e3ebf --- /dev/null +++ b/set-shell-environment-variable-64.patch @@ -0,0 +1,25 @@ +From 7f207ed0aa45063e90db2452a311b91f34b1b7e2 Mon Sep 17 00:00:00 2001 +From: Johannes Renner +Date: Thu, 11 Jan 2018 15:55:25 +0100 +Subject: [PATCH] Set SHELL environment variable (#64) + +--- + pkg/suse/salt-api.service | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/pkg/suse/salt-api.service b/pkg/suse/salt-api.service +index 6634b74a7d..5c73bb9022 100644 +--- a/pkg/suse/salt-api.service ++++ b/pkg/suse/salt-api.service +@@ -6,6 +6,7 @@ After=network.target + [Service] + User=salt + Type=simple ++Environment=SHELL=/bin/bash + LimitNOFILE=8192 + ExecStart=/usr/bin/salt-api + TimeoutStopSec=3 +-- +2.13.6 + + diff --git a/split-only-strings-if-they-are-such.patch b/split-only-strings-if-they-are-such.patch new file mode 100644 index 0000000..8ee7afb --- /dev/null +++ b/split-only-strings-if-they-are-such.patch @@ -0,0 +1,50 @@ +From 358d18a0cc635b04503d5392ce337227c1f191af Mon Sep 17 00:00:00 2001 +From: Bo Maryniuk +Date: Thu, 14 Dec 2017 14:43:52 +0100 +Subject: [PATCH] Split only strings, if they are such + +* Use unicode literals +* Lintfix: PEP8 + +See: https://bugzilla.suse.com/show_bug.cgi?id=1072218 + https://github.com/saltstack/salt/pull/44991 +--- + salt/pillar/sql_base.py | 7 +++---- + 1 file changed, 3 insertions(+), 4 deletions(-) + +diff --git a/salt/pillar/sql_base.py b/salt/pillar/sql_base.py +index e7abceb134..a59c45331f 100644 +--- a/salt/pillar/sql_base.py ++++ b/salt/pillar/sql_base.py +@@ -168,7 +168,7 @@ More complete example for MySQL (to also show configuration) + as_list: True + with_lists: [1,3] + ''' +-from __future__ import absolute_import ++from __future__ import absolute_import, unicode_literals + + # Please don't strip redundant parentheses from this file. + # I have added some for clarity. +@@ -275,7 +275,7 @@ class SqlBaseExtPillar(six.with_metaclass(abc.ABCMeta, object)): + # May set 'as_list' from qb[1][2]. + else: + defaults.update(qb[1]) +- if defaults['with_lists']: ++ if defaults['with_lists'] and isinstance(defaults['with_lists'], six.string_types): + defaults['with_lists'] = [ + int(i) for i in defaults['with_lists'].split(',') + ] +@@ -437,8 +437,7 @@ class SqlBaseExtPillar(six.with_metaclass(abc.ABCMeta, object)): + cursor.execute(details['query'], (minion_id,)) + + # Extract the field names the db has returned and process them +- self.process_fields([row[0] for row in cursor.description], +- details['depth']) ++ self.process_fields([row[0] for row in cursor.description], details['depth']) + self.enter_root(root) + self.as_list = details['as_list'] + if details['with_lists']: +-- +2.15.1 + + diff --git a/update-documentation.sh b/update-documentation.sh index 0f35957..f0e66f4 100644 --- a/update-documentation.sh +++ b/update-documentation.sh @@ -4,10 +4,35 @@ # Author: Bo Maryniuk # +NO_SPHINX_PARAM="--without-sphinx" + +function build_virtenv() { + virtualenv --system-site-packages $1 + source $1/bin/activate + pip install --upgrade pip + if [ -z "$2" ]; then + pip install -I Sphinx + fi +} + function check_env() { - for cmd in "sphinx-build" "make" "quilt"; do + if [[ -z "$1" || "$1" != "$NO_SPHINX_PARAM" ]] && [ ! -z "$(which sphinx-build 2>/dev/null)" ]; then + cat </dev/null)" ]; then - echo "Error: '$cmd' is missing." + echo "Error: '$cmd' is still missing. Install it, please." exit 1; fi done @@ -26,7 +51,7 @@ function build_docs() { cd _build/html chmod -R -x+X * cd .. - tar cvf - html | bzip2 > /tmp/html.tar.bz2 + tar cvf - html | bzip2 > $2/html.tar.bz2 } function write_changelog() { @@ -46,19 +71,30 @@ EOF } if [ -z "$1" ]; then - echo "Usage: $0 " + echo "Usage: $0 [--without-sphinx]" exit 1; fi -check_env; +check_env $2; + START=$(pwd) +V_ENV="sphinx_doc_gen" +V_TMP=$(mktemp -d) + +for f in "salt.spec" "salt*tar.gz"; do + cp -v $f $V_TMP +done + +cd $V_TMP; +build_virtenv $V_ENV $2; + SRC_DIR="salt-$(cat salt.spec | grep ^Version: | cut -d: -f2 | sed -e 's/[[:blank:]]//g')"; quilt_setup $SRC_DIR -build_docs doc +build_docs doc $V_TMP cd $START -rm -rf $SRC_DIR -mv /tmp/html.tar.bz2 $START +mv $V_TMP/html.tar.bz2 $START +rm -rf $V_TMP echo "Done" echo "---------------" diff --git a/use-home-to-get-the-user-home-directory-instead-usin.patch b/use-home-to-get-the-user-home-directory-instead-usin.patch index 58650bf..00dc83c 100644 --- a/use-home-to-get-the-user-home-directory-instead-usin.patch +++ b/use-home-to-get-the-user-home-directory-instead-usin.patch @@ -2,7 +2,7 @@ From 418bcf80ca263c5523e701801e97bae60fdf9b35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pablo=20Su=C3=A1rez=20Hern=C3=A1ndez?= Date: Mon, 11 Sep 2017 19:57:28 +0200 -Subject: [PATCH 2/6] Use $HOME to get the user home directory instead using +Subject: [PATCH] Use $HOME to get the user home directory instead using '~' char --- @@ -24,5 +24,6 @@ index 480361fe23..00174c072f 100644 if [ ! -d "$(dirname ${_salt_cache_functions})" ]; then -- -2.14.2 +2.15.1 + diff --git a/v2017.7.2.tar.gz b/v2017.7.2.tar.gz new file mode 100644 index 0000000..b757ea3 --- /dev/null +++ b/v2017.7.2.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b9f9dd9ddd129ddadadf963178383b50c32283aeb1c338d9c23cc01b11722db2 +size 11483585 diff --git a/zyppnotify b/zyppnotify deleted file mode 100644 index c548ac4..0000000 --- a/zyppnotify +++ /dev/null @@ -1,59 +0,0 @@ -#!/usr/bin/python3 -# -# Copyright (c) 2016 SUSE Linux LLC -# All Rights Reserved. -# -# Author: Bo Maryniuk - -import sys -import os -import hashlib - -from zypp_plugin import Plugin - - -class DriftDetector(Plugin): - """ - Return diff of the installed packages outside the Salt. - """ - def __init__(self): - Plugin.__init__(self) - self.ck_path = "/var/cache/salt/minion/rpmdb.cookie" - self.rpm_path = "/var/lib/rpm/Packages" - - def _get_mtime(self): - ''' - Get the modified time of the RPM Database. - Returns: - Unix ticks - ''' - return os.path.exists(self.rpm_path) and int(os.path.getmtime(self.rpm_path)) or 0 - - def _get_checksum(self): - ''' - Get the checksum of the RPM Database. - Returns: - hexdigest - ''' - digest = hashlib.md5() - with open(self.rpm_path, "rb") as rpm_db_fh: - while True: - buff = rpm_db_fh.read(0x1000) - if not buff: - break - digest.update(buff) - - return digest.hexdigest() - - def PLUGINEND(self, headers, body): - """ - Hook when plugin closes Zypper's transaction. - """ - if 'SALT_RUNNING' not in os.environ: - with open(self.ck_path, 'w') as ck_fh: - ck_fh.write('{chksum} {mtime}\n'.format(chksum=self._get_checksum(), mtime=self._get_mtime())) - - self.ack() - - -DriftDetector().main()