Fix stacktrace in return from win_pkg

Returns a meaningful message without the stacktrace
Adds some tests
This commit is contained in:
twangboy 2020-04-28 16:27:52 -06:00 committed by Daniel Wozniak
parent 5852d60dbf
commit dfdcf95d93
3 changed files with 277 additions and 26 deletions

View file

@ -1015,12 +1015,17 @@ def refresh_db(**kwargs):
# Cache repo-ng locally
log.info("Fetching *.sls files from {0}".format(repo_details.winrepo_source_dir))
__salt__["cp.cache_dir"](
path=repo_details.winrepo_source_dir,
saltenv=saltenv,
include_pat="*.sls",
exclude_pat=r"E@\/\..*?\/", # Exclude all hidden directories (.git)
)
try:
__salt__["cp.cache_dir"](
path=repo_details.winrepo_source_dir,
saltenv=saltenv,
include_pat="*.sls",
exclude_pat=r"E@\/\..*?\/", # Exclude all hidden directories (.git)
)
except MinionError as exc:
log.exception(
"Failed to cache %s" % repo_details.winrepo_source_dir, exc_info=exc
)
return genrepo(saltenv=saltenv, verbose=verbose, failhard=failhard)
@ -1300,12 +1305,14 @@ def _get_source_sum(source_hash, file_path, saltenv):
if source_hash_scheme in schemes:
# The source_hash is a file on a server
cached_hash_file = __salt__["cp.cache_file"](source_hash, saltenv)
try:
cached_hash_file = __salt__["cp.cache_file"](source_hash, saltenv)
except MinionError as exc:
log.exception("Failed to cache %s" % source_hash, exc_info=exc)
raise
if not cached_hash_file:
raise CommandExecutionError(
("Source hash file {0} not" " found").format(source_hash)
)
raise CommandExecutionError("Source hash file %s not found" % source_hash)
ret = __salt__["file.extract_hash"](cached_hash_file, "", file_path)
if ret is None:
@ -1609,13 +1616,18 @@ def install(name=None, refresh=False, pkgs=None, **kwargs):
# single files
if cache_dir and installer.startswith("salt:"):
path, _ = os.path.split(installer)
__salt__["cp.cache_dir"](
path=path,
saltenv=saltenv,
include_empty=False,
include_pat=None,
exclude_pat="E@init.sls$",
)
try:
__salt__["cp.cache_dir"](
path=path,
saltenv=saltenv,
include_empty=False,
include_pat=None,
exclude_pat="E@init.sls$",
)
except MinionError as exc:
msg = "Failed to cache %s" % path
log.exception(msg, exc_info=exc)
return "%s\n%s" % (msg, exc)
# Check to see if the cache_file is cached... if passed
if cache_file and cache_file.startswith("salt:"):
@ -1623,13 +1635,23 @@ def install(name=None, refresh=False, pkgs=None, **kwargs):
# Check to see if the file is cached
cached_file = __salt__["cp.is_cached"](cache_file, saltenv)
if not cached_file:
cached_file = __salt__["cp.cache_file"](cache_file, saltenv)
try:
cached_file = __salt__["cp.cache_file"](cache_file, saltenv)
except MinionError as exc:
msg = "Failed to cache %s" % cache_file
log.exception(msg, exc_info=exc)
return "%s\n%s" % (msg, exc)
# Make sure the cached file is the same as the source
if __salt__["cp.hash_file"](cache_file, saltenv) != __salt__[
"cp.hash_file"
](cached_file):
cached_file = __salt__["cp.cache_file"](cache_file, saltenv)
try:
cached_file = __salt__["cp.cache_file"](cache_file, saltenv)
except MinionError as exc:
msg = "Failed to cache %s" % cache_file
log.exception(msg, exc_info=exc)
return "%s\n%s" % (msg, exc)
# Check if the cache_file was cached successfully
if not cached_file:
@ -1641,7 +1663,12 @@ def install(name=None, refresh=False, pkgs=None, **kwargs):
cached_pkg = __salt__["cp.is_cached"](installer, saltenv)
if not cached_pkg:
# It's not cached. Cache it, mate.
cached_pkg = __salt__["cp.cache_file"](installer, saltenv)
try:
cached_pkg = __salt__["cp.cache_file"](installer, saltenv)
except MinionError as exc:
msg = "Failed to cache %s" % installer
log.exception(msg, exc_info=exc)
return "%s\n%s" % (msg, exc)
# Check if the installer was cached successfully
if not cached_pkg:
@ -1660,7 +1687,9 @@ def install(name=None, refresh=False, pkgs=None, **kwargs):
try:
cached_pkg = __salt__["cp.cache_file"](installer, saltenv)
except MinionError as exc:
return "{0}: {1}".format(exc, installer)
msg = "Failed to cache %s" % installer
log.exception(msg, exc_info=exc)
return "%s\n%s" % (msg, exc)
# Check if the installer was cached successfully
if not cached_pkg:
@ -2023,13 +2052,25 @@ def remove(name=None, pkgs=None, **kwargs):
if cache_dir and uninstaller.startswith("salt:"):
path, _ = os.path.split(uninstaller)
__salt__["cp.cache_dir"](path, saltenv, False, None, "E@init.sls$")
try:
__salt__["cp.cache_dir"](
path, saltenv, False, None, "E@init.sls$"
)
except MinionError as exc:
msg = "Failed to cache %s" % path
log.exception(msg, exc_info=exc)
return "%s\n%s" % (msg, exc)
# Check to see if the uninstaller is cached
cached_pkg = __salt__["cp.is_cached"](uninstaller, saltenv)
if not cached_pkg:
# It's not cached. Cache it, mate.
cached_pkg = __salt__["cp.cache_file"](uninstaller, saltenv)
try:
cached_pkg = __salt__["cp.cache_file"](uninstaller, saltenv)
except MinionError as exc:
msg = "Failed to cache %s" % uninstaller
log.exception(msg, exc_info=exc)
return "%s\n%s" % (msg, exc)
# Check if the uninstaller was cached successfully
if not cached_pkg:
@ -2047,7 +2088,9 @@ def remove(name=None, pkgs=None, **kwargs):
try:
cached_pkg = __salt__["cp.cache_file"](uninstaller, saltenv)
except MinionError as exc:
return "{0}: {1}".format(exc, uninstaller)
msg = "Failed to cache %s" % uninstaller
log.exception(msg, exc_info=exc)
return "%s\n%s" % (msg, exc)
# Check if the installer was cached successfully
if not cached_pkg:

View file

@ -609,8 +609,9 @@ class GitProvider(object):
# According to stackoverflow (http://goo.gl/l74GC8), we are setting LANGUAGE as well
# just to be sure.
env = os.environ.copy()
env[b"LANGUAGE"] = b"C"
env[b"LC_ALL"] = b"C"
if not salt.utils.platform.is_windows():
env[b"LANGUAGE"] = b"C"
env[b"LC_ALL"] = b"C"
cmd = subprocess.Popen(
shlex.split(cmd_str),

View file

@ -13,6 +13,7 @@ import salt.modules.win_pkg as win_pkg
import salt.utils.data
import salt.utils.platform
import salt.utils.win_reg as win_reg
from salt.exceptions import MinionError
# Import 3rd Party Libs
from salt.ext import six
@ -283,3 +284,209 @@ class WinPkgInstallTestCase(TestCase, LoaderModuleMockMixin):
self.assertFalse(
"-e True -test_flag True" in str(mock_cmd_run_all.call_args[0])
)
def test_pkg_install_minion_error_https(self):
"""
Test pkg.install when cp.cache_file encounters a minion error
"""
ret__get_package_info = {
"3.03": {
"uninstaller": "%program.exe",
"reboot": False,
"msiexec": False,
"installer": "https://repo.test.com/runme.exe",
"uninstall_flags": "/S",
"locale": "en_US",
"install_flags": "/s",
"full_name": "Firebox 3.03 (x86 en-US)",
}
}
err_msg = "Error: [Errno 11001] getaddrinfo failed reading https://repo.test.com/runme.exe"
mock_none = MagicMock(return_value=None)
mock_minion_error = MagicMock(side_effect=MinionError(err_msg))
mock_parse = MagicMock(return_value=[{"firebox": "3.03"}, None])
with patch.object(
salt.utils.data, "is_true", MagicMock(return_value=True)
), patch.object(
win_pkg, "_get_package_info", MagicMock(return_value=ret__get_package_info)
), patch.dict(
win_pkg.__salt__,
{
"pkg_resource.parse_targets": mock_parse,
"cp.is_cached": mock_none,
"cp.cache_file": mock_minion_error,
},
):
ret = win_pkg.install(name="firebox", version="3.03",)
expected = (
"Failed to cache https://repo.test.com/runme.exe\n"
"Error: [Errno 11001] getaddrinfo failed reading https://repo.test.com/runme.exe"
)
self.assertEqual(ret, expected)
def test_pkg_install_minion_error_salt(self):
"""
Test pkg.install when cp.cache_file encounters a minion error
"""
ret__get_package_info = {
"3.03": {
"uninstaller": "%program.exe",
"reboot": False,
"msiexec": False,
"installer": "salt://software/runme.exe",
"uninstall_flags": "/S",
"locale": "en_US",
"install_flags": "/s",
"full_name": "Firebox 3.03 (x86 en-US)",
}
}
err_msg = "Error: [Errno 1] failed reading salt://software/runme.exe"
mock_none = MagicMock(return_value=None)
mock_minion_error = MagicMock(side_effect=MinionError(err_msg))
mock_parse = MagicMock(return_value=[{"firebox": "3.03"}, None])
with patch.object(
salt.utils.data, "is_true", MagicMock(return_value=True)
), patch.object(
win_pkg, "_get_package_info", MagicMock(return_value=ret__get_package_info)
), patch.dict(
win_pkg.__salt__,
{
"pkg_resource.parse_targets": mock_parse,
"cp.is_cached": mock_none,
"cp.cache_file": mock_minion_error,
},
):
ret = win_pkg.install(name="firebox", version="3.03",)
expected = (
"Failed to cache salt://software/runme.exe\n"
"Error: [Errno 1] failed reading salt://software/runme.exe"
)
self.assertEqual(ret, expected)
def test_pkg_install_minion_error_salt_cache_dir(self):
"""
Test pkg.install when cp.cache_dir encounters a minion error
"""
ret__get_package_info = {
"3.03": {
"uninstaller": "%program.exe",
"reboot": False,
"msiexec": False,
"installer": "salt://software/runme.exe",
"cache_dir": True,
"uninstall_flags": "/S",
"locale": "en_US",
"install_flags": "/s",
"full_name": "Firebox 3.03 (x86 en-US)",
}
}
err_msg = "Error: [Errno 1] failed reading salt://software"
mock_none = MagicMock(return_value=None)
mock_minion_error = MagicMock(side_effect=MinionError(err_msg))
mock_parse = MagicMock(return_value=[{"firebox": "3.03"}, None])
with patch.object(
salt.utils.data, "is_true", MagicMock(return_value=True)
), patch.object(
win_pkg, "_get_package_info", MagicMock(return_value=ret__get_package_info)
), patch.dict(
win_pkg.__salt__, {"cp.cache_dir": mock_minion_error},
):
ret = win_pkg.install(name="firebox", version="3.03",)
expected = (
"Failed to cache salt://software\n"
"Error: [Errno 1] failed reading salt://software"
)
self.assertEqual(ret, expected)
def test_pkg_remove_minion_error_salt_cache_dir(self):
"""
Test pkg.remove when cp.cache_dir encounters a minion error
"""
ret__get_package_info = {
"3.03": {
"uninstaller": "salt://software/runme.exe",
"reboot": False,
"msiexec": False,
"installer": "salt://software/runme.exe",
"cache_dir": True,
"uninstall_flags": "/U /S",
"locale": "en_US",
"install_flags": "/s",
"full_name": "Firebox 3.03 (x86 en-US)",
}
}
err_msg = "Error: [Errno 1] failed reading salt://software"
mock_minion_error = MagicMock(side_effect=MinionError(err_msg))
mock_parse = MagicMock(return_value=[{"firebox": "3.03"}, None])
se_list_pkgs = {"firebox": ["3.03"]}
with patch.object(
win_pkg, "list_pkgs", return_value=se_list_pkgs
), patch.object(
salt.utils.data, "is_true", MagicMock(return_value=True)
), patch.object(
win_pkg, "_get_package_info", MagicMock(return_value=ret__get_package_info)
), patch.dict(
win_pkg.__salt__,
{
"pkg_resource.parse_targets": mock_parse,
"cp.cache_dir": mock_minion_error,
},
):
ret = win_pkg.remove(name="firebox")
expected = (
"Failed to cache salt://software\n"
"Error: [Errno 1] failed reading salt://software"
)
self.assertEqual(ret, expected)
def test_pkg_remove_minion_error_salt(self):
"""
Test pkg.remove when cp.cache_file encounters a minion error
"""
ret__get_package_info = {
"3.03": {
"uninstaller": "salt://software/runme.exe",
"reboot": False,
"msiexec": False,
"installer": "salt://software/runme.exe",
"uninstall_flags": "/U /S",
"locale": "en_US",
"install_flags": "/s",
"full_name": "Firebox 3.03 (x86 en-US)",
}
}
err_msg = "Error: [Errno 1] failed reading salt://software/runme.exe"
mock_minion_error = MagicMock(side_effect=MinionError(err_msg))
mock_none = MagicMock(return_value=None)
mock_parse = MagicMock(return_value=[{"firebox": "3.03"}, None])
se_list_pkgs = {"firebox": ["3.03"]}
with patch.object(
win_pkg, "list_pkgs", return_value=se_list_pkgs
), patch.object(
salt.utils.data, "is_true", MagicMock(return_value=True)
), patch.object(
win_pkg, "_get_package_info", MagicMock(return_value=ret__get_package_info)
), patch.dict(
win_pkg.__salt__,
{
"pkg_resource.parse_targets": mock_parse,
"cp.is_cached": mock_none,
"cp.cache_file": mock_minion_error,
},
):
ret = win_pkg.remove(name="firebox")
expected = (
"Failed to cache salt://software/runme.exe\n"
"Error: [Errno 1] failed reading salt://software/runme.exe"
)
self.assertEqual(ret, expected)