mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
Merge 3006.x into master
Conflicts: * requirements/darwin.txt * requirements/pytest.txt * requirements/static/ci/common.in * requirements/static/ci/darwin.in * requirements/static/ci/freebsd.in * requirements/static/ci/linux.in * requirements/static/ci/py3.10/cloud.txt * requirements/static/ci/py3.10/darwin.txt * requirements/static/ci/py3.10/freebsd.txt * requirements/static/ci/py3.10/lint.txt * requirements/static/ci/py3.10/linux.txt * requirements/static/ci/py3.10/windows.txt * requirements/static/ci/py3.11/windows.txt * requirements/static/ci/py3.7/cloud.txt * requirements/static/ci/py3.7/freebsd.txt * requirements/static/ci/py3.7/lint.txt * requirements/static/ci/py3.7/linux.txt * requirements/static/ci/py3.8/cloud.txt * requirements/static/ci/py3.8/freebsd.txt * requirements/static/ci/py3.8/lint.txt * requirements/static/ci/py3.8/linux.txt * requirements/static/ci/py3.8/windows.txt * requirements/static/ci/py3.9/cloud.txt * requirements/static/ci/py3.9/darwin.txt * requirements/static/ci/py3.9/freebsd.txt * requirements/static/ci/py3.9/lint.txt * requirements/static/ci/py3.9/linux.txt * requirements/static/ci/py3.9/windows.txt * requirements/static/pkg/freebsd.in * requirements/static/pkg/linux.in * requirements/static/pkg/py3.10/darwin.txt * requirements/static/pkg/py3.10/windows.txt * requirements/static/pkg/py3.11/windows.txt * requirements/static/pkg/py3.8/windows.txt * requirements/static/pkg/py3.9/darwin.txt * requirements/static/pkg/py3.9/windows.txt * requirements/windows.txt
This commit is contained in:
commit
f389c29473
81 changed files with 1105 additions and 860 deletions
|
@ -238,7 +238,7 @@ jobs:
|
|||
SKIP_INITIAL_GH_ACTIONS_FAILURES: "1"
|
||||
run: |
|
||||
sudo -E nox --force-color -e ${{ inputs.nox-session }} -- ${{ matrix.test-chunk }} \
|
||||
${{ contains(matrix.test-chunk, 'upgrade') && format('--prev-version {0}', matrix.version) || ''}}
|
||||
${{ matrix.version && format('--prev-version {0}', matrix.version) || ''}}
|
||||
|
||||
- name: Run Package Tests
|
||||
env:
|
||||
|
@ -252,7 +252,7 @@ jobs:
|
|||
COVERAGE_CONTEXT: ${{ inputs.distro-slug }}
|
||||
run: |
|
||||
sudo -E nox --force-color -e ${{ inputs.nox-session }} -- ${{ matrix.test-chunk }} \
|
||||
${{ contains(matrix.test-chunk, 'upgrade') && format('--prev-version {0}', matrix.version) || ''}}
|
||||
${{ matrix.version && format('--prev-version {0}', matrix.version) || ''}}
|
||||
|
||||
- name: Fix file ownership
|
||||
run: |
|
||||
|
|
4
.github/workflows/test-packages-action.yml
vendored
4
.github/workflows/test-packages-action.yml
vendored
|
@ -268,13 +268,13 @@ jobs:
|
|||
run: |
|
||||
tools --timestamps --timeout-secs=1800 vm testplan --skip-requirements-install \
|
||||
--nox-session=${{ inputs.nox-session }} ${{ inputs.distro-slug }} -- ${{ matrix.test-chunk }} \
|
||||
${{ contains(matrix.test-chunk, 'upgrade') && format('--prev-version {0}', matrix.version) || ''}}
|
||||
${{ matrix.version && format('--prev-version {0}', matrix.version) || ''}}
|
||||
|
||||
- name: Run Package Tests
|
||||
run: |
|
||||
tools --timestamps --no-output-timeout-secs=1800 --timeout-secs=14400 vm test --skip-requirements-install \
|
||||
--nox-session=${{ inputs.nox-session }} --rerun-failures ${{ inputs.distro-slug }} -- ${{ matrix.test-chunk }} \
|
||||
${{ contains(matrix.test-chunk, 'upgrade') && format('--prev-version {0}', matrix.version) || ''}}
|
||||
${{ matrix.version && format('--prev-version {0}', matrix.version) || ''}}
|
||||
|
||||
- name: Download Test Run Artifacts
|
||||
id: download-artifacts-from-vm
|
||||
|
|
1
changelog/64597.fixed.md
Normal file
1
changelog/64597.fixed.md
Normal file
|
@ -0,0 +1 @@
|
|||
Fixed some issues in x509_v2 execution module private key functions
|
1
changelog/65086.fixed.md
Normal file
1
changelog/65086.fixed.md
Normal file
|
@ -0,0 +1 @@
|
|||
Moved gitfs locks to salt working dir to avoid lock wipes
|
1
changelog/65152.fixed.md
Normal file
1
changelog/65152.fixed.md
Normal file
|
@ -0,0 +1 @@
|
|||
speed up yumpkg list_pkgs by not requiring digest or signature verification on lookup.
|
1
changelog/65165.fixed.md
Normal file
1
changelog/65165.fixed.md
Normal file
|
@ -0,0 +1 @@
|
|||
Fix pkg.latest failing on windows for winrepo packages where the package is already up to date
|
|
@ -12,13 +12,10 @@ for a given release.
|
|||
Add release specific details below
|
||||
-->
|
||||
|
||||
.. Warning::
|
||||
Due to a known issue with the newest release of setuptools,
|
||||
users who use pip to install Salt will experience an install
|
||||
failure. This issue also impacts pip installs for older versions
|
||||
of Salt. The core Salt team is currently investigating the issue
|
||||
and has documented a workaround. To follow the issue and get the
|
||||
latest workaround, see: https://github.com/saltstack/salt/issues/65149
|
||||
| **IMPORTANT** |
|
||||
| ------------- |
|
||||
| Due to a known issue with the newest release of setuptools, users who use pip to install Salt will experience an install failure. This issue also impacts pip installs for older versions of Salt. The core Salt team is currently investigating the issue and has documented a workaround. To follow the issue and get the latest workaround, see: <https://github.com/saltstack/salt/issues/65149> |
|
||||
|
||||
|
||||
<!--
|
||||
Do not edit the changelog below.
|
||||
|
|
17
noxfile.py
17
noxfile.py
|
@ -1843,6 +1843,16 @@ def test_pkgs_onedir(session):
|
|||
"--no-uninstall",
|
||||
"pkg/tests/upgrade/",
|
||||
],
|
||||
"downgrade": [
|
||||
"--downgrade",
|
||||
"--no-uninstall",
|
||||
"pkg/tests/downgrade/",
|
||||
],
|
||||
"downgrade-classic": [
|
||||
"--downgrade",
|
||||
"--no-uninstall",
|
||||
"pkg/tests/downgrade/",
|
||||
],
|
||||
"download-pkgs": [
|
||||
"--download-pkgs",
|
||||
"pkg/tests/download/",
|
||||
|
@ -1884,7 +1894,7 @@ def test_pkgs_onedir(session):
|
|||
"PKG_TEST_TYPE": chunk,
|
||||
}
|
||||
|
||||
if chunk == "upgrade-classic":
|
||||
if chunk in ("upgrade-classic", "downgrade-classic"):
|
||||
cmd_args.append("--classic")
|
||||
# Workaround for installing and running classic packages from 3005.1
|
||||
# They can only run with importlib-metadata<5.0.0.
|
||||
|
@ -1901,6 +1911,7 @@ def test_pkgs_onedir(session):
|
|||
+ session.posargs
|
||||
)
|
||||
_pytest(session, coverage=False, cmd_args=pytest_args, env=env)
|
||||
|
||||
if chunk not in ("install", "download-pkgs"):
|
||||
cmd_args = chunks["install"]
|
||||
pytest_args = (
|
||||
|
@ -1914,5 +1925,9 @@ def test_pkgs_onedir(session):
|
|||
]
|
||||
+ session.posargs
|
||||
)
|
||||
if "downgrade" in chunk:
|
||||
pytest_args.append("--use-prev-version")
|
||||
if chunk in ("upgrade-classic", "downgrade-classic"):
|
||||
pytest_args.append("--classic")
|
||||
_pytest(session, coverage=False, cmd_args=pytest_args, env=env)
|
||||
sys.exit(0)
|
||||
|
|
|
@ -77,6 +77,8 @@ Description: remote manager to administer servers via salt
|
|||
|
||||
Package: salt-minion
|
||||
Architecture: amd64 arm64
|
||||
Replaces: salt-common (<= 3006.1)
|
||||
Breaks: salt-common (<= 3006.1)
|
||||
Depends: bsdmainutils,
|
||||
dctrl-tools,
|
||||
salt-common (= ${source:Version}),
|
||||
|
@ -129,6 +131,7 @@ Description: master-of-masters for salt, the distributed remote execution system
|
|||
|
||||
Package: salt-ssh
|
||||
Architecture: amd64 arm64
|
||||
Breaks: salt-common (<= 3006.3)
|
||||
Depends: salt-common (= ${source:Version}),
|
||||
openssh-client,
|
||||
${misc:Depends}
|
||||
|
@ -157,6 +160,7 @@ Description: remote manager to administer servers via Salt SSH
|
|||
|
||||
Package: salt-cloud
|
||||
Architecture: amd64 arm64
|
||||
Breaks: salt-common (<= 3006.3)
|
||||
Depends: salt-common (= ${source:Version}),
|
||||
${misc:Depends}
|
||||
Description: public cloud VM management system
|
||||
|
|
1
pkg/debian/salt-cloud.install
Normal file
1
pkg/debian/salt-cloud.install
Normal file
|
@ -0,0 +1 @@
|
|||
conf/cloud /etc/salt
|
|
@ -3,3 +3,4 @@
|
|||
/var/run/salt
|
||||
/usr/share/fish/vendor_completions.d
|
||||
/opt/saltstack/salt
|
||||
/etc/salt
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
conf/roster /etc/salt
|
||||
conf/cloud /etc/salt
|
||||
pkg/common/salt-common.logrotate /etc/logrotate.d/salt
|
||||
pkg/common/fish-completions/salt-cp.fish /usr/share/fish/vendor_completions.d
|
||||
pkg/common/fish-completions/salt-call.fish /usr/share/fish/vendor_completions.d
|
||||
|
|
1
pkg/debian/salt-ssh.install
Normal file
1
pkg/debian/salt-ssh.install
Normal file
|
@ -0,0 +1 @@
|
|||
conf/roster /etc/salt
|
|
@ -6,17 +6,19 @@
|
|||
# Date: December 2020
|
||||
#
|
||||
# Description: This notarizes the macOS Installer Package (.pkg). It uses the
|
||||
# `altool` xcode utility which is only available in the full
|
||||
# Xcode package. It is not available in Command Line Tools.
|
||||
# `notarytool` xcode utility which became available in Xcode 13.
|
||||
# Xcode 13 requires macOS Big Sur 11.3 or higher. However, the
|
||||
# notarytool binary can be extracted and run on macOS Catalina
|
||||
# 10.15.7 and higher. It is not available in Command Line Tools.
|
||||
#
|
||||
# This script will upload a copy of the package to Apple and wait
|
||||
# for the notarization to return. This can take several minutes.
|
||||
#
|
||||
# If this command is run with sudo, you need to pass the `-E`
|
||||
# option to make sure the environment variables pass through to the
|
||||
# sudo environment. For example:
|
||||
# This script requires the presence of some environment variables.
|
||||
# If running this script with sudo, be sure to pass the `-E`
|
||||
# option.
|
||||
#
|
||||
# sudo -E ./notarize.sh
|
||||
# sudo -E ./notarize.sh salt-3006.2-signed.pkg
|
||||
#
|
||||
# Requirements:
|
||||
# - Full Xcode Installation
|
||||
|
@ -31,24 +33,26 @@
|
|||
# The package that will be notarized (must be signed)
|
||||
#
|
||||
# Example:
|
||||
# The following will notarize the 'salt-3006.1-1-signed.pkg' file
|
||||
# The following will notarize the 'salt-3006.2-signed.pkg' file:
|
||||
#
|
||||
# ./notarize.sh salt-3006.1-1-signed.pkg
|
||||
# ./notarize.sh salt-3006.2-signed.pkg
|
||||
#
|
||||
# Environment Setup:
|
||||
#
|
||||
# Define Environment Variables:
|
||||
# Create two environment variables for the Apple account and the
|
||||
# app-specific password associated with that account. To generate the
|
||||
# app-specific password see: https://support.apple.com/en-us/HT204397
|
||||
# Create three environment variables for the apple account, apple team
|
||||
# ID, and the app-specific password associated with that account. To
|
||||
# generate the app-specific password see:
|
||||
# https://support.apple.com/en-us/HT204397
|
||||
#
|
||||
# export APPLE_ACCT="username@domain.com"
|
||||
# export APPLE_TEAM_ID="AB283DVDS5"
|
||||
# export APP_SPEC_PWD="abcd-efgh-ijkl-mnop"
|
||||
#
|
||||
################################################################################
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Variables
|
||||
# Check input parameters
|
||||
#-------------------------------------------------------------------------------
|
||||
if [ "$1" == "" ]; then
|
||||
echo "Must supply a package to notarize"
|
||||
|
@ -57,28 +61,9 @@ else
|
|||
PACKAGE=$1
|
||||
fi
|
||||
|
||||
BUNDLE_ID="com.saltstack.salt"
|
||||
CMD_OUTPUT=$(mktemp -t cmd.log)
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Functions
|
||||
#-------------------------------------------------------------------------------
|
||||
# _usage
|
||||
#
|
||||
# Prints out help text
|
||||
_usage() {
|
||||
echo ""
|
||||
echo "Script to notarize the Salt package:"
|
||||
echo ""
|
||||
echo "usage: ${0}"
|
||||
echo " [-h|--help]"
|
||||
echo ""
|
||||
echo " -h, --help this message"
|
||||
echo ""
|
||||
echo " To notarize the Salt package:"
|
||||
echo " example: $0 salt-3006.1-1-signed.pkg"
|
||||
}
|
||||
|
||||
# _msg
|
||||
#
|
||||
# Prints the message with a dash... no new line
|
||||
|
@ -99,38 +84,32 @@ _success() {
|
|||
_failure() {
|
||||
printf "\e[31m%s\e[0m\n" "Failure"
|
||||
echo "output >>>>>>"
|
||||
cat "$CMD_OUTPUT" 1>&2
|
||||
cat "$NOTARIZE_LOG" 1>&2
|
||||
echo "<<<<<< output"
|
||||
exit 1
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Get Parameters
|
||||
# Environment Variables
|
||||
#-------------------------------------------------------------------------------
|
||||
while true; do
|
||||
if [[ -z "$1" ]]; then break; fi
|
||||
case "$1" in
|
||||
-h | --help )
|
||||
_usage
|
||||
exit 0
|
||||
;;
|
||||
-*)
|
||||
echo "Invalid Option: $1"
|
||||
echo ""
|
||||
_usage
|
||||
exit 1
|
||||
;;
|
||||
* )
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
_msg "Setting Variables"
|
||||
NOTARIZE_LOG=$(mktemp -t notarize-app.log)
|
||||
NOTARY_TOOL=$(xcrun --find notarytool)
|
||||
_success
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Check for notarytool
|
||||
#-------------------------------------------------------------------------------
|
||||
if [ ! -f "$NOTARY_TOOL" ]; then
|
||||
echo "This script requires the NotaryTool binary"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Delete temporary files on exit
|
||||
#-------------------------------------------------------------------------------
|
||||
function finish {
|
||||
rm "$CMD_OUTPUT"
|
||||
rm "$NOTARIZE_LOG"
|
||||
}
|
||||
trap finish EXIT
|
||||
|
||||
|
@ -139,87 +118,34 @@ trap finish EXIT
|
|||
#-------------------------------------------------------------------------------
|
||||
printf "=%.0s" {1..80}; printf "\n"
|
||||
echo "Notarize Salt Package"
|
||||
echo "- This can take up to 30 minutes"
|
||||
printf -- "-%.0s" {1..80}; printf "\n"
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
# Submit app for notarization
|
||||
#-------------------------------------------------------------------------------
|
||||
_msg "Submitting package for notarization"
|
||||
if xcrun altool --notarize-app \
|
||||
--primary-bundle-id "$BUNDLE_ID" \
|
||||
--username "$APPLE_ACCT" \
|
||||
--password "$APP_SPEC_PWD" \
|
||||
-f "$PACKAGE" > "$CMD_OUTPUT" 2>&1; then
|
||||
_msg "Submitting Package for Notarization"
|
||||
if $NOTARY_TOOL submit \
|
||||
--apple-id "$APPLE_ACCT" \
|
||||
--team-id "$APPLE_TEAM_ID" \
|
||||
--password "$APP_SPEC_PWD" \
|
||||
--wait \
|
||||
"$PACKAGE" > "$NOTARIZE_LOG" 2>&1; then
|
||||
_success
|
||||
else
|
||||
_failure
|
||||
fi
|
||||
|
||||
# Get RequestUUID from the CMD_OUTPUT
|
||||
# Uncomment for debugging
|
||||
# cat "$CMD_OUTPUT"
|
||||
|
||||
_msg "Verifying successful upload"
|
||||
if grep -q "No errors uploading" "$CMD_OUTPUT"; then
|
||||
# Make sure the status is "Accepted", then staple
|
||||
_msg "Verifying accepted status"
|
||||
if grep -q "status: Accepted" "$NOTARIZE_LOG"; then
|
||||
_success
|
||||
else
|
||||
echo ">>>>>> Failed Uploading Package <<<<<<" > "$CMD_OUTPUT"
|
||||
_failure
|
||||
fi
|
||||
RequestUUID=$(awk -F ' = ' '/RequestUUID/ {print $2}' "$CMD_OUTPUT")
|
||||
|
||||
# Clear CMD_OUTPUT
|
||||
echo "" > "$CMD_OUTPUT"
|
||||
|
||||
echo "- Checking Notarization Status (every 30 seconds):"
|
||||
echo -n " "
|
||||
# Though it usually takes 5 minutes, notarization can take up to 30 minutes
|
||||
# Check status every 30 seconds for 40 minutes
|
||||
tries=0
|
||||
while sleep 30; do
|
||||
((tries++))
|
||||
echo -n "."
|
||||
|
||||
# check notarization status
|
||||
if ! xcrun altool --notarization-info "$RequestUUID" \
|
||||
--username "$APPLE_ACCT" \
|
||||
--password "$APP_SPEC_PWD" > "$CMD_OUTPUT" 2>&1; then
|
||||
echo ""
|
||||
cat "$CMD_OUTPUT" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Look for Status in the CMD_OUTPUT
|
||||
# Uncomment for debugging
|
||||
# cat "$CMD_OUTPUT"
|
||||
|
||||
# Continue checking until Status is no longer "in progress"
|
||||
if ! grep -q "Status: in progress" "$CMD_OUTPUT"; then
|
||||
echo ""
|
||||
break
|
||||
fi
|
||||
|
||||
if (( tries > 80 )); then
|
||||
echo ""
|
||||
echo "Failed after 40 minutes"
|
||||
echo "Log: $CMD_OUTPUT"
|
||||
cat "$CMD_OUTPUT" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
done
|
||||
|
||||
# Make sure the result is "success", then staple
|
||||
if ! grep -q "Status: success" "$CMD_OUTPUT"; then
|
||||
echo "**** There was a problem notarizing the package"
|
||||
echo "**** View the log for details:"
|
||||
awk -F ': ' '/LogFileURL/ {print $2}' "$CMD_OUTPUT"
|
||||
exit 1
|
||||
fi
|
||||
echo " Notarization Complete"
|
||||
|
||||
_msg "Stapling notarization to the package"
|
||||
if xcrun stapler staple "$PACKAGE" > "$CMD_OUTPUT"; then
|
||||
_msg "Stapling Notarization to the Package"
|
||||
if xcrun stapler staple "$PACKAGE" > "$NOTARIZE_LOG"; then
|
||||
_success
|
||||
else
|
||||
_failure
|
||||
|
|
|
@ -31,7 +31,7 @@ def version(install_salt):
|
|||
"""
|
||||
get version number from artifact
|
||||
"""
|
||||
return install_salt.get_version(version_only=True)
|
||||
return install_salt.version
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
|
@ -87,6 +87,12 @@ def pytest_addoption(parser):
|
|||
action="store_true",
|
||||
help="Install previous version and then upgrade then run tests",
|
||||
)
|
||||
test_selection_group.addoption(
|
||||
"--downgrade",
|
||||
default=False,
|
||||
action="store_true",
|
||||
help="Install current version and then downgrade to the previous version and run tests",
|
||||
)
|
||||
test_selection_group.addoption(
|
||||
"--no-install",
|
||||
default=False,
|
||||
|
@ -110,6 +116,11 @@ def pytest_addoption(parser):
|
|||
action="store",
|
||||
help="Test an upgrade from the version specified.",
|
||||
)
|
||||
test_selection_group.addoption(
|
||||
"--use-prev-version",
|
||||
action="store_true",
|
||||
help="Tells the test suite to validate the version using the previous version (for downgrades)",
|
||||
)
|
||||
test_selection_group.addoption(
|
||||
"--download-pkgs",
|
||||
default=False,
|
||||
|
@ -168,10 +179,12 @@ def install_salt(request, salt_factories_root_dir):
|
|||
conf_dir=salt_factories_root_dir / "etc" / "salt",
|
||||
system_service=request.config.getoption("--system-service"),
|
||||
upgrade=request.config.getoption("--upgrade"),
|
||||
downgrade=request.config.getoption("--downgrade"),
|
||||
no_uninstall=request.config.getoption("--no-uninstall"),
|
||||
no_install=request.config.getoption("--no-install"),
|
||||
classic=request.config.getoption("--classic"),
|
||||
prev_version=request.config.getoption("--prev-version"),
|
||||
use_prev_version=request.config.getoption("--use-prev-version"),
|
||||
) as fixture:
|
||||
yield fixture
|
||||
|
||||
|
@ -362,22 +375,20 @@ def salt_master(salt_factories, install_salt, state_tree, pillar_tree):
|
|||
assert _file.owner() == "salt"
|
||||
assert _file.group() == "salt"
|
||||
|
||||
if (platform.is_windows() or platform.is_darwin()) and install_salt.singlebin:
|
||||
start_timeout = 240
|
||||
# For every minion started we have to accept it's key.
|
||||
# On windows, using single binary, it has to decompress it and run the command. Too slow.
|
||||
# So, just in this scenario, use open mode
|
||||
config_overrides["open_mode"] = True
|
||||
master_script = False
|
||||
if platform.is_windows():
|
||||
if install_salt.classic:
|
||||
master_script = True
|
||||
# this check will need to be changed to install_salt.relenv
|
||||
# once the package version returns 3006 and not 3005 on master
|
||||
if install_salt.relenv:
|
||||
master_script = True
|
||||
elif not install_salt.upgrade:
|
||||
master_script = True
|
||||
if (
|
||||
not install_salt.relenv
|
||||
and install_salt.use_prev_version
|
||||
and not install_salt.classic
|
||||
):
|
||||
master_script = False
|
||||
|
||||
if master_script:
|
||||
salt_factories.system_install = False
|
||||
|
@ -439,8 +450,6 @@ def salt_minion(salt_factories, salt_master, install_salt):
|
|||
Start up a minion
|
||||
"""
|
||||
start_timeout = None
|
||||
if (platform.is_windows() or platform.is_darwin()) and install_salt.singlebin:
|
||||
start_timeout = 240
|
||||
minion_id = random_string("minion-")
|
||||
# Since the daemons are "packaged" with tiamat, the salt plugins provided
|
||||
# by salt-factories won't be discovered. Provide the required `*_dirs` on
|
||||
|
@ -531,8 +540,6 @@ def salt_api(salt_master, install_salt, extras_pypath):
|
|||
"""
|
||||
shutil.rmtree(str(extras_pypath), ignore_errors=True)
|
||||
start_timeout = None
|
||||
if platform.is_windows() and install_salt.singlebin:
|
||||
start_timeout = 240
|
||||
factory = salt_master.salt_api_daemon()
|
||||
with factory.started(start_timeout=start_timeout):
|
||||
yield factory
|
||||
|
|
0
pkg/tests/downgrade/__init__.py
Normal file
0
pkg/tests/downgrade/__init__.py
Normal file
64
pkg/tests/downgrade/test_salt_downgrade.py
Normal file
64
pkg/tests/downgrade/test_salt_downgrade.py
Normal file
|
@ -0,0 +1,64 @@
|
|||
import shutil
|
||||
|
||||
import packaging.version
|
||||
import pytest
|
||||
from pytestskipmarkers.utils import platform
|
||||
|
||||
|
||||
def test_salt_downgrade(salt_call_cli, install_salt):
|
||||
"""
|
||||
Test an upgrade of Salt.
|
||||
"""
|
||||
if not install_salt.downgrade:
|
||||
pytest.skip("Not testing a downgrade, do not run")
|
||||
|
||||
is_downgrade_to_relenv = packaging.version.parse(
|
||||
install_salt.prev_version
|
||||
) >= packaging.version.parse("3006.0")
|
||||
|
||||
if is_downgrade_to_relenv:
|
||||
original_py_version = install_salt.package_python_version()
|
||||
|
||||
# Verify current install version is setup correctly and works
|
||||
ret = salt_call_cli.run("test.version")
|
||||
assert ret.returncode == 0
|
||||
assert packaging.version.parse(ret.data) == packaging.version.parse(
|
||||
install_salt.artifact_version
|
||||
)
|
||||
|
||||
# Test pip install before a downgrade
|
||||
dep = "PyGithub==1.56.0"
|
||||
install = salt_call_cli.run("--local", "pip.install", dep)
|
||||
assert install.returncode == 0
|
||||
|
||||
# Verify we can use the module dependent on the installed package
|
||||
repo = "https://github.com/saltstack/salt.git"
|
||||
use_lib = salt_call_cli.run("--local", "github.get_repo_info", repo)
|
||||
assert "Authentication information could" in use_lib.stderr
|
||||
|
||||
# Downgrade Salt to the previous version and test
|
||||
install_salt.install(downgrade=True)
|
||||
bin_file = "salt"
|
||||
if platform.is_windows():
|
||||
if not is_downgrade_to_relenv:
|
||||
bin_file = install_salt.install_dir / "salt-call.bat"
|
||||
else:
|
||||
bin_file = install_salt.install_dir / "salt-call.exe"
|
||||
elif platform.is_darwin() and install_salt.classic:
|
||||
bin_file = install_salt.bin_dir / "salt-call"
|
||||
|
||||
ret = install_salt.proc.run(bin_file, "--version")
|
||||
assert ret.returncode == 0
|
||||
assert packaging.version.parse(
|
||||
ret.stdout.strip().split()[1]
|
||||
) < packaging.version.parse(install_salt.artifact_version)
|
||||
|
||||
# Windows does not keep the extras directory around in the same state
|
||||
# TODO: Fix this problem in windows installers
|
||||
# TODO: Fix this problem in macos installers
|
||||
if is_downgrade_to_relenv and not (platform.is_windows() or platform.is_darwin()):
|
||||
new_py_version = install_salt.package_python_version()
|
||||
if new_py_version == original_py_version:
|
||||
# test pip install after a downgrade
|
||||
use_lib = salt_call_cli.run("--local", "github.get_repo_info", repo)
|
||||
assert "Authentication information could" in use_lib.stderr
|
|
@ -12,6 +12,12 @@ pytestmark = [
|
|||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def _skip_on_non_relenv(install_salt):
|
||||
if not install_salt.relenv:
|
||||
pytest.skip("This test is for relenv versions of salt")
|
||||
|
||||
|
||||
def test_check_no_import_error(salt_call_cli, salt_master):
|
||||
"""
|
||||
Test that we don't have any errors on teardown of python when using a py-rendered sls file
|
||||
|
|
|
@ -8,9 +8,6 @@ def test_services(install_salt, salt_cli, salt_minion):
|
|||
"""
|
||||
Check if Services are enabled/disabled
|
||||
"""
|
||||
if install_salt.compressed:
|
||||
pytest.skip("Skip test on single binary and onedir package")
|
||||
|
||||
if install_salt.distro_id in ("ubuntu", "debian"):
|
||||
services_enabled = ["salt-master", "salt-minion", "salt-syndic", "salt-api"]
|
||||
services_disabled = []
|
||||
|
|
|
@ -1,14 +1,31 @@
|
|||
import subprocess
|
||||
|
||||
from pytestskipmarkers.utils import platform
|
||||
|
||||
|
||||
def test_help(install_salt):
|
||||
"""
|
||||
Test --help works for all salt cmds
|
||||
"""
|
||||
for cmd in install_salt.binary_paths.values():
|
||||
# TODO: add back salt-cloud and salt-ssh when its fixed
|
||||
cmd = [str(x) for x in cmd]
|
||||
if "python" in cmd[0]:
|
||||
ret = install_salt.proc.run(*cmd, "--version")
|
||||
|
||||
if len(cmd) > 1 and "shell" in cmd[1]:
|
||||
# Singlebin build, unable to get the version
|
||||
continue
|
||||
|
||||
# TODO: Remove this condition once the fixed 3005.x classic packages are released.
|
||||
if "salt-proxy" in cmd[0] and platform.is_darwin() and install_salt.classic:
|
||||
continue
|
||||
|
||||
if "python" in cmd[0] and len(cmd) == 1:
|
||||
ret = install_salt.proc.run(
|
||||
*cmd, "--version", stdout=subprocess.PIPE, stderr=subprocess.PIPE
|
||||
)
|
||||
assert "Python" in ret.stdout
|
||||
else:
|
||||
ret = install_salt.proc.run(*cmd, "--help")
|
||||
ret = install_salt.proc.run(
|
||||
*cmd, "--help", stdout=subprocess.PIPE, stderr=subprocess.PIPE
|
||||
)
|
||||
assert "Usage" in ret.stdout
|
||||
assert ret.returncode == 0
|
||||
|
|
|
@ -2,6 +2,7 @@ import os
|
|||
import pathlib
|
||||
import subprocess
|
||||
|
||||
import packaging.version
|
||||
import psutil
|
||||
import pytest
|
||||
|
||||
|
@ -10,6 +11,16 @@ pytestmark = [
|
|||
]
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def _skip_on_less_than_3006_1(install_salt):
|
||||
if packaging.version.parse(install_salt.version) <= packaging.version.parse(
|
||||
"3006.1"
|
||||
):
|
||||
pytest.skip(
|
||||
"Multi-minion script only available on versions greater than 3006.1"
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def mm_script(install_salt):
|
||||
yield install_salt.ssm_bin.parent / "multi-minion.ps1"
|
||||
|
|
|
@ -12,10 +12,8 @@ from pytestskipmarkers.utils import platform
|
|||
def pypath():
|
||||
if platform.is_windows():
|
||||
return pathlib.Path(os.getenv("ProgramFiles"), "Salt Project", "Salt")
|
||||
elif platform.is_darwin():
|
||||
return pathlib.Path("/opt", "salt", "bin")
|
||||
else:
|
||||
return pathlib.Path("/opt", "saltstack", "salt", "bin")
|
||||
return pathlib.Path("/opt", "saltstack", "salt", "pypath", "bin")
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
|
@ -44,7 +42,7 @@ def wipe_pydeps(shell, install_salt, extras_pypath):
|
|||
shutil.rmtree(dirname, ignore_errors=True)
|
||||
|
||||
|
||||
def test_pip_install(salt_call_cli):
|
||||
def test_pip_install(salt_call_cli, install_salt, shell):
|
||||
"""
|
||||
Test pip.install and ensure module can use installed library
|
||||
"""
|
||||
|
@ -68,6 +66,8 @@ def test_pip_install_extras(shell, install_salt, extras_pypath_bin):
|
|||
"""
|
||||
Test salt-pip installs into the correct directory
|
||||
"""
|
||||
if not install_salt.relenv:
|
||||
pytest.skip("The extras directory is only in relenv versions")
|
||||
dep = "pep8"
|
||||
extras_keyword = "extras-3"
|
||||
if platform.is_windows():
|
||||
|
@ -86,7 +86,7 @@ def test_pip_install_extras(shell, install_salt, extras_pypath_bin):
|
|||
break
|
||||
else:
|
||||
pytest.fail(
|
||||
f"The {dep!r} package was not found installed. Packages Installed: {pkgs_installed}"
|
||||
f"The {dep!r} package was not found installed. Packages Installed: {ret.data}"
|
||||
)
|
||||
|
||||
show_ret = shell.run(*(install_salt.binary_paths["pip"] + ["show", dep]))
|
||||
|
@ -109,8 +109,12 @@ def demote(user_uid, user_gid):
|
|||
|
||||
|
||||
@pytest.mark.skip_on_windows(reason="We can't easily demote users on Windows")
|
||||
def test_pip_non_root(shell, install_salt, test_account, extras_pypath_bin):
|
||||
def test_pip_non_root(shell, install_salt, test_account, extras_pypath_bin, pypath):
|
||||
if install_salt.classic:
|
||||
pytest.skip("We can install non-root for classic packages")
|
||||
check_path = extras_pypath_bin / "pep8"
|
||||
if not install_salt.relenv and not install_salt.classic:
|
||||
check_path = pypath / "pep8"
|
||||
# We should be able to issue a --help without being root
|
||||
ret = subprocess.run(
|
||||
install_salt.binary_paths["salt"] + ["--help"],
|
||||
|
@ -150,7 +154,7 @@ def test_pip_non_root(shell, install_salt, test_account, extras_pypath_bin):
|
|||
text=True,
|
||||
)
|
||||
|
||||
assert check_path.exists()
|
||||
assert check_path.exists(), shutil.which("pep8")
|
||||
|
||||
assert ret.returncode == 0, ret.stderr
|
||||
|
||||
|
@ -160,6 +164,8 @@ def test_pip_install_salt_extension_in_extras(install_salt, extras_pypath, shell
|
|||
Test salt-pip installs into the correct directory and the salt extension
|
||||
is properly loaded.
|
||||
"""
|
||||
if not install_salt.relenv:
|
||||
pytest.skip("The extras directory is only in relenv versions")
|
||||
dep = "salt-analytics-framework"
|
||||
dep_version = "0.1.0"
|
||||
|
||||
|
|
|
@ -5,11 +5,18 @@ import pytest
|
|||
from tests.support.helpers import TESTS_DIR
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def python_script_bin(install_salt):
|
||||
# Tiamat builds run scripts via `salt python`
|
||||
if not install_salt.relenv and not install_salt.classic:
|
||||
return install_salt.binary_paths["python"][:1] + ["python"]
|
||||
return install_salt.binary_paths["python"]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("exp_ret,user_arg", [(1, "false"), (0, "true")])
|
||||
def test_python_script(install_salt, exp_ret, user_arg):
|
||||
ret = subprocess.run(
|
||||
install_salt.binary_paths["python"]
|
||||
+ [str(TESTS_DIR / "files" / "check_python.py"), user_arg],
|
||||
def test_python_script(install_salt, exp_ret, user_arg, python_script_bin):
|
||||
ret = install_salt.proc.run(
|
||||
*(python_script_bin + [str(TESTS_DIR / "files" / "check_python.py"), user_arg]),
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
check=False,
|
||||
|
@ -19,10 +26,9 @@ def test_python_script(install_salt, exp_ret, user_arg):
|
|||
assert ret.returncode == exp_ret, ret.stderr
|
||||
|
||||
|
||||
def test_python_script_exception(install_salt):
|
||||
ret = subprocess.run(
|
||||
install_salt.binary_paths["python"]
|
||||
+ [str(TESTS_DIR / "files" / "check_python.py"), "raise"],
|
||||
def test_python_script_exception(install_salt, python_script_bin):
|
||||
ret = install_salt.proc.run(
|
||||
*(python_script_bin + [str(TESTS_DIR / "files" / "check_python.py"), "raise"]),
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
check=False,
|
||||
|
|
|
@ -7,15 +7,22 @@ pytestmark = [
|
|||
]
|
||||
|
||||
|
||||
def test_salt_cmd_run(salt_cli, salt_minion):
|
||||
@pytest.fixture
|
||||
def cat_file(tmp_path):
|
||||
fp = tmp_path / "cat-file"
|
||||
fp.write_text(str(fp))
|
||||
return fp
|
||||
|
||||
|
||||
def test_salt_cmd_run(salt_cli, salt_minion, cat_file):
|
||||
"""
|
||||
Test salt cmd.run 'ipconfig' or 'ls -lah /'
|
||||
Test salt cmd.run 'ipconfig' or 'cat <file>'
|
||||
"""
|
||||
ret = None
|
||||
if platform.startswith("win"):
|
||||
ret = salt_cli.run("cmd.run", "ipconfig", minion_tgt=salt_minion.id)
|
||||
else:
|
||||
ret = salt_cli.run("cmd.run", "ls -lah /", minion_tgt=salt_minion.id)
|
||||
ret = salt_cli.run("cmd.run", f"cat {str(cat_file)}", minion_tgt=salt_minion.id)
|
||||
assert ret
|
||||
assert ret.stdout
|
||||
|
||||
|
|
|
@ -3,10 +3,9 @@ import pathlib
|
|||
import subprocess
|
||||
import sys
|
||||
|
||||
import packaging.version
|
||||
import psutil
|
||||
import pytest
|
||||
import yaml
|
||||
from pytestskipmarkers.utils import platform
|
||||
|
||||
pytestmark = [
|
||||
pytest.mark.skip_on_windows,
|
||||
|
@ -61,6 +60,12 @@ def pkg_paths_salt_user_exclusions():
|
|||
return paths
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def _skip_on_non_relenv(install_salt):
|
||||
if not install_salt.relenv:
|
||||
pytest.skip("The salt user only exists on relenv versions of salt")
|
||||
|
||||
|
||||
def test_salt_user_master(salt_master, install_salt):
|
||||
"""
|
||||
Test the correct user is running the Salt Master
|
||||
|
@ -129,6 +134,10 @@ def test_pkg_paths(
|
|||
"""
|
||||
Test package paths ownership
|
||||
"""
|
||||
if packaging.version.parse(install_salt.version) <= packaging.version.parse(
|
||||
"3006.2"
|
||||
):
|
||||
pytest.skip("Package path ownership was changed in salt 3006.3")
|
||||
salt_user_subdirs = []
|
||||
for _path in pkg_paths:
|
||||
pkg_path = pathlib.Path(_path)
|
||||
|
|
|
@ -23,6 +23,8 @@ def test_salt_versions_report_master(install_salt):
|
|||
"""
|
||||
Test running --versions-report on master
|
||||
"""
|
||||
if not install_salt.relenv and not install_salt.classic:
|
||||
pytest.skip("Unable to get the python version dynamically from tiamat builds")
|
||||
test_bin = os.path.join(*install_salt.binary_paths["master"])
|
||||
python_bin = os.path.join(*install_salt.binary_paths["python"])
|
||||
ret = install_salt.proc.run(test_bin, "--versions-report")
|
||||
|
@ -52,14 +54,13 @@ def test_compare_versions(version, binary, install_salt):
|
|||
"""
|
||||
Test compare versions
|
||||
"""
|
||||
if platform.is_windows() and install_salt.singlebin:
|
||||
pytest.skip(
|
||||
"Already tested in `test_salt_version`. No need to repeat for "
|
||||
"Windows single binary installs."
|
||||
)
|
||||
|
||||
if binary in install_salt.binary_paths:
|
||||
ret = install_salt.proc.run(*install_salt.binary_paths[binary], "--version")
|
||||
ret = install_salt.proc.run(
|
||||
*install_salt.binary_paths[binary],
|
||||
"--version",
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
)
|
||||
ret.stdout.matcher.fnmatch_lines([f"*{version}*"])
|
||||
else:
|
||||
if platform.is_windows():
|
||||
|
@ -93,11 +94,10 @@ def test_symlinks_created(version, symlink, install_salt):
|
|||
"""
|
||||
Test symlinks created
|
||||
"""
|
||||
if not install_salt.installer_pkg:
|
||||
pytest.skip(
|
||||
"This test is for the installer package only (pkg). It does not "
|
||||
"apply to the tarball"
|
||||
)
|
||||
if install_salt.classic:
|
||||
pytest.skip("Symlinks not created for classic macos builds, we adjust the path")
|
||||
if not install_salt.relenv and symlink == "spm":
|
||||
symlink = "salt-spm"
|
||||
ret = install_salt.proc.run(pathlib.Path("/usr/local/sbin") / symlink, "--version")
|
||||
ret.stdout.matcher.fnmatch_lines([f"*{version}*"])
|
||||
|
||||
|
|
|
@ -6,11 +6,9 @@ import pathlib
|
|||
import pprint
|
||||
import re
|
||||
import shutil
|
||||
import tarfile
|
||||
import textwrap
|
||||
import time
|
||||
from typing import TYPE_CHECKING, Any, Dict, List
|
||||
from zipfile import ZipFile
|
||||
from typing import TYPE_CHECKING, Dict, List
|
||||
|
||||
import attr
|
||||
import distro
|
||||
|
@ -43,13 +41,6 @@ try:
|
|||
except ImportError:
|
||||
HAS_PWD = False
|
||||
|
||||
try:
|
||||
import winreg
|
||||
|
||||
HAS_WINREG = True
|
||||
except ImportError:
|
||||
HAS_WINREG = False
|
||||
|
||||
TESTS_DIR = pathlib.Path(__file__).resolve().parent.parent
|
||||
CODE_DIR = TESTS_DIR.parent
|
||||
ARTIFACTS_DIR = CODE_DIR / "artifacts"
|
||||
|
@ -59,57 +50,52 @@ log = logging.getLogger(__name__)
|
|||
|
||||
@attr.s(kw_only=True, slots=True)
|
||||
class SaltPkgInstall:
|
||||
conf_dir: pathlib.Path = attr.ib()
|
||||
system_service: bool = attr.ib(default=False)
|
||||
proc: Subprocess = attr.ib(init=False, repr=False)
|
||||
pkgs: List[str] = attr.ib(factory=list)
|
||||
onedir: bool = attr.ib(default=False)
|
||||
singlebin: bool = attr.ib(default=False)
|
||||
compressed: bool = attr.ib(default=False)
|
||||
hashes: Dict[str, Dict[str, Any]] = attr.ib(repr=False)
|
||||
system_service: bool = attr.ib(default=False)
|
||||
|
||||
# Paths
|
||||
root: pathlib.Path = attr.ib(default=None)
|
||||
run_root: pathlib.Path = attr.ib(default=None)
|
||||
ssm_bin: pathlib.Path = attr.ib(default=None)
|
||||
bin_dir: pathlib.Path = attr.ib(default=None)
|
||||
# The artifact is an installer (exe, msi, pkg, rpm, deb)
|
||||
installer_pkg: bool = attr.ib(default=False)
|
||||
install_dir: pathlib.Path = attr.ib(init=False)
|
||||
binary_paths: Dict[str, List[pathlib.Path]] = attr.ib(init=False)
|
||||
config_path: str = attr.ib(init=False)
|
||||
conf_dir: pathlib.Path = attr.ib()
|
||||
|
||||
# Test selection flags
|
||||
upgrade: bool = attr.ib(default=False)
|
||||
# install salt or not. This allows someone
|
||||
# to test a currently installed version of salt
|
||||
downgrade: bool = attr.ib(default=False)
|
||||
classic: bool = attr.ib(default=False)
|
||||
|
||||
# Installing flags
|
||||
no_install: bool = attr.ib(default=False)
|
||||
no_uninstall: bool = attr.ib(default=False)
|
||||
|
||||
# Distribution/system information
|
||||
distro_id: str = attr.ib(init=False)
|
||||
distro_codename: str = attr.ib(init=False)
|
||||
distro_name: str = attr.ib(init=False)
|
||||
distro_version: str = attr.ib(init=False)
|
||||
|
||||
# Package (and management) metadata
|
||||
pkg_mngr: str = attr.ib(init=False)
|
||||
rm_pkg: str = attr.ib(init=False)
|
||||
salt_pkgs: List[str] = attr.ib(init=False)
|
||||
install_dir: pathlib.Path = attr.ib(init=False)
|
||||
binary_paths: Dict[str, List[pathlib.Path]] = attr.ib(init=False)
|
||||
classic: bool = attr.ib(default=False)
|
||||
prev_version: str = attr.ib()
|
||||
pkg_version: str = attr.ib(default="1")
|
||||
repo_data: str = attr.ib(init=False, repr=False)
|
||||
major: str = attr.ib(init=False)
|
||||
minor: str = attr.ib(init=False)
|
||||
relenv: bool = attr.ib(default=True)
|
||||
pkgs: List[str] = attr.ib(factory=list)
|
||||
file_ext: bool = attr.ib(default=None)
|
||||
config_path: str = attr.ib(init=False)
|
||||
relenv: bool = attr.ib(default=True)
|
||||
|
||||
# Version information
|
||||
prev_version: str = attr.ib()
|
||||
use_prev_version: str = attr.ib()
|
||||
artifact_version: str = attr.ib(init=False)
|
||||
version: str = attr.ib(init=False)
|
||||
|
||||
@proc.default
|
||||
def _default_proc(self):
|
||||
return Subprocess()
|
||||
|
||||
@hashes.default
|
||||
def _default_hashes(self):
|
||||
return {
|
||||
"BLAKE2B": {"file": None, "tool": "-blake2b512"},
|
||||
"SHA3_512": {"file": None, "tool": "-sha3-512"},
|
||||
"SHA512": {"file": None, "tool": "-sha512"},
|
||||
}
|
||||
|
||||
@distro_id.default
|
||||
def _default_distro_id(self):
|
||||
return distro.id().lower()
|
||||
|
@ -166,7 +152,6 @@ class SaltPkgInstall:
|
|||
os.getenv("ProgramFiles"), "Salt Project", "Salt"
|
||||
).resolve()
|
||||
elif platform.is_darwin():
|
||||
# TODO: Add mac install dir path
|
||||
install_dir = pathlib.Path("/opt", "salt")
|
||||
else:
|
||||
install_dir = pathlib.Path("/opt", "saltstack", "salt")
|
||||
|
@ -183,197 +168,99 @@ class SaltPkgInstall:
|
|||
config_path = pathlib.Path("/etc", "salt")
|
||||
return config_path
|
||||
|
||||
@repo_data.default
|
||||
def _default_repo_data(self):
|
||||
@version.default
|
||||
def _default_version(self):
|
||||
"""
|
||||
Query to see the published Salt artifacts
|
||||
from repo.json
|
||||
The version to be installed at the start
|
||||
"""
|
||||
url = "https://repo.saltproject.io/salt/onedir/repo.json"
|
||||
ret = requests.get(url)
|
||||
data = ret.json()
|
||||
return data
|
||||
if not self.upgrade and not self.use_prev_version:
|
||||
version = self.artifact_version
|
||||
else:
|
||||
version = self.prev_version
|
||||
parsed = packaging.version.parse(version)
|
||||
version = f"{parsed.major}.{parsed.minor}"
|
||||
if self.distro_id in ("ubuntu", "debian"):
|
||||
self.stop_services()
|
||||
return version
|
||||
|
||||
def check_relenv(self, version):
|
||||
@artifact_version.default
|
||||
def _default_artifact_version(self):
|
||||
"""
|
||||
Detects if we are using relenv
|
||||
onedir build
|
||||
The version of the local salt artifacts being tested, based on regex matching
|
||||
"""
|
||||
relenv = False
|
||||
if packaging.version.parse(version) >= packaging.version.parse("3006.0"):
|
||||
relenv = True
|
||||
return relenv
|
||||
version = ""
|
||||
for artifact in ARTIFACTS_DIR.glob("**/*.*"):
|
||||
version = re.search(
|
||||
r"([0-9].*)(\-[0-9].fc|\-[0-9].el|\+ds|\_all|\_any|\_amd64|\_arm64|\-[0-9].am|(\-[0-9]-[a-z]*-[a-z]*[0-9_]*.|\-[0-9]*.*)(exe|msi|pkg|rpm|deb))",
|
||||
artifact.name,
|
||||
)
|
||||
if version:
|
||||
version = version.groups()[0].replace("_", "-").replace("~", "")
|
||||
version = version.split("-")[0]
|
||||
break
|
||||
return version
|
||||
|
||||
def update_process_path(self):
|
||||
# The installer updates the path for the system, but that doesn't
|
||||
# make it to this python session, so we need to update that
|
||||
os.environ["PATH"] = ";".join([str(self.install_dir), os.getenv("path")])
|
||||
|
||||
# When the MSI installer is run from self.proc.run, it doesn't update
|
||||
# the registry. When run from a normal command prompt it does. Until we
|
||||
# figure that out, we will update the process path as above. This
|
||||
# doesn't really check that the path is being set though... but I see
|
||||
# no other way around this
|
||||
# if HAS_WINREG:
|
||||
# log.debug("Refreshing the path")
|
||||
# # Get the updated system path from the registry
|
||||
# path_key = winreg.OpenKeyEx(
|
||||
# winreg.HKEY_LOCAL_MACHINE,
|
||||
# r"SYSTEM\CurrentControlSet\Control\Session Manager\Environment",
|
||||
# )
|
||||
# current_path = winreg.QueryValueEx(path_key, "path")[0]
|
||||
# path_key.Close()
|
||||
# # Update the path for the current running process
|
||||
# os.environ["PATH"] = current_path
|
||||
|
||||
def get_version(self, version_only=False):
|
||||
"""
|
||||
Return the version information
|
||||
needed to install a previous version
|
||||
of Salt.
|
||||
"""
|
||||
prev_version = self.prev_version
|
||||
pkg_version = None
|
||||
if not self.upgrade:
|
||||
# working with local artifact
|
||||
version = ""
|
||||
for artifact in ARTIFACTS_DIR.glob("**/*.*"):
|
||||
version = re.search(
|
||||
r"([0-9].*)(\-[0-9].fc|\-[0-9].el|\+ds|\_all|\_any|\_amd64|\_arm64|\-[0-9].am|(\-[0-9]-[a-z]*-[a-z]*[0-9_]*.|\-[0-9]*.*)(tar.gz|tar.xz|zip|exe|msi|pkg|rpm|deb))",
|
||||
artifact.name,
|
||||
)
|
||||
if version:
|
||||
version = version.groups()[0].replace("_", "-").replace("~", "")
|
||||
version = version.split("-")[0]
|
||||
# TODO: Remove this clause. This is to handle a versioning difficulty between pre-3006
|
||||
# dev versions and older salt versions on deb-based distros
|
||||
if version.startswith("1:"):
|
||||
version = version[2:]
|
||||
break
|
||||
major, minor = version.split(".", 1)
|
||||
else:
|
||||
if not prev_version:
|
||||
# We did not pass in a version, lets detect the latest
|
||||
# version information of a Salt artifact.
|
||||
latest = list(self.repo_data["latest"].keys())[0]
|
||||
version = self.repo_data["latest"][latest]["version"]
|
||||
if "-" in version:
|
||||
prev_version, pkg_version = version.split("-")
|
||||
else:
|
||||
prev_version, pkg_version = version, None
|
||||
else:
|
||||
# We passed in a version, but lets check if the pkg_version
|
||||
# is defined. Relenv pkgs do not define a pkg build number
|
||||
if "-" not in prev_version and not self.check_relenv(
|
||||
version=prev_version
|
||||
):
|
||||
pkg_numbers = [
|
||||
x for x in self.repo_data.keys() if prev_version in x
|
||||
]
|
||||
pkg_version = 1
|
||||
for number in pkg_numbers:
|
||||
number = int(number.split("-")[1])
|
||||
if number > pkg_version:
|
||||
pkg_version = number
|
||||
major, minor = prev_version.split(".")
|
||||
if version_only:
|
||||
return version
|
||||
return major, minor, prev_version, pkg_version
|
||||
|
||||
def __attrs_post_init__(self):
|
||||
self.major, self.minor, self.prev_version, self.pkg_version = self.get_version()
|
||||
self.relenv = self.check_relenv(self.major)
|
||||
file_ext_re = r"tar\.gz"
|
||||
self.relenv = packaging.version.parse(self.version) >= packaging.version.parse(
|
||||
"3006.0"
|
||||
)
|
||||
|
||||
file_ext_re = "rpm|deb"
|
||||
if platform.is_darwin():
|
||||
file_ext_re = r"tar\.gz|pkg"
|
||||
file_ext_re = "pkg"
|
||||
if platform.is_windows():
|
||||
file_ext_re = "zip|exe|msi"
|
||||
file_ext_re = "exe|msi"
|
||||
|
||||
for f_path in ARTIFACTS_DIR.glob("**/*.*"):
|
||||
f_path = str(f_path)
|
||||
if re.search(f"salt-(.*).({file_ext_re})$", f_path, re.IGNORECASE):
|
||||
# Compressed can be zip, tar.gz, exe, or pkg. All others are
|
||||
# deb and rpm
|
||||
self.compressed = True
|
||||
self.file_ext = os.path.splitext(f_path)[1].strip(".")
|
||||
if self.file_ext == "gz":
|
||||
if f_path.endswith("tar.gz"):
|
||||
self.file_ext = "tar.gz"
|
||||
self.pkgs.append(f_path)
|
||||
if platform.is_windows():
|
||||
self.root = pathlib.Path(os.getenv("LocalAppData")).resolve()
|
||||
if self.file_ext == "zip":
|
||||
with ZipFile(f_path, "r") as zip:
|
||||
first = zip.infolist()[0]
|
||||
if first.filename == "salt/ssm.exe":
|
||||
self.onedir = True
|
||||
self.bin_dir = self.root / "salt" / "salt"
|
||||
self.run_root = self.bin_dir / "salt.exe"
|
||||
self.ssm_bin = self.root / "salt" / "ssm.exe"
|
||||
elif first.filename == "salt.exe":
|
||||
self.singlebin = True
|
||||
self.run_root = self.root / "salt.exe"
|
||||
self.ssm_bin = self.root / "ssm.exe"
|
||||
else:
|
||||
log.error(
|
||||
"Unexpected archive layout. First: %s",
|
||||
first.filename,
|
||||
)
|
||||
elif self.file_ext in ["exe", "msi"]:
|
||||
self.compressed = False
|
||||
self.onedir = True
|
||||
self.installer_pkg = True
|
||||
if self.file_ext in ["exe", "msi"]:
|
||||
self.root = self.install_dir.parent
|
||||
self.bin_dir = self.install_dir
|
||||
self.ssm_bin = self.install_dir / "ssm.exe"
|
||||
self.run_root = self.bin_dir / "bin" / "salt.exe"
|
||||
if not self.relenv and not self.classic:
|
||||
self.ssm_bin = self.bin_dir / "bin" / "ssm.exe"
|
||||
else:
|
||||
log.error("Unexpected file extension: %s", self.file_ext)
|
||||
else:
|
||||
if platform.is_darwin():
|
||||
self.root = pathlib.Path(os.sep, "opt")
|
||||
else:
|
||||
self.root = pathlib.Path(os.sep, "usr", "local", "bin")
|
||||
if self.use_prev_version:
|
||||
self.bin_dir = self.install_dir / "bin"
|
||||
self.run_root = self.bin_dir / "salt.exe"
|
||||
self.ssm_bin = self.bin_dir / "ssm.exe"
|
||||
if self.file_ext == "msi" or self.relenv:
|
||||
self.ssm_bin = self.install_dir / "ssm.exe"
|
||||
if (
|
||||
self.install_dir / "salt-minion.exe"
|
||||
).exists() and not self.relenv:
|
||||
log.debug(
|
||||
f"Removing {(self.install_dir / 'salt-minion.exe')}"
|
||||
)
|
||||
(self.install_dir / "salt-minion.exe").unlink()
|
||||
|
||||
elif platform.is_darwin():
|
||||
self.root = pathlib.Path("/opt")
|
||||
if self.file_ext == "pkg":
|
||||
self.compressed = False
|
||||
self.onedir = True
|
||||
self.installer_pkg = True
|
||||
self.bin_dir = self.root / "salt" / "bin"
|
||||
self.run_root = self.bin_dir / "run"
|
||||
elif self.file_ext == "tar.gz":
|
||||
with tarfile.open(f_path) as tar:
|
||||
# The first item will be called salt
|
||||
first = next(iter(tar.getmembers()))
|
||||
if first.name == "salt" and first.isdir():
|
||||
self.onedir = True
|
||||
self.bin_dir = self.root / "salt" / "run"
|
||||
self.run_root = self.bin_dir / "run"
|
||||
elif first.name == "salt" and first.isfile():
|
||||
self.singlebin = True
|
||||
self.run_root = self.root / "salt"
|
||||
else:
|
||||
log.error(
|
||||
"Unexpected archive layout. First: %s (isdir: %s, isfile: %s)",
|
||||
first.name,
|
||||
first.isdir(),
|
||||
first.isfile(),
|
||||
)
|
||||
else:
|
||||
log.error("Unexpected file extension: %s", self.file_ext)
|
||||
|
||||
if re.search(
|
||||
r"salt(.*)(x86_64|all|amd64|aarch64|arm64)\.(rpm|deb)$", f_path
|
||||
):
|
||||
self.installer_pkg = True
|
||||
self.pkgs.append(f_path)
|
||||
|
||||
if not self.pkgs:
|
||||
pytest.fail("Could not find Salt Artifacts")
|
||||
|
||||
python_bin = self.install_dir / "bin" / "python3"
|
||||
if platform.is_windows():
|
||||
python_bin = self.install_dir / "Scripts" / "python.exe"
|
||||
if not self.compressed:
|
||||
if platform.is_windows():
|
||||
if self.relenv:
|
||||
self.binary_paths = {
|
||||
"call": ["salt-call.exe"],
|
||||
"cp": ["salt-cp.exe"],
|
||||
|
@ -381,11 +268,29 @@ class SaltPkgInstall:
|
|||
"pip": ["salt-pip.exe"],
|
||||
"python": [python_bin],
|
||||
}
|
||||
elif self.classic:
|
||||
self.binary_paths = {
|
||||
"call": [self.install_dir / "salt-call.bat"],
|
||||
"cp": [self.install_dir / "salt-cp.bat"],
|
||||
"minion": [self.install_dir / "salt-minion.bat"],
|
||||
"python": [self.bin_dir / "python.exe"],
|
||||
}
|
||||
self.binary_paths["pip"] = self.binary_paths["python"] + ["-m", "pip"]
|
||||
else:
|
||||
if os.path.exists(self.install_dir / "bin" / "salt"):
|
||||
install_dir = self.install_dir / "bin"
|
||||
else:
|
||||
install_dir = self.install_dir
|
||||
self.binary_paths = {
|
||||
"call": [str(self.run_root), "call"],
|
||||
"cp": [str(self.run_root), "cp"],
|
||||
"minion": [str(self.run_root), "minion"],
|
||||
"pip": [str(self.run_root), "pip"],
|
||||
"python": [str(self.run_root), "shell"],
|
||||
}
|
||||
|
||||
else:
|
||||
if os.path.exists(self.install_dir / "bin" / "salt"):
|
||||
install_dir = self.install_dir / "bin"
|
||||
else:
|
||||
install_dir = self.install_dir
|
||||
if self.relenv:
|
||||
self.binary_paths = {
|
||||
"salt": [install_dir / "salt"],
|
||||
"api": [install_dir / "salt-api"],
|
||||
|
@ -403,61 +308,56 @@ class SaltPkgInstall:
|
|||
"pip": [install_dir / "salt-pip"],
|
||||
"python": [python_bin],
|
||||
}
|
||||
else:
|
||||
if self.run_root and os.path.exists(self.run_root):
|
||||
if platform.is_windows():
|
||||
self.binary_paths = {
|
||||
"call": [str(self.run_root), "call"],
|
||||
"cp": [str(self.run_root), "cp"],
|
||||
"minion": [str(self.run_root), "minion"],
|
||||
"pip": [str(self.run_root), "pip"],
|
||||
"python": [python_bin],
|
||||
}
|
||||
else:
|
||||
self.binary_paths = {
|
||||
"salt": [str(self.run_root)],
|
||||
"api": [str(self.run_root), "api"],
|
||||
"call": [str(self.run_root), "call"],
|
||||
"cloud": [str(self.run_root), "cloud"],
|
||||
"cp": [str(self.run_root), "cp"],
|
||||
"key": [str(self.run_root), "key"],
|
||||
"master": [str(self.run_root), "master"],
|
||||
"minion": [str(self.run_root), "minion"],
|
||||
"proxy": [str(self.run_root), "proxy"],
|
||||
"run": [str(self.run_root), "run"],
|
||||
"ssh": [str(self.run_root), "ssh"],
|
||||
"syndic": [str(self.run_root), "syndic"],
|
||||
"spm": [str(self.run_root), "spm"],
|
||||
"pip": [str(self.run_root), "pip"],
|
||||
"python": [python_bin],
|
||||
}
|
||||
else:
|
||||
if platform.is_windows():
|
||||
self.binary_paths = {
|
||||
"call": [self.install_dir / "salt-call.exe"],
|
||||
"cp": [self.install_dir / "salt-cp.exe"],
|
||||
"minion": [self.install_dir / "salt-minion.exe"],
|
||||
"pip": [self.install_dir / "salt-pip.exe"],
|
||||
"python": [python_bin],
|
||||
}
|
||||
self.binary_paths = {
|
||||
"salt": [shutil.which("salt")],
|
||||
"api": [shutil.which("salt-api")],
|
||||
"call": [shutil.which("salt-call")],
|
||||
"cloud": [shutil.which("salt-cloud")],
|
||||
"cp": [shutil.which("salt-cp")],
|
||||
"key": [shutil.which("salt-key")],
|
||||
"master": [shutil.which("salt-master")],
|
||||
"minion": [shutil.which("salt-minion")],
|
||||
"proxy": [shutil.which("salt-proxy")],
|
||||
"run": [shutil.which("salt-run")],
|
||||
"ssh": [shutil.which("salt-ssh")],
|
||||
"syndic": [shutil.which("salt-syndic")],
|
||||
"spm": [shutil.which("spm")],
|
||||
"python": [str(pathlib.Path("/usr/bin/python3"))],
|
||||
}
|
||||
if self.classic:
|
||||
if platform.is_darwin():
|
||||
# `which` is not catching the right paths on downgrades, explicitly defining them here
|
||||
self.binary_paths = {
|
||||
"salt": [self.bin_dir / "salt"],
|
||||
"api": [self.bin_dir / "salt-api"],
|
||||
"call": [self.bin_dir / "salt-call"],
|
||||
"cloud": [self.bin_dir / "salt-cloud"],
|
||||
"cp": [self.bin_dir / "salt-cp"],
|
||||
"key": [self.bin_dir / "salt-key"],
|
||||
"master": [self.bin_dir / "salt-master"],
|
||||
"minion": [self.bin_dir / "salt-minion"],
|
||||
"proxy": [self.bin_dir / "salt-proxy"],
|
||||
"run": [self.bin_dir / "salt-run"],
|
||||
"ssh": [self.bin_dir / "salt-ssh"],
|
||||
"syndic": [self.bin_dir / "salt-syndic"],
|
||||
"spm": [self.bin_dir / "spm"],
|
||||
"python": [str(self.bin_dir / "python3")],
|
||||
"pip": [str(self.bin_dir / "pip3")],
|
||||
}
|
||||
else:
|
||||
self.binary_paths["pip"] = [str(pathlib.Path("/usr/bin/pip3"))]
|
||||
self.proc.run(*self.binary_paths["pip"], "install", "-U", "pip")
|
||||
self.proc.run(
|
||||
*self.binary_paths["pip"], "install", "-U", "pyopenssl"
|
||||
)
|
||||
else:
|
||||
self.binary_paths = {
|
||||
"salt": [self.install_dir / "salt"],
|
||||
"api": [self.install_dir / "salt-api"],
|
||||
"call": [self.install_dir / "salt-call"],
|
||||
"cloud": [self.install_dir / "salt-cloud"],
|
||||
"cp": [self.install_dir / "salt-cp"],
|
||||
"key": [self.install_dir / "salt-key"],
|
||||
"master": [self.install_dir / "salt-master"],
|
||||
"minion": [self.install_dir / "salt-minion"],
|
||||
"proxy": [self.install_dir / "salt-proxy"],
|
||||
"run": [self.install_dir / "salt-run"],
|
||||
"ssh": [self.install_dir / "salt-ssh"],
|
||||
"syndic": [self.install_dir / "salt-syndic"],
|
||||
"spm": [self.install_dir / "spm"],
|
||||
"pip": [self.install_dir / "salt-pip"],
|
||||
"python": [python_bin],
|
||||
}
|
||||
self.binary_paths["python"] = [shutil.which("salt"), "shell"]
|
||||
if platform.is_darwin():
|
||||
self.binary_paths["pip"] = [self.run_root, "pip"]
|
||||
self.binary_paths["spm"] = [shutil.which("salt-spm")]
|
||||
else:
|
||||
self.binary_paths["pip"] = [shutil.which("salt-pip")]
|
||||
|
||||
@staticmethod
|
||||
def salt_factories_root_dir(system_service: bool = False) -> pathlib.Path:
|
||||
|
@ -479,79 +379,10 @@ class SaltPkgInstall:
|
|||
assert ret.returncode == 0
|
||||
return True
|
||||
|
||||
@property
|
||||
def salt_hashes(self):
|
||||
for _hash in self.hashes.keys():
|
||||
for fpath in ARTIFACTS_DIR.glob(f"**/*{_hash}*"):
|
||||
fpath = str(fpath)
|
||||
if re.search(f"{_hash}", fpath):
|
||||
self.hashes[_hash]["file"] = fpath
|
||||
|
||||
return self.hashes
|
||||
|
||||
def _install_ssm_service(self):
|
||||
# Register the services
|
||||
# run_root and ssm_bin are configured in helper.py to point to the
|
||||
# correct binary location
|
||||
log.debug("Installing master service")
|
||||
ret = self.proc.run(
|
||||
str(self.ssm_bin),
|
||||
"install",
|
||||
"salt-master",
|
||||
str(self.run_root),
|
||||
"master",
|
||||
"-c",
|
||||
str(self.conf_dir),
|
||||
)
|
||||
self._check_retcode(ret)
|
||||
log.debug("Installing minion service")
|
||||
ret = self.proc.run(
|
||||
str(self.ssm_bin),
|
||||
"install",
|
||||
"salt-minion",
|
||||
str(self.run_root),
|
||||
"minion",
|
||||
"-c",
|
||||
str(self.conf_dir),
|
||||
)
|
||||
self._check_retcode(ret)
|
||||
log.debug("Installing api service")
|
||||
ret = self.proc.run(
|
||||
str(self.ssm_bin),
|
||||
"install",
|
||||
"salt-api",
|
||||
str(self.run_root),
|
||||
"api",
|
||||
"-c",
|
||||
str(self.conf_dir),
|
||||
)
|
||||
self._check_retcode(ret)
|
||||
|
||||
def _install_compressed(self, upgrade=False):
|
||||
pkg = self.pkgs[0]
|
||||
log.info("Installing %s", pkg)
|
||||
if platform.is_windows():
|
||||
if pkg.endswith("zip"):
|
||||
# Extract the files
|
||||
log.debug("Extracting zip file")
|
||||
with ZipFile(pkg, "r") as zip:
|
||||
zip.extractall(path=self.root)
|
||||
elif pkg.endswith("exe") or pkg.endswith("msi"):
|
||||
log.error("Not a compressed package type: %s", pkg)
|
||||
else:
|
||||
log.error("Unknown package type: %s", pkg)
|
||||
if self.system_service:
|
||||
self._install_ssm_service()
|
||||
elif platform.is_darwin():
|
||||
log.debug("Extracting tarball into %s", self.root)
|
||||
with tarfile.open(pkg) as tar: # , "r:gz")
|
||||
tar.extractall(path=str(self.root))
|
||||
else:
|
||||
log.debug("Extracting tarball into %s", self.root)
|
||||
with tarfile.open(pkg) as tar: # , "r:gz")
|
||||
tar.extractall(path=str(self.root))
|
||||
|
||||
def _install_pkgs(self, upgrade=False):
|
||||
def _install_pkgs(self, upgrade=False, downgrade=False):
|
||||
if downgrade:
|
||||
self.install_previous(downgrade=downgrade)
|
||||
return True
|
||||
pkg = self.pkgs[0]
|
||||
if platform.is_windows():
|
||||
if upgrade:
|
||||
|
@ -586,7 +417,7 @@ class SaltPkgInstall:
|
|||
self.update_process_path()
|
||||
|
||||
elif platform.is_darwin():
|
||||
daemons_dir = pathlib.Path(os.sep, "Library", "LaunchDaemons")
|
||||
daemons_dir = pathlib.Path("/Library", "LaunchDaemons")
|
||||
service_name = "com.saltstack.salt.minion"
|
||||
plist_file = daemons_dir / f"{service_name}.plist"
|
||||
log.debug("Installing: %s", str(pkg))
|
||||
|
@ -621,18 +452,22 @@ class SaltPkgInstall:
|
|||
ret = self.proc.run(self.pkg_mngr, "install", "-y", *self.pkgs)
|
||||
if not platform.is_darwin() and not platform.is_windows():
|
||||
# Make sure we don't have any trailing references to old package file locations
|
||||
ret.returncode == 0
|
||||
assert ret.returncode == 0
|
||||
assert "/saltstack/salt/run" not in ret.stdout
|
||||
log.info(ret)
|
||||
self._check_retcode(ret)
|
||||
|
||||
def install(self, upgrade=False):
|
||||
if self.compressed:
|
||||
self._install_compressed(upgrade=upgrade)
|
||||
else:
|
||||
self._install_pkgs(upgrade=upgrade)
|
||||
if self.distro_id in ("ubuntu", "debian"):
|
||||
self.stop_services()
|
||||
def package_python_version(self):
|
||||
return self.proc.run(
|
||||
str(self.binary_paths["python"][0]),
|
||||
"-c",
|
||||
"import sys; print('{}.{}'.format(*sys.version_info))",
|
||||
).stdout.strip()
|
||||
|
||||
def install(self, upgrade=False, downgrade=False):
|
||||
self._install_pkgs(upgrade=upgrade, downgrade=downgrade)
|
||||
if self.distro_id in ("ubuntu", "debian"):
|
||||
self.stop_services()
|
||||
|
||||
def stop_services(self):
|
||||
"""
|
||||
|
@ -641,29 +476,28 @@ class SaltPkgInstall:
|
|||
settings we have set. This will also verify the expected
|
||||
services are up and running.
|
||||
"""
|
||||
retval = True
|
||||
for service in ["salt-syndic", "salt-master", "salt-minion"]:
|
||||
check_run = self.proc.run("systemctl", "status", service)
|
||||
if check_run.returncode != 0:
|
||||
# The system was not started automatically and we
|
||||
# are expecting it to be on install
|
||||
log.debug("The service %s was not started on install.", service)
|
||||
return False
|
||||
stop_service = self.proc.run("systemctl", "stop", service)
|
||||
self._check_retcode(stop_service)
|
||||
return True
|
||||
retval = False
|
||||
else:
|
||||
stop_service = self.proc.run("systemctl", "stop", service)
|
||||
self._check_retcode(stop_service)
|
||||
return retval
|
||||
|
||||
def install_previous(self):
|
||||
def install_previous(self, downgrade=False):
|
||||
"""
|
||||
Install previous version. This is used for
|
||||
upgrade tests.
|
||||
"""
|
||||
major_ver = self.major
|
||||
minor_ver = self.minor
|
||||
pkg_version = self.pkg_version
|
||||
full_version = f"{self.major}.{self.minor}-{pkg_version}"
|
||||
relenv = int(major_ver) >= 3006
|
||||
|
||||
min_ver = f"{major_ver}"
|
||||
major_ver = packaging.version.parse(self.prev_version).major
|
||||
relenv = packaging.version.parse(self.prev_version) >= packaging.version.parse(
|
||||
"3006.0"
|
||||
)
|
||||
distro_name = self.distro_name
|
||||
if distro_name == "centos" or distro_name == "fedora":
|
||||
distro_name = "redhat"
|
||||
|
@ -672,6 +506,7 @@ class SaltPkgInstall:
|
|||
root_url = "py3/"
|
||||
|
||||
if self.distro_name in ["redhat", "centos", "amazon", "fedora", "vmware"]:
|
||||
# Removing EPEL repo files
|
||||
for fp in pathlib.Path("/etc", "yum.repos.d").glob("epel*"):
|
||||
fp.unlink()
|
||||
gpg_key = "SALTSTACK-GPG-KEY.pub"
|
||||
|
@ -696,10 +531,23 @@ class SaltPkgInstall:
|
|||
)
|
||||
ret = self.proc.run(self.pkg_mngr, "clean", "expire-cache")
|
||||
self._check_retcode(ret)
|
||||
cmd_action = "downgrade" if downgrade else "install"
|
||||
pkgs_to_install = self.salt_pkgs.copy()
|
||||
if self.distro_version == "8" and self.classic:
|
||||
# centosstream 8 doesn't downgrade properly using the downgrade command for some reason
|
||||
# So we explicitly install the correct version here
|
||||
list_ret = self.proc.run(
|
||||
self.pkg_mngr, "list", "--available", "salt"
|
||||
).stdout.split("\n")
|
||||
list_ret = [_.strip() for _ in list_ret]
|
||||
idx = list_ret.index("Available Packages")
|
||||
old_ver = list_ret[idx + 1].split()[1]
|
||||
pkgs_to_install = [f"{pkg}-{old_ver}" for pkg in pkgs_to_install]
|
||||
cmd_action = "install"
|
||||
ret = self.proc.run(
|
||||
self.pkg_mngr,
|
||||
"install",
|
||||
*self.salt_pkgs,
|
||||
cmd_action,
|
||||
*pkgs_to_install,
|
||||
"-y",
|
||||
)
|
||||
self._check_retcode(ret)
|
||||
|
@ -710,7 +558,7 @@ class SaltPkgInstall:
|
|||
ret = self.proc.run(self.pkg_mngr, "install", "apt-transport-https", "-y")
|
||||
self._check_retcode(ret)
|
||||
## only classic 3005 has arm64 support
|
||||
if self.major >= "3006" and platform.is_aarch64():
|
||||
if relenv and platform.is_aarch64():
|
||||
arch = "arm64"
|
||||
elif platform.is_aarch64() and self.classic:
|
||||
arch = "arm64"
|
||||
|
@ -733,29 +581,65 @@ class SaltPkgInstall:
|
|||
f"deb [signed-by=/etc/apt/keyrings/{gpg_dest} arch={arch}] "
|
||||
f"https://repo.saltproject.io/{root_url}{distro_name}/{self.distro_version}/{arch}/{major_ver} {self.distro_codename} main"
|
||||
)
|
||||
ret = self.proc.run(self.pkg_mngr, "update")
|
||||
self._check_retcode(ret)
|
||||
ret = self.proc.run(
|
||||
|
||||
cmd = [
|
||||
self.pkg_mngr,
|
||||
"install",
|
||||
*self.salt_pkgs,
|
||||
"-y",
|
||||
)
|
||||
self._check_retcode(ret)
|
||||
]
|
||||
|
||||
if downgrade:
|
||||
pref_file = pathlib.Path("/etc", "apt", "preferences.d", "salt.pref")
|
||||
pref_file.parent.mkdir(exist_ok=True)
|
||||
pref_file.write_text(
|
||||
textwrap.dedent(
|
||||
"""\
|
||||
Package: salt*
|
||||
Pin: origin "repo.saltproject.io"
|
||||
Pin-Priority: 1001
|
||||
"""
|
||||
)
|
||||
)
|
||||
cmd.append("--allow-downgrades")
|
||||
env = os.environ.copy()
|
||||
env["DEBIAN_FRONTEND"] = "noninteractive"
|
||||
extra_args = [
|
||||
"-o",
|
||||
"DPkg::Options::=--force-confdef",
|
||||
"-o",
|
||||
"DPkg::Options::=--force-confold",
|
||||
]
|
||||
ret = self.proc.run(self.pkg_mngr, "update", *extra_args, env=env)
|
||||
|
||||
cmd.extend(extra_args)
|
||||
|
||||
ret = self.proc.run(*cmd, env=env)
|
||||
# Pre-relenv packages down get downgraded to cleanly programmatically
|
||||
# They work manually, and the install tests after downgrades will catch problems with the install
|
||||
# Let's not check the returncode if this is the case
|
||||
if not (
|
||||
downgrade
|
||||
and not packaging.version.parse(self.prev_version)
|
||||
>= packaging.version.parse("3006.0")
|
||||
):
|
||||
self._check_retcode(ret)
|
||||
if downgrade:
|
||||
pref_file.unlink()
|
||||
self.stop_services()
|
||||
elif platform.is_windows():
|
||||
self.onedir = True
|
||||
self.installer_pkg = True
|
||||
self.bin_dir = self.install_dir / "bin"
|
||||
self.run_root = self.bin_dir / f"salt.exe"
|
||||
self.run_root = self.bin_dir / "salt.exe"
|
||||
self.ssm_bin = self.bin_dir / "ssm.exe"
|
||||
if self.file_ext == "msi" or relenv:
|
||||
self.ssm_bin = self.install_dir / "ssm.exe"
|
||||
|
||||
if not self.classic:
|
||||
if not relenv:
|
||||
win_pkg = f"salt-{self.prev_version}-windows-amd64.{self.file_ext}"
|
||||
win_pkg_url = f"https://repo.saltproject.io/salt/py3/windows/{self.prev_version}/{win_pkg}"
|
||||
win_pkg = (
|
||||
f"salt-{self.prev_version}-1-windows-amd64.{self.file_ext}"
|
||||
)
|
||||
else:
|
||||
if self.file_ext == "msi":
|
||||
win_pkg = (
|
||||
|
@ -763,12 +647,14 @@ class SaltPkgInstall:
|
|||
)
|
||||
elif self.file_ext == "exe":
|
||||
win_pkg = f"Salt-Minion-{self.prev_version}-Py3-AMD64-Setup.{self.file_ext}"
|
||||
win_pkg_url = f"https://repo.saltproject.io/salt/py3/windows/{major_ver}/{win_pkg}"
|
||||
win_pkg_url = f"https://repo.saltproject.io/salt/py3/windows/{major_ver}/{win_pkg}"
|
||||
else:
|
||||
if self.file_ext == "msi":
|
||||
win_pkg = f"Salt-Minion-{min_ver}-1-Py3-AMD64.{self.file_ext}"
|
||||
win_pkg = (
|
||||
f"Salt-Minion-{self.prev_version}-Py3-AMD64.{self.file_ext}"
|
||||
)
|
||||
elif self.file_ext == "exe":
|
||||
win_pkg = f"Salt-Minion-{min_ver}-1-Py3-AMD64-Setup.{self.file_ext}"
|
||||
win_pkg = f"Salt-Minion-{self.prev_version}-Py3-AMD64-Setup.{self.file_ext}"
|
||||
win_pkg_url = f"https://repo.saltproject.io/windows/{win_pkg}"
|
||||
pkg_path = pathlib.Path(r"C:\TEMP", win_pkg)
|
||||
pkg_path.parent.mkdir(exist_ok=True)
|
||||
|
@ -802,11 +688,12 @@ class SaltPkgInstall:
|
|||
mac_pkg_url = f"https://repo.saltproject.io/osx/{mac_pkg}"
|
||||
else:
|
||||
if not relenv:
|
||||
mac_pkg = f"salt-{self.prev_version}-macos-x86_64.pkg"
|
||||
mac_pkg_url = f"https://repo.saltproject.io/salt/py3/macos/{self.prev_version}/{mac_pkg}"
|
||||
mac_pkg = f"salt-{self.prev_version}-1-macos-x86_64.pkg"
|
||||
else:
|
||||
mac_pkg = f"salt-{self.prev_version}-py3-x86_64.pkg"
|
||||
mac_pkg_url = f"https://repo.saltproject.io/salt/py3/macos/{major_ver}/{mac_pkg}"
|
||||
mac_pkg_url = (
|
||||
f"https://repo.saltproject.io/salt/py3/macos/{major_ver}/{mac_pkg}"
|
||||
)
|
||||
|
||||
mac_pkg_path = f"/tmp/{mac_pkg}"
|
||||
if not os.path.exists(mac_pkg_path):
|
||||
|
@ -818,28 +705,21 @@ class SaltPkgInstall:
|
|||
ret = self.proc.run("installer", "-pkg", mac_pkg_path, "-target", "/")
|
||||
self._check_retcode(ret)
|
||||
|
||||
def _uninstall_compressed(self):
|
||||
def uninstall(self):
|
||||
pkg = self.pkgs[0]
|
||||
if platform.is_windows():
|
||||
if self.system_service:
|
||||
# Uninstall the services
|
||||
log.debug("Uninstalling master service")
|
||||
self.proc.run(str(self.ssm_bin), "stop", "salt-master")
|
||||
self.proc.run(str(self.ssm_bin), "remove", "salt-master", "confirm")
|
||||
log.debug("Uninstalling minion service")
|
||||
self.proc.run(str(self.ssm_bin), "stop", "salt-minion")
|
||||
self.proc.run(str(self.ssm_bin), "remove", "salt-minion", "confirm")
|
||||
log.debug("Uninstalling api service")
|
||||
self.proc.run(str(self.ssm_bin), "stop", "salt-api")
|
||||
self.proc.run(str(self.ssm_bin), "remove", "salt-api", "confirm")
|
||||
log.debug("Removing the Salt Service Manager")
|
||||
if self.ssm_bin:
|
||||
try:
|
||||
self.ssm_bin.unlink()
|
||||
except PermissionError:
|
||||
atexit.register(self.ssm_bin.unlink)
|
||||
if platform.is_darwin():
|
||||
log.info("Uninstalling %s", pkg)
|
||||
if pkg.endswith("exe"):
|
||||
uninst = self.install_dir / "uninst.exe"
|
||||
ret = self.proc.run(uninst, "/S")
|
||||
self._check_retcode(ret)
|
||||
elif pkg.endswith("msi"):
|
||||
ret = self.proc.run("msiexec.exe", "/qn", "/x", pkg)
|
||||
self._check_retcode(ret)
|
||||
|
||||
elif platform.is_darwin():
|
||||
# From here: https://stackoverflow.com/a/46118276/4581998
|
||||
daemons_dir = pathlib.Path(os.sep, "Library", "LaunchDaemons")
|
||||
daemons_dir = pathlib.Path("/Library", "LaunchDaemons")
|
||||
for service in ("minion", "master", "api", "syndic"):
|
||||
service_name = f"com.saltstack.salt.{service}"
|
||||
plist_file = daemons_dir / f"{service_name}.plist"
|
||||
|
@ -883,42 +763,13 @@ class SaltPkgInstall:
|
|||
# Remove receipt
|
||||
self.proc.run("pkgutil", "--forget", "com.saltstack.salt")
|
||||
|
||||
if self.singlebin:
|
||||
log.debug("Deleting the salt binary: %s", self.run_root)
|
||||
if self.run_root:
|
||||
try:
|
||||
self.run_root.unlink()
|
||||
except PermissionError:
|
||||
atexit.register(self.run_root.unlink)
|
||||
else:
|
||||
log.debug("Deleting the onedir directory: %s", self.root / "salt")
|
||||
shutil.rmtree(str(self.root / "salt"))
|
||||
|
||||
def _uninstall_pkgs(self):
|
||||
pkg = self.pkgs[0]
|
||||
if platform.is_windows():
|
||||
log.info("Uninstalling %s", pkg)
|
||||
if pkg.endswith("exe"):
|
||||
uninst = self.install_dir / "uninst.exe"
|
||||
ret = self.proc.run(uninst, "/S")
|
||||
self._check_retcode(ret)
|
||||
elif pkg.endswith("msi"):
|
||||
ret = self.proc.run("msiexec.exe", "/qn", "/x", pkg)
|
||||
self._check_retcode(ret)
|
||||
|
||||
elif platform.is_darwin():
|
||||
self._uninstall_compressed()
|
||||
else:
|
||||
log.debug("Un-Installing packages:\n%s", pprint.pformat(self.salt_pkgs))
|
||||
ret = self.proc.run(self.pkg_mngr, self.rm_pkg, "-y", *self.salt_pkgs)
|
||||
self._check_retcode(ret)
|
||||
|
||||
def uninstall(self):
|
||||
if self.compressed:
|
||||
self._uninstall_compressed()
|
||||
else:
|
||||
self._uninstall_pkgs()
|
||||
|
||||
def assert_uninstalled(self):
|
||||
"""
|
||||
Assert that the paths in /opt/saltstack/ were correctly
|
||||
|
@ -958,7 +809,7 @@ class SaltPkgInstall:
|
|||
ret = self.proc.run("launchctl", "list", service_name)
|
||||
# 113 means it couldn't find a service with that name
|
||||
if ret.returncode == 113:
|
||||
daemons_dir = pathlib.Path(os.sep, "Library", "LaunchDaemons")
|
||||
daemons_dir = pathlib.Path("/Library", "LaunchDaemons")
|
||||
plist_file = daemons_dir / f"{service_name}.plist"
|
||||
# Make sure we're using this plist file
|
||||
if plist_file.exists():
|
||||
|
@ -1034,9 +885,7 @@ class SaltPkgInstall:
|
|||
binary = shutil.which(binary[0]) or binary[0]
|
||||
elif isinstance(binary, list):
|
||||
binary = " ".join(binary)
|
||||
unit_path = pathlib.Path(
|
||||
os.sep, "etc", "systemd", "system", f"{service}.service"
|
||||
)
|
||||
unit_path = pathlib.Path("/etc", "systemd", "system", f"{service}.service")
|
||||
contents = contents.format(
|
||||
service=service, tgt=binary, conf_dir=self.conf_dir
|
||||
)
|
||||
|
@ -1077,7 +926,7 @@ class PkgLaunchdSaltDaemonImpl(PkgSystemdSaltDaemonImpl):
|
|||
|
||||
@plist_file.default
|
||||
def _default_plist_file(self):
|
||||
daemons_dir = pathlib.Path(os.sep, "Library", "LaunchDaemons")
|
||||
daemons_dir = pathlib.Path("/Library", "LaunchDaemons")
|
||||
return daemons_dir / f"{self.get_service_name()}.plist"
|
||||
|
||||
def get_service_name(self):
|
||||
|
@ -1364,11 +1213,7 @@ class PkgMixin:
|
|||
salt_pkg_install: SaltPkgInstall = attr.ib()
|
||||
|
||||
def get_script_path(self):
|
||||
if self.salt_pkg_install.compressed or (
|
||||
platform.is_darwin()
|
||||
and self.salt_pkg_install.classic
|
||||
and self.salt_pkg_install.upgrade
|
||||
):
|
||||
if platform.is_darwin() and self.salt_pkg_install.classic:
|
||||
if self.salt_pkg_install.run_root and os.path.exists(
|
||||
self.salt_pkg_install.run_root
|
||||
):
|
||||
|
@ -1379,23 +1224,8 @@ class PkgMixin:
|
|||
return str(self.salt_pkg_install.install_dir / self.script_name)
|
||||
return super().get_script_path()
|
||||
|
||||
def get_base_script_args(self):
|
||||
base_script_args = []
|
||||
if self.salt_pkg_install.run_root and os.path.exists(
|
||||
self.salt_pkg_install.run_root
|
||||
):
|
||||
if self.salt_pkg_install.compressed:
|
||||
if self.script_name == "spm":
|
||||
base_script_args.append(self.script_name)
|
||||
elif self.script_name != "salt":
|
||||
base_script_args.append(self.script_name.split("salt-")[-1])
|
||||
base_script_args.extend(super().get_base_script_args())
|
||||
return base_script_args
|
||||
|
||||
def cmdline(self, *args, **kwargs):
|
||||
_cmdline = super().cmdline(*args, **kwargs)
|
||||
if self.salt_pkg_install.compressed is False:
|
||||
return _cmdline
|
||||
if _cmdline[0] == self.python_executable:
|
||||
_cmdline.pop(0)
|
||||
return _cmdline
|
||||
|
|
0
pkg/tests/upgrade/__init__.py
Normal file
0
pkg/tests/upgrade/__init__.py
Normal file
|
@ -1,37 +1,44 @@
|
|||
import packaging.version
|
||||
import pytest
|
||||
|
||||
|
||||
def test_salt_upgrade(salt_call_cli, salt_minion, install_salt):
|
||||
def test_salt_upgrade(salt_call_cli, install_salt):
|
||||
"""
|
||||
Test upgrade of Salt
|
||||
Test an upgrade of Salt.
|
||||
"""
|
||||
if not install_salt.upgrade:
|
||||
pytest.skip("Not testing an upgrade, do not run")
|
||||
# verify previous install version is setup correctly and works
|
||||
ret = salt_call_cli.run("test.ping")
|
||||
assert ret.returncode == 0
|
||||
assert ret.data
|
||||
|
||||
# test pip install before an upgrade
|
||||
if install_salt.relenv:
|
||||
original_py_version = install_salt.package_python_version()
|
||||
|
||||
# Verify previous install version is setup correctly and works
|
||||
ret = salt_call_cli.run("test.version")
|
||||
assert ret.returncode == 0
|
||||
assert packaging.version.parse(ret.data) < packaging.version.parse(
|
||||
install_salt.artifact_version
|
||||
)
|
||||
|
||||
# Test pip install before an upgrade
|
||||
dep = "PyGithub==1.56.0"
|
||||
install = salt_call_cli.run("--local", "pip.install", dep)
|
||||
assert install.returncode == 0
|
||||
|
||||
# Verify we can use the module dependent on the installed package
|
||||
repo = "https://github.com/saltstack/salt.git"
|
||||
install = salt_call_cli.run("--local", "pip.install", dep)
|
||||
assert install.returncode == 0
|
||||
use_lib = salt_call_cli.run("--local", "github.get_repo_info", repo)
|
||||
assert "Authentication information could" in use_lib.stderr
|
||||
|
||||
# upgrade Salt from previous version and test
|
||||
# Upgrade Salt from previous version and test
|
||||
install_salt.install(upgrade=True)
|
||||
ret = salt_call_cli.run("test.ping")
|
||||
ret = salt_call_cli.run("test.version")
|
||||
assert ret.returncode == 0
|
||||
assert ret.data
|
||||
assert packaging.version.parse(ret.data) == packaging.version.parse(
|
||||
install_salt.artifact_version
|
||||
)
|
||||
|
||||
# install dep following upgrade
|
||||
# TODO: Remove this once we figure out how to
|
||||
# preserve things installed via PIP between upgrades.
|
||||
install = salt_call_cli.run("--local", "pip.install", dep)
|
||||
assert install.returncode == 0
|
||||
|
||||
# test pip install after an upgrade
|
||||
use_lib = salt_call_cli.run("--local", "github.get_repo_info", repo)
|
||||
assert "Authentication information could" in use_lib.stderr
|
||||
if install_salt.relenv:
|
||||
new_py_version = install_salt.package_python_version()
|
||||
if new_py_version == original_py_version:
|
||||
# test pip install after an upgrade
|
||||
use_lib = salt_call_cli.run("--local", "github.get_repo_info", repo)
|
||||
|
|
|
@ -3,10 +3,9 @@
|
|||
-r zeromq.txt
|
||||
|
||||
apache-libcloud>=2.4.0
|
||||
backports.ssl_match_hostname>=3.7.0.1; python_version < '3.7'
|
||||
cherrypy>=17.4.1
|
||||
gitpython>=3.1.30
|
||||
cryptography>=41.0.3
|
||||
gitpython>=3.1.30
|
||||
idna>=2.8
|
||||
linode-python>=1.1.1
|
||||
pyasn1>=0.4.8
|
||||
|
|
|
@ -2,10 +2,9 @@
|
|||
--constraint=../pkg/py{py_version}/{platform}.txt
|
||||
|
||||
pyiface
|
||||
pygit2<1.11.0; python_version < '3.8'
|
||||
pygit2>=1.11.0; python_version >= '3.8'
|
||||
pygit2>=1.4.0
|
||||
pymysql>=1.0.2
|
||||
ansible>=4.4.0,<5.0.1; python_version <= '3.8'
|
||||
ansible>=4.4.0,<5.0.1; python_version < '3.9'
|
||||
ansible>=7.0.0; python_version >= '3.9'
|
||||
twilio
|
||||
python-telegram-bot>=13.7
|
||||
|
|
|
@ -36,13 +36,13 @@ bcrypt==4.0.1
|
|||
# via
|
||||
# -r requirements/static/ci/common.in
|
||||
# paramiko
|
||||
boto3==1.26.152
|
||||
boto3==1.21.46
|
||||
# via
|
||||
# -r requirements/static/ci/common.in
|
||||
# moto
|
||||
boto==2.49.0
|
||||
# via -r requirements/static/ci/common.in
|
||||
botocore==1.29.152
|
||||
botocore==1.24.46
|
||||
# via
|
||||
# boto3
|
||||
# moto
|
||||
|
@ -140,7 +140,7 @@ gitdb==4.0.10
|
|||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.10/darwin.txt
|
||||
# gitpython
|
||||
gitpython==3.1.32
|
||||
gitpython==3.1.35
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.10/darwin.txt
|
||||
# -r requirements/darwin.txt
|
||||
|
@ -445,7 +445,7 @@ rfc3987==1.3.8
|
|||
# via -r requirements/static/ci/common.in
|
||||
rsa==4.9
|
||||
# via google-auth
|
||||
s3transfer==0.6.1
|
||||
s3transfer==0.5.2
|
||||
# via boto3
|
||||
scp==0.14.5
|
||||
# via
|
||||
|
|
|
@ -33,13 +33,13 @@ bcrypt==4.0.1
|
|||
# via
|
||||
# -r requirements/static/ci/common.in
|
||||
# paramiko
|
||||
boto3==1.26.152
|
||||
boto3==1.21.46
|
||||
# via
|
||||
# -r requirements/static/ci/common.in
|
||||
# moto
|
||||
boto==2.49.0
|
||||
# via -r requirements/static/ci/common.in
|
||||
botocore==1.29.152
|
||||
botocore==1.24.46
|
||||
# via
|
||||
# boto3
|
||||
# moto
|
||||
|
@ -135,7 +135,7 @@ geomet==0.2.1.post1
|
|||
# via cassandra-driver
|
||||
gitdb==4.0.10
|
||||
# via gitpython
|
||||
gitpython==3.1.32
|
||||
gitpython==3.1.35
|
||||
# via -r requirements/static/ci/common.in
|
||||
google-auth==2.19.1
|
||||
# via kubernetes
|
||||
|
@ -438,7 +438,7 @@ rfc3987==1.3.8
|
|||
# via -r requirements/static/ci/common.in
|
||||
rsa==4.9
|
||||
# via google-auth
|
||||
s3transfer==0.6.1
|
||||
s3transfer==0.5.2
|
||||
# via boto3
|
||||
scp==0.14.5
|
||||
# via
|
||||
|
|
|
@ -14,7 +14,7 @@ mccabe==0.6.1
|
|||
# via pylint
|
||||
modernize==0.5
|
||||
# via saltpylint
|
||||
pycodestyle==2.10.0
|
||||
pycodestyle==2.5.0
|
||||
# via saltpylint
|
||||
pylint==2.4.4
|
||||
# via
|
||||
|
|
|
@ -44,13 +44,13 @@ bcrypt==4.0.1
|
|||
# via
|
||||
# -r requirements/static/ci/common.in
|
||||
# paramiko
|
||||
boto3==1.26.152
|
||||
boto3==1.21.46
|
||||
# via
|
||||
# -r requirements/static/ci/common.in
|
||||
# moto
|
||||
boto==2.49.0
|
||||
# via -r requirements/static/ci/common.in
|
||||
botocore==1.29.152
|
||||
botocore==1.24.46
|
||||
# via
|
||||
# boto3
|
||||
# moto
|
||||
|
@ -151,7 +151,7 @@ geomet==0.2.1.post1
|
|||
# via cassandra-driver
|
||||
gitdb==4.0.10
|
||||
# via gitpython
|
||||
gitpython==3.1.31
|
||||
gitpython==3.1.35
|
||||
# via -r requirements/static/ci/common.in
|
||||
google-auth==2.19.1
|
||||
# via kubernetes
|
||||
|
@ -325,7 +325,7 @@ portend==3.1.0
|
|||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.10/linux.txt
|
||||
# cherrypy
|
||||
psutil==5.8.0
|
||||
psutil==5.9.5
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.10/linux.txt
|
||||
# -r requirements/base.txt
|
||||
|
@ -352,15 +352,15 @@ pydantic==1.10.8
|
|||
# inflect
|
||||
pyeapi==1.0.0
|
||||
# via napalm
|
||||
pygit2==1.12.1 ; python_version >= "3.8"
|
||||
pygit2==1.12.1
|
||||
# via -r requirements/static/ci/linux.in
|
||||
pyiface==0.0.11
|
||||
# via -r requirements/static/ci/linux.in
|
||||
pyinotify==0.9.6 ; sys_platform != "win32" and sys_platform != "darwin" and platform_system != "openbsd"
|
||||
# via -r requirements/static/ci/common.in
|
||||
pyjwt==2.7.0
|
||||
pyjwt==2.4.0
|
||||
# via twilio
|
||||
pymysql==1.0.3
|
||||
pymysql==1.0.2
|
||||
# via -r requirements/static/ci/linux.in
|
||||
pynacl==1.5.0
|
||||
# via
|
||||
|
@ -490,7 +490,7 @@ rpm-vercmp==0.1.2
|
|||
# -r requirements/static/pkg/linux.in
|
||||
rsa==4.9
|
||||
# via google-auth
|
||||
s3transfer==0.6.1
|
||||
s3transfer==0.5.2
|
||||
# via boto3
|
||||
scp==0.14.5
|
||||
# via
|
||||
|
|
|
@ -25,13 +25,13 @@ autocommand==2.2.2
|
|||
# jaraco.text
|
||||
bcrypt==4.0.1
|
||||
# via -r requirements/static/ci/common.in
|
||||
boto3==1.26.152
|
||||
boto3==1.21.46
|
||||
# via
|
||||
# -r requirements/static/ci/common.in
|
||||
# moto
|
||||
boto==2.49.0
|
||||
# via -r requirements/static/ci/common.in
|
||||
botocore==1.29.152
|
||||
botocore==1.24.46
|
||||
# via
|
||||
# boto3
|
||||
# moto
|
||||
|
@ -115,7 +115,7 @@ docker==6.1.3
|
|||
# via -r requirements/pytest.txt
|
||||
etcd3-py==0.1.6
|
||||
# via -r requirements/static/ci/common.in
|
||||
exceptiongroup==1.1.1
|
||||
exceptiongroup==1.0.4
|
||||
# via pytest
|
||||
filelock==3.12.1
|
||||
# via virtualenv
|
||||
|
@ -133,7 +133,7 @@ gitdb==4.0.10
|
|||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.10/windows.txt
|
||||
# gitpython
|
||||
gitpython==3.1.32
|
||||
gitpython==3.1.35
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.10/windows.txt
|
||||
# -r requirements/static/ci/common.in
|
||||
|
@ -160,6 +160,10 @@ inflect==6.0.4
|
|||
# jaraco.text
|
||||
iniconfig==2.0.0
|
||||
# via pytest
|
||||
ioloop==0.1a0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.10/windows.txt
|
||||
# -r requirements/windows.txt
|
||||
ipaddress==1.0.23
|
||||
# via kubernetes
|
||||
jaraco.collections==4.1.0
|
||||
|
@ -258,7 +262,7 @@ portend==3.1.0
|
|||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.10/windows.txt
|
||||
# cherrypy
|
||||
psutil==5.8.0
|
||||
psutil==5.9.5
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.10/windows.txt
|
||||
# -r requirements/base.txt
|
||||
|
@ -408,7 +412,7 @@ rfc3987==1.3.8
|
|||
# via -r requirements/static/ci/common.in
|
||||
rsa==4.9
|
||||
# via google-auth
|
||||
s3transfer==0.6.1
|
||||
s3transfer==0.5.2
|
||||
# via boto3
|
||||
sed==0.3.1
|
||||
# via -r requirements/static/ci/windows.in
|
||||
|
|
|
@ -138,7 +138,7 @@ gitdb==4.0.10
|
|||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.11/darwin.txt
|
||||
# gitpython
|
||||
gitpython==3.1.31
|
||||
gitpython==3.1.35
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.11/darwin.txt
|
||||
# -r requirements/darwin.txt
|
||||
|
|
|
@ -133,7 +133,7 @@ geomet==0.2.1.post1
|
|||
# via cassandra-driver
|
||||
gitdb==4.0.10
|
||||
# via gitpython
|
||||
gitpython==3.1.31
|
||||
gitpython==3.1.35
|
||||
# via -r requirements/static/ci/common.in
|
||||
google-auth==2.19.1
|
||||
# via kubernetes
|
||||
|
|
|
@ -147,7 +147,7 @@ geomet==0.2.1.post1
|
|||
# via cassandra-driver
|
||||
gitdb==4.0.10
|
||||
# via gitpython
|
||||
gitpython==3.1.31
|
||||
gitpython==3.1.35
|
||||
# via -r requirements/static/ci/common.in
|
||||
google-auth==2.19.1
|
||||
# via kubernetes
|
||||
|
@ -348,7 +348,7 @@ pydantic==1.10.8
|
|||
# inflect
|
||||
pyeapi==1.0.0
|
||||
# via napalm
|
||||
pygit2==1.12.1 ; python_version >= "3.8"
|
||||
pygit2==1.12.1
|
||||
# via -r requirements/static/ci/linux.in
|
||||
pyiface==0.0.11
|
||||
# via -r requirements/static/ci/linux.in
|
||||
|
|
|
@ -118,7 +118,7 @@ pytest-system-statistics==1.0.2
|
|||
# via pytest-salt-factories
|
||||
pytest-tempdir==2019.10.12
|
||||
# via pytest-salt-factories
|
||||
pytest==7.3.1
|
||||
pytest==7.3.2
|
||||
# via
|
||||
# pytest-helpers-namespace
|
||||
# pytest-salt-factories
|
||||
|
|
|
@ -32,7 +32,7 @@ distro==1.8.0
|
|||
# via
|
||||
# -r requirements/base.txt
|
||||
# pytest-skip-markers
|
||||
docker==6.1.2
|
||||
docker==6.1.3
|
||||
# via -r requirements/static/ci/pkgtests.in
|
||||
filelock==3.9.0
|
||||
# via virtualenv
|
||||
|
@ -115,7 +115,7 @@ pytest-system-statistics==1.0.2
|
|||
# via pytest-salt-factories
|
||||
pytest-tempdir==2019.10.12
|
||||
# via pytest-salt-factories
|
||||
pytest==7.3.1
|
||||
pytest==7.3.2
|
||||
# via
|
||||
# pytest-helpers-namespace
|
||||
# pytest-salt-factories
|
||||
|
|
|
@ -25,13 +25,13 @@ autocommand==2.2.2
|
|||
# jaraco.text
|
||||
bcrypt==4.0.1
|
||||
# via -r requirements/static/ci/common.in
|
||||
boto3==1.26.152
|
||||
boto3==1.21.46
|
||||
# via
|
||||
# -r requirements/static/ci/common.in
|
||||
# moto
|
||||
boto==2.49.0
|
||||
# via -r requirements/static/ci/common.in
|
||||
botocore==1.29.152
|
||||
botocore==1.24.46
|
||||
# via
|
||||
# boto3
|
||||
# moto
|
||||
|
@ -115,7 +115,7 @@ docker==6.1.3
|
|||
# via -r requirements/pytest.txt
|
||||
etcd3-py==0.1.6
|
||||
# via -r requirements/static/ci/common.in
|
||||
filelock==3.12.1
|
||||
filelock==3.12.3
|
||||
# via virtualenv
|
||||
flaky==3.7.0
|
||||
# via -r requirements/pytest.txt
|
||||
|
@ -131,7 +131,7 @@ gitdb==4.0.10
|
|||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.11/windows.txt
|
||||
# gitpython
|
||||
gitpython==3.1.32
|
||||
gitpython==3.1.35
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.11/windows.txt
|
||||
# -r requirements/static/ci/common.in
|
||||
|
@ -158,6 +158,10 @@ inflect==6.0.4
|
|||
# jaraco.text
|
||||
iniconfig==2.0.0
|
||||
# via pytest
|
||||
ioloop==0.1a0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.11/windows.txt
|
||||
# -r requirements/windows.txt
|
||||
ipaddress==1.0.23
|
||||
# via kubernetes
|
||||
jaraco.collections==4.1.0
|
||||
|
@ -256,7 +260,7 @@ portend==3.1.0
|
|||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.11/windows.txt
|
||||
# cherrypy
|
||||
psutil==5.8.0
|
||||
psutil==5.9.5
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.11/windows.txt
|
||||
# -r requirements/base.txt
|
||||
|
@ -406,7 +410,7 @@ rfc3987==1.3.8
|
|||
# via -r requirements/static/ci/common.in
|
||||
rsa==4.9
|
||||
# via google-auth
|
||||
s3transfer==0.6.1
|
||||
s3transfer==0.5.2
|
||||
# via boto3
|
||||
sed==0.3.1
|
||||
# via -r requirements/static/ci/windows.in
|
||||
|
|
|
@ -33,13 +33,13 @@ bcrypt==4.0.1
|
|||
# via
|
||||
# -r requirements/static/ci/common.in
|
||||
# paramiko
|
||||
boto3==1.26.152
|
||||
boto3==1.21.46
|
||||
# via
|
||||
# -r requirements/static/ci/common.in
|
||||
# moto
|
||||
boto==2.49.0
|
||||
# via -r requirements/static/ci/common.in
|
||||
botocore==1.29.152
|
||||
botocore==1.24.46
|
||||
# via
|
||||
# boto3
|
||||
# moto
|
||||
|
@ -79,6 +79,8 @@ cherrypy==18.8.0
|
|||
# -c requirements/static/ci/../pkg/py3.8/freebsd.txt
|
||||
# -r requirements/static/ci/common.in
|
||||
# -r requirements/static/pkg/freebsd.in
|
||||
ciscoconfparse==1.7.24
|
||||
# via napalm
|
||||
click==8.1.3
|
||||
# via geomet
|
||||
clustershell==1.9.1
|
||||
|
@ -99,6 +101,8 @@ cryptography==41.0.3
|
|||
# paramiko
|
||||
# pyopenssl
|
||||
# vcert
|
||||
deprecat==2.1.1
|
||||
# via ciscoconfparse
|
||||
distlib==0.3.6
|
||||
# via virtualenv
|
||||
distro==1.8.0
|
||||
|
@ -110,6 +114,7 @@ distro==1.8.0
|
|||
dnspython==2.3.0
|
||||
# via
|
||||
# -r requirements/static/ci/common.in
|
||||
# ciscoconfparse
|
||||
# python-etcd
|
||||
docker==6.1.3
|
||||
# via -r requirements/pytest.txt
|
||||
|
@ -135,7 +140,7 @@ geomet==0.2.1.post1
|
|||
# via cassandra-driver
|
||||
gitdb==4.0.10
|
||||
# via gitpython
|
||||
gitpython==3.1.32
|
||||
gitpython==3.1.35
|
||||
# via -r requirements/static/ci/common.in
|
||||
google-auth==2.19.1
|
||||
# via kubernetes
|
||||
|
@ -217,6 +222,8 @@ kubernetes==3.0.0
|
|||
# via -r requirements/static/ci/common.in
|
||||
libnacl==1.8.0 ; sys_platform != "win32" and sys_platform != "darwin"
|
||||
# via -r requirements/static/ci/common.in
|
||||
loguru==0.6.0
|
||||
# via ciscoconfparse
|
||||
looseversion==1.2.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.8/freebsd.txt
|
||||
|
@ -258,12 +265,10 @@ multidict==6.0.4
|
|||
# via
|
||||
# aiohttp
|
||||
# yarl
|
||||
napalm==4.1.0 ; sys_platform != "win32"
|
||||
napalm==3.1.0 ; sys_platform != "win32"
|
||||
# via -r requirements/static/ci/common.in
|
||||
ncclient==0.6.13
|
||||
# via
|
||||
# junos-eznc
|
||||
# napalm
|
||||
# via junos-eznc
|
||||
netaddr==0.8.0
|
||||
# via
|
||||
# junos-eznc
|
||||
|
@ -271,8 +276,6 @@ netaddr==0.8.0
|
|||
# pyeapi
|
||||
netmiko==4.2.0
|
||||
# via napalm
|
||||
netutils==1.4.1
|
||||
# via napalm
|
||||
ntc-templates==3.4.0
|
||||
# via netmiko
|
||||
oscrypto==1.3.0
|
||||
|
@ -292,7 +295,9 @@ paramiko==3.2.0 ; sys_platform != "win32" and sys_platform != "darwin"
|
|||
# netmiko
|
||||
# scp
|
||||
passlib==1.7.4
|
||||
# via -r requirements/static/ci/common.in
|
||||
# via
|
||||
# -r requirements/static/ci/common.in
|
||||
# ciscoconfparse
|
||||
pathspec==0.11.1
|
||||
# via yamllint
|
||||
platformdirs==3.5.3
|
||||
|
@ -442,7 +447,7 @@ rfc3987==1.3.8
|
|||
# via -r requirements/static/ci/common.in
|
||||
rsa==4.9
|
||||
# via google-auth
|
||||
s3transfer==0.6.1
|
||||
s3transfer==0.5.2
|
||||
# via boto3
|
||||
scp==0.14.5
|
||||
# via
|
||||
|
@ -495,7 +500,9 @@ timelib==0.3.0
|
|||
# -c requirements/static/ci/../pkg/py3.8/freebsd.txt
|
||||
# -r requirements/static/pkg/freebsd.in
|
||||
toml==0.10.2
|
||||
# via -r requirements/static/ci/common.in
|
||||
# via
|
||||
# -r requirements/static/ci/common.in
|
||||
# ciscoconfparse
|
||||
tomli==2.0.1
|
||||
# via pytest
|
||||
tornado==6.3.2 ; python_version >= "3.8"
|
||||
|
@ -504,18 +511,11 @@ tornado==6.3.2 ; python_version >= "3.8"
|
|||
# -r requirements/base.txt
|
||||
transitions==0.9.0
|
||||
# via junos-eznc
|
||||
ttp-templates==0.3.5
|
||||
# via napalm
|
||||
ttp==0.9.4
|
||||
# via
|
||||
# napalm
|
||||
# ttp-templates
|
||||
types-pyyaml==6.0.1
|
||||
# via responses
|
||||
typing-extensions==4.6.2
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.8/freebsd.txt
|
||||
# napalm
|
||||
# pydantic
|
||||
# pytest-shell-utilities
|
||||
# pytest-system-statistics
|
||||
|
@ -547,6 +547,8 @@ werkzeug==2.3.6
|
|||
# via
|
||||
# moto
|
||||
# pytest-httpserver
|
||||
wrapt==1.15.0
|
||||
# via deprecat
|
||||
xmldiff==2.6.3
|
||||
# via -r requirements/static/ci/common.in
|
||||
xmltodict==0.13.0
|
||||
|
|
|
@ -14,7 +14,7 @@ mccabe==0.6.1
|
|||
# via pylint
|
||||
modernize==0.5
|
||||
# via saltpylint
|
||||
pycodestyle==2.10.0
|
||||
pycodestyle==2.5.0
|
||||
# via saltpylint
|
||||
pylint==2.4.4
|
||||
# via
|
||||
|
@ -31,4 +31,6 @@ toml==0.10.2
|
|||
# -c requirements/static/ci/py3.8/linux.txt
|
||||
# -r requirements/static/ci/lint.in
|
||||
wrapt==1.11.2
|
||||
# via astroid
|
||||
# via
|
||||
# -c requirements/static/ci/py3.8/linux.txt
|
||||
# astroid
|
||||
|
|
|
@ -15,7 +15,7 @@ aiosignal==1.3.1
|
|||
# via aiohttp
|
||||
ansible-core==2.11.12
|
||||
# via ansible
|
||||
ansible==4.10.0 ; python_version <= "3.8"
|
||||
ansible==4.10.0 ; python_version < "3.9"
|
||||
# via -r requirements/static/ci/linux.in
|
||||
anyio==3.7.0
|
||||
# via httpcore
|
||||
|
@ -44,13 +44,13 @@ bcrypt==4.0.1
|
|||
# via
|
||||
# -r requirements/static/ci/common.in
|
||||
# paramiko
|
||||
boto3==1.26.152
|
||||
boto3==1.21.46
|
||||
# via
|
||||
# -r requirements/static/ci/common.in
|
||||
# moto
|
||||
boto==2.49.0
|
||||
# via -r requirements/static/ci/common.in
|
||||
botocore==1.29.152
|
||||
botocore==1.24.46
|
||||
# via
|
||||
# boto3
|
||||
# moto
|
||||
|
@ -93,6 +93,8 @@ cherrypy==18.8.0
|
|||
# -c requirements/static/ci/../pkg/py3.8/linux.txt
|
||||
# -r requirements/static/ci/common.in
|
||||
# -r requirements/static/pkg/linux.in
|
||||
ciscoconfparse==1.7.24
|
||||
# via napalm
|
||||
click==8.1.3
|
||||
# via geomet
|
||||
clustershell==1.9.1
|
||||
|
@ -114,6 +116,8 @@ cryptography==41.0.3
|
|||
# paramiko
|
||||
# pyopenssl
|
||||
# vcert
|
||||
deprecat==2.1.1
|
||||
# via ciscoconfparse
|
||||
distlib==0.3.6
|
||||
# via virtualenv
|
||||
distro==1.8.0
|
||||
|
@ -124,6 +128,7 @@ distro==1.8.0
|
|||
dnspython==2.3.0
|
||||
# via
|
||||
# -r requirements/static/ci/common.in
|
||||
# ciscoconfparse
|
||||
# python-etcd
|
||||
docker==6.1.3
|
||||
# via -r requirements/pytest.txt
|
||||
|
@ -151,7 +156,7 @@ geomet==0.2.1.post1
|
|||
# via cassandra-driver
|
||||
gitdb==4.0.10
|
||||
# via gitpython
|
||||
gitpython==3.1.32
|
||||
gitpython==3.1.35
|
||||
# via -r requirements/static/ci/common.in
|
||||
google-auth==2.19.1
|
||||
# via kubernetes
|
||||
|
@ -242,6 +247,8 @@ kubernetes==3.0.0
|
|||
# via -r requirements/static/ci/common.in
|
||||
libnacl==1.8.0 ; sys_platform != "win32" and sys_platform != "darwin"
|
||||
# via -r requirements/static/ci/common.in
|
||||
loguru==0.6.0
|
||||
# via ciscoconfparse
|
||||
looseversion==1.2.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.8/linux.txt
|
||||
|
@ -283,12 +290,10 @@ multidict==6.0.4
|
|||
# via
|
||||
# aiohttp
|
||||
# yarl
|
||||
napalm==4.1.0 ; sys_platform != "win32"
|
||||
napalm==3.1.0 ; sys_platform != "win32"
|
||||
# via -r requirements/static/ci/common.in
|
||||
ncclient==0.6.13
|
||||
# via
|
||||
# junos-eznc
|
||||
# napalm
|
||||
# via junos-eznc
|
||||
netaddr==0.8.0
|
||||
# via
|
||||
# junos-eznc
|
||||
|
@ -296,8 +301,6 @@ netaddr==0.8.0
|
|||
# pyeapi
|
||||
netmiko==4.2.0
|
||||
# via napalm
|
||||
netutils==1.4.1
|
||||
# via napalm
|
||||
ntc-templates==3.4.0
|
||||
# via netmiko
|
||||
oscrypto==1.3.0
|
||||
|
@ -318,7 +321,9 @@ paramiko==3.2.0 ; sys_platform != "win32" and sys_platform != "darwin"
|
|||
# netmiko
|
||||
# scp
|
||||
passlib==1.7.4
|
||||
# via -r requirements/static/ci/common.in
|
||||
# via
|
||||
# -r requirements/static/ci/common.in
|
||||
# ciscoconfparse
|
||||
pathspec==0.11.1
|
||||
# via yamllint
|
||||
platformdirs==3.5.3
|
||||
|
@ -356,15 +361,15 @@ pydantic==1.10.8
|
|||
# inflect
|
||||
pyeapi==1.0.0
|
||||
# via napalm
|
||||
pygit2==1.12.1 ; python_version >= "3.8"
|
||||
pygit2==1.12.1
|
||||
# via -r requirements/static/ci/linux.in
|
||||
pyiface==0.0.11
|
||||
# via -r requirements/static/ci/linux.in
|
||||
pyinotify==0.9.6 ; sys_platform != "win32" and sys_platform != "darwin" and platform_system != "openbsd"
|
||||
# via -r requirements/static/ci/common.in
|
||||
pyjwt==2.7.0
|
||||
pyjwt==2.4.0
|
||||
# via twilio
|
||||
pymysql==1.0.3
|
||||
pymysql==1.0.2
|
||||
# via -r requirements/static/ci/linux.in
|
||||
pynacl==1.5.0
|
||||
# via
|
||||
|
@ -494,7 +499,7 @@ rpm-vercmp==0.1.2
|
|||
# -r requirements/static/pkg/linux.in
|
||||
rsa==4.9
|
||||
# via google-auth
|
||||
s3transfer==0.6.1
|
||||
s3transfer==0.5.2
|
||||
# via boto3
|
||||
scp==0.14.5
|
||||
# via
|
||||
|
@ -557,7 +562,9 @@ timelib==0.3.0
|
|||
# -c requirements/static/ci/../pkg/py3.8/linux.txt
|
||||
# -r requirements/static/pkg/linux.in
|
||||
toml==0.10.2
|
||||
# via -r requirements/static/ci/common.in
|
||||
# via
|
||||
# -r requirements/static/ci/common.in
|
||||
# ciscoconfparse
|
||||
tomli==2.0.1
|
||||
# via pytest
|
||||
tornado==6.3.2 ; python_version >= "3.8"
|
||||
|
@ -566,12 +573,6 @@ tornado==6.3.2 ; python_version >= "3.8"
|
|||
# -r requirements/base.txt
|
||||
transitions==0.9.0
|
||||
# via junos-eznc
|
||||
ttp-templates==0.3.5
|
||||
# via napalm
|
||||
ttp==0.9.4
|
||||
# via
|
||||
# napalm
|
||||
# ttp-templates
|
||||
twilio==8.2.2
|
||||
# via -r requirements/static/ci/linux.in
|
||||
types-pyyaml==6.0.1
|
||||
|
@ -579,7 +580,6 @@ types-pyyaml==6.0.1
|
|||
typing-extensions==4.6.2
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.8/linux.txt
|
||||
# napalm
|
||||
# pydantic
|
||||
# pytest-shell-utilities
|
||||
# pytest-system-statistics
|
||||
|
@ -611,6 +611,8 @@ werkzeug==2.3.6
|
|||
# via
|
||||
# moto
|
||||
# pytest-httpserver
|
||||
wrapt==1.11.2
|
||||
# via deprecat
|
||||
xmldiff==2.6.3
|
||||
# via -r requirements/static/ci/common.in
|
||||
xmltodict==0.13.0
|
||||
|
|
|
@ -25,13 +25,13 @@ autocommand==2.2.2
|
|||
# jaraco.text
|
||||
bcrypt==4.0.1
|
||||
# via -r requirements/static/ci/common.in
|
||||
boto3==1.26.152
|
||||
boto3==1.21.46
|
||||
# via
|
||||
# -r requirements/static/ci/common.in
|
||||
# moto
|
||||
boto==2.49.0
|
||||
# via -r requirements/static/ci/common.in
|
||||
botocore==1.29.152
|
||||
botocore==1.24.46
|
||||
# via
|
||||
# boto3
|
||||
# moto
|
||||
|
@ -115,7 +115,7 @@ docker==6.1.3
|
|||
# via -r requirements/pytest.txt
|
||||
etcd3-py==0.1.6
|
||||
# via -r requirements/static/ci/common.in
|
||||
exceptiongroup==1.1.1
|
||||
exceptiongroup==1.0.4
|
||||
# via pytest
|
||||
filelock==3.12.1
|
||||
# via virtualenv
|
||||
|
@ -133,7 +133,7 @@ gitdb==4.0.10
|
|||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.8/windows.txt
|
||||
# gitpython
|
||||
gitpython==3.1.32
|
||||
gitpython==3.1.35
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.8/windows.txt
|
||||
# -r requirements/static/ci/common.in
|
||||
|
@ -164,6 +164,10 @@ inflect==6.0.4
|
|||
# jaraco.text
|
||||
iniconfig==2.0.0
|
||||
# via pytest
|
||||
ioloop==0.1a0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.8/windows.txt
|
||||
# -r requirements/windows.txt
|
||||
ipaddress==1.0.23
|
||||
# via kubernetes
|
||||
jaraco.collections==4.1.0
|
||||
|
@ -262,7 +266,7 @@ portend==3.1.0
|
|||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.8/windows.txt
|
||||
# cherrypy
|
||||
psutil==5.8.0
|
||||
psutil==5.9.5
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.8/windows.txt
|
||||
# -r requirements/base.txt
|
||||
|
@ -413,7 +417,7 @@ rfc3987==1.3.8
|
|||
# via -r requirements/static/ci/common.in
|
||||
rsa==4.9
|
||||
# via google-auth
|
||||
s3transfer==0.6.1
|
||||
s3transfer==0.5.2
|
||||
# via boto3
|
||||
sed==0.3.1
|
||||
# via -r requirements/static/ci/windows.in
|
||||
|
|
|
@ -36,13 +36,13 @@ bcrypt==4.0.1
|
|||
# via
|
||||
# -r requirements/static/ci/common.in
|
||||
# paramiko
|
||||
boto3==1.26.152
|
||||
boto3==1.21.46
|
||||
# via
|
||||
# -r requirements/static/ci/common.in
|
||||
# moto
|
||||
boto==2.49.0
|
||||
# via -r requirements/static/ci/common.in
|
||||
botocore==1.29.152
|
||||
botocore==1.24.46
|
||||
# via
|
||||
# boto3
|
||||
# moto
|
||||
|
@ -83,6 +83,8 @@ cherrypy==18.8.0
|
|||
# -c requirements/static/ci/../pkg/py3.9/darwin.txt
|
||||
# -r requirements/darwin.txt
|
||||
# -r requirements/static/ci/common.in
|
||||
ciscoconfparse==1.7.24
|
||||
# via napalm
|
||||
click==8.1.3
|
||||
# via geomet
|
||||
clustershell==1.9.1
|
||||
|
@ -103,6 +105,8 @@ cryptography==41.0.3
|
|||
# paramiko
|
||||
# pyopenssl
|
||||
# vcert
|
||||
deprecat==2.1.1
|
||||
# via ciscoconfparse
|
||||
distlib==0.3.6
|
||||
# via virtualenv
|
||||
distro==1.8.0
|
||||
|
@ -113,6 +117,7 @@ distro==1.8.0
|
|||
dnspython==2.3.0
|
||||
# via
|
||||
# -r requirements/static/ci/common.in
|
||||
# ciscoconfparse
|
||||
# python-etcd
|
||||
docker==6.1.3
|
||||
# via -r requirements/pytest.txt
|
||||
|
@ -140,7 +145,7 @@ gitdb==4.0.10
|
|||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.9/darwin.txt
|
||||
# gitpython
|
||||
gitpython==3.1.32
|
||||
gitpython==3.1.35
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.9/darwin.txt
|
||||
# -r requirements/darwin.txt
|
||||
|
@ -218,6 +223,8 @@ linode-python==1.1.1
|
|||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.9/darwin.txt
|
||||
# -r requirements/darwin.txt
|
||||
loguru==0.6.0
|
||||
# via ciscoconfparse
|
||||
looseversion==1.2.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.9/darwin.txt
|
||||
|
@ -259,12 +266,10 @@ multidict==6.0.4
|
|||
# via
|
||||
# aiohttp
|
||||
# yarl
|
||||
napalm==4.1.0 ; sys_platform != "win32"
|
||||
napalm==3.1.0 ; sys_platform != "win32"
|
||||
# via -r requirements/static/ci/common.in
|
||||
ncclient==0.6.13
|
||||
# via
|
||||
# junos-eznc
|
||||
# napalm
|
||||
# via junos-eznc
|
||||
netaddr==0.8.0
|
||||
# via
|
||||
# junos-eznc
|
||||
|
@ -272,8 +277,6 @@ netaddr==0.8.0
|
|||
# pyeapi
|
||||
netmiko==4.2.0
|
||||
# via napalm
|
||||
netutils==1.4.1
|
||||
# via napalm
|
||||
ntc-templates==3.4.0
|
||||
# via netmiko
|
||||
oscrypto==1.3.0
|
||||
|
@ -292,7 +295,9 @@ paramiko==3.2.0
|
|||
# netmiko
|
||||
# scp
|
||||
passlib==1.7.4
|
||||
# via -r requirements/static/ci/common.in
|
||||
# via
|
||||
# -r requirements/static/ci/common.in
|
||||
# ciscoconfparse
|
||||
pathspec==0.11.1
|
||||
# via yamllint
|
||||
platformdirs==3.5.3
|
||||
|
@ -445,7 +450,7 @@ rfc3987==1.3.8
|
|||
# via -r requirements/static/ci/common.in
|
||||
rsa==4.9
|
||||
# via google-auth
|
||||
s3transfer==0.6.1
|
||||
s3transfer==0.5.2
|
||||
# via boto3
|
||||
scp==0.14.5
|
||||
# via
|
||||
|
@ -499,7 +504,9 @@ timelib==0.3.0
|
|||
# -c requirements/static/ci/../pkg/py3.9/darwin.txt
|
||||
# -r requirements/darwin.txt
|
||||
toml==0.10.2
|
||||
# via -r requirements/static/ci/common.in
|
||||
# via
|
||||
# -r requirements/static/ci/common.in
|
||||
# ciscoconfparse
|
||||
tomli==2.0.1
|
||||
# via pytest
|
||||
tornado==6.3.2 ; python_version >= "3.8"
|
||||
|
@ -508,18 +515,11 @@ tornado==6.3.2 ; python_version >= "3.8"
|
|||
# -r requirements/base.txt
|
||||
transitions==0.9.0
|
||||
# via junos-eznc
|
||||
ttp-templates==0.3.5
|
||||
# via napalm
|
||||
ttp==0.9.4
|
||||
# via
|
||||
# napalm
|
||||
# ttp-templates
|
||||
types-pyyaml==6.0.1
|
||||
# via responses
|
||||
typing-extensions==4.6.2
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.9/darwin.txt
|
||||
# napalm
|
||||
# pydantic
|
||||
# pytest-shell-utilities
|
||||
# pytest-system-statistics
|
||||
|
@ -555,6 +555,8 @@ werkzeug==2.3.6
|
|||
# via
|
||||
# moto
|
||||
# pytest-httpserver
|
||||
wrapt==1.15.0
|
||||
# via deprecat
|
||||
xmldiff==2.6.3
|
||||
# via -r requirements/static/ci/common.in
|
||||
xmltodict==0.13.0
|
||||
|
|
|
@ -33,13 +33,13 @@ bcrypt==4.0.1
|
|||
# via
|
||||
# -r requirements/static/ci/common.in
|
||||
# paramiko
|
||||
boto3==1.26.152
|
||||
boto3==1.21.46
|
||||
# via
|
||||
# -r requirements/static/ci/common.in
|
||||
# moto
|
||||
boto==2.49.0
|
||||
# via -r requirements/static/ci/common.in
|
||||
botocore==1.29.152
|
||||
botocore==1.24.46
|
||||
# via
|
||||
# boto3
|
||||
# moto
|
||||
|
@ -79,6 +79,8 @@ cherrypy==18.8.0
|
|||
# -c requirements/static/ci/../pkg/py3.9/freebsd.txt
|
||||
# -r requirements/static/ci/common.in
|
||||
# -r requirements/static/pkg/freebsd.in
|
||||
ciscoconfparse==1.7.24
|
||||
# via napalm
|
||||
click==8.1.3
|
||||
# via geomet
|
||||
clustershell==1.9.1
|
||||
|
@ -99,6 +101,8 @@ cryptography==41.0.3
|
|||
# paramiko
|
||||
# pyopenssl
|
||||
# vcert
|
||||
deprecat==2.1.1
|
||||
# via ciscoconfparse
|
||||
distlib==0.3.6
|
||||
# via virtualenv
|
||||
distro==1.8.0
|
||||
|
@ -110,6 +114,7 @@ distro==1.8.0
|
|||
dnspython==2.3.0
|
||||
# via
|
||||
# -r requirements/static/ci/common.in
|
||||
# ciscoconfparse
|
||||
# python-etcd
|
||||
docker==6.1.3
|
||||
# via -r requirements/pytest.txt
|
||||
|
@ -135,7 +140,7 @@ geomet==0.2.1.post1
|
|||
# via cassandra-driver
|
||||
gitdb==4.0.10
|
||||
# via gitpython
|
||||
gitpython==3.1.32
|
||||
gitpython==3.1.35
|
||||
# via -r requirements/static/ci/common.in
|
||||
google-auth==2.19.1
|
||||
# via kubernetes
|
||||
|
@ -213,6 +218,8 @@ kubernetes==3.0.0
|
|||
# via -r requirements/static/ci/common.in
|
||||
libnacl==1.8.0 ; sys_platform != "win32" and sys_platform != "darwin"
|
||||
# via -r requirements/static/ci/common.in
|
||||
loguru==0.6.0
|
||||
# via ciscoconfparse
|
||||
looseversion==1.2.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.9/freebsd.txt
|
||||
|
@ -254,12 +261,10 @@ multidict==6.0.4
|
|||
# via
|
||||
# aiohttp
|
||||
# yarl
|
||||
napalm==4.1.0 ; sys_platform != "win32"
|
||||
napalm==3.1.0 ; sys_platform != "win32"
|
||||
# via -r requirements/static/ci/common.in
|
||||
ncclient==0.6.13
|
||||
# via
|
||||
# junos-eznc
|
||||
# napalm
|
||||
# via junos-eznc
|
||||
netaddr==0.8.0
|
||||
# via
|
||||
# junos-eznc
|
||||
|
@ -267,8 +272,6 @@ netaddr==0.8.0
|
|||
# pyeapi
|
||||
netmiko==4.2.0
|
||||
# via napalm
|
||||
netutils==1.4.1
|
||||
# via napalm
|
||||
ntc-templates==3.4.0
|
||||
# via netmiko
|
||||
oscrypto==1.3.0
|
||||
|
@ -288,7 +291,9 @@ paramiko==3.2.0 ; sys_platform != "win32" and sys_platform != "darwin"
|
|||
# netmiko
|
||||
# scp
|
||||
passlib==1.7.4
|
||||
# via -r requirements/static/ci/common.in
|
||||
# via
|
||||
# -r requirements/static/ci/common.in
|
||||
# ciscoconfparse
|
||||
pathspec==0.11.1
|
||||
# via yamllint
|
||||
platformdirs==3.5.3
|
||||
|
@ -438,7 +443,7 @@ rfc3987==1.3.8
|
|||
# via -r requirements/static/ci/common.in
|
||||
rsa==4.9
|
||||
# via google-auth
|
||||
s3transfer==0.6.1
|
||||
s3transfer==0.5.2
|
||||
# via boto3
|
||||
scp==0.14.5
|
||||
# via
|
||||
|
@ -491,7 +496,9 @@ timelib==0.3.0
|
|||
# -c requirements/static/ci/../pkg/py3.9/freebsd.txt
|
||||
# -r requirements/static/pkg/freebsd.in
|
||||
toml==0.10.2
|
||||
# via -r requirements/static/ci/common.in
|
||||
# via
|
||||
# -r requirements/static/ci/common.in
|
||||
# ciscoconfparse
|
||||
tomli==2.0.1
|
||||
# via pytest
|
||||
tornado==6.3.2 ; python_version >= "3.8"
|
||||
|
@ -500,18 +507,11 @@ tornado==6.3.2 ; python_version >= "3.8"
|
|||
# -r requirements/base.txt
|
||||
transitions==0.9.0
|
||||
# via junos-eznc
|
||||
ttp-templates==0.3.5
|
||||
# via napalm
|
||||
ttp==0.9.4
|
||||
# via
|
||||
# napalm
|
||||
# ttp-templates
|
||||
types-pyyaml==6.0.1
|
||||
# via responses
|
||||
typing-extensions==4.6.2
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.9/freebsd.txt
|
||||
# napalm
|
||||
# pydantic
|
||||
# pytest-shell-utilities
|
||||
# pytest-system-statistics
|
||||
|
@ -543,6 +543,8 @@ werkzeug==2.3.6
|
|||
# via
|
||||
# moto
|
||||
# pytest-httpserver
|
||||
wrapt==1.15.0
|
||||
# via deprecat
|
||||
xmldiff==2.6.3
|
||||
# via -r requirements/static/ci/common.in
|
||||
xmltodict==0.13.0
|
||||
|
|
|
@ -14,7 +14,7 @@ mccabe==0.6.1
|
|||
# via pylint
|
||||
modernize==0.5
|
||||
# via saltpylint
|
||||
pycodestyle==2.10.0
|
||||
pycodestyle==2.5.0
|
||||
# via saltpylint
|
||||
pylint==2.4.4
|
||||
# via
|
||||
|
@ -31,4 +31,6 @@ toml==0.10.2
|
|||
# -c requirements/static/ci/py3.9/linux.txt
|
||||
# -r requirements/static/ci/lint.in
|
||||
wrapt==1.11.2
|
||||
# via astroid
|
||||
# via
|
||||
# -c requirements/static/ci/py3.9/linux.txt
|
||||
# astroid
|
||||
|
|
|
@ -44,13 +44,13 @@ bcrypt==4.0.1
|
|||
# via
|
||||
# -r requirements/static/ci/common.in
|
||||
# paramiko
|
||||
boto3==1.26.152
|
||||
boto3==1.21.46
|
||||
# via
|
||||
# -r requirements/static/ci/common.in
|
||||
# moto
|
||||
boto==2.49.0
|
||||
# via -r requirements/static/ci/common.in
|
||||
botocore==1.29.152
|
||||
botocore==1.24.46
|
||||
# via
|
||||
# boto3
|
||||
# moto
|
||||
|
@ -93,6 +93,8 @@ cherrypy==18.8.0
|
|||
# -c requirements/static/ci/../pkg/py3.9/linux.txt
|
||||
# -r requirements/static/ci/common.in
|
||||
# -r requirements/static/pkg/linux.in
|
||||
ciscoconfparse==1.7.24
|
||||
# via napalm
|
||||
click==8.1.3
|
||||
# via geomet
|
||||
clustershell==1.9.1
|
||||
|
@ -114,6 +116,8 @@ cryptography==41.0.3
|
|||
# paramiko
|
||||
# pyopenssl
|
||||
# vcert
|
||||
deprecat==2.1.1
|
||||
# via ciscoconfparse
|
||||
distlib==0.3.6
|
||||
# via virtualenv
|
||||
distro==1.8.0
|
||||
|
@ -124,6 +128,7 @@ distro==1.8.0
|
|||
dnspython==2.3.0
|
||||
# via
|
||||
# -r requirements/static/ci/common.in
|
||||
# ciscoconfparse
|
||||
# python-etcd
|
||||
docker==6.1.3
|
||||
# via -r requirements/pytest.txt
|
||||
|
@ -151,7 +156,7 @@ geomet==0.2.1.post1
|
|||
# via cassandra-driver
|
||||
gitdb==4.0.10
|
||||
# via gitpython
|
||||
gitpython==3.1.32
|
||||
gitpython==3.1.35
|
||||
# via -r requirements/static/ci/common.in
|
||||
google-auth==2.19.1
|
||||
# via kubernetes
|
||||
|
@ -240,6 +245,8 @@ kubernetes==3.0.0
|
|||
# via -r requirements/static/ci/common.in
|
||||
libnacl==1.8.0 ; sys_platform != "win32" and sys_platform != "darwin"
|
||||
# via -r requirements/static/ci/common.in
|
||||
loguru==0.6.0
|
||||
# via ciscoconfparse
|
||||
looseversion==1.2.0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.9/linux.txt
|
||||
|
@ -281,12 +288,10 @@ multidict==6.0.4
|
|||
# via
|
||||
# aiohttp
|
||||
# yarl
|
||||
napalm==4.1.0 ; sys_platform != "win32"
|
||||
napalm==3.1.0 ; sys_platform != "win32"
|
||||
# via -r requirements/static/ci/common.in
|
||||
ncclient==0.6.13
|
||||
# via
|
||||
# junos-eznc
|
||||
# napalm
|
||||
# via junos-eznc
|
||||
netaddr==0.8.0
|
||||
# via
|
||||
# junos-eznc
|
||||
|
@ -294,8 +299,6 @@ netaddr==0.8.0
|
|||
# pyeapi
|
||||
netmiko==4.2.0
|
||||
# via napalm
|
||||
netutils==1.4.1
|
||||
# via napalm
|
||||
ntc-templates==3.4.0
|
||||
# via netmiko
|
||||
oscrypto==1.3.0
|
||||
|
@ -316,7 +319,9 @@ paramiko==3.2.0 ; sys_platform != "win32" and sys_platform != "darwin"
|
|||
# netmiko
|
||||
# scp
|
||||
passlib==1.7.4
|
||||
# via -r requirements/static/ci/common.in
|
||||
# via
|
||||
# -r requirements/static/ci/common.in
|
||||
# ciscoconfparse
|
||||
pathspec==0.11.1
|
||||
# via yamllint
|
||||
platformdirs==3.5.3
|
||||
|
@ -354,15 +359,15 @@ pydantic==1.10.8
|
|||
# inflect
|
||||
pyeapi==1.0.0
|
||||
# via napalm
|
||||
pygit2==1.12.1 ; python_version >= "3.8"
|
||||
pygit2==1.12.1
|
||||
# via -r requirements/static/ci/linux.in
|
||||
pyiface==0.0.11
|
||||
# via -r requirements/static/ci/linux.in
|
||||
pyinotify==0.9.6 ; sys_platform != "win32" and sys_platform != "darwin" and platform_system != "openbsd"
|
||||
# via -r requirements/static/ci/common.in
|
||||
pyjwt==2.7.0
|
||||
pyjwt==2.4.0
|
||||
# via twilio
|
||||
pymysql==1.0.3
|
||||
pymysql==1.0.2
|
||||
# via -r requirements/static/ci/linux.in
|
||||
pynacl==1.5.0
|
||||
# via
|
||||
|
@ -492,7 +497,7 @@ rpm-vercmp==0.1.2
|
|||
# -r requirements/static/pkg/linux.in
|
||||
rsa==4.9
|
||||
# via google-auth
|
||||
s3transfer==0.6.1
|
||||
s3transfer==0.5.2
|
||||
# via boto3
|
||||
scp==0.14.5
|
||||
# via
|
||||
|
@ -555,7 +560,9 @@ timelib==0.3.0
|
|||
# -c requirements/static/ci/../pkg/py3.9/linux.txt
|
||||
# -r requirements/static/pkg/linux.in
|
||||
toml==0.10.2
|
||||
# via -r requirements/static/ci/common.in
|
||||
# via
|
||||
# -r requirements/static/ci/common.in
|
||||
# ciscoconfparse
|
||||
tomli==2.0.1
|
||||
# via pytest
|
||||
tornado==6.3.2 ; python_version >= "3.8"
|
||||
|
@ -564,12 +571,6 @@ tornado==6.3.2 ; python_version >= "3.8"
|
|||
# -r requirements/base.txt
|
||||
transitions==0.9.0
|
||||
# via junos-eznc
|
||||
ttp-templates==0.3.5
|
||||
# via napalm
|
||||
ttp==0.9.4
|
||||
# via
|
||||
# napalm
|
||||
# ttp-templates
|
||||
twilio==8.2.2
|
||||
# via -r requirements/static/ci/linux.in
|
||||
types-pyyaml==6.0.1
|
||||
|
@ -577,7 +578,6 @@ types-pyyaml==6.0.1
|
|||
typing-extensions==4.6.2
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.9/linux.txt
|
||||
# napalm
|
||||
# pydantic
|
||||
# pytest-shell-utilities
|
||||
# pytest-system-statistics
|
||||
|
@ -609,6 +609,8 @@ werkzeug==2.3.6
|
|||
# via
|
||||
# moto
|
||||
# pytest-httpserver
|
||||
wrapt==1.11.2
|
||||
# via deprecat
|
||||
xmldiff==2.6.3
|
||||
# via -r requirements/static/ci/common.in
|
||||
xmltodict==0.13.0
|
||||
|
|
|
@ -25,13 +25,13 @@ autocommand==2.2.2
|
|||
# jaraco.text
|
||||
bcrypt==4.0.1
|
||||
# via -r requirements/static/ci/common.in
|
||||
boto3==1.26.152
|
||||
boto3==1.21.46
|
||||
# via
|
||||
# -r requirements/static/ci/common.in
|
||||
# moto
|
||||
boto==2.49.0
|
||||
# via -r requirements/static/ci/common.in
|
||||
botocore==1.29.152
|
||||
botocore==1.24.46
|
||||
# via
|
||||
# boto3
|
||||
# moto
|
||||
|
@ -115,7 +115,7 @@ docker==6.1.3
|
|||
# via -r requirements/pytest.txt
|
||||
etcd3-py==0.1.6
|
||||
# via -r requirements/static/ci/common.in
|
||||
exceptiongroup==1.1.1
|
||||
exceptiongroup==1.0.4
|
||||
# via pytest
|
||||
filelock==3.12.1
|
||||
# via virtualenv
|
||||
|
@ -133,7 +133,7 @@ gitdb==4.0.10
|
|||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.9/windows.txt
|
||||
# gitpython
|
||||
gitpython==3.1.32
|
||||
gitpython==3.1.35
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.9/windows.txt
|
||||
# -r requirements/static/ci/common.in
|
||||
|
@ -160,6 +160,10 @@ inflect==6.0.4
|
|||
# jaraco.text
|
||||
iniconfig==2.0.0
|
||||
# via pytest
|
||||
ioloop==0.1a0
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.9/windows.txt
|
||||
# -r requirements/windows.txt
|
||||
ipaddress==1.0.23
|
||||
# via kubernetes
|
||||
jaraco.collections==4.1.0
|
||||
|
@ -258,7 +262,7 @@ portend==3.1.0
|
|||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.9/windows.txt
|
||||
# cherrypy
|
||||
psutil==5.8.0
|
||||
psutil==5.9.5
|
||||
# via
|
||||
# -c requirements/static/ci/../pkg/py3.9/windows.txt
|
||||
# -r requirements/base.txt
|
||||
|
@ -409,7 +413,7 @@ rfc3987==1.3.8
|
|||
# via -r requirements/static/ci/common.in
|
||||
rsa==4.9
|
||||
# via google-auth
|
||||
s3transfer==0.6.1
|
||||
s3transfer==0.5.2
|
||||
# via boto3
|
||||
sed==0.3.1
|
||||
# via -r requirements/static/ci/windows.in
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
# Any non hard dependencies of Salt for FreeBSD can go here
|
||||
cherrypy
|
||||
cryptography>=41.0.3
|
||||
backports.ssl_match_hostname>=3.7.0.1; python_version < '3.7'
|
||||
pyopenssl>=23.2.0
|
||||
python-dateutil>=2.8.0
|
||||
python-gnupg>=0.4.4
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
# This file only exists to trigger the right static compiled requirements destination.
|
||||
# Any non hard dependencies of Salt for linux can go here
|
||||
cherrypy
|
||||
backports.ssl_match_hostname>=3.7.0.1; python_version < '3.7'
|
||||
pyopenssl>=23.2.0
|
||||
python-dateutil>=2.8.0
|
||||
python-gnupg>=0.4.4
|
||||
|
|
|
@ -29,7 +29,7 @@ distro==1.8.0
|
|||
# via -r requirements/base.txt
|
||||
gitdb==4.0.10
|
||||
# via gitpython
|
||||
gitpython==3.1.32
|
||||
gitpython==3.1.35
|
||||
# via -r requirements/darwin.txt
|
||||
idna==3.4
|
||||
# via
|
||||
|
|
|
@ -66,7 +66,7 @@ packaging==23.1
|
|||
# via -r requirements/base.txt
|
||||
portend==3.1.0
|
||||
# via cherrypy
|
||||
psutil==5.8.0
|
||||
psutil==5.9.5
|
||||
# via -r requirements/base.txt
|
||||
pycparser==2.21
|
||||
# via cffi
|
||||
|
|
|
@ -34,7 +34,7 @@ distro==1.8.0
|
|||
# via -r requirements/base.txt
|
||||
gitdb==4.0.10
|
||||
# via gitpython
|
||||
gitpython==3.1.32
|
||||
gitpython==3.1.35
|
||||
# via -r requirements/windows.txt
|
||||
idna==3.4
|
||||
# via requests
|
||||
|
@ -44,6 +44,8 @@ importlib-metadata==6.6.0
|
|||
# via -r requirements/windows.txt
|
||||
inflect==6.0.4
|
||||
# via jaraco.text
|
||||
ioloop==0.1a0
|
||||
# via -r requirements/windows.txt
|
||||
jaraco.collections==4.1.0
|
||||
# via cherrypy
|
||||
jaraco.context==4.3.0
|
||||
|
@ -79,7 +81,7 @@ packaging==23.1
|
|||
# via -r requirements/base.txt
|
||||
portend==3.1.0
|
||||
# via cherrypy
|
||||
psutil==5.8.0
|
||||
psutil==5.9.5
|
||||
# via -r requirements/base.txt
|
||||
pyasn1==0.4.8
|
||||
# via -r requirements/windows.txt
|
||||
|
|
|
@ -29,7 +29,7 @@ distro==1.8.0
|
|||
# via -r requirements/base.txt
|
||||
gitdb==4.0.10
|
||||
# via gitpython
|
||||
gitpython==3.1.31
|
||||
gitpython==3.1.35
|
||||
# via -r requirements/darwin.txt
|
||||
idna==3.4
|
||||
# via
|
||||
|
|
|
@ -34,7 +34,7 @@ distro==1.8.0
|
|||
# via -r requirements/base.txt
|
||||
gitdb==4.0.10
|
||||
# via gitpython
|
||||
gitpython==3.1.32
|
||||
gitpython==3.1.35
|
||||
# via -r requirements/windows.txt
|
||||
idna==3.4
|
||||
# via requests
|
||||
|
@ -44,6 +44,8 @@ importlib-metadata==6.6.0
|
|||
# via -r requirements/windows.txt
|
||||
inflect==6.0.4
|
||||
# via jaraco.text
|
||||
ioloop==0.1a0
|
||||
# via -r requirements/windows.txt
|
||||
jaraco.collections==4.1.0
|
||||
# via cherrypy
|
||||
jaraco.context==4.3.0
|
||||
|
@ -79,7 +81,7 @@ packaging==23.1
|
|||
# via -r requirements/base.txt
|
||||
portend==3.1.0
|
||||
# via cherrypy
|
||||
psutil==5.8.0
|
||||
psutil==5.9.5
|
||||
# via -r requirements/base.txt
|
||||
pyasn1==0.4.8
|
||||
# via -r requirements/windows.txt
|
||||
|
|
|
@ -34,7 +34,7 @@ distro==1.8.0
|
|||
# via -r requirements/base.txt
|
||||
gitdb==4.0.10
|
||||
# via gitpython
|
||||
gitpython==3.1.32
|
||||
gitpython==3.1.35
|
||||
# via -r requirements/windows.txt
|
||||
idna==3.4
|
||||
# via requests
|
||||
|
@ -46,6 +46,8 @@ importlib-resources==5.12.0
|
|||
# via jaraco.text
|
||||
inflect==6.0.4
|
||||
# via jaraco.text
|
||||
ioloop==0.1a0
|
||||
# via -r requirements/windows.txt
|
||||
jaraco.collections==4.1.0
|
||||
# via cherrypy
|
||||
jaraco.context==4.3.0
|
||||
|
@ -81,7 +83,7 @@ packaging==23.1
|
|||
# via -r requirements/base.txt
|
||||
portend==3.1.0
|
||||
# via cherrypy
|
||||
psutil==5.8.0
|
||||
psutil==5.9.5
|
||||
# via -r requirements/base.txt
|
||||
pyasn1==0.4.8
|
||||
# via -r requirements/windows.txt
|
||||
|
|
|
@ -29,7 +29,7 @@ distro==1.8.0
|
|||
# via -r requirements/base.txt
|
||||
gitdb==4.0.10
|
||||
# via gitpython
|
||||
gitpython==3.1.32
|
||||
gitpython==3.1.35
|
||||
# via -r requirements/darwin.txt
|
||||
idna==3.4
|
||||
# via
|
||||
|
|
|
@ -34,7 +34,7 @@ distro==1.8.0
|
|||
# via -r requirements/base.txt
|
||||
gitdb==4.0.10
|
||||
# via gitpython
|
||||
gitpython==3.1.32
|
||||
gitpython==3.1.35
|
||||
# via -r requirements/windows.txt
|
||||
idna==3.4
|
||||
# via requests
|
||||
|
@ -44,6 +44,8 @@ importlib-metadata==6.6.0
|
|||
# via -r requirements/windows.txt
|
||||
inflect==6.0.4
|
||||
# via jaraco.text
|
||||
ioloop==0.1a0
|
||||
# via -r requirements/windows.txt
|
||||
jaraco.collections==4.1.0
|
||||
# via cherrypy
|
||||
jaraco.context==4.3.0
|
||||
|
@ -79,7 +81,7 @@ packaging==23.1
|
|||
# via -r requirements/base.txt
|
||||
portend==3.1.0
|
||||
# via cherrypy
|
||||
psutil==5.8.0
|
||||
psutil==5.9.5
|
||||
# via -r requirements/base.txt
|
||||
pyasn1==0.4.8
|
||||
# via -r requirements/windows.txt
|
||||
|
|
|
@ -6,12 +6,13 @@ pywin32>=305
|
|||
wmi>=1.5.1
|
||||
pythonnet>=3.0.1
|
||||
|
||||
backports.ssl-match-hostname>=3.7.0.1; python_version < '3.7'
|
||||
certifi>=2022.12.07
|
||||
cffi>=1.14.5
|
||||
cherrypy>=18.6.1
|
||||
gitpython>=3.1.30
|
||||
cryptography>=41.0.3
|
||||
gitpython>=3.1.30
|
||||
ioloop>=0.1a0
|
||||
lxml>=4.6.3
|
||||
pyasn1>=0.4.8
|
||||
pymssql>=2.2.1
|
||||
|
|
|
@ -255,8 +255,8 @@ def create_certificate(
|
|||
Instead of returning the certificate, write it to this file path.
|
||||
|
||||
overwrite
|
||||
If ``path`` is specified and the file exists, do not overwrite it.
|
||||
Defaults to false.
|
||||
If ``path`` is specified and the file exists, overwrite it.
|
||||
Defaults to true.
|
||||
|
||||
raw
|
||||
Return the encoded raw bytes instead of a string. Defaults to false.
|
||||
|
@ -614,7 +614,7 @@ def _create_certificate_local(
|
|||
path=os.path.join(copypath, f"{prepend}{cert.serial_number:x}.crt"),
|
||||
pem_type="CERTIFICATE",
|
||||
)
|
||||
return builder.sign(signing_private_key, algorithm=algorithm), private_key_loaded
|
||||
return cert, private_key_loaded
|
||||
|
||||
|
||||
def encode_certificate(
|
||||
|
@ -1196,7 +1196,7 @@ def create_private_key(
|
|||
keysize
|
||||
For ``rsa``, specifies the bitlength of the private key (2048, 3072, 4096).
|
||||
For ``ec``, specifies the NIST curve to use (256, 384, 521).
|
||||
Irrelevant for Edwards-curve schemes (`ed25519``, ``ed448``).
|
||||
Irrelevant for Edwards-curve schemes (``ed25519``, ``ed448``).
|
||||
Defaults to 2048 for RSA and 256 for EC.
|
||||
|
||||
passphrase
|
||||
|
@ -1246,6 +1246,7 @@ def create_private_key(
|
|||
raise CommandExecutionError(
|
||||
f"Invalid value '{encoding}' for encoding. Valid: der, pem, pkcs12"
|
||||
)
|
||||
|
||||
out = encode_private_key(
|
||||
_generate_pk(algo=algo, keysize=keysize),
|
||||
encoding=encoding,
|
||||
|
@ -1258,7 +1259,9 @@ def create_private_key(
|
|||
return out
|
||||
|
||||
if encoding == "pem":
|
||||
return write_pem(out.decode(), path, pem_type="(?:RSA )?PRIVATE KEY")
|
||||
return write_pem(
|
||||
out.decode(), path, pem_type="(?:(RSA|ENCRYPTED) )?PRIVATE KEY"
|
||||
)
|
||||
with salt.utils.files.fopen(path, "wb") as fp_:
|
||||
fp_.write(out)
|
||||
return
|
||||
|
@ -1268,6 +1271,7 @@ def encode_private_key(
|
|||
private_key,
|
||||
encoding="pem",
|
||||
passphrase=None,
|
||||
private_key_passphrase=None,
|
||||
pkcs12_encryption_compat=False,
|
||||
raw=False,
|
||||
):
|
||||
|
@ -1280,7 +1284,7 @@ def encode_private_key(
|
|||
|
||||
salt '*' x509.encode_private_key /etc/pki/my.key der
|
||||
|
||||
csr
|
||||
private_key
|
||||
The private key to encode.
|
||||
|
||||
encoding
|
||||
|
@ -1288,6 +1292,23 @@ def encode_private_key(
|
|||
as a ``pem`` string, base64-encoded ``der`` and base64-encoded ``pkcs12``.
|
||||
Defaults to ``pem``.
|
||||
|
||||
passphrase
|
||||
If this is specified, the private key will be encrypted using this
|
||||
passphrase. The encryption algorithm cannot be selected, it will be
|
||||
determined automatically as the best available one.
|
||||
|
||||
private_key_passphrase
|
||||
.. versionadded:: 3006.2
|
||||
|
||||
If the current ``private_key`` is encrypted, the passphrase to
|
||||
decrypt it.
|
||||
|
||||
pkcs12_encryption_compat
|
||||
Some operating systems are incompatible with the encryption defaults
|
||||
for PKCS12 used since OpenSSL v3. This switch triggers a fallback to
|
||||
``PBESv1SHA1And3KeyTripleDESCBC``.
|
||||
Please consider the `notes on PKCS12 encryption <https://cryptography.io/en/stable/hazmat/primitives/asymmetric/serialization/#cryptography.hazmat.primitives.serialization.pkcs12.serialize_key_and_certificates>`_.
|
||||
|
||||
raw
|
||||
Return the encoded raw bytes instead of a string. Defaults to false.
|
||||
"""
|
||||
|
@ -1295,6 +1316,7 @@ def encode_private_key(
|
|||
raise CommandExecutionError(
|
||||
f"Invalid value '{encoding}' for encoding. Valid: der, pem, pkcs12"
|
||||
)
|
||||
private_key = x509util.load_privkey(private_key, passphrase=private_key_passphrase)
|
||||
if passphrase is None:
|
||||
cipher = serialization.NoEncryption()
|
||||
else:
|
||||
|
@ -1553,7 +1575,7 @@ def get_public_key(key, passphrase=None, asObj=None):
|
|||
except SaltInvocationError:
|
||||
pass
|
||||
raise CommandExecutionError(
|
||||
"Could not load key as certificate, public key, private key, CSR or CRL"
|
||||
"Could not load key as certificate, public key, private key or CSR"
|
||||
)
|
||||
|
||||
|
||||
|
@ -1940,7 +1962,7 @@ def verify_private_key(private_key, public_key, passphrase=None):
|
|||
passphrase
|
||||
If ``private_key`` is encrypted, the passphrase to decrypt it.
|
||||
"""
|
||||
privkey = x509util.load_privkey(private_key, passphrase=None)
|
||||
privkey = x509util.load_privkey(private_key, passphrase=passphrase)
|
||||
pubkey = x509util.load_pubkey(get_public_key(public_key))
|
||||
return x509util.is_pair(pubkey, privkey)
|
||||
|
||||
|
|
|
@ -747,6 +747,8 @@ def list_pkgs(versions_as_list=False, **kwargs):
|
|||
cmd = [
|
||||
"rpm",
|
||||
"-qa",
|
||||
"--nodigest",
|
||||
"--nosignature",
|
||||
"--queryformat",
|
||||
salt.utils.pkg.rpm.QUERYFORMAT.replace("%{REPOID}", "(none)") + "\n",
|
||||
]
|
||||
|
|
|
@ -1416,7 +1416,7 @@ class Minions(LowDataAdapter):
|
|||
POST /minions HTTP/1.1
|
||||
Host: localhost:8000
|
||||
Accept: application/x-yaml
|
||||
Content-Type: application/json
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
|
||||
tgt=*&fun=status.diskusage
|
||||
|
||||
|
|
|
@ -2859,7 +2859,8 @@ def latest(
|
|||
x
|
||||
for x in targets
|
||||
if not changes.get(x)
|
||||
or targets[x] not in changes[x].get("new").split(",")
|
||||
or changes[x].get("new") is not None
|
||||
and targets[x] not in changes[x].get("new").split(",")
|
||||
and targets[x] != "latest"
|
||||
]
|
||||
successful = [x for x in targets if x not in failed]
|
||||
|
|
|
@ -82,7 +82,7 @@ the certificate to the mine, where it can be easily retrieved by other minions.
|
|||
- keysize: 4096
|
||||
- backup: true
|
||||
- require:
|
||||
- file: /etc/pki
|
||||
- file: /etc/pki/issued_certs
|
||||
|
||||
Create self-signed CA certificate:
|
||||
x509.certificate_managed:
|
||||
|
@ -1274,7 +1274,7 @@ def private_key_managed(
|
|||
keysize
|
||||
For ``rsa``, specifies the bitlength of the private key (2048, 3072, 4096).
|
||||
For ``ec``, specifies the NIST curve to use (256, 384, 521).
|
||||
Irrelevant for Edwards-curve schemes (`ed25519``, ``ed448``).
|
||||
Irrelevant for Edwards-curve schemes (``ed25519``, ``ed448``).
|
||||
Defaults to 2048 for RSA and 256 for EC.
|
||||
|
||||
passphrase
|
||||
|
@ -1450,7 +1450,7 @@ def private_key_managed(
|
|||
and algo in ("rsa", "ec")
|
||||
and current.key_size != check_keysize
|
||||
):
|
||||
changes["keysize"] = keysize
|
||||
changes["keysize"] = check_keysize
|
||||
if encoding != current_encoding:
|
||||
changes["encoding"] = encoding
|
||||
elif file_exists and new:
|
||||
|
|
|
@ -566,7 +566,7 @@ class GitProvider:
|
|||
return ret
|
||||
|
||||
def _get_lock_file(self, lock_type="update"):
|
||||
return salt.utils.path.join(self.gitdir, lock_type + ".lk")
|
||||
return salt.utils.path.join(self._salt_working_dir, lock_type + ".lk")
|
||||
|
||||
@classmethod
|
||||
def add_conf_overlay(cls, name):
|
||||
|
@ -858,7 +858,6 @@ class GitProvider:
|
|||
self.id,
|
||||
desired_ssl_verify,
|
||||
)
|
||||
self._ssl_verfiy = self.opts.get(f"{self.role}_ssl_verify", None)
|
||||
conf_changed = True
|
||||
|
||||
# Write changes, if necessary
|
||||
|
|
|
@ -1424,13 +1424,20 @@ def test_create_private_key_pkcs12(x509, passphrase):
|
|||
|
||||
@pytest.mark.parametrize("encoding", ["pem", "der"])
|
||||
def test_create_private_key_write_to_path(x509, encoding, tmp_path):
|
||||
tgt = tmp_path / "csr"
|
||||
tgt = tmp_path / "pk"
|
||||
x509.create_private_key(encoding=encoding, path=str(tgt))
|
||||
assert tgt.exists()
|
||||
if encoding == "pem":
|
||||
assert tgt.read_text().startswith("-----BEGIN PRIVATE KEY-----")
|
||||
|
||||
|
||||
def test_create_private_key_write_to_path_encrypted(x509, tmp_path):
|
||||
tgt = tmp_path / "pk"
|
||||
x509.create_private_key(path=str(tgt), passphrase="hunter1")
|
||||
assert tgt.exists()
|
||||
assert tgt.read_text().startswith("-----BEGIN ENCRYPTED PRIVATE KEY-----")
|
||||
|
||||
|
||||
@pytest.mark.parametrize("encoding", ["pem", "der"])
|
||||
def test_create_private_key_write_to_path_overwrite(x509, encoding, tmp_path):
|
||||
tgt = tmp_path / "cert"
|
||||
|
@ -1589,8 +1596,32 @@ def test_verify_crl(x509, crl, ca_cert):
|
|||
assert x509.verify_crl(crl, ca_cert) is True
|
||||
|
||||
|
||||
def test_verify_private_key(x509, ca_key, ca_cert):
|
||||
assert x509.verify_private_key(ca_key, ca_cert) is True
|
||||
def test_encode_private_key(x509, rsa_privkey):
|
||||
pk = x509.create_private_key()
|
||||
res = x509.encode_private_key(pk)
|
||||
assert res.strip() == pk.strip()
|
||||
|
||||
|
||||
def test_encode_private_key_encrypted(x509, ca_key, ca_key_enc):
|
||||
pk = x509.create_private_key()
|
||||
pk_enc = x509.encode_private_key(pk, passphrase="hunter1")
|
||||
res = x509.encode_private_key(pk_enc, private_key_passphrase="hunter1")
|
||||
assert res.strip() == pk.strip()
|
||||
|
||||
|
||||
@pytest.mark.parametrize("privkey,expected", [("ca_key", True), ("rsa_privkey", False)])
|
||||
def test_verify_private_key(x509, request, privkey, expected, ca_cert):
|
||||
pk = request.getfixturevalue(privkey)
|
||||
assert x509.verify_private_key(pk, ca_cert) is expected
|
||||
|
||||
|
||||
def test_verify_private_key_with_passphrase(x509, ca_key_enc, ca_cert):
|
||||
assert (
|
||||
x509.verify_private_key(
|
||||
ca_key_enc, ca_cert, passphrase="correct horse battery staple"
|
||||
)
|
||||
is True
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("algo", ["rsa", "ec", "ed25519", "ed448"])
|
||||
|
|
41
tests/pytests/functional/modules/test_yumpkg.py
Normal file
41
tests/pytests/functional/modules/test_yumpkg.py
Normal file
|
@ -0,0 +1,41 @@
|
|||
import pytest
|
||||
|
||||
import salt.modules.cmdmod
|
||||
import salt.modules.pkg_resource
|
||||
import salt.modules.yumpkg
|
||||
import salt.utils.pkg.rpm
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def configure_loader_modules(minion_opts):
|
||||
return {
|
||||
salt.modules.yumpkg: {
|
||||
"__salt__": {
|
||||
"cmd.run": salt.modules.cmdmod.run,
|
||||
"pkg_resource.add_pkg": salt.modules.pkg_resource.add_pkg,
|
||||
"pkg_resource.format_pkg_list": salt.modules.pkg_resource.format_pkg_list,
|
||||
},
|
||||
"__grains__": {"osarch": salt.utils.pkg.rpm.get_osarch()},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.slow_test
|
||||
def test_yum_list_pkgs(grains):
|
||||
"""
|
||||
compare the output of rpm -qa vs the return of yumpkg.list_pkgs,
|
||||
make sure that any changes to ympkg.list_pkgs still returns.
|
||||
"""
|
||||
|
||||
if grains["os_family"] != "RedHat":
|
||||
pytest.skip("Skip if not RedHat")
|
||||
cmd = [
|
||||
"rpm",
|
||||
"-qa",
|
||||
"--queryformat",
|
||||
"%{NAME}\n",
|
||||
]
|
||||
known_pkgs = salt.modules.cmdmod.run(cmd, python_shell=False)
|
||||
listed_pkgs = salt.modules.yumpkg.list_pkgs()
|
||||
for line in known_pkgs.splitlines():
|
||||
assert any(line in d for d in listed_pkgs)
|
|
@ -2170,6 +2170,21 @@ def test_private_key_managed_existing(x509, pk_args):
|
|||
_assert_not_changed(ret)
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("existing_pk")
|
||||
@pytest.mark.parametrize(
|
||||
"existing_pk",
|
||||
[
|
||||
{"algo": "rsa", "keysize": 3072},
|
||||
],
|
||||
indirect=True,
|
||||
)
|
||||
def test_private_key_managed_existing_keysize_change_to_default(x509, pk_args):
|
||||
pk_args.pop("keysize")
|
||||
ret = x509.private_key_managed(**pk_args)
|
||||
assert ret.changes
|
||||
assert ret.changes["keysize"] == 2048
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("existing_pk")
|
||||
def test_private_key_managed_existing_new(x509, pk_args):
|
||||
cur = _get_privkey(pk_args["name"])
|
||||
|
|
|
@ -238,3 +238,38 @@ def test_gitpython_remote_map(gitpython_gitfs_opts):
|
|||
@skipif_no_pygit2
|
||||
def test_pygit2_remote_map(pygit2_gitfs_opts):
|
||||
_test_remote_map(pygit2_gitfs_opts)
|
||||
|
||||
|
||||
def _test_lock(opts):
|
||||
g = _get_gitfs(
|
||||
opts,
|
||||
"https://github.com/saltstack/salt-test-pillar-gitfs.git",
|
||||
)
|
||||
g.fetch_remotes()
|
||||
assert len(g.remotes) == 1
|
||||
repo = g.remotes[0]
|
||||
assert repo.get_salt_working_dir() in repo._get_lock_file()
|
||||
assert repo.lock() == (
|
||||
[
|
||||
"Set update lock for gitfs remote 'https://github.com/saltstack/salt-test-pillar-gitfs.git'"
|
||||
],
|
||||
[],
|
||||
)
|
||||
assert os.path.isfile(repo._get_lock_file())
|
||||
assert repo.clear_lock() == (
|
||||
[
|
||||
"Removed update lock for gitfs remote 'https://github.com/saltstack/salt-test-pillar-gitfs.git'"
|
||||
],
|
||||
[],
|
||||
)
|
||||
assert not os.path.isfile(repo._get_lock_file())
|
||||
|
||||
|
||||
@skipif_no_gitpython
|
||||
def test_gitpython_lock(gitpython_gitfs_opts):
|
||||
_test_lock(gitpython_gitfs_opts)
|
||||
|
||||
|
||||
@skipif_no_pygit2
|
||||
def test_pygit2_lock(pygit2_gitfs_opts):
|
||||
_test_lock(pygit2_gitfs_opts)
|
||||
|
|
|
@ -328,3 +328,38 @@ def test_gitpython_remote_map(gitpython_pillar_opts):
|
|||
@skipif_no_pygit2
|
||||
def test_pygit2_remote_map(pygit2_pillar_opts):
|
||||
_test_remote_map(pygit2_pillar_opts)
|
||||
|
||||
|
||||
def _test_lock(opts):
|
||||
p = _get_pillar(
|
||||
opts,
|
||||
"https://github.com/saltstack/salt-test-pillar-gitfs.git",
|
||||
)
|
||||
p.fetch_remotes()
|
||||
assert len(p.remotes) == 1
|
||||
repo = p.remotes[0]
|
||||
assert repo.get_salt_working_dir() in repo._get_lock_file()
|
||||
assert repo.lock() == (
|
||||
[
|
||||
"Set update lock for git_pillar remote 'https://github.com/saltstack/salt-test-pillar-gitfs.git'"
|
||||
],
|
||||
[],
|
||||
)
|
||||
assert os.path.isfile(repo._get_lock_file())
|
||||
assert repo.clear_lock() == (
|
||||
[
|
||||
"Removed update lock for git_pillar remote 'https://github.com/saltstack/salt-test-pillar-gitfs.git'"
|
||||
],
|
||||
[],
|
||||
)
|
||||
assert not os.path.isfile(repo._get_lock_file())
|
||||
|
||||
|
||||
@skipif_no_gitpython
|
||||
def test_gitpython_lock(gitpython_pillar_opts):
|
||||
_test_lock(gitpython_pillar_opts)
|
||||
|
||||
|
||||
@skipif_no_pygit2
|
||||
def test_pygit2_lock(pygit2_pillar_opts):
|
||||
_test_lock(pygit2_pillar_opts)
|
||||
|
|
|
@ -127,3 +127,38 @@ def test_gitpython_remote_map(gitpython_winrepo_opts):
|
|||
@skipif_no_pygit2
|
||||
def test_pygit2_remote_map(pygit2_winrepo_opts):
|
||||
_test_remote_map(pygit2_winrepo_opts)
|
||||
|
||||
|
||||
def _test_lock(opts):
|
||||
w = _get_winrepo(
|
||||
opts,
|
||||
"https://github.com/saltstack/salt-test-pillar-gitfs.git",
|
||||
)
|
||||
w.fetch_remotes()
|
||||
assert len(w.remotes) == 1
|
||||
repo = w.remotes[0]
|
||||
assert repo.get_salt_working_dir() in repo._get_lock_file()
|
||||
assert repo.lock() == (
|
||||
[
|
||||
"Set update lock for winrepo remote 'https://github.com/saltstack/salt-test-pillar-gitfs.git'"
|
||||
],
|
||||
[],
|
||||
)
|
||||
assert os.path.isfile(repo._get_lock_file())
|
||||
assert repo.clear_lock() == (
|
||||
[
|
||||
"Removed update lock for winrepo remote 'https://github.com/saltstack/salt-test-pillar-gitfs.git'"
|
||||
],
|
||||
[],
|
||||
)
|
||||
assert not os.path.isfile(repo._get_lock_file())
|
||||
|
||||
|
||||
@skipif_no_gitpython
|
||||
def test_gitpython_lock(gitpython_winrepo_opts):
|
||||
_test_lock(gitpython_winrepo_opts)
|
||||
|
||||
|
||||
@skipif_no_pygit2
|
||||
def test_pygit2_lock(pygit2_winrepo_opts):
|
||||
_test_lock(pygit2_winrepo_opts)
|
||||
|
|
|
@ -123,9 +123,10 @@ def test_list_pkgs():
|
|||
"openssh_|-(none)_|-6.6.1p1_|-33.el7_3_|-x86_64_|-(none)_|-1487838485",
|
||||
"virt-what_|-(none)_|-1.13_|-8.el7_|-x86_64_|-(none)_|-1487838486",
|
||||
]
|
||||
cmd_mod = MagicMock(return_value=os.linesep.join(rpm_out))
|
||||
with patch.dict(yumpkg.__grains__, {"osarch": "x86_64"}), patch.dict(
|
||||
yumpkg.__salt__,
|
||||
{"cmd.run": MagicMock(return_value=os.linesep.join(rpm_out))},
|
||||
{"cmd.run": cmd_mod},
|
||||
), patch.dict(yumpkg.__salt__, {"pkg_resource.add_pkg": _add_data}), patch.dict(
|
||||
yumpkg.__salt__,
|
||||
{"pkg_resource.format_pkg_list": pkg_resource.format_pkg_list},
|
||||
|
@ -152,6 +153,18 @@ def test_list_pkgs():
|
|||
}.items():
|
||||
assert pkgs.get(pkg_name) is not None
|
||||
assert pkgs[pkg_name] == [pkg_version]
|
||||
cmd_mod.assert_called_once_with(
|
||||
[
|
||||
"rpm",
|
||||
"-qa",
|
||||
"--nodigest",
|
||||
"--nosignature",
|
||||
"--queryformat",
|
||||
"%{NAME}_|-%{EPOCH}_|-%{VERSION}_|-%{RELEASE}_|-%{ARCH}_|-(none)_|-%{INSTALLTIME}\n",
|
||||
],
|
||||
output_loglevel="trace",
|
||||
python_shell=False,
|
||||
)
|
||||
|
||||
|
||||
def test_list_pkgs_no_context():
|
||||
|
|
|
@ -1270,3 +1270,24 @@ def test_latest_multiple_versions():
|
|||
with patch.dict(pkg.__salt__, salt_dict):
|
||||
ret = pkg.latest(pkg_name)
|
||||
assert ret.get("result", False) is True
|
||||
|
||||
|
||||
def test_latest_no_change_windows():
|
||||
"""
|
||||
Test pkg.latest with no change to the package version for winrepo packages
|
||||
|
||||
See: https://github.com/saltstack/salt/issues/65165
|
||||
"""
|
||||
pkg_name = "fake_pkg"
|
||||
version = "1.2.2"
|
||||
latest_version_mock = MagicMock(return_value={pkg_name: version})
|
||||
current_version_mock = MagicMock(return_value={pkg_name: version})
|
||||
install_mock = MagicMock(return_value={pkg_name: {"install status": "success"}})
|
||||
salt_dict = {
|
||||
"pkg.latest_version": latest_version_mock,
|
||||
"pkg.version": current_version_mock,
|
||||
"pkg.install": install_mock,
|
||||
}
|
||||
with patch.dict(pkg.__salt__, salt_dict):
|
||||
ret = pkg.latest(pkg_name)
|
||||
assert ret.get("result", False) is True
|
||||
|
|
18
tools/ci.py
18
tools/ci.py
|
@ -716,6 +716,7 @@ def pkg_matrix(
|
|||
# we allow for 3006.0 jobs to run, because then
|
||||
# we will have arm64 onedir packages to upgrade from
|
||||
sessions.append("upgrade")
|
||||
sessions.append("downgrade")
|
||||
# TODO: Remove this block when we reach version 3009.0, we will no longer be testing upgrades from classic packages
|
||||
if (
|
||||
distro_slug
|
||||
|
@ -730,12 +731,13 @@ def pkg_matrix(
|
|||
):
|
||||
# Packages for these OSs where never built for classic previously
|
||||
sessions.append("upgrade-classic")
|
||||
sessions.append("downgrade-classic")
|
||||
|
||||
for session in sessions:
|
||||
versions: list[str | None] = [None]
|
||||
if session == "upgrade":
|
||||
if session in ("upgrade", "downgrade"):
|
||||
versions = [str(version) for version in testing_releases]
|
||||
elif session == "upgrade-classic":
|
||||
elif session in ("upgrade-classic", "downgrade-classic"):
|
||||
versions = [
|
||||
str(version)
|
||||
for version in testing_releases
|
||||
|
@ -974,7 +976,7 @@ def get_testing_releases(
|
|||
ctx.exit(1, "The 'GITHUB_OUTPUT' variable is not set.")
|
||||
else:
|
||||
# We aren't testing upgrades from anything before 3006.0 except the latest 3005.x
|
||||
threshold_major = 3006
|
||||
threshold_major = 3005
|
||||
parsed_salt_version = tools.utils.Version(salt_version)
|
||||
# We want the latest 4 major versions, removing the oldest if this version is a new major
|
||||
num_major_versions = 4
|
||||
|
@ -997,16 +999,6 @@ def get_testing_releases(
|
|||
]
|
||||
testing_releases.append(minors_of_major[-1])
|
||||
|
||||
# TODO: Remove this block when we reach version 3009.0
|
||||
# Append the latest minor version of 3005 if we don't have enough major versions to test against
|
||||
if len(testing_releases) != num_major_versions:
|
||||
url = "https://repo.saltproject.io/salt/onedir/repo.json"
|
||||
ret = ctx.web.get(url)
|
||||
repo_data = ret.json()
|
||||
latest = list(repo_data["latest"].keys())[0]
|
||||
version = repo_data["latest"][latest]["version"]
|
||||
testing_releases = [version] + testing_releases
|
||||
|
||||
str_releases = [str(version) for version in testing_releases]
|
||||
|
||||
with open(github_output, "a", encoding="utf-8") as wfh:
|
||||
|
|
|
@ -125,7 +125,19 @@ def setup_testsuite(
|
|||
)
|
||||
|
||||
if run_id is None:
|
||||
ctx.error("Unable to find the appropriate workflow run ID")
|
||||
run_id = tools.utils.gh.discover_run_id(
|
||||
ctx,
|
||||
branch=branch,
|
||||
nightly=nightly,
|
||||
pr=pr,
|
||||
completed_status=False,
|
||||
)
|
||||
if run_id is None:
|
||||
ctx.error("Unable to find the appropriate workflow run ID")
|
||||
else:
|
||||
ctx.warn(
|
||||
f"Looks like we found run_id {run_id} but it's not yet in the completed state"
|
||||
)
|
||||
ctx.exit(1)
|
||||
|
||||
exitcode = tools.utils.gh.download_onedir_artifact(
|
||||
|
|
|
@ -217,6 +217,7 @@ def download_file(
|
|||
auth: str | None = None,
|
||||
headers: dict[str, str] | None = None,
|
||||
) -> pathlib.Path:
|
||||
ctx.info(f"Downloading {dest.name!r} @ {url} ...")
|
||||
curl = shutil.which("curl")
|
||||
if curl is not None:
|
||||
command = [curl, "-sS", "-L"]
|
||||
|
@ -243,7 +244,6 @@ def download_file(
|
|||
ctx.exit(1)
|
||||
return dest
|
||||
# NOTE the stream=True parameter below
|
||||
ctx.info(f"Downloading {url} ...")
|
||||
with ctx.web as web:
|
||||
web.headers.update(headers)
|
||||
with web.get(url, stream=True, auth=auth) as r:
|
||||
|
|
|
@ -63,6 +63,9 @@ def download_onedir_artifact(
|
|||
artifact_name += ".zip"
|
||||
else:
|
||||
artifact_name += ".tar.xz"
|
||||
ctx.info(
|
||||
f"Searching for artifact {artifact_name} from run_id {run_id} in repository {repository} ..."
|
||||
)
|
||||
found_artifact_name = download_artifact(
|
||||
ctx,
|
||||
dest=artifacts_path,
|
||||
|
@ -73,15 +76,24 @@ def download_onedir_artifact(
|
|||
if found_artifact_name is None:
|
||||
return ExitCode.FAIL
|
||||
found_artifact_path = artifacts_path / found_artifact_name
|
||||
checksum_algo = "sha512"
|
||||
ctx.info(f"Validating {found_artifact_name!r} {checksum_algo} checksum ...")
|
||||
artifact_expected_checksum = (
|
||||
artifacts_path.joinpath(f"{found_artifact_name}.SHA512").read_text().strip()
|
||||
artifacts_path.joinpath(f"{found_artifact_name}.{checksum_algo.upper()}")
|
||||
.read_text()
|
||||
.strip()
|
||||
)
|
||||
artifact_checksum = tools.utils.get_file_checksum(
|
||||
found_artifact_path, checksum_algo
|
||||
)
|
||||
artifact_checksum = tools.utils.get_file_checksum(found_artifact_path, "sha512")
|
||||
if artifact_expected_checksum != artifact_checksum:
|
||||
ctx.error("The 'sha512' checksum does not match")
|
||||
ctx.error(f"The {checksum_algo} checksum does not match")
|
||||
ctx.error(f"{artifact_checksum!r} != {artifact_expected_checksum!r}")
|
||||
return ExitCode.FAIL
|
||||
|
||||
ctx.info(
|
||||
f"Decompressing {found_artifact_name!r} to {artifacts_path.relative_to(tools.utils.REPO_ROOT)}{os.path.sep} ..."
|
||||
)
|
||||
if found_artifact_path.suffix == ".zip":
|
||||
with zipfile.ZipFile(found_artifact_path) as zfile:
|
||||
zfile.extractall(path=artifacts_path)
|
||||
|
@ -112,6 +124,9 @@ def download_nox_artifact(
|
|||
)
|
||||
return ExitCode.SOFT_FAIL
|
||||
artifact_name = f"nox-{slug}-{nox_env}"
|
||||
ctx.info(
|
||||
f"Searching for artifact {artifact_name} from run_id {run_id} in repository {repository} ..."
|
||||
)
|
||||
found_artifact_name = download_artifact(
|
||||
ctx,
|
||||
dest=tools.utils.REPO_ROOT,
|
||||
|
@ -181,6 +196,9 @@ def download_pkgs_artifact(
|
|||
artifacts_path = tools.utils.REPO_ROOT / "pkg" / "artifacts"
|
||||
artifacts_path.mkdir(exist_ok=True)
|
||||
|
||||
ctx.info(
|
||||
f"Searching for artifact {artifact_name} from run_id {run_id} in repository {repository} ..."
|
||||
)
|
||||
found_artifact_name = download_artifact(
|
||||
ctx,
|
||||
dest=artifacts_path,
|
||||
|
@ -229,16 +247,18 @@ def download_artifact(
|
|||
headers = {
|
||||
"Accept": "application/vnd.github+json",
|
||||
"Authorization": f"Bearer {github_token}",
|
||||
"X-GitHub-Api-Version": "2022-11-28",
|
||||
}
|
||||
web.headers.update(headers)
|
||||
page = 0
|
||||
listed_artifacts: set[str] = set()
|
||||
while True:
|
||||
if found_artifact is not None:
|
||||
break
|
||||
page += 1
|
||||
params = {
|
||||
"per_page": 100,
|
||||
"page": 1,
|
||||
"page": page,
|
||||
}
|
||||
ret = web.get(
|
||||
f"https://api.github.com/repos/{repository}/actions/runs/{run_id}/artifacts",
|
||||
|
@ -250,21 +270,30 @@ def download_artifact(
|
|||
)
|
||||
ctx.exit(1)
|
||||
data = ret.json()
|
||||
if data["total_count"] <= len(listed_artifacts):
|
||||
ctx.info("Already gone through all of the listed artifacts:")
|
||||
ctx.print(sorted(listed_artifacts))
|
||||
break
|
||||
ctx.debug(f"Processing artifacts listing (page: {page}) ...")
|
||||
if not data["artifacts"]:
|
||||
break
|
||||
for artifact in data["artifacts"]:
|
||||
listed_artifacts.add(artifact["name"])
|
||||
ctx.debug(
|
||||
f"Checking if {artifact['name']!r} matches {artifact_name!r} "
|
||||
f"({len(listed_artifacts)}/{data['total_count']}) ..."
|
||||
)
|
||||
if fnmatch.fnmatch(artifact["name"], artifact_name):
|
||||
found_artifact = artifact["name"]
|
||||
tempdir_path = pathlib.Path(tempfile.gettempdir())
|
||||
download_url = artifact["archive_download_url"]
|
||||
ctx.info(f"Downloading {download_url}")
|
||||
downloaded_artifact = tools.utils.download_file(
|
||||
ctx,
|
||||
download_url,
|
||||
tempdir_path / f"{artifact['name']}.zip",
|
||||
headers=headers,
|
||||
)
|
||||
ctx.info("Downloaded", downloaded_artifact)
|
||||
ctx.info(f"Downloaded {downloaded_artifact}")
|
||||
with zipfile.ZipFile(downloaded_artifact) as zfile:
|
||||
zfile.extractall(path=dest)
|
||||
break
|
||||
|
@ -279,22 +308,25 @@ def discover_run_id(
|
|||
nightly: str = None,
|
||||
pr: int = None,
|
||||
repository: str = "saltstack/salt",
|
||||
completed_status: bool = True,
|
||||
) -> int | None:
|
||||
ctx.info(f"Discovering the run_id({branch=}, {nightly=}, {pr=}, {repository=})")
|
||||
run_id: int | None = None
|
||||
with ctx.web as web:
|
||||
headers = {
|
||||
"Accept": "application/vnd.github+json",
|
||||
"X-GitHub-Api-Version": "2022-11-28",
|
||||
}
|
||||
github_token = get_github_token(ctx)
|
||||
if github_token is not None:
|
||||
headers["Authorization"] = f"Bearer {github_token}"
|
||||
web.headers.update(headers)
|
||||
|
||||
params = {
|
||||
params: dict[str, str | int] = {
|
||||
"per_page": 100,
|
||||
"status": "completed",
|
||||
}
|
||||
if completed_status is True:
|
||||
params["status"] = "completed"
|
||||
if branch is not None:
|
||||
ret = web.get(
|
||||
f"https://api.github.com/repos/{repository}/git/ref/heads/{branch}"
|
||||
|
|
18
tools/vm.py
18
tools/vm.py
|
@ -592,9 +592,19 @@ def sync_cache(
|
|||
cached_instances = {}
|
||||
if STATE_DIR.exists():
|
||||
for state_path in STATE_DIR.iterdir():
|
||||
instance_id_path = state_path / "instance-id"
|
||||
if instance_id_path.exists():
|
||||
instance_id = instance_id_path.read_text()
|
||||
try:
|
||||
instance_id = (state_path / "instance-id").read_text()
|
||||
except FileNotFoundError:
|
||||
if not delete:
|
||||
log.info(
|
||||
f"Would remove {state_path.name} (No valid ID) from cache at {state_path}"
|
||||
)
|
||||
else:
|
||||
shutil.rmtree(state_path)
|
||||
log.info(
|
||||
f"REMOVED {state_path.name} (No valid ID) from cache at {state_path}"
|
||||
)
|
||||
else:
|
||||
cached_instances[instance_id] = state_path.name
|
||||
|
||||
# Find what instances we are missing in our cached states
|
||||
|
@ -1194,7 +1204,7 @@ class VM:
|
|||
timeout = self.config.terminate_timeout
|
||||
timeout_progress = 0.0
|
||||
progress = create_progress_bar()
|
||||
task = progress.add_task(f"Terminatting {self!r}...", total=timeout)
|
||||
task = progress.add_task(f"Terminating {self!r}...", total=timeout)
|
||||
self.instance.terminate()
|
||||
try:
|
||||
with progress:
|
||||
|
|
Loading…
Add table
Reference in a new issue