mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Merge pull request #33637 from rallytime/merge-2016.3
[2016.3] Merge forward from 2015.8 to 2016.3
This commit is contained in:
commit
b379dc57fd
8 changed files with 249 additions and 74 deletions
|
@ -150,12 +150,16 @@ def install(feature, recurse=False):
|
|||
'-WarningAction SilentlyContinue'.format(_cmd_quote(feature), sub)
|
||||
out = _pshell_json(cmd)
|
||||
|
||||
ret = {'ExitCode': out['ExitCode'],
|
||||
'DisplayName': out['FeatureResult'][0]['DisplayName'],
|
||||
'RestartNeeded': out['FeatureResult'][0]['RestartNeeded'],
|
||||
'Success': out['Success']}
|
||||
|
||||
return ret
|
||||
if out['FeatureResult']:
|
||||
return {'ExitCode': out['ExitCode'],
|
||||
'DisplayName': out['FeatureResult'][0]['DisplayName'],
|
||||
'RestartNeeded': out['FeatureResult'][0]['RestartNeeded'],
|
||||
'Success': out['Success']}
|
||||
else:
|
||||
return {'ExitCode': out['ExitCode'],
|
||||
'DisplayName': '{0} (already installed)'.format(feature),
|
||||
'RestartNeeded': False,
|
||||
'Success': out['Success']}
|
||||
|
||||
|
||||
def remove(feature):
|
||||
|
@ -185,9 +189,13 @@ def remove(feature):
|
|||
'-WarningAction SilentlyContinue'.format(_cmd_quote(feature))
|
||||
out = _pshell_json(cmd)
|
||||
|
||||
ret = {'ExitCode': out['ExitCode'],
|
||||
'DisplayName': out['FeatureResult'][0]['DisplayName'],
|
||||
'RestartNeeded': out['FeatureResult'][0]['RestartNeeded'],
|
||||
'Success': out['Success']}
|
||||
|
||||
return ret
|
||||
if out['FeatureResult']:
|
||||
return {'ExitCode': out['ExitCode'],
|
||||
'DisplayName': out['FeatureResult'][0]['DisplayName'],
|
||||
'RestartNeeded': out['FeatureResult'][0]['RestartNeeded'],
|
||||
'Success': out['Success']}
|
||||
else:
|
||||
return {'ExitCode': out['ExitCode'],
|
||||
'DisplayName': '{0} (not installed)'.format(feature),
|
||||
'RestartNeeded': False,
|
||||
'Success': out['Success']}
|
||||
|
|
|
@ -242,6 +242,54 @@ external template file.
|
|||
following tags: `macro`, `set`, `load_yaml`, `load_json`, `import_yaml` and
|
||||
`import_json`.
|
||||
|
||||
Escaping Jinja
|
||||
==============
|
||||
|
||||
Occasionally, it may be necessary to escape Jinja syntax. There are two ways to
|
||||
to do this in Jinja. One is escaping individual variables or strings and the
|
||||
other is to escape entire blocks.
|
||||
|
||||
To escape a string commonly used in Jinja syntax such as ``{{``, you can use the
|
||||
following syntax:
|
||||
|
||||
.. code-block:: jinja
|
||||
|
||||
{{ '{{' }}
|
||||
|
||||
For larger blocks that contain Jinja syntax that needs to be escaped, you can use
|
||||
raw blocks:
|
||||
|
||||
.. code-block:: jinja
|
||||
|
||||
{% raw %]
|
||||
some text that contains jinja characters that need to be escaped
|
||||
{% endraw %}
|
||||
|
||||
See the `Escaping`_ section of Jinja's documentation to learn more.
|
||||
|
||||
A real-word example of needing to use raw tags to escape a larger block of code
|
||||
is when using ``file.managed`` with the ``contents_pillar`` option to manage
|
||||
files that contain something like consul-template, which shares a syntax subset
|
||||
with Jinja. Raw blocks are necessary here because the Jinja in the pillar would
|
||||
be rendered before the file.managed is ever called, so the Jinja syntax must be
|
||||
escaped:
|
||||
|
||||
.. code-block:: jinja
|
||||
|
||||
{% raw %}
|
||||
- contents_pillar: |
|
||||
job "example-job" {
|
||||
<snipped>
|
||||
task "example" {
|
||||
driver = "docker"
|
||||
|
||||
config {
|
||||
image = "docker-registry.service.consul:5000/example-job:{{key "nomad/jobs/example-job/version"}}"
|
||||
<snipped>
|
||||
{% endraw %}
|
||||
|
||||
.. _`Escaping`: http://jinja.pocoo.org/docs/dev/templates/#escaping
|
||||
|
||||
Calling Salt Functions
|
||||
======================
|
||||
|
||||
|
|
|
@ -407,14 +407,14 @@ def clean_old_jobs():
|
|||
for final in t_path_dirs:
|
||||
f_path = os.path.join(t_path, final)
|
||||
jid_file = os.path.join(f_path, 'jid')
|
||||
if not os.path.isfile(jid_file):
|
||||
if not os.path.isfile(jid_file) and os.path.exists(t_path):
|
||||
# No jid file means corrupted cache entry, scrub it
|
||||
# by removing the entire t_path directory
|
||||
shutil.rmtree(t_path)
|
||||
else:
|
||||
elif os.path.isfile(jid_file):
|
||||
jid_ctime = os.stat(jid_file).st_ctime
|
||||
hours_difference = (cur - jid_ctime) / 3600.0
|
||||
if hours_difference > __opts__['keep_jobs']:
|
||||
if hours_difference > __opts__['keep_jobs'] and os.path.exists(t_path):
|
||||
# Remove the entire t_path from the original JID dir
|
||||
shutil.rmtree(t_path)
|
||||
|
||||
|
|
|
@ -3,6 +3,9 @@
|
|||
Manage Windows features via the ServerManager powershell module
|
||||
'''
|
||||
|
||||
# Import salt modules
|
||||
import salt.utils
|
||||
|
||||
|
||||
def __virtual__():
|
||||
'''
|
||||
|
@ -49,10 +52,13 @@ def installed(name, recurse=False, force=False):
|
|||
'comment': ''}
|
||||
|
||||
# Determine if the feature is installed
|
||||
if name not in __salt__['win_servermanager.list_installed']():
|
||||
ret['changes'] = {'feature': '{0} will be installed recurse={1}'.format(name, recurse)}
|
||||
old = __salt__['win_servermanager.list_installed']()
|
||||
if name not in old:
|
||||
ret['changes']['feature'] = \
|
||||
'{0} will be installed recurse={1}'.format(name, recurse)
|
||||
elif force and recurse:
|
||||
ret['changes'] = {'feature': '{0} already installed but might install sub-features'.format(name)}
|
||||
ret['changes']['feature'] = \
|
||||
'{0} already installed but might install sub-features'.format(name)
|
||||
else:
|
||||
ret['comment'] = 'The feature {0} is already installed'.format(name)
|
||||
return ret
|
||||
|
@ -61,19 +67,26 @@ def installed(name, recurse=False, force=False):
|
|||
ret['result'] = None
|
||||
return ret
|
||||
|
||||
# Install the features
|
||||
ret['changes'] = {'feature': __salt__['win_servermanager.install'](name, recurse)}
|
||||
if ret['changes']['feature']:
|
||||
ret['comment'] = ret['changes']['feature']
|
||||
|
||||
if 'Success' in ret['changes']['feature']:
|
||||
ret['result'] = ret['changes']['feature']['Success']
|
||||
if not ret['result']:
|
||||
ret['comment'] = 'Failed to install {0}: {1}'.format(name, ret['changes']['feature']['ExitCode'])
|
||||
else:
|
||||
ret['comment'] = 'Installed {0}'.format(name)
|
||||
else:
|
||||
ret['result'] = False
|
||||
ret['comment'] = 'Failed to install {0}.\nError Message:\n{1}'.format(name, ret['changes']['feature'])
|
||||
ret['changes'] = {}
|
||||
ret['changes'] = {}
|
||||
|
||||
# Install the features
|
||||
status = __salt__['win_servermanager.install'](name, recurse)
|
||||
|
||||
ret['result'] = status['Success']
|
||||
if not ret['result']:
|
||||
ret['comment'] = 'Failed to install {0}: {1}'\
|
||||
.format(name, status['ExitCode'])
|
||||
|
||||
new = __salt__['win_servermanager.list_installed']()
|
||||
changes = salt.utils.compare_dicts(old, new)
|
||||
|
||||
if changes:
|
||||
ret['comment'] = 'Installed {0}'.format(name)
|
||||
ret['changes'] = status
|
||||
ret['changes']['feature'] = changes
|
||||
|
||||
return ret
|
||||
|
||||
|
@ -107,8 +120,9 @@ def removed(name):
|
|||
'changes': {},
|
||||
'comment': ''}
|
||||
# Determine if the feature is installed
|
||||
if name in __salt__['win_servermanager.list_installed']():
|
||||
ret['changes'] = {'feature': '{0} will be removed'.format(name)}
|
||||
old = __salt__['win_servermanager.list_installed']()
|
||||
if name in old:
|
||||
ret['changes']['feature'] = '{0} will be removed'.format(name)
|
||||
else:
|
||||
ret['comment'] = 'The feature {0} is not installed'.format(name)
|
||||
return ret
|
||||
|
@ -117,10 +131,22 @@ def removed(name):
|
|||
ret['result'] = None
|
||||
return ret
|
||||
|
||||
ret['changes'] = {}
|
||||
|
||||
# Remove the features
|
||||
ret['changes'] = {'feature': __salt__['win_servermanager.remove'](name)}
|
||||
ret['result'] = ret['changes']['feature']['Success']
|
||||
status = __salt__['win_servermanager.remove'](name)
|
||||
|
||||
ret['result'] = status['Success']
|
||||
if not ret['result']:
|
||||
ret['comment'] = 'Failed to uninstall the feature {0}'.format(ret['changes']['feature']['ExitCode'])
|
||||
ret['comment'] = 'Failed to uninstall the feature {0}'\
|
||||
.format(status['ExitCode'])
|
||||
|
||||
new = __salt__['win_servermanager.list_installed']()
|
||||
changes = salt.utils.compare_dicts(old, new)
|
||||
|
||||
if changes:
|
||||
ret['comment'] = 'Removed {0}'.format(name)
|
||||
ret['changes'] = status
|
||||
ret['changes']['feature'] = changes
|
||||
|
||||
return ret
|
||||
|
|
|
@ -95,6 +95,22 @@ class RpmTestCase(TestCase):
|
|||
self.assertDictEqual(rpm.owner('/usr/bin/python', '/usr/bin/vim'),
|
||||
ret)
|
||||
|
||||
# 'checksum' function tests: 1
|
||||
|
||||
def test_checksum(self):
|
||||
'''
|
||||
Test if checksum validate as expected
|
||||
'''
|
||||
ret = {
|
||||
"file1.rpm": True,
|
||||
"file2.rpm": False,
|
||||
"file3.rpm": False,
|
||||
}
|
||||
|
||||
mock = MagicMock(side_effect=[True, 0, True, 1, False, 0])
|
||||
with patch.dict(rpm.__salt__, {'file.file_exists': mock, 'cmd.retcode': mock}):
|
||||
self.assertDictEqual(rpm.checksum("file1.rpm", "file2.rpm", "file3.rpm"), ret)
|
||||
|
||||
@patch('salt.modules.rpm.HAS_RPM', True)
|
||||
def test_version_cmp_rpm(self):
|
||||
'''
|
||||
|
|
19
tests/unit/modules/zypp/zypper-download.xml
Normal file
19
tests/unit/modules/zypp/zypper-download.xml
Normal file
|
@ -0,0 +1,19 @@
|
|||
<?xml version='1.0'?>
|
||||
<stream>
|
||||
<message type="info">Loading repository data...</message>
|
||||
<message type="info">Reading installed packages...</message>
|
||||
<message type="warning">Argument resolves to no package: foo</message>
|
||||
<progress id="" name="(1/1) /var/cache/zypp/packages/SLE-12-x86_64-Pool/x86_64/nmap-6.46-1.72.x86_64.rpm"/>
|
||||
<download-result>
|
||||
<solvable>
|
||||
<kind>package</kind>
|
||||
<name>nmap</name>
|
||||
<edition epoch="0" version="6.46" release="1.72"/>
|
||||
<arch>x86_64</arch>
|
||||
<repository name="SLE-12-x86_64-Pool" alias="SLE-12-x86_64-Pool"/>
|
||||
</solvable>
|
||||
<localfile path="/var/cache/zypp/packages/SLE-12-x86_64-Pool/x86_64/nmap-6.46-1.72.x86_64.rpm"/>
|
||||
</download-result>
|
||||
<progress id="" name="(1/1) /var/cache/zypp/packages/SLE-12-x86_64-Pool/x86_64/nmap-6.46-1.72.x86_64.rpm" done="0"/>
|
||||
<message type="info">download: Done.</message>
|
||||
</stream>
|
|
@ -355,6 +355,30 @@ class ZypperTestCase(TestCase):
|
|||
self.assertTrue(pkgs.get(pkg_name))
|
||||
self.assertEqual(pkgs[pkg_name], pkg_version)
|
||||
|
||||
def test_download(self):
|
||||
'''
|
||||
Test package download
|
||||
:return:
|
||||
'''
|
||||
download_out = {
|
||||
'stdout': get_test_data('zypper-download.xml'),
|
||||
'stderr': None,
|
||||
'retcode': 0
|
||||
}
|
||||
|
||||
test_out = {
|
||||
'nmap': {
|
||||
'repository-alias': u'SLE-12-x86_64-Pool',
|
||||
'repository-name': u'SLE-12-x86_64-Pool'
|
||||
}
|
||||
}
|
||||
|
||||
with patch.dict(zypper.__salt__, {'cmd.run_all': MagicMock(return_value=download_out)}):
|
||||
with patch.dict(zypper.__salt__, {'lowpkg.checksum': MagicMock(return_value=True)}):
|
||||
self.assertEqual(zypper.download("nmap"), test_out)
|
||||
test_out['_error'] = "The following package(s) failed to download: foo"
|
||||
self.assertEqual(zypper.download("nmap", "foo"), test_out)
|
||||
|
||||
def test_remove_purge(self):
|
||||
'''
|
||||
Test package removal
|
||||
|
|
|
@ -35,58 +35,92 @@ class WinServermanagerTestCase(TestCase):
|
|||
'''
|
||||
Test to install the windows feature
|
||||
'''
|
||||
ret = {'name': 'salt',
|
||||
'changes': {},
|
||||
'result': True,
|
||||
'comment': ''}
|
||||
mock = MagicMock(side_effect=['salt', 'stack', 'stack'])
|
||||
mock1 = MagicMock(return_value={'Success': True})
|
||||
mock_list = MagicMock(
|
||||
side_effect=[{'spongebob': 'squarepants'},
|
||||
{'squidward': 'patrick'},
|
||||
{'spongebob': 'squarepants'},
|
||||
{'spongebob': 'squarepants',
|
||||
'squidward': 'patrick'}])
|
||||
mock_install = MagicMock(
|
||||
return_value={'Success': True,
|
||||
'RestartNeeded': False,
|
||||
'ExitCode': 1234})
|
||||
with patch.dict(win_servermanager.__salt__,
|
||||
{"win_servermanager.list_installed": mock,
|
||||
"win_servermanager.install": mock1}):
|
||||
ret.update({'comment': 'The feature salt is already installed'})
|
||||
self.assertDictEqual(win_servermanager.installed('salt'), ret)
|
||||
{"win_servermanager.list_installed": mock_list,
|
||||
"win_servermanager.install": mock_install}):
|
||||
ret = {'name': 'spongebob',
|
||||
'changes': {},
|
||||
'result': True,
|
||||
'comment': 'The feature spongebob is already installed'}
|
||||
self.assertDictEqual(win_servermanager.installed('spongebob'), ret)
|
||||
|
||||
with patch.dict(win_servermanager.__opts__, {"test": True}):
|
||||
ret.update({'changes': {'feature':
|
||||
'salt will be installed'
|
||||
' recurse=False'}, 'result': None,
|
||||
'comment': ''})
|
||||
self.assertDictEqual(win_servermanager.installed('salt'), ret)
|
||||
ret = {'name': 'spongebob',
|
||||
'result': None,
|
||||
'comment': '',
|
||||
'changes': {
|
||||
'feature': 'spongebob will be installed '
|
||||
'recurse=False'}}
|
||||
self.assertDictEqual(
|
||||
win_servermanager.installed('spongebob'), ret)
|
||||
|
||||
with patch.dict(win_servermanager.__opts__, {"test": False}):
|
||||
ret.update({'changes': {'feature': {'Success': True}},
|
||||
'result': True, 'comment': 'Installed salt'})
|
||||
self.assertDictEqual(win_servermanager.installed('salt'),
|
||||
ret)
|
||||
with patch.dict(win_servermanager.__opts__, {"test": False}):
|
||||
ret = {'name': 'squidward',
|
||||
'result': True,
|
||||
'comment': 'Installed squidward',
|
||||
'changes': {
|
||||
'Success': True,
|
||||
'RestartNeeded': False,
|
||||
'ExitCode': 1234,
|
||||
'feature': {'squidward': {'new': 'patrick',
|
||||
'old': ''}}}}
|
||||
self.assertDictEqual(
|
||||
win_servermanager.installed('squidward'), ret)
|
||||
|
||||
def test_removed(self):
|
||||
'''
|
||||
Test to remove the windows feature
|
||||
'''
|
||||
ret = {'name': 'salt',
|
||||
'changes': {},
|
||||
'result': True,
|
||||
'comment': ''}
|
||||
mock = MagicMock(side_effect=['stack', 'salt', 'salt'])
|
||||
mock1 = MagicMock(return_value={'Success': True})
|
||||
mock_list = MagicMock(
|
||||
side_effect=[{'spongebob': 'squarepants'},
|
||||
{'squidward': 'patrick'},
|
||||
{'spongebob': 'squarepants',
|
||||
'squidward': 'patrick'},
|
||||
{'spongebob': 'squarepants'}])
|
||||
mock_remove = MagicMock(
|
||||
return_value={'Success': True,
|
||||
'RestartNeeded': False,
|
||||
'ExitCode': 1234})
|
||||
with patch.dict(win_servermanager.__salt__,
|
||||
{"win_servermanager.list_installed": mock,
|
||||
"win_servermanager.remove": mock1}):
|
||||
ret.update({'comment': 'The feature salt is not installed'})
|
||||
self.assertDictEqual(win_servermanager.removed('salt'), ret)
|
||||
{"win_servermanager.list_installed": mock_list,
|
||||
"win_servermanager.remove": mock_remove}):
|
||||
ret = {'name': 'squidward',
|
||||
'changes': {},
|
||||
'result': True,
|
||||
'comment': 'The feature squidward is not installed'}
|
||||
self.assertDictEqual(
|
||||
win_servermanager.removed('squidward'), ret)
|
||||
|
||||
with patch.dict(win_servermanager.__opts__, {"test": True}):
|
||||
ret.update({'changes': {'feature':
|
||||
'salt will be removed'},
|
||||
'result': None, 'comment': ''})
|
||||
self.assertDictEqual(win_servermanager.removed('salt'), ret)
|
||||
ret = {'name': 'squidward',
|
||||
'result': None,
|
||||
'comment': '',
|
||||
'changes': {'feature': 'squidward will be removed'}}
|
||||
self.assertDictEqual(
|
||||
win_servermanager.removed('squidward'), ret)
|
||||
|
||||
with patch.dict(win_servermanager.__opts__, {"test": False}):
|
||||
ret.update({'changes': {'feature': {'Success': True}},
|
||||
'result': True})
|
||||
self.assertDictEqual(win_servermanager.removed('salt'),
|
||||
ret)
|
||||
with patch.dict(win_servermanager.__opts__, {"test": False}):
|
||||
ret = {'name': 'squidward',
|
||||
'result': True,
|
||||
'comment': 'Removed squidward',
|
||||
'changes': {
|
||||
'Success': True,
|
||||
'RestartNeeded': False,
|
||||
'ExitCode': 1234,
|
||||
'feature': {'squidward': {'new': '',
|
||||
'old': 'patrick'}}}}
|
||||
self.assertDictEqual(
|
||||
win_servermanager.removed('squidward'), ret)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
Loading…
Add table
Reference in a new issue