From 8cad34f27346bf7fd9e9742554d8bb56703a395c Mon Sep 17 00:00:00 2001 From: Mike Place Date: Mon, 22 Oct 2018 08:33:59 -0600 Subject: [PATCH 1/5] Merge pull request #50141 from mchugh19/ssh_auth_manage create ssh_auth.manage --- doc/topics/releases/neon.rst | 293 +++++++++++++++++++++++++++++++++++ salt/states/ssh_auth.py | 131 ++++++++++++++-- 2 files changed, 407 insertions(+), 17 deletions(-) diff --git a/doc/topics/releases/neon.rst b/doc/topics/releases/neon.rst index 780a8d9e429b..c3cba88e5293 100644 --- a/doc/topics/releases/neon.rst +++ b/doc/topics/releases/neon.rst @@ -3,3 +3,296 @@ ================================== Salt Release Notes - Codename Neon ================================== +<<<<<<< HEAD +======= + + +Saltcheck Updates +================= + +Available since 2018.3, the saltcheck module has been enhanced to: + * Support saltenv environments + * Associate tests with states by naming convention + * Adds empty and notempty assertions + * Adds skip keyword + * Adds print_result keyword + * Adds assertion_section keyword + * Use saltcheck.state_apply to run state.apply for test setup or teardown + * Changes output to display test time + +Saltcheck provides unittest like functionality requiring only the knowledge of +salt module execution and yaml. Saltcheck uses salt modules to return data, then +runs an assertion against that return. This allows for testing with all the +features included in salt modules. + +In order to run state and highstate saltcheck tests, a sub-folder in the state directory +must be created and named ``saltcheck-tests``. Tests for a state should be created in files +ending in ``*.tst`` and placed in the ``saltcheck-tests`` folder. ``tst`` files are run +through the salt rendering system, enabling tests to be written in yaml (or renderer of choice), +and include jinja, as well as the usual grain and pillar information. Like states, multiple tests can +be specified in a ``tst`` file. Multiple ``tst`` files can be created in the ``saltcheck-tests`` +folder, and should be named the same as the associated state. The ``id`` of a test works in the +same manner as in salt state files and should be unique and descriptive. + +Usage +----- + +Example file system layout: + +.. code-block:: txt + + /srv/salt/apache/ + init.sls + config.sls + saltcheck-tests/ + init.tst + config.tst + deployment_validation.tst + +Tests can be run for each state by name, for all apache/saltcheck/*.tst files, or for all states +assigned to the minion in top.sls. Tests may also be created with no associated state. These tests +will be run through the use of ``saltcheck.run_state_tests``, but will not be automatically run +by ``saltcheck.run_highstate_tests``. + +.. code-block:: bash + + salt '*' saltcheck.run_state_tests apache,apache.config + salt '*' saltcheck.run_state_tests apache check_all=True + salt '*' saltcheck.run_highstate_tests + salt '*' saltcheck.run_state_tests apache.deployment_validation + +Example Tests +------------- + +.. code-block:: jinja + + {# will run the common salt state before further testing #} + setup_test_environment: + module_and_function: saltcheck.state_apply + args: + - common + pillar-data: + data: value + + {% for package in ["apache2", "openssh"] %} + {# or another example #} + {# for package in salt['pillar.get']("packages") #} + jinja_test_{{ package }}_latest: + module_and_function: pkg.upgrade_available + args: + - {{ package }} + assertion: assertFalse + {% endfor %} + + validate_user_present_and_shell: + module_and_function: user.info + args: + - root + assertion: assertEqual + expected-return: /bin/bash + assertion_section: shell + print_result: False + + skip_test: + module_and_function: pkg.upgrade_available + args: + - apache2 + assertion: assertFalse + skip: True + +Output Format Changes +--------------------- + +Saltcheck output has been enhanced to display the time taken per test. This results +in a change to the output format. + +Previous Output: + +.. code-block:: text + + local: + |_ + ---------- + ntp: + ---------- + ntp-client-installed: + Pass + ntp-service-status: + Pass + |_ + ---------- + TEST RESULTS: + ---------- + Failed: + 0 + Missing Tests: + 0 + Passed: + 2 + +New output: + +.. code-block:: text + + local: + |_ + ---------- + ntp: + ---------- + ntp-client-installed: + ---------- + duration: + 1.0408 + status: + Pass + ntp-service-status: + ---------- + duration: + 1.464 + status: + Pass + |_ + ---------- + TEST RESULTS: + ---------- + Execution Time: + 2.5048 + Failed: + 0 + Missing Tests: + 0 + Passed: + 2 + Skipped: + 0 + +XML Module +========== + +A new state and execution module for editing XML files is now included. Currently it allows for +editing values from an xpath query, or editing XML IDs. + +.. code-block:: bash + + # salt-call xml.set_attribute /tmp/test.xml ".//actor[@id='3']" editedby "Jane Doe" + local: + True + # salt-call xml.get_attribute /tmp/test.xml ".//actor[@id='3']" + local: + ---------- + editedby: + Jane Doe + id: + 3 + # salt-call xml.get_value /tmp/test.xml ".//actor[@id='2']" + local: + Liam Neeson + # salt-call xml.set_value /tmp/test.xml ".//actor[@id='2']" "Patrick Stewart" + local: + True + # salt-call xml.get_value /tmp/test.xml ".//actor[@id='2']" + local: + Patrick Stewart + +.. code-block:: yaml + + ensure_value_true: + xml.value_present: + - name: /tmp/test.xml + - xpath: .//actor[@id='1'] + - value: William Shatner + + + +State Changes +============= + +- The :py:func:`file.rename ` state will now return a + ``True`` result (and make no changes) when the destination file already + exists, and ``Force`` is not set to ``True``. In previous releases, a + ``False`` result would be returned, but this meant that subsequent runs of + the state would fail due to the destination file being present. + +- The ``onchanges`` and ``prereq`` :ref:`requisites ` now behave + properly in test mode. + +- Added new :py:func:`ssh_auth.manage ` state to + ensure only the specified ssh keys are present for the specified user. + +Module Changes +============== + +- The :py:func:`debian_ip ` module used by the + :py:func:`network.managed ` state has been + heavily refactored. The order that options appear in inet/inet6 blocks may + produce cosmetic changes. Many options without an 'ipvX' prefix will now be + shared between inet and inet6 blocks. The options ``enable_ipv4`` and + ``enabled_ipv6`` will now fully remove relevant inet/inet6 blocks. Overriding + options by prefixing them with 'ipvX' will now work with most options (i.e. + ``dns`` can be overriden by ``ipv4dns`` or ``ipv6dns``). The ``proto`` option + is now required. + +Salt Cloud Features +=================== + +GCE Driver +---------- + +The GCE salt cloud driver can now be used with GCE instance credentials by +setting the configuration paramaters ``service_account_private_key`` and +``service_account_private_email`` to an empty string. + +Deprecations +============ + +RAET Transport +-------------- + +Support for RAET has been removed. Please use the ``zeromq`` or ``tcp`` transport +instead of ``raet``. + +Module Deprecations +------------------- + +- The :py:mod:`dockermod ` module has been + changed as follows: + + - Support for the ``tags`` kwarg has been removed from the + :py:func:`dockermod.resolve_tag ` + function. + - Support for the ``network_id`` kwarg has been removed from the + :py:func:`dockermod.connect_container_to_network ` + function. Please use ``net_id`` instead. + - Support for the ``name`` kwarg has been removed from the + :py:func:`dockermod.sls_build ` + function. Please use ``repository`` and ``tag`` instead. + - Support for the ``image`` kwarg has been removed from the following + functions. In all cases, please use both the ``repository`` and ``tag`` + options instead: + + - :py:func:`dockermod.build ` + - :py:func:`dockermod.commit ` + - :py:func:`dockermod.import ` + - :py:func:`dockermod.load ` + - :py:func:`dockermod.tag ` + +- The :py:mod:`ssh ` execution module has been + changed as follows: + + - Support for the ``ssh.get_known_host`` function has been removed. Please use the + :py:func:`ssh.get_known_host_entries ` + function instead. + - Support for the ``ssh.recv_known_host`` function has been removed. Please use the + :py:func:`ssh.recv_known_host_entries ` + function instead. + +State Deprecations +------------------ + +- The :py:mod:`win_servermanager ` state has been + changed as follows: + + - Support for the ``force`` kwarg has been removed from the + :py:func:`win_servermanager.installed ` + function. Please use ``recurse`` instead. +>>>>>>> 560a1db1e1... Merge pull request #50141 from mchugh19/ssh_auth_manage diff --git a/salt/states/ssh_auth.py b/salt/states/ssh_auth.py index 2aff1dc1e9d4..1db9dd7aaad3 100644 --- a/salt/states/ssh_auth.py +++ b/salt/states/ssh_auth.py @@ -44,6 +44,20 @@ - ssh-dss AAAAB3NzaCL0sQ9fJ5bYTEyY== user@domain - option3="value3" ssh-dss AAAAB3NzaC1kcQ9J5bYTEyY== other@testdomain - AAAAB3NzaC1kcQ9fJFF435bYTEyY== newcomment + + sshkeys: + ssh_auth.manage: + - user: root + - enc: ssh-rsa + - options: + - option1="value1" + - option2="value2 flag2" + - comment: myuser + - ssh_keys: + - AAAAB3NzaC1kc3MAAACBAL0sQ9fJ5bYTEyY== + - ssh-dss AAAAB3NzaCL0sQ9fJ5bYTEyY== user@domain + - option3="value3" ssh-dss AAAAB3NzaC1kcQ9J5bYTEyY== other@testdomain + - AAAAB3NzaC1kcQ9fJFF435bYTEyY== newcomment ''' # Import python libs @@ -125,7 +139,7 @@ def _present_test(user, name, enc, comment, options, source, config, fingerprint elif check == 'exists': result = True comment = ('The authorized host key {0} is already present ' - 'for user {1}'.format(name, user)) + 'for user {1}'.format(name, user)) return result, comment @@ -251,14 +265,7 @@ def present( fingerprint_hash_type The public key fingerprint hash type that the public key fingerprint - was originally hashed with. This defaults to ``md5`` if not specified. - - .. versionadded:: 2016.11.7 - - .. note:: - - The default value of the ``fingerprint_hash_type`` will change to - ``sha256`` in Salt 2017.7.0. + was originally hashed with. This defaults to ``sha256`` if not specified. ''' ret = {'name': name, 'changes': {}, @@ -325,7 +332,7 @@ def present( saltenv=__env__, fingerprint_hash_type=fingerprint_hash_type) else: - # Split keyline to get key und comment + # Split keyline to get key and comment keyline = keyline.split(' ') key_type = keyline[0] key_value = keyline[1] @@ -423,15 +430,9 @@ def absent(name, fingerprint_hash_type The public key fingerprint hash type that the public key fingerprint - was originally hashed with. This defaults to ``md5`` if not specified. + was originally hashed with. This defaults to ``sha256`` if not specified. .. versionadded:: 2016.11.7 - - .. note:: - - The default value of the ``fingerprint_hash_type`` will change to - ``sha256`` in Salt 2017.7.0. - ''' ret = {'name': name, 'changes': {}, @@ -506,3 +507,99 @@ def absent(name, ret['changes'][name] = 'Removed' return ret + + +def manage( + name, + ssh_keys, + user, + enc='ssh-rsa', + comment='', + source='', + options=None, + config='.ssh/authorized_keys', + fingerprint_hash_type=None, + **kwargs): + ''' + .. versionadded:: Neon + + Ensures that only the specified ssh_keys are present for the specified user + + ssh_keys + The SSH key to manage + + user + The user who owns the SSH authorized keys file to modify + + enc + Defines what type of key is being used; can be ed25519, ecdsa, ssh-rsa + or ssh-dss + + comment + The comment to be placed with the SSH public key + + source + The source file for the key(s). Can contain any number of public keys, + in standard "authorized_keys" format. If this is set, comment and enc + will be ignored. + + .. note:: + The source file must contain keys in the format `` + ``. If you have generated a keypair using PuTTYgen, then you + will need to do the following to retrieve an OpenSSH-compatible public + key. + + 1. In PuTTYgen, click ``Load``, and select the *private* key file (not + the public key), and click ``Open``. + 2. Copy the public key from the box labeled ``Public key for pasting + into OpenSSH authorized_keys file``. + 3. Paste it into a new file. + + options + The options passed to the keys, pass a list object + + config + The location of the authorized keys file relative to the user's home + directory, defaults to ".ssh/authorized_keys". Token expansion %u and + %h for username and home path supported. + + fingerprint_hash_type + The public key fingerprint hash type that the public key fingerprint + was originally hashed with. This defaults to ``sha256`` if not specified. + ''' + ret = {'name': '', + 'changes': {}, + 'result': True, + 'comment': ''} + + all_potential_keys = [] + for ssh_key in ssh_keys: + # gather list potential ssh keys for removal comparison + # options, enc, and comments could be in the mix + all_potential_keys.extend(ssh_key.split(' ')) + existing_keys = __salt__['ssh.auth_keys'](user=user).keys() + remove_keys = set(existing_keys).difference(all_potential_keys) + for remove_key in remove_keys: + if __opts__['test']: + remove_comment = '{0} Key set for removal'.format(remove_key) + ret['comment'] = remove_comment + ret['result'] = None + else: + remove_comment = absent(remove_key, user)['comment'] + ret['changes'][remove_key] = remove_comment + + for ssh_key in ssh_keys: + run_return = present(ssh_key, user, enc, comment, source, + options, config, fingerprint_hash_type, **kwargs) + if run_return['changes']: + ret['changes'].update(run_return['changes']) + else: + ret['comment'] += '\n' + run_return['comment'] + ret['comment'].strip() + + if run_return['result'] is None: + ret['result'] = None + elif not run_return['result']: + ret['result'] = False + + return ret From 4f6b8ed7cedc028f2d08d1684a08b1e4aebe9eb1 Mon Sep 17 00:00:00 2001 From: Christian McHugh Date: Sat, 12 Oct 2019 21:40:10 +0100 Subject: [PATCH 2/5] wip --- doc/topics/releases/neon.rst | 3 --- tests/unit/states/test_ssh_auth.py | 37 ++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/doc/topics/releases/neon.rst b/doc/topics/releases/neon.rst index c3cba88e5293..bc9d39b647fd 100644 --- a/doc/topics/releases/neon.rst +++ b/doc/topics/releases/neon.rst @@ -3,8 +3,6 @@ ================================== Salt Release Notes - Codename Neon ================================== -<<<<<<< HEAD -======= Saltcheck Updates @@ -295,4 +293,3 @@ State Deprecations - Support for the ``force`` kwarg has been removed from the :py:func:`win_servermanager.installed ` function. Please use ``recurse`` instead. ->>>>>>> 560a1db1e1... Merge pull request #50141 from mchugh19/ssh_auth_manage diff --git a/tests/unit/states/test_ssh_auth.py b/tests/unit/states/test_ssh_auth.py index 57a7cc99afb7..cda100311195 100644 --- a/tests/unit/states/test_ssh_auth.py +++ b/tests/unit/states/test_ssh_auth.py @@ -102,3 +102,40 @@ def test_absent(self): ret.update({'comment': comt, 'result': True, 'changes': {name: 'Removed'}}) self.assertDictEqual(ssh_auth.absent(name, user, source), ret) + +def test_manage(self): + ''' + Test to verifies that the specified SSH key is absent. + ''' + name = 'sshkeys' + user = 'root' + source = 'salt://ssh_keys/id_rsa.pub' + + ret = {'name': name, + 'changes': {}, + 'result': None, + 'comment': ''} + + mock = MagicMock(side_effect=['User authorized keys file not present', + 'Key removed']) + mock_up = MagicMock(side_effect=['update', 'updated']) + with patch.dict(ssh_auth.__salt__, {'ssh.rm_auth_key': mock, + 'ssh.check_key': mock_up}): + with patch.dict(ssh_auth.__opts__, {'test': True}): + comt = ('Key sshkeys for user root is set for removal') + ret.update({'comment': comt}) + self.assertDictEqual(ssh_auth.absent(name, user, source), ret) + + comt = ('Key is already absent') + ret.update({'comment': comt, 'result': True}) + self.assertDictEqual(ssh_auth.manage(name, user, source), ret) + + with patch.dict(ssh_auth.__opts__, {'test': False}): + comt = ('User authorized keys file not present') + ret.update({'comment': comt, 'result': False}) + self.assertDictEqual(ssh_auth.absent(name, user, source), ret) + + comt = ('Key removed') + ret.update({'comment': comt, 'result': True, + 'changes': {name: 'Removed'}}) + self.assertDictEqual(ssh_auth.manage(name, user, source), ret) From 74008ca9f8b42cba1f19dd7de3bbf973927b813a Mon Sep 17 00:00:00 2001 From: Christian McHugh Date: Sun, 13 Oct 2019 09:00:33 +0100 Subject: [PATCH 3/5] Add tests --- salt/states/ssh_auth.py | 2 +- tests/unit/states/test_ssh_auth.py | 90 +++++++++++++++++++++--------- 2 files changed, 65 insertions(+), 27 deletions(-) diff --git a/salt/states/ssh_auth.py b/salt/states/ssh_auth.py index 1db9dd7aaad3..d73330dff175 100644 --- a/salt/states/ssh_auth.py +++ b/salt/states/ssh_auth.py @@ -595,7 +595,7 @@ def manage( ret['changes'].update(run_return['changes']) else: ret['comment'] += '\n' + run_return['comment'] - ret['comment'].strip() + ret['comment'] = ret['comment'].strip() if run_return['result'] is None: ret['result'] = None diff --git a/tests/unit/states/test_ssh_auth.py b/tests/unit/states/test_ssh_auth.py index cda100311195..ae5ebc811579 100644 --- a/tests/unit/states/test_ssh_auth.py +++ b/tests/unit/states/test_ssh_auth.py @@ -103,39 +103,77 @@ def test_absent(self): 'changes': {name: 'Removed'}}) self.assertDictEqual(ssh_auth.absent(name, user, source), ret) -def test_manage(self): + def test_manage(self): ''' Test to verifies that the specified SSH key is absent. ''' - name = 'sshkeys' user = 'root' - source = 'salt://ssh_keys/id_rsa.pub' - - ret = {'name': name, + ret = {'name': '', 'changes': {}, 'result': None, 'comment': ''} - mock = MagicMock(side_effect=['User authorized keys file not present', + mock_rm = MagicMock(side_effect=['User authorized keys file not present', 'Key removed']) mock_up = MagicMock(side_effect=['update', 'updated']) - with patch.dict(ssh_auth.__salt__, {'ssh.rm_auth_key': mock, - 'ssh.check_key': mock_up}): - with patch.dict(ssh_auth.__opts__, {'test': True}): - comt = ('Key sshkeys for user root is set for removal') - ret.update({'comment': comt}) - self.assertDictEqual(ssh_auth.absent(name, user, source), ret) - - comt = ('Key is already absent') - ret.update({'comment': comt, 'result': True}) - self.assertDictEqual(ssh_auth.manage(name, user, source), ret) - - with patch.dict(ssh_auth.__opts__, {'test': False}): - comt = ('User authorized keys file not present') - ret.update({'comment': comt, 'result': False}) - self.assertDictEqual(ssh_auth.absent(name, user, source), ret) - - comt = ('Key removed') - ret.update({'comment': comt, 'result': True, - 'changes': {name: 'Removed'}}) - self.assertDictEqual(ssh_auth.manage(name, user, source), ret) + mock_set = MagicMock(side_effect=['replace', 'new']) + mock_keys = MagicMock(return_value={'somekey': { + "enc": "ssh-rsa", + "comment": "user@host", + "options": [], + "fingerprint": "b7"}}) + with patch.dict(ssh_auth.__salt__, {'ssh.rm_auth_key': mock_rm, + 'ssh.set_auth_key': mock_set, + 'ssh.check_key': mock_up, + 'ssh.auth_keys': mock_keys}): + with patch('salt.states.ssh_auth.present') as call_mocked_present: + mock_present = {'comment': '', + 'changes': {}, + 'result': None + } + call_mocked_present.return_value=mock_present + with patch.dict(ssh_auth.__opts__, {'test': True}): + # test: expected keys found. No chanages + self.assertDictEqual(ssh_auth.manage('sshid', ['somekey'], user), ret) + + comt = ('somekey Key set for removal') + ret.update({'comment': comt}) + # test: unexpected sshkey found. Should be removed. + self.assertDictEqual(ssh_auth.manage('sshid', [], user), ret) + + with patch('salt.states.ssh_auth.present') as call_mocked_present: + mock_present = {'comment': '', + 'changes': {}, + 'result': True + } + call_mocked_present.return_value=mock_present + with patch.dict(ssh_auth.__opts__, {'test': False}): + # expected keys found. No changes + ret = {'name': '', + 'changes': {}, + 'result': True, + 'comment': ''} + self.assertDictEqual(ssh_auth.manage('sshid', ['somekey'], user), ret) + + with patch('salt.states.ssh_auth.absent') as call_mocked_absent: + mock_absent = {'comment': 'Key removed'} + call_mocked_absent.return_value=mock_absent + ret.update({'comment': '', 'result': True, + 'changes': {'somekey': 'Key removed'}}) + # unexpected sshkey found. Was removed. + self.assertDictEqual(ssh_auth.manage('sshid', ['addkey'], user), ret) + + # add a key + with patch('salt.states.ssh_auth.present') as call_mocked_present: + mock_present = {'comment': 'The authorized host key newkey for user {} was added'.format(user), + 'changes': {'newkey': 'New'}, + 'result': True + } + call_mocked_present.return_value=mock_present + with patch.dict(ssh_auth.__opts__, {'test': False}): + # added key newkey + ret = {'name': '', + 'changes': {'newkey': 'New'}, + 'result': True, + 'comment': ''} + self.assertDictEqual(ssh_auth.manage('sshid', ['newkey', 'somekey'], user), ret) From b7839fcff5a5dc451ab6bb6708fb606a3fdfcde0 Mon Sep 17 00:00:00 2001 From: Christian McHugh Date: Wed, 13 Nov 2019 22:27:46 +0000 Subject: [PATCH 4/5] update release notes --- doc/topics/releases/neon.rst | 284 ----------------------------------- 1 file changed, 284 deletions(-) diff --git a/doc/topics/releases/neon.rst b/doc/topics/releases/neon.rst index bc9d39b647fd..bc21ad1d4763 100644 --- a/doc/topics/releases/neon.rst +++ b/doc/topics/releases/neon.rst @@ -4,292 +4,8 @@ Salt Release Notes - Codename Neon ================================== - -Saltcheck Updates -================= - -Available since 2018.3, the saltcheck module has been enhanced to: - * Support saltenv environments - * Associate tests with states by naming convention - * Adds empty and notempty assertions - * Adds skip keyword - * Adds print_result keyword - * Adds assertion_section keyword - * Use saltcheck.state_apply to run state.apply for test setup or teardown - * Changes output to display test time - -Saltcheck provides unittest like functionality requiring only the knowledge of -salt module execution and yaml. Saltcheck uses salt modules to return data, then -runs an assertion against that return. This allows for testing with all the -features included in salt modules. - -In order to run state and highstate saltcheck tests, a sub-folder in the state directory -must be created and named ``saltcheck-tests``. Tests for a state should be created in files -ending in ``*.tst`` and placed in the ``saltcheck-tests`` folder. ``tst`` files are run -through the salt rendering system, enabling tests to be written in yaml (or renderer of choice), -and include jinja, as well as the usual grain and pillar information. Like states, multiple tests can -be specified in a ``tst`` file. Multiple ``tst`` files can be created in the ``saltcheck-tests`` -folder, and should be named the same as the associated state. The ``id`` of a test works in the -same manner as in salt state files and should be unique and descriptive. - -Usage ------ - -Example file system layout: - -.. code-block:: txt - - /srv/salt/apache/ - init.sls - config.sls - saltcheck-tests/ - init.tst - config.tst - deployment_validation.tst - -Tests can be run for each state by name, for all apache/saltcheck/*.tst files, or for all states -assigned to the minion in top.sls. Tests may also be created with no associated state. These tests -will be run through the use of ``saltcheck.run_state_tests``, but will not be automatically run -by ``saltcheck.run_highstate_tests``. - -.. code-block:: bash - - salt '*' saltcheck.run_state_tests apache,apache.config - salt '*' saltcheck.run_state_tests apache check_all=True - salt '*' saltcheck.run_highstate_tests - salt '*' saltcheck.run_state_tests apache.deployment_validation - -Example Tests -------------- - -.. code-block:: jinja - - {# will run the common salt state before further testing #} - setup_test_environment: - module_and_function: saltcheck.state_apply - args: - - common - pillar-data: - data: value - - {% for package in ["apache2", "openssh"] %} - {# or another example #} - {# for package in salt['pillar.get']("packages") #} - jinja_test_{{ package }}_latest: - module_and_function: pkg.upgrade_available - args: - - {{ package }} - assertion: assertFalse - {% endfor %} - - validate_user_present_and_shell: - module_and_function: user.info - args: - - root - assertion: assertEqual - expected-return: /bin/bash - assertion_section: shell - print_result: False - - skip_test: - module_and_function: pkg.upgrade_available - args: - - apache2 - assertion: assertFalse - skip: True - -Output Format Changes ---------------------- - -Saltcheck output has been enhanced to display the time taken per test. This results -in a change to the output format. - -Previous Output: - -.. code-block:: text - - local: - |_ - ---------- - ntp: - ---------- - ntp-client-installed: - Pass - ntp-service-status: - Pass - |_ - ---------- - TEST RESULTS: - ---------- - Failed: - 0 - Missing Tests: - 0 - Passed: - 2 - -New output: - -.. code-block:: text - - local: - |_ - ---------- - ntp: - ---------- - ntp-client-installed: - ---------- - duration: - 1.0408 - status: - Pass - ntp-service-status: - ---------- - duration: - 1.464 - status: - Pass - |_ - ---------- - TEST RESULTS: - ---------- - Execution Time: - 2.5048 - Failed: - 0 - Missing Tests: - 0 - Passed: - 2 - Skipped: - 0 - -XML Module -========== - -A new state and execution module for editing XML files is now included. Currently it allows for -editing values from an xpath query, or editing XML IDs. - -.. code-block:: bash - - # salt-call xml.set_attribute /tmp/test.xml ".//actor[@id='3']" editedby "Jane Doe" - local: - True - # salt-call xml.get_attribute /tmp/test.xml ".//actor[@id='3']" - local: - ---------- - editedby: - Jane Doe - id: - 3 - # salt-call xml.get_value /tmp/test.xml ".//actor[@id='2']" - local: - Liam Neeson - # salt-call xml.set_value /tmp/test.xml ".//actor[@id='2']" "Patrick Stewart" - local: - True - # salt-call xml.get_value /tmp/test.xml ".//actor[@id='2']" - local: - Patrick Stewart - -.. code-block:: yaml - - ensure_value_true: - xml.value_present: - - name: /tmp/test.xml - - xpath: .//actor[@id='1'] - - value: William Shatner - - - State Changes ============= -- The :py:func:`file.rename ` state will now return a - ``True`` result (and make no changes) when the destination file already - exists, and ``Force`` is not set to ``True``. In previous releases, a - ``False`` result would be returned, but this meant that subsequent runs of - the state would fail due to the destination file being present. - -- The ``onchanges`` and ``prereq`` :ref:`requisites ` now behave - properly in test mode. - - Added new :py:func:`ssh_auth.manage ` state to ensure only the specified ssh keys are present for the specified user. - -Module Changes -============== - -- The :py:func:`debian_ip ` module used by the - :py:func:`network.managed ` state has been - heavily refactored. The order that options appear in inet/inet6 blocks may - produce cosmetic changes. Many options without an 'ipvX' prefix will now be - shared between inet and inet6 blocks. The options ``enable_ipv4`` and - ``enabled_ipv6`` will now fully remove relevant inet/inet6 blocks. Overriding - options by prefixing them with 'ipvX' will now work with most options (i.e. - ``dns`` can be overriden by ``ipv4dns`` or ``ipv6dns``). The ``proto`` option - is now required. - -Salt Cloud Features -=================== - -GCE Driver ----------- - -The GCE salt cloud driver can now be used with GCE instance credentials by -setting the configuration paramaters ``service_account_private_key`` and -``service_account_private_email`` to an empty string. - -Deprecations -============ - -RAET Transport --------------- - -Support for RAET has been removed. Please use the ``zeromq`` or ``tcp`` transport -instead of ``raet``. - -Module Deprecations -------------------- - -- The :py:mod:`dockermod ` module has been - changed as follows: - - - Support for the ``tags`` kwarg has been removed from the - :py:func:`dockermod.resolve_tag ` - function. - - Support for the ``network_id`` kwarg has been removed from the - :py:func:`dockermod.connect_container_to_network ` - function. Please use ``net_id`` instead. - - Support for the ``name`` kwarg has been removed from the - :py:func:`dockermod.sls_build ` - function. Please use ``repository`` and ``tag`` instead. - - Support for the ``image`` kwarg has been removed from the following - functions. In all cases, please use both the ``repository`` and ``tag`` - options instead: - - - :py:func:`dockermod.build ` - - :py:func:`dockermod.commit ` - - :py:func:`dockermod.import ` - - :py:func:`dockermod.load ` - - :py:func:`dockermod.tag ` - -- The :py:mod:`ssh ` execution module has been - changed as follows: - - - Support for the ``ssh.get_known_host`` function has been removed. Please use the - :py:func:`ssh.get_known_host_entries ` - function instead. - - Support for the ``ssh.recv_known_host`` function has been removed. Please use the - :py:func:`ssh.recv_known_host_entries ` - function instead. - -State Deprecations ------------------- - -- The :py:mod:`win_servermanager ` state has been - changed as follows: - - - Support for the ``force`` kwarg has been removed from the - :py:func:`win_servermanager.installed ` - function. Please use ``recurse`` instead. From ab2a74a93c7cff4eaeaba38442899b6014aaefd2 Mon Sep 17 00:00:00 2001 From: Daniel Wozniak Date: Thu, 14 Nov 2019 15:10:05 -0700 Subject: [PATCH 5/5] Resolve linter issues --- tests/unit/states/test_ssh_auth.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/unit/states/test_ssh_auth.py b/tests/unit/states/test_ssh_auth.py index ae5ebc811579..2d3bb084783d 100644 --- a/tests/unit/states/test_ssh_auth.py +++ b/tests/unit/states/test_ssh_auth.py @@ -131,7 +131,7 @@ def test_manage(self): 'changes': {}, 'result': None } - call_mocked_present.return_value=mock_present + call_mocked_present.return_value = mock_present with patch.dict(ssh_auth.__opts__, {'test': True}): # test: expected keys found. No chanages self.assertDictEqual(ssh_auth.manage('sshid', ['somekey'], user), ret) @@ -146,7 +146,7 @@ def test_manage(self): 'changes': {}, 'result': True } - call_mocked_present.return_value=mock_present + call_mocked_present.return_value = mock_present with patch.dict(ssh_auth.__opts__, {'test': False}): # expected keys found. No changes ret = {'name': '', @@ -157,7 +157,7 @@ def test_manage(self): with patch('salt.states.ssh_auth.absent') as call_mocked_absent: mock_absent = {'comment': 'Key removed'} - call_mocked_absent.return_value=mock_absent + call_mocked_absent.return_value = mock_absent ret.update({'comment': '', 'result': True, 'changes': {'somekey': 'Key removed'}}) # unexpected sshkey found. Was removed. @@ -169,7 +169,7 @@ def test_manage(self): 'changes': {'newkey': 'New'}, 'result': True } - call_mocked_present.return_value=mock_present + call_mocked_present.return_value = mock_present with patch.dict(ssh_auth.__opts__, {'test': False}): # added key newkey ret = {'name': '',