Add Salt package type to versions report and grain

This commit is contained in:
Megan Wilhite 2023-06-09 12:22:04 -06:00 committed by Pedro Algarvio
parent b49eb84027
commit 34e3f90035
12 changed files with 136 additions and 37 deletions

1
changelog/62589.added.md Normal file
View file

@ -0,0 +1 @@
Added new grain to detect the Salt package type: system or onedir

1
changelog/62961.added.md Normal file
View file

@ -0,0 +1 @@
Add salt package type information. Either system or onedir.

View file

@ -31,6 +31,7 @@ grains modules
nvme
nxos
opts
package
panos
pending_reboot
philips_hue

View file

@ -0,0 +1,5 @@
salt.grains.package
===================
.. automodule:: salt.grains.package
:members:

25
salt/grains/package.py Normal file
View file

@ -0,0 +1,25 @@
"""
Grains for detecting what type of package Salt is using
.. versionadded:: 3007.0
"""
import logging
import salt.utils.package
log = logging.getLogger(__name__)
__virtualname__ = "package"
def __virtual__():
return __virtualname__
def package():
"""
Function to determine if the user is currently using
onedir package or system level package of Salt.
"""
return {"package": salt.utils.package.pkg_type()}

View file

@ -90,6 +90,7 @@ import salt.utils.data
import salt.utils.files
import salt.utils.json
import salt.utils.locales
import salt.utils.package
import salt.utils.platform
import salt.utils.stringutils
import salt.utils.url
@ -136,7 +137,7 @@ def _clear_context(bin_env=None):
"""
contextkey = "pip.version"
if bin_env is not None:
contextkey = "{}.{}".format(contextkey, bin_env)
contextkey = f"{contextkey}.{bin_env}"
__context__.pop(contextkey, None)
@ -144,7 +145,7 @@ def _check_bundled():
"""
Gather run-time information to indicate if we are running from source or bundled.
"""
if hasattr(sys, "RELENV"):
if salt.utils.package.type() == "onedir":
return True
return False
@ -189,7 +190,7 @@ def _get_pip_bin(bin_env):
bin_path,
)
raise CommandNotFoundError(
"Could not find a pip binary in virtualenv {}".format(bin_env)
f"Could not find a pip binary in virtualenv {bin_env}"
)
# bin_env is the python or pip binary
@ -201,12 +202,10 @@ def _get_pip_bin(bin_env):
# We have been passed a pip binary, use the pip binary.
return [os.path.normpath(bin_env)]
raise CommandExecutionError(
"Could not find a pip binary within {}".format(bin_env)
)
raise CommandExecutionError(f"Could not find a pip binary within {bin_env}")
else:
raise CommandNotFoundError(
"Access denied to {}, could not find a pip binary".format(bin_env)
f"Access denied to {bin_env}, could not find a pip binary"
)
@ -412,9 +411,7 @@ def _format_env_vars(env_vars):
val = str(val)
ret[key] = val
else:
raise CommandExecutionError(
"env_vars {} is not a dictionary".format(env_vars)
)
raise CommandExecutionError(f"env_vars {env_vars} is not a dictionary")
return ret
@ -464,7 +461,7 @@ def install(
cache_dir=None,
no_binary=None,
disable_version_check=False,
**kwargs
**kwargs,
):
"""
Install packages with pip
@ -757,9 +754,9 @@ def install(
if log:
if os.path.isdir(log):
raise OSError("'{}' is a directory. Use --log path_to_file".format(log))
raise OSError(f"'{log}' is a directory. Use --log path_to_file")
elif not os.access(log, os.W_OK):
raise OSError("'{}' is not writeable".format(log))
raise OSError(f"'{log}' is not writeable")
cmd.extend(["--log", log])
@ -784,9 +781,7 @@ def install(
raise ValueError("Timeout cannot be a float")
int(timeout)
except ValueError:
raise ValueError(
"'{}' is not a valid timeout, must be an integer".format(timeout)
)
raise ValueError(f"'{timeout}' is not a valid timeout, must be an integer")
cmd.extend(["--timeout", timeout])
if find_links:
@ -797,9 +792,7 @@ def install(
if not (
salt.utils.url.validate(link, VALID_PROTOS) or os.path.exists(link)
):
raise CommandExecutionError(
"'{}' is not a valid URL or path".format(link)
)
raise CommandExecutionError(f"'{link}' is not a valid URL or path")
cmd.extend(["--find-links", link])
if no_index and (index_url or extra_index_url):
@ -809,14 +802,12 @@ def install(
if index_url:
if not salt.utils.url.validate(index_url, VALID_PROTOS):
raise CommandExecutionError("'{}' is not a valid URL".format(index_url))
raise CommandExecutionError(f"'{index_url}' is not a valid URL")
cmd.extend(["--index-url", index_url])
if extra_index_url:
if not salt.utils.url.validate(extra_index_url, VALID_PROTOS):
raise CommandExecutionError(
"'{}' is not a valid URL".format(extra_index_url)
)
raise CommandExecutionError(f"'{extra_index_url}' is not a valid URL")
cmd.extend(["--extra-index-url", extra_index_url])
if no_index:
@ -836,7 +827,7 @@ def install(
cmd.append("--use-mirrors")
for mirror in mirrors:
if not mirror.startswith("http://"):
raise CommandExecutionError("'{}' is not a valid URL".format(mirror))
raise CommandExecutionError(f"'{mirror}' is not a valid URL")
cmd.extend(["--mirrors", mirror])
if disable_version_check:
@ -994,7 +985,7 @@ def install(
# Don't allow any recursion into keyword arg definitions
# Don't allow multiple definitions of a keyword
if isinstance(val, (dict, list)):
raise TypeError("Too many levels in: {}".format(key))
raise TypeError(f"Too many levels in: {key}")
# This is a a normal one-to-one keyword argument
cmd.extend([key, val])
# It is a positional argument, append it to the list
@ -1107,7 +1098,7 @@ def uninstall(
# TODO make this check if writeable
os.path.exists(log)
except OSError:
raise OSError("'{}' is not writeable".format(log))
raise OSError(f"'{log}' is not writeable")
cmd.extend(["--log", log])
@ -1132,9 +1123,7 @@ def uninstall(
raise ValueError("Timeout cannot be a float")
int(timeout)
except ValueError:
raise ValueError(
"'{}' is not a valid timeout, must be an integer".format(timeout)
)
raise ValueError(f"'{timeout}' is not a valid timeout, must be an integer")
cmd.extend(["--timeout", timeout])
if pkgs:
@ -1336,7 +1325,7 @@ def list_(prefix=None, bin_env=None, user=None, cwd=None, env_vars=None, **kwarg
user=user,
cwd=cwd,
env_vars=env_vars,
**kwargs
**kwargs,
)
cmd = _get_pip_bin(bin_env)
@ -1394,7 +1383,7 @@ def version(bin_env=None, cwd=None, user=None):
cwd = _pip_bin_env(cwd, bin_env)
contextkey = "pip.version"
if bin_env is not None:
contextkey = "{}.{}".format(contextkey, bin_env)
contextkey = f"{contextkey}.{bin_env}"
if contextkey in __context__:
return __context__[contextkey]
@ -1650,14 +1639,12 @@ def list_all_versions(
if index_url:
if not salt.utils.url.validate(index_url, VALID_PROTOS):
raise CommandExecutionError("'{}' is not a valid URL".format(index_url))
raise CommandExecutionError(f"'{index_url}' is not a valid URL")
cmd.extend(["--index-url", index_url])
if extra_index_url:
if not salt.utils.url.validate(extra_index_url, VALID_PROTOS):
raise CommandExecutionError(
"'{}' is not a valid URL".format(extra_index_url)
)
raise CommandExecutionError(f"'{extra_index_url}' is not a valid URL")
cmd.extend(["--extra-index-url", extra_index_url])
# Is the `pip index` command available
@ -1669,7 +1656,7 @@ def list_all_versions(
if salt.utils.versions.compare(ver1=pip_version, oper=">=", ver2="20.3"):
cmd.append("--use-deprecated=legacy-resolver")
regex = re.compile(r"\s*Could not find a version.* \(from versions: (.*)\)")
cmd.extend(["install", "{}==versions".format(pkg)])
cmd.extend(["install", f"{pkg}==versions"])
cmd_kwargs = dict(
cwd=cwd, runas=user, output_loglevel="quiet", redirect_stderr=True

11
salt/utils/package.py Normal file
View file

@ -0,0 +1,11 @@
import sys
def pkg_type():
"""
Gather run-time information to indicate if we are running from onedir or .
"""
if hasattr(sys, "RELENV"):
return "onedir"
else:
return "system"

View file

@ -685,6 +685,16 @@ def salt_information():
yield "Salt", __version__
def package_information():
"""
Report package type
"""
import salt.utils.package
yield "Package Type", salt.utils.package.pkg_type()
def dependency_information(include_salt_cloud=False):
"""
Report versions of library dependencies.
@ -867,12 +877,14 @@ def versions_information(include_salt_cloud=False, include_extensions=True):
salt_info = list(salt_information())
lib_info = list(dependency_information(include_salt_cloud))
sys_info = list(system_information())
package_info = list(package_information())
info = {
"Salt Version": dict(salt_info),
"Python Version": dict(py_info),
"Dependency Versions": dict(lib_info),
"System Versions": dict(sys_info),
"Salt Package Information": dict(package_info),
}
if include_extensions:
extensions_info = extensions_information()
@ -905,6 +917,7 @@ def versions_report(include_salt_cloud=False, include_extensions=True):
"Python Version",
"Dependency Versions",
"Salt Extensions",
"Salt Package Information",
"System Versions",
):
if ver_type == "Salt Extensions" and ver_type not in ver_info:

View file

@ -1,6 +1,7 @@
import logging
import os
import shutil
import sys
import pytest
@ -56,7 +57,7 @@ def test_versions_report(salt_cli):
ret_lines = [line.strip() for line in ret_lines]
for header in expected:
assert "{}:".format(header) in ret_lines
assert f"{header}:" in ret_lines
ret_dict = {}
expected_keys = set()
@ -80,6 +81,11 @@ def test_versions_report(salt_cli):
assert key in expected_keys
expected_keys.remove(key)
assert not expected_keys
if hasattr(sys, "RELENV"):
assert "onedir" in ret_dict["Salt Package Information"]["Package Type"]
else:
assert "system" in ret_dict["Salt Package Information"]["Package Type"]
if os.environ.get("ONEDIR_TESTRUN", "0") == "0":
# Stop any more testing
return

View file

@ -0,0 +1,24 @@
import sys
import pytest
@pytest.fixture(scope="module")
def grains(modules):
return modules.grains
def test_grains_items(grains):
"""
Test running grains.items and assert
certain information is included in
the return
"""
ret = grains.items()
if hasattr(sys, "RELENV"):
assert ret["package"] == "onedir"
else:
assert ret["package"] == "system"
for key in ["num_cpus", "cpu_model", "os_family"]:
assert key in ret.keys()

View file

@ -0,0 +1,14 @@
import sys
import salt.grains.package
def test_grain_package_type(tmp_path):
"""
Test grains.package_type for both package types
"""
ret = salt.grains.package.package()["package"]
if hasattr(sys, "RELENV"):
assert ret == "onedir"
else:
assert ret == "system"

View file

@ -0,0 +1,11 @@
import sys
import salt.utils.package
def test_pkg_type():
ret = salt.utils.package.pkg_type()
if hasattr(sys, "RELENV"):
assert ret == "onedir"
else:
assert ret == "system"