Merge branch '2015.8' into '2016.3'

Conflicts:
  -   -   -   -   -   -   -   -   - doc/conf.py
This commit is contained in:
Nicole Thomas 2016-05-31 11:02:20 -04:00
commit 74a7b78e00
8 changed files with 250 additions and 74 deletions

View file

@ -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']}

View file

@ -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
======================

View file

@ -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)

View file

@ -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

View file

@ -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):
'''

View 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>

View file

@ -355,6 +355,31 @@ 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': {
'path': u'/var/cache/zypp/packages/SLE-12-x86_64-Pool/x86_64/nmap-6.46-1.72.x86_64.rpm',
'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

View file

@ -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__':