Hello community, here is the log from the commit of package salt-shaptools for openSUSE:Factory checked in at 2020-01-25 13:24:46 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/salt-shaptools (Old) and /work/SRC/openSUSE:Factory/.salt-shaptools.new.26092 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "salt-shaptools" Sat Jan 25 13:24:46 2020 rev:10 rq:766938 version:0.3.0 Changes: -------- --- /work/SRC/openSUSE:Factory/salt-shaptools/salt-shaptools.changes 2020-01-10 17:51:46.578134140 +0100 +++ /work/SRC/openSUSE:Factory/.salt-shaptools.new.26092/salt-shaptools.changes 2020-01-25 13:24:52.104055178 +0100 @@ -1,0 +2,6 @@ +Wed Jan 22 10:52:20 UTC 2020 - Dario Maiocchi <[email protected]> + +- Version 0.3.0 + * Add first version of saptune module to apply specific solution + +------------------------------------------------------------------- Old: ---- salt-shaptools-0.2.12.tar.gz New: ---- salt-shaptools-0.3.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ salt-shaptools.spec ++++++ --- /var/tmp/diff_new_pack.PwcBnI/_old 2020-01-25 13:24:53.860055948 +0100 +++ /var/tmp/diff_new_pack.PwcBnI/_new 2020-01-25 13:24:53.892055962 +0100 @@ -19,7 +19,7 @@ # See also https://en.opensuse.org/openSUSE:Specfile_guidelines Name: salt-shaptools -Version: 0.2.12 +Version: 0.3.0 Release: 0 Summary: Salt modules and states for SAP Applications and SLE-HA components management @@ -49,6 +49,8 @@ cp -R salt/states/drbdmod.py %{buildroot}/srv/salt/_states cp -R salt/modules/netweavermod.py %{buildroot}/srv/salt/_modules cp -R salt/states/netweavermod.py %{buildroot}/srv/salt/_states +cp -R salt/modules/saptunemod.py %{buildroot}/srv/salt/_modules +cp -R salt/states/saptunemod.py %{buildroot}/srv/salt/_states %files ++++++ salt-shaptools-0.2.12.tar.gz -> salt-shaptools-0.3.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/salt-shaptools-0.2.12/README.md new/salt-shaptools-0.3.0/README.md --- old/salt-shaptools-0.2.12/README.md 2020-01-09 16:37:15.619797345 +0100 +++ new/salt-shaptools-0.3.0/README.md 2020-01-23 12:08:57.968470309 +0100 @@ -23,7 +23,7 @@ To run the state modules (there is a demo example in the demo folder) run: ```bash cd salt-shaptools -sudo salt-call --local --retcode-passthrough -l debug -m . state.template demo/primary.sls +sudo salt-call --retcode-passthrough -l debug -m . state.template demo/primary.sls ``` ### Run in minions @@ -33,12 +33,15 @@ 2. Copy the content of **states** in your "salt://_states/" (by default /srv/salt/_states) 3. Synchronize modules with the minions. For that run: ```bash -sudo salt '*' saltutil.sync_states +sudo salt-call saltutil.sync_all ``` 4. Execute the module functionalities. For that run: ```bash sudo salt-call hana.is_installed ``` +## Writing unit test + +You can have look at: https://docs.saltstack.com/en/latest/topics/development/tests/unit.html ## How to run the tests Salt has a quite particular way to execute the tests. As a summary, tests are splitted @@ -51,17 +54,29 @@ is in a separated repository, the easiest way is to copy our project code to a actual salt repository and run the tests. For that follow the next instructions: -1. Download the salt project in the same folder of this project: +1. Download 2 **needed extra projects**: (saltstack and shaptools) + ```bash -git clone [email protected]:saltstack/salt.git +git clone --depth=50 https://github.com/openSUSE/salt +git clone https://github.com/SUSE/shaptools.git +``` + +Your directory layout should looks like ( all the 3 dirs are in same three dir level) +``` +- salt-shaptools +- salt +- shaptools ``` -2. Create a virtual environment (python2 must be used here) and install dependencies: + + +2. Create a virtual environment, inside the `salt-shaptools` dir and install dependencies: ```bash virtualenv saltvirtenv source saltvirtenv/bin/activate -pip install pyzmq PyYAML pycrypto msgpack-python jinja2 psutil futures tornado pytest-salt mock -pip install -e salt -pip install -e shaptools #put the correct path +pip install pyzmq PyYAML pycrypto msgpack-python jinja2 psutil futures tornado pytest-salt mock pytest-cov +pip install -e ../salt +pip install -e ../shaptools +rm ../salt/tests/conftest.py # remove this file from the saltstack repo ``` 3. Run the tests. For that: @@ -71,6 +86,21 @@ ./tests/run.sh ``` +4) Running your modules/states: + +For testing/running modules: + +``` +salt-call --local saptune.apply_solution "SAP-ASE" + +``` + +For testing/running states: +``` +salt-call --local state.single saptune.solution_applied "HANA" +``` + + ## Dependencies List of dependencies are specified in the ["Requirements file"](requirements.txt). Items can be installed using pip: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/salt-shaptools-0.2.12/salt/modules/saptunemod.py new/salt-shaptools-0.3.0/salt/modules/saptunemod.py --- old/salt-shaptools-0.2.12/salt/modules/saptunemod.py 1970-01-01 01:00:00.000000000 +0100 +++ new/salt-shaptools-0.3.0/salt/modules/saptunemod.py 2020-01-23 12:08:57.968470309 +0100 @@ -0,0 +1,77 @@ +# -*- coding: utf-8 -*- +''' +Module to provide Saptune functionality to Salt + +.. versionadded:: pending + +:maintainer: Dario Maiocchi <[email protected]> +:maturity: alpha +:depends: ``saptune`` package +:platform: all + +:configuration: This module requires the saptune package +''' + +# Import Python libs +from __future__ import absolute_import, unicode_literals, print_function +import logging + +from salt import exceptions +import salt.utils.path +import salt.utils.files + + +__virtualname__ = 'saptune' + +SAPTUNE_BIN = '/usr/sbin/saptune' +SAPTUNE_CONF = '/etc/sysconfig/saptune' +MINIMAL_SAPTUNE_SUP_VERSION = '2.0.0' + +LOGGER = logging.getLogger(__name__) + + +def __virtual__(): + ''' + Only load this module if saptune package is installed + ''' + if bool(salt.utils.path.which(SAPTUNE_BIN)): + version = __salt__['pkg.version']('saptune') + # don't support older then 2.0 + use_saptune_sup = __salt__['pkg.version_cmp'](version, MINIMAL_SAPTUNE_SUP_VERSION) >= 0 + + if use_saptune_sup: + return __virtualname__ + + return ( + False, + 'The saptune execution module failed to load: the saptune package' + ' is not available, or the version is older than {}'.format(MINIMAL_SAPTUNE_SUP_VERSION)) + + +def is_solution_applied(solution_name): + ''' + check if the saptune solution is applied or not + ''' + + solution_to_search = "TUNE_FOR_SOLUTIONS=\"{}\"".format(solution_name) + + # open the config file and search if the solution is enabled + with salt.utils.files.fopen(SAPTUNE_CONF) as conf: + if solution_to_search in conf.read(): + return True + return False + + +def apply_solution(solution_name): + ''' + Tune system for all notes applicable to your SAP solution: + + + CLI Example: + + .. code-block:: bash + + salt '*' saptune.apply_solution solution-name + ''' + cmd = '{} solution apply {}'.format(SAPTUNE_BIN, solution_name) + return __salt__['cmd.retcode'](cmd) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/salt-shaptools-0.2.12/salt/states/saptunemod.py new/salt-shaptools-0.3.0/salt/states/saptunemod.py --- old/salt-shaptools-0.2.12/salt/states/saptunemod.py 1970-01-01 01:00:00.000000000 +0100 +++ new/salt-shaptools-0.3.0/salt/states/saptunemod.py 2020-01-23 12:08:57.968470309 +0100 @@ -0,0 +1,83 @@ +''' +State module to provide Saptune functionality to Salt + +.. versionadded:: pending + +:maintainer: Dario Maiocchi <[email protected]> +:maturity: alpha +:depends: saptune +:platform: all + +:configuration: This module requires the saptune python module +''' + + +# Import python libs +from __future__ import absolute_import, unicode_literals, print_function + + +# Import salt libs +from salt import exceptions +from salt.ext import six + + +__virtualname__ = 'saptune' + + +def __virtual__(): # pragma: no cover + ''' + Only load if the saptune module is in __salt__ + ''' + return 'saptune.apply_solution' in __salt__ + + +def solution_applied(name): + """ + Apply a saptune solution + + solution_name + Solution to be applied by saptune + + """ + ret = {'name': name, + 'changes': {}, + 'result': False, + 'comment': ''} + + if __salt__['saptune.is_solution_applied'](solution_name=name): + ret['result'] = True + ret['comment'] = 'Saptune {} solution is already applied'.format(name) + return ret + + if __opts__['test']: + ret['result'] = None + ret['comment'] = 'Saptune {} solution would be applied'.format(name) + ret['changes']['name'] = name + return ret + + try: + + # Here starts the actual process + result = __salt__['saptune.apply_solution'](solution_name=name) + + # result is not null 0, so we have error + if result: + ret['comment'] = 'Error appling saptune solution' + ret['result'] = False + return ret + + # check if the solution was applied or not (if an already is applied we can't apply a new one) + if not __salt__['saptune.is_solution_applied'](solution_name=name): + ret['result'] = False + ret['comment'] = 'Saptune solution was not applied correctly. Perhaps an already '\ + 'applied solution need to be reverted first' + return ret + + ret['changes']['name'] = name + ret['comment'] = 'Saptune solution applied' + ret['result'] = True + return ret + + except exceptions.CommandExecutionError as err: + ret['comment'] = six.text_type(err) + return ret diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/salt-shaptools-0.2.12/salt-shaptools.changes new/salt-shaptools-0.3.0/salt-shaptools.changes --- old/salt-shaptools-0.2.12/salt-shaptools.changes 2020-01-09 16:37:15.619797345 +0100 +++ new/salt-shaptools-0.3.0/salt-shaptools.changes 2020-01-23 12:08:57.968470309 +0100 @@ -1,4 +1,10 @@ ------------------------------------------------------------------- +Wed Jan 22 10:52:20 UTC 2020 - Dario Maiocchi <[email protected]> + +- Version 0.3.0 + * Add first version of saptune module to apply specific solution + +------------------------------------------------------------------- Thu Jan 9 15:28:29 UTC 2020 - Simranpal Singh <[email protected]> - Version 0.2.12 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/salt-shaptools-0.2.12/salt-shaptools.spec new/salt-shaptools-0.3.0/salt-shaptools.spec --- old/salt-shaptools-0.2.12/salt-shaptools.spec 2020-01-09 16:37:15.619797345 +0100 +++ new/salt-shaptools-0.3.0/salt-shaptools.spec 2020-01-23 12:08:57.968470309 +0100 @@ -19,7 +19,7 @@ # See also https://en.opensuse.org/openSUSE:Specfile_guidelines Name: salt-shaptools -Version: 0.2.12 +Version: 0.3.0 Release: 0 Summary: Salt modules and states for SAP Applications and SLE-HA components management @@ -49,6 +49,8 @@ cp -R salt/states/drbdmod.py %{buildroot}/srv/salt/_states cp -R salt/modules/netweavermod.py %{buildroot}/srv/salt/_modules cp -R salt/states/netweavermod.py %{buildroot}/srv/salt/_states +cp -R salt/modules/saptunemod.py %{buildroot}/srv/salt/_modules +cp -R salt/states/saptunemod.py %{buildroot}/srv/salt/_states %files diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/salt-shaptools-0.2.12/tests/run.sh new/salt-shaptools-0.3.0/tests/run.sh --- old/salt-shaptools-0.2.12/tests/run.sh 2020-01-09 16:37:15.619797345 +0100 +++ new/salt-shaptools-0.3.0/tests/run.sh 2020-01-23 12:08:57.968470309 +0100 @@ -2,4 +2,4 @@ cp salt/states/*.py ../salt/salt/states/ cp tests/unit/modules/*.py ../salt/tests/unit/modules/ cp tests/unit/states/*.py ../salt/tests/unit/states/ -py.test -vv ../salt/tests/unit/modules/test_hanamod.py ../salt/tests/unit/states/test_hanamod.py ../salt/tests/unit/modules/test_crmshmod.py ../salt/tests/unit/states/test_crmshmod.py ../salt/tests/unit/modules/test_drbdmod.py ../salt/tests/unit/states/test_drbdmod.py ../salt/tests/unit/modules/test_netweavermod.py ../salt/tests/unit/states/test_netweavermod.py --cov=salt.modules.hanamod --cov=salt.states.hanamod --cov=salt.modules.crmshmod --cov=salt.states.crmshmod --cov=salt.modules.drbdmod --cov=salt.states.drbdmod --cov=salt.modules.netweavermod --cov=salt.states.netweavermod --cov-config .coveragerc --cov-report term --cov-report xml +py.test -vv ../salt/tests/unit/modules/test_hanamod.py ../salt/tests/unit/states/test_hanamod.py ../salt/tests/unit/modules/test_crmshmod.py ../salt/tests/unit/modules/test_saptunemod.py ../salt/tests/unit/states/test_crmshmod.py ../salt/tests/unit/modules/test_drbdmod.py ../salt/tests/unit/states/test_drbdmod.py ../salt/tests/unit/states/test_saptunemod.py ../salt/tests/unit/modules/test_netweavermod.py ../salt/tests/unit/states/test_netweavermod.py --cov=salt.modules.hanamod --cov=salt.states.hanamod --cov=salt.modules.crmshmod --cov=salt.states.crmshmod --cov=salt.modules.drbdmod --cov=salt.modules.saptunemod --cov=salt.states.saptunemod --cov=salt.states.drbdmod --cov=salt.modules.netweavermod --cov=salt.states.netweavermod --cov-config .coveragerc --cov-report term --cov-report xml --cov-report html diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/salt-shaptools-0.2.12/tests/unit/modules/test_saptunemod.py new/salt-shaptools-0.3.0/tests/unit/modules/test_saptunemod.py --- old/salt-shaptools-0.2.12/tests/unit/modules/test_saptunemod.py 1970-01-01 01:00:00.000000000 +0100 +++ new/salt-shaptools-0.3.0/tests/unit/modules/test_saptunemod.py 2020-01-23 12:08:57.968470309 +0100 @@ -0,0 +1,95 @@ + +# -*- coding: utf-8 -*- +''' + :codeauthor: Dario Maiocchi <[email protected]> +''' + +# Import Python Libs +from __future__ import absolute_import, print_function, unicode_literals + +# Import Salt Testing Libs +from tests.support.mixins import LoaderModuleMockMixin +from tests.support.unit import TestCase, skipIf +from tests.support import mock +from tests.support.mock import ( + MagicMock, + patch, + mock_open, + NO_MOCK, + NO_MOCK_REASON +) + +# Import Salt Libs +import salt.modules.saptunemod as saptune + + +@skipIf(NO_MOCK, NO_MOCK_REASON) +class SaptuneModuleTest(TestCase, LoaderModuleMockMixin): + ''' + This class contains a set of functions that test salt.modules.saptune. + ''' + + def setup_loader_modules(self): + return {saptune: {}} + + @mock.patch('salt.utils.path.which') + def test_virtual_saptune(self, mock_which): + mock_pkg_version = MagicMock(return_value='2.0.0') + mock_pkg_version_cmp = MagicMock(return_value=2) + mock_which.return_value = True + with patch.dict(saptune.__salt__, { + 'pkg.version': mock_pkg_version, + 'pkg.version_cmp': mock_pkg_version_cmp}): + assert saptune.__virtual__() == 'saptune' + + mock_which.return_value = False + assert saptune.__virtual__() == ( + False, 'The saptune execution module failed to load: the saptune' + ' package is not available, or the version is older than 2.0.0') + # test_lower_then_supported_version + mock_pkg_version = MagicMock(return_value='1.0.0') + mock_pkg_version_cmp = MagicMock(return_value=2) + mock_which.return_value = True + with patch.dict(saptune.__salt__, { + 'pkg.version': mock_pkg_version, + 'pkg.version_cmp': mock_pkg_version_cmp}): + assert saptune.__virtual__() == 'saptune' + + mock_which.return_value = False + assert saptune.__virtual__() == ( + False, 'The saptune execution module failed to load: the saptune' + ' package is not available, or the version is older than 2.0.0') + + def test_is_solution_applied(self): + ''' + Test is_solution_applied method + ''' + + builtin_name = "salt.utils.files.fopen" + + sol_name = "foo" + file_content = "TUNE_FOR_SOLUTIONS=\"foo\"" + with patch(builtin_name, mock_open(read_data=file_content)) as mock_file: + assert saptune.is_solution_applied(sol_name) + #mock_file.assert_called_once_with(saptune.SAPTUNE_CONF) + + file_content = "TUNE_FOR_SOLUTIONS=\"baz\"" + with patch(builtin_name, mock_open(read_data=file_content)) as mock_file: + assert not saptune.is_solution_applied(sol_name) + #mock_file.assert_called_once_with(saptune.SAPTUNE_CONF) + + def test_apply_solution(self): + ''' + Test apply solution method + ''' + mock_cmd = MagicMock(return_value=True) + with patch.dict(saptune.__salt__, {'cmd.retcode': mock_cmd}): + assert saptune.apply_solution('foo') + + def test_apply_solution_false(self): + ''' + Test apply solution method + ''' + mock_cmd = MagicMock(return_value=False) + with patch.dict(saptune.__salt__, {'cmd.retcode': mock_cmd}): + assert not saptune.apply_solution('foo_false') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/salt-shaptools-0.2.12/tests/unit/states/test_saptunemod.py new/salt-shaptools-0.3.0/tests/unit/states/test_saptunemod.py --- old/salt-shaptools-0.2.12/tests/unit/states/test_saptunemod.py 1970-01-01 01:00:00.000000000 +0100 +++ new/salt-shaptools-0.3.0/tests/unit/states/test_saptunemod.py 2020-01-23 12:08:57.968470309 +0100 @@ -0,0 +1,132 @@ + +# -*- coding: utf-8 -*- +''' + :codeauthor: Dario Maiocchi <[email protected]> +''' +# Import Python libs +from __future__ import absolute_import, unicode_literals, print_function + +from salt import exceptions + +# Import Salt Testing Libs +from tests.support.mixins import LoaderModuleMockMixin +from tests.support.unit import skipIf, TestCase +from tests.support import mock +from tests.support.mock import ( + NO_MOCK, + NO_MOCK_REASON, + MagicMock, + patch +) + +# Import Salt Libs +import salt.states.saptunemod as saptune + + +@skipIf(NO_MOCK, NO_MOCK_REASON) +class SaptunemodTestCase(TestCase, LoaderModuleMockMixin): + ''' + Test cases for salt.states.saptunemod + ''' + def setup_loader_modules(self): + return {saptune: {'__opts__': {'test': False}}} + + def test_solution_applied_true(self): + ''' + Test solution is applied method true + ''' + solution_name = 'normalmode' + expected_ret = { + 'changes': {}, + 'result': True, + 'name': solution_name, + 'comment': "Saptune {} solution is already applied".format(solution_name) + } + expected_ret2 = { + 'changes': {'name': 'normalmode'}, + 'result': True, + 'name': solution_name, + 'comment': "Saptune solution applied" + } + + sol_applied_resp = MagicMock(return_value=True) + with patch.dict(saptune.__salt__, {'saptune.is_solution_applied': sol_applied_resp}): + assert saptune.solution_applied(solution_name) == expected_ret + + with patch.dict(saptune.__salt__, { + 'saptune.is_solution_applied': MagicMock(side_effect=[False, True]), + 'saptune.apply_solution': MagicMock(return_value=0)}): + assert saptune.solution_applied(solution_name) == expected_ret2 + + def test_solution_applied_already(self): + ''' + Test solution is applied method already + ''' + solution_name = 'normalmode' + + expected_ret = { + 'changes': {}, + 'result': False, + 'name': solution_name, + 'comment': 'Saptune solution was not applied correctly. Perhaps an already applied ' + 'solution need to be reverted first' + } + + with patch.dict(saptune.__salt__, { + 'saptune.is_solution_applied': MagicMock(return_value=False), + 'saptune.apply_solution': MagicMock(return_value=0)}): + assert saptune.solution_applied(solution_name) == expected_ret + + def test_solution_applied_error(self): + ''' + Test solution is applied method error + ''' + solution_name = 'normalmode' + expected_ret = { + 'changes': {}, + 'result': False, + 'name': solution_name, + 'comment': "Error appling saptune solution" + } + + with patch.dict(saptune.__salt__, { + 'saptune.is_solution_applied': MagicMock(return_value=False), + 'saptune.apply_solution': MagicMock(return_value=1)}): + assert saptune.solution_applied(solution_name) == expected_ret + + def test_solution_applied_test_mode(self): + ''' + Test solution is applied method false + ''' + solution_name = 'testmode' + expected_ret = { + 'changes': {'name': solution_name}, + 'result': None, + 'name': solution_name, + 'comment': "Saptune {} solution would be applied".format(solution_name) + } + + response = MagicMock(return_value=False) + + with patch.dict(saptune.__salt__, {'saptune.is_solution_applied': response}): + with patch.dict(saptune.__opts__, {'test': True}): + ret = saptune.solution_applied(solution_name) + assert ret == expected_ret + + def test_solution_applied_error_exception(self): + ''' + Test solution is applied method error exception + ''' + solution_name = 'normalmode' + + expected_ret = { + 'changes': {}, + 'result': False, + 'name': solution_name, + 'comment': 'saptune error' + } + + with patch.dict(saptune.__salt__, { + 'saptune.is_solution_applied': MagicMock(side_effect=[False, True]), + 'saptune.apply_solution': MagicMock(side_effect=exceptions.CommandExecutionError('saptune error'))}): + assert saptune.solution_applied(solution_name) == expected_ret
