mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Add Salt package type to versions report and grain
This commit is contained in:
parent
b49eb84027
commit
34e3f90035
12 changed files with 136 additions and 37 deletions
1
changelog/62589.added.md
Normal file
1
changelog/62589.added.md
Normal file
|
@ -0,0 +1 @@
|
|||
Added new grain to detect the Salt package type: system or onedir
|
1
changelog/62961.added.md
Normal file
1
changelog/62961.added.md
Normal file
|
@ -0,0 +1 @@
|
|||
Add salt package type information. Either system or onedir.
|
|
@ -31,6 +31,7 @@ grains modules
|
|||
nvme
|
||||
nxos
|
||||
opts
|
||||
package
|
||||
panos
|
||||
pending_reboot
|
||||
philips_hue
|
||||
|
|
5
doc/ref/grains/all/salt.grains.package.rst
Normal file
5
doc/ref/grains/all/salt.grains.package.rst
Normal file
|
@ -0,0 +1,5 @@
|
|||
salt.grains.package
|
||||
===================
|
||||
|
||||
.. automodule:: salt.grains.package
|
||||
:members:
|
25
salt/grains/package.py
Normal file
25
salt/grains/package.py
Normal 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()}
|
|
@ -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
11
salt/utils/package.py
Normal 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"
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
24
tests/pytests/functional/modules/test_grains.py
Normal file
24
tests/pytests/functional/modules/test_grains.py
Normal 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()
|
14
tests/pytests/unit/grains/test_package.py
Normal file
14
tests/pytests/unit/grains/test_package.py
Normal 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"
|
11
tests/pytests/unit/utils/test_package.py
Normal file
11
tests/pytests/unit/utils/test_package.py
Normal 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"
|
Loading…
Add table
Reference in a new issue