diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6d2c98b6280e..9b5fbaa3f424 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -470,7 +470,7 @@ jobs: cache-seed: ${{ needs.prepare-workflow.outputs.cache-seed }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" relenv-version: "0.22.4" - python-version: "3.11.14" + python-version: "3.12.12" ci-python-version: "3.11" matrix: ${{ toJSON(fromJSON(needs.prepare-workflow.outputs.config)['build-matrix']) }} linux_arm_runner: ${{ fromJSON(needs.prepare-workflow.outputs.config)['linux_arm_runner'] }} @@ -487,7 +487,7 @@ jobs: salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }} relenv-version: "0.22.4" - python-version: "3.11.14" + python-version: "3.12.12" ci-python-version: "3.11" source: "onedir" matrix: ${{ toJSON(fromJSON(needs.prepare-workflow.outputs.config)['build-matrix']) }} @@ -504,7 +504,7 @@ jobs: salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }} relenv-version: "0.22.4" - python-version: "3.11.14" + python-version: "3.12.12" ci-python-version: "3.11" source: "src" matrix: ${{ toJSON(fromJSON(needs.prepare-workflow.outputs.config)['build-matrix']) }} @@ -519,10 +519,10 @@ jobs: with: nox-session: ci-test-onedir nox-version: 2022.8.7 - python-version: "3.11.14" + python-version: "3.12.12" ci-python-version: "3.11" salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.11.14 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.12.12 nox-archive-hash: "${{ needs.prepare-workflow.outputs.nox-archive-hash }}" matrix: ${{ toJSON(fromJSON(needs.prepare-workflow.outputs.config)['build-matrix']) }} linux_arm_runner: ${{ fromJSON(needs.prepare-workflow.outputs.config)['linux_arm_runner'] }} @@ -539,7 +539,7 @@ jobs: salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" nox-version: 2022.8.7 ci-python-version: "3.11" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.11.14 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.12.12 skip-code-coverage: ${{ fromJSON(needs.prepare-workflow.outputs.config)['skip_code_coverage'] }} testing-releases: ${{ needs.prepare-workflow.outputs.testing-releases }} matrix: ${{ toJSON(fromJSON(needs.prepare-workflow.outputs.config)['pkg-test-matrix']) }} @@ -557,7 +557,7 @@ jobs: ci-python-version: "3.11" testrun: ${{ toJSON(fromJSON(needs.prepare-workflow.outputs.config)['testrun']) }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.11.14 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.12.12 skip-code-coverage: ${{ fromJSON(needs.prepare-workflow.outputs.config)['skip_code_coverage'] }} workflow-slug: ci default-timeout: 180 diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 5020f2a760e8..8e7c34b28860 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -465,7 +465,7 @@ jobs: cache-seed: ${{ needs.prepare-workflow.outputs.cache-seed }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" relenv-version: "0.22.4" - python-version: "3.11.14" + python-version: "3.12.12" ci-python-version: "3.11" matrix: ${{ toJSON(fromJSON(needs.prepare-workflow.outputs.config)['build-matrix']) }} linux_arm_runner: ${{ fromJSON(needs.prepare-workflow.outputs.config)['linux_arm_runner'] }} @@ -482,7 +482,7 @@ jobs: salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }} relenv-version: "0.22.4" - python-version: "3.11.14" + python-version: "3.12.12" ci-python-version: "3.11" source: "onedir" matrix: ${{ toJSON(fromJSON(needs.prepare-workflow.outputs.config)['build-matrix']) }} @@ -503,7 +503,7 @@ jobs: salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }} relenv-version: "0.22.4" - python-version: "3.11.14" + python-version: "3.12.12" ci-python-version: "3.11" source: "src" matrix: ${{ toJSON(fromJSON(needs.prepare-workflow.outputs.config)['build-matrix']) }} @@ -522,10 +522,10 @@ jobs: with: nox-session: ci-test-onedir nox-version: 2022.8.7 - python-version: "3.11.14" + python-version: "3.12.12" ci-python-version: "3.11" salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.11.14 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.12.12 nox-archive-hash: "${{ needs.prepare-workflow.outputs.nox-archive-hash }}" matrix: ${{ toJSON(fromJSON(needs.prepare-workflow.outputs.config)['build-matrix']) }} linux_arm_runner: ${{ fromJSON(needs.prepare-workflow.outputs.config)['linux_arm_runner'] }} @@ -542,7 +542,7 @@ jobs: salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" nox-version: 2022.8.7 ci-python-version: "3.11" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.11.14 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.12.12 skip-code-coverage: true testing-releases: ${{ needs.prepare-workflow.outputs.testing-releases }} matrix: ${{ toJSON(fromJSON(needs.prepare-workflow.outputs.config)['pkg-test-matrix']) }} @@ -560,7 +560,7 @@ jobs: ci-python-version: "3.11" testrun: ${{ toJSON(fromJSON(needs.prepare-workflow.outputs.config)['testrun']) }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.11.14 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.12.12 skip-code-coverage: true workflow-slug: nightly default-timeout: 360 diff --git a/.github/workflows/scheduled.yml b/.github/workflows/scheduled.yml index 83d32acdeef7..007ef715d89e 100644 --- a/.github/workflows/scheduled.yml +++ b/.github/workflows/scheduled.yml @@ -513,7 +513,7 @@ jobs: cache-seed: ${{ needs.prepare-workflow.outputs.cache-seed }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" relenv-version: "0.22.4" - python-version: "3.11.14" + python-version: "3.12.12" ci-python-version: "3.11" matrix: ${{ toJSON(fromJSON(needs.prepare-workflow.outputs.config)['build-matrix']) }} linux_arm_runner: ${{ fromJSON(needs.prepare-workflow.outputs.config)['linux_arm_runner'] }} @@ -530,7 +530,7 @@ jobs: salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }} relenv-version: "0.22.4" - python-version: "3.11.14" + python-version: "3.12.12" ci-python-version: "3.11" source: "onedir" matrix: ${{ toJSON(fromJSON(needs.prepare-workflow.outputs.config)['build-matrix']) }} @@ -547,7 +547,7 @@ jobs: salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }} relenv-version: "0.22.4" - python-version: "3.11.14" + python-version: "3.12.12" ci-python-version: "3.11" source: "src" matrix: ${{ toJSON(fromJSON(needs.prepare-workflow.outputs.config)['build-matrix']) }} @@ -562,10 +562,10 @@ jobs: with: nox-session: ci-test-onedir nox-version: 2022.8.7 - python-version: "3.11.14" + python-version: "3.12.12" ci-python-version: "3.11" salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.11.14 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.12.12 nox-archive-hash: "${{ needs.prepare-workflow.outputs.nox-archive-hash }}" matrix: ${{ toJSON(fromJSON(needs.prepare-workflow.outputs.config)['build-matrix']) }} linux_arm_runner: ${{ fromJSON(needs.prepare-workflow.outputs.config)['linux_arm_runner'] }} @@ -582,7 +582,7 @@ jobs: salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" nox-version: 2022.8.7 ci-python-version: "3.11" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.11.14 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.12.12 skip-code-coverage: true testing-releases: ${{ needs.prepare-workflow.outputs.testing-releases }} matrix: ${{ toJSON(fromJSON(needs.prepare-workflow.outputs.config)['pkg-test-matrix']) }} @@ -600,7 +600,7 @@ jobs: ci-python-version: "3.11" testrun: ${{ toJSON(fromJSON(needs.prepare-workflow.outputs.config)['testrun']) }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.11.14 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.12.12 skip-code-coverage: true workflow-slug: scheduled default-timeout: 360 diff --git a/.github/workflows/staging.yml b/.github/workflows/staging.yml index 0b5de3fadb67..ce8cb4e7419c 100644 --- a/.github/workflows/staging.yml +++ b/.github/workflows/staging.yml @@ -497,7 +497,7 @@ jobs: cache-seed: ${{ needs.prepare-workflow.outputs.cache-seed }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" relenv-version: "0.22.4" - python-version: "3.11.14" + python-version: "3.12.12" ci-python-version: "3.11" matrix: ${{ toJSON(fromJSON(needs.prepare-workflow.outputs.config)['build-matrix']) }} linux_arm_runner: ${{ fromJSON(needs.prepare-workflow.outputs.config)['linux_arm_runner'] }} @@ -515,7 +515,7 @@ jobs: salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }} relenv-version: "0.22.4" - python-version: "3.11.14" + python-version: "3.12.12" ci-python-version: "3.11" source: "onedir" matrix: ${{ toJSON(fromJSON(needs.prepare-workflow.outputs.config)['build-matrix']) }} @@ -537,7 +537,7 @@ jobs: salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }} relenv-version: "0.22.4" - python-version: "3.11.14" + python-version: "3.12.12" ci-python-version: "3.11" source: "src" matrix: ${{ toJSON(fromJSON(needs.prepare-workflow.outputs.config)['build-matrix']) }} @@ -556,10 +556,10 @@ jobs: with: nox-session: ci-test-onedir nox-version: 2022.8.7 - python-version: "3.11.14" + python-version: "3.12.12" ci-python-version: "3.11" salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.11.14 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.12.12 nox-archive-hash: "${{ needs.prepare-workflow.outputs.nox-archive-hash }}" matrix: ${{ toJSON(fromJSON(needs.prepare-workflow.outputs.config)['build-matrix']) }} linux_arm_runner: ${{ fromJSON(needs.prepare-workflow.outputs.config)['linux_arm_runner'] }} @@ -576,7 +576,7 @@ jobs: salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" nox-version: 2022.8.7 ci-python-version: "3.11" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.11.14 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.12.12 skip-code-coverage: true testing-releases: ${{ needs.prepare-workflow.outputs.testing-releases }} matrix: ${{ toJSON(fromJSON(needs.prepare-workflow.outputs.config)['pkg-test-matrix']) }} @@ -594,7 +594,7 @@ jobs: ci-python-version: "3.11" testrun: ${{ toJSON(fromJSON(needs.prepare-workflow.outputs.config)['testrun']) }} salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}" - cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.11.14 + cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.12.12 skip-code-coverage: true workflow-slug: staging default-timeout: 180 diff --git a/.gitignore b/.gitignore index 440b47a105f8..cfb9177de42b 100644 --- a/.gitignore +++ b/.gitignore @@ -155,3 +155,7 @@ nox.*.tar.xz /.aiderignore /aider.conf.yml /.gemini +venv310/ +venv312/ +*.json +*.txt diff --git a/cicd/shared-gh-workflows-context.yml b/cicd/shared-gh-workflows-context.yml index 1632de2dd513..3f7df6dd43bb 100644 --- a/cicd/shared-gh-workflows-context.yml +++ b/cicd/shared-gh-workflows-context.yml @@ -3,7 +3,7 @@ # Tool versions nox_version: "2022.8.7" -python_version: "3.11.14" +python_version: "3.12.12" relenv_version: "0.22.4" release_branches: - "3006.x" diff --git a/noxfile.py b/noxfile.py index 8c69b2418cb0..07ebef8b7d5a 100644 --- a/noxfile.py +++ b/noxfile.py @@ -85,7 +85,7 @@ else: ONEDIR_PYTHON_PATH = ONEDIR_ARTIFACT_PATH / "bin" / "python3" # Python versions to run against -_PYTHON_VERSIONS = ("3", "3.8", "3.9", "3.10", "3.11") +_PYTHON_VERSIONS = ("3", "3.8", "3.9", "3.10", "3.11", "3.12") # Nox options # Reuse existing virtualenvs diff --git a/pkg/macos/install_salt.sh b/pkg/macos/install_salt.sh index fc6d23d7b88a..5e3211fab8f6 100755 --- a/pkg/macos/install_salt.sh +++ b/pkg/macos/install_salt.sh @@ -127,7 +127,7 @@ fi # Install Requirements into the Python Environment #------------------------------------------------------------------------------- _msg "Installing Salt requirements" -$PIP_BIN install -r "$REQ_FILE" > /dev/null 2>&1 +CFLAGS="${CFLAGS} -Wno-int-conversion" $PIP_BIN install -r "$REQ_FILE" > /dev/null 2>&1 if [ -f "$BUILD_DIR/bin/distro" ]; then _success else diff --git a/requirements/static/ci/common.in b/requirements/static/ci/common.in index 6358a8b1f95d..78b74709d74e 100644 --- a/requirements/static/ci/common.in +++ b/requirements/static/ci/common.in @@ -24,6 +24,7 @@ google-auth==2.35.0; python_version == '3.9' jmespath>=1.1.0 jsonschema junos-eznc; sys_platform != 'win32' +ncclient>=0.6.16; sys_platform != 'win32' junit-xml>=1.9 jxmlease; sys_platform != 'win32' kazoo; sys_platform != 'win32' and sys_platform != 'darwin' diff --git a/requirements/static/ci/darwin.in b/requirements/static/ci/darwin.in index 96ded57cab8f..2420386d3778 100644 --- a/requirements/static/ci/darwin.in +++ b/requirements/static/ci/darwin.in @@ -1,6 +1,6 @@ -pygit2>=1.10.1 +pygit2>=1.14.0 yamllint -mercurial +mercurial>=6.7 hglib # Pin versions to match 3007.x apache-libcloud>=3.8.0 diff --git a/requirements/static/ci/freebsd.in b/requirements/static/ci/freebsd.in index a6d21d5a499a..7b24f942361c 100644 --- a/requirements/static/ci/freebsd.in +++ b/requirements/static/ci/freebsd.in @@ -1,5 +1,5 @@ # FreeBSD static CI requirements yamllint -mercurial +mercurial>=6.7 hglib diff --git a/requirements/static/ci/linux.in b/requirements/static/ci/linux.in index 73cd0bfed347..f39cbdd0eccf 100644 --- a/requirements/static/ci/linux.in +++ b/requirements/static/ci/linux.in @@ -1,6 +1,6 @@ # Linux static CI requirements pyiface -pygit2>=1.10.1 +pygit2>=1.14.0 pymysql>=1.1.1 ansible>=10.7.0; python_version >= '3.10' and python_version < '3.11' ansible>=12.3.0; python_version >= '3.11' and python_version < '3.12' @@ -10,7 +10,7 @@ ansible>=4.4.0,<5.0.1; python_version < '3.9' twilio python-telegram-bot>=13.7 yamllint -mercurial +mercurial>=6.7 hglib redis-py-cluster python-consul diff --git a/requirements/static/ci/py3.10/cloud.txt b/requirements/static/ci/py3.10/cloud.txt index 16a7f05de3e3..cb0b84a3ac90 100644 --- a/requirements/static/ci/py3.10/cloud.txt +++ b/requirements/static/ci/py3.10/cloud.txt @@ -231,6 +231,10 @@ iniconfig==2.0.0 # via # -c requirements/static/ci/py3.10/linux.txt # pytest +invoke==2.2.1 + # via + # -c requirements/static/ci/py3.10/linux.txt + # paramiko jaraco-collections==4.1.0 # via # -c requirements/static/ci/py3.10/linux.txt @@ -279,7 +283,7 @@ junit-xml==1.9 # via # -c requirements/static/ci/py3.10/linux.txt # -r requirements/static/ci/common.in -junos-eznc==2.6.7 +junos-eznc==2.7.6 # via # -c requirements/static/ci/py3.10/linux.txt # -r requirements/static/ci/common.in @@ -308,7 +312,7 @@ looseversion==1.3.0 # -c requirements/static/ci/py3.10/linux.txt # -c requirements/static/pkg/py3.10/linux.txt # -r requirements/base.txt -lxml==4.9.2 +lxml==6.0.2 # via # -c requirements/static/ci/py3.10/linux.txt # junos-eznc @@ -351,21 +355,19 @@ msgpack==1.0.7 # -c requirements/static/pkg/py3.10/linux.txt # -r requirements/base.txt # pytest-salt-factories -multidict==6.7.1 +multidict==6.1.0 # via # -c requirements/static/ci/py3.10/linux.txt # -c requirements/static/pkg/py3.10/linux.txt # aiohttp # yarl -ncclient==0.6.13 +ncclient==0.7.0 # via # -c requirements/static/ci/py3.10/linux.txt + # -r requirements/static/ci/common.in # junos-eznc netaddr==0.8.0 - # via - # -c requirements/static/ci/py3.10/linux.txt - # -r requirements/static/ci/cloud.in - # junos-eznc + # via -r requirements/static/ci/cloud.in oauthlib==3.3.1 # via # -c requirements/static/ci/py3.10/linux.txt @@ -380,7 +382,7 @@ packaging==24.0 # -c requirements/static/pkg/py3.10/linux.txt # -r requirements/base.txt # pytest -paramiko==3.4.0 +paramiko==4.0.0 # via # -c requirements/static/ci/py3.10/linux.txt # -r requirements/static/ci/common.in @@ -580,7 +582,7 @@ pyyaml==6.0.1 # kubernetes # pytest-salt-factories # responses - # yamlordereddictloader + # yamlloader pyzmq==25.1.2 # via # -c requirements/static/ci/py3.10/linux.txt @@ -653,7 +655,6 @@ six==1.16.0 # junos-eznc # kazoo # kubernetes - # ncclient # profitbricks # python-dateutil # pyvmomi @@ -783,7 +784,7 @@ xmltodict==0.13.0 # -c requirements/static/ci/py3.10/linux.txt # moto # pywinrm -yamlordereddictloader==0.4.0 +yamlloader==1.6.0 # via # -c requirements/static/ci/py3.10/linux.txt # junos-eznc diff --git a/requirements/static/ci/py3.10/darwin.txt b/requirements/static/ci/py3.10/darwin.txt index 81faf76e4d30..861860e2eb45 100644 --- a/requirements/static/ci/py3.10/darwin.txt +++ b/requirements/static/ci/py3.10/darwin.txt @@ -176,6 +176,8 @@ importlib-metadata==8.7.0 # -r requirements/base.txt iniconfig==2.0.0 # via pytest +invoke==2.2.1 + # via paramiko jaraco-collections==4.1.0 # via # -c requirements/static/pkg/py3.10/darwin.txt @@ -214,7 +216,7 @@ jsonschema==3.2.0 # via -r requirements/static/ci/common.in junit-xml==1.9 # via -r requirements/static/ci/common.in -junos-eznc==2.6.7 +junos-eznc==2.7.6 # via -r requirements/static/ci/common.in jxmlease==1.0.3 # via -r requirements/static/ci/common.in @@ -226,7 +228,7 @@ looseversion==1.3.0 # via # -c requirements/static/pkg/py3.10/darwin.txt # -r requirements/base.txt -lxml==4.9.2 +lxml==6.0.2 # via # junos-eznc # ncclient @@ -240,7 +242,7 @@ markupsafe==2.1.3 # jinja2 # mako # werkzeug -mercurial==6.4.4 +mercurial==7.2 # via -r requirements/static/ci/darwin.in mock==5.1.0 # via -r requirements/pytest.txt @@ -260,15 +262,15 @@ msgpack==1.0.7 # -c requirements/static/pkg/py3.10/darwin.txt # -r requirements/base.txt # pytest-salt-factories -multidict==6.7.1 +multidict==6.1.0 # via # -c requirements/static/pkg/py3.10/darwin.txt # aiohttp # yarl -ncclient==0.6.13 - # via junos-eznc -netaddr==0.8.0 - # via junos-eznc +ncclient==0.7.0 + # via + # -r requirements/static/ci/common.in + # junos-eznc oauthlib==3.3.1 # via requests-oauthlib oscrypto==1.3.0 @@ -278,7 +280,7 @@ packaging==24.0 # -c requirements/static/pkg/py3.10/darwin.txt # -r requirements/base.txt # pytest -paramiko==3.4.0 +paramiko==4.0.0 # via # junos-eznc # ncclient @@ -325,7 +327,7 @@ pycryptodomex==3.19.1 # -r requirements/crypto.txt pyfakefs==5.3.1 # via -r requirements/pytest.txt -pygit2==1.13.1 +pygit2==1.18.2 # via -r requirements/static/ci/darwin.in pynacl==1.5.0 # via @@ -416,7 +418,7 @@ pyyaml==6.0.1 # pytest-salt-factories # responses # yamllint - # yamlordereddictloader + # yamlloader pyzmq==25.1.2 # via # -c requirements/static/pkg/py3.10/darwin.txt @@ -460,7 +462,6 @@ six==1.16.0 # junit-xml # junos-eznc # kubernetes - # ncclient # python-dateutil # pyvmomi # textfsm @@ -548,7 +549,7 @@ xmltodict==0.13.0 # via moto yamllint==1.32.0 # via -r requirements/static/ci/darwin.in -yamlordereddictloader==0.4.0 +yamlloader==1.6.0 # via junos-eznc yarl==1.23.0 # via diff --git a/requirements/static/ci/py3.10/docs.txt b/requirements/static/ci/py3.10/docs.txt index 24cd0ad991f6..e38855c582c0 100644 --- a/requirements/static/ci/py3.10/docs.txt +++ b/requirements/static/ci/py3.10/docs.txt @@ -173,7 +173,7 @@ msgpack==1.0.7 # via # -c requirements/static/ci/py3.10/linux.txt # -r requirements/base.txt -multidict==6.7.1 +multidict==6.1.0 # via # -c requirements/static/ci/py3.10/linux.txt # aiohttp diff --git a/requirements/static/ci/py3.10/freebsd.txt b/requirements/static/ci/py3.10/freebsd.txt index ff7e3794f3d8..4a8fdf75eb35 100644 --- a/requirements/static/ci/py3.10/freebsd.txt +++ b/requirements/static/ci/py3.10/freebsd.txt @@ -186,6 +186,8 @@ importlib-metadata==8.7.0 # -r requirements/static/pkg/freebsd.in iniconfig==2.0.0 # via pytest +invoke==2.2.1 ; sys_platform != 'win32' + # via paramiko jaraco-collections==4.1.0 # via # -c requirements/static/pkg/py3.10/freebsd.txt @@ -224,7 +226,7 @@ jsonschema==3.2.0 # via -r requirements/static/ci/common.in junit-xml==1.9 # via -r requirements/static/ci/common.in -junos-eznc==2.6.7 ; sys_platform != 'win32' +junos-eznc==2.7.6 ; sys_platform != 'win32' # via -r requirements/static/ci/common.in jxmlease==1.0.3 ; sys_platform != 'win32' # via -r requirements/static/ci/common.in @@ -256,7 +258,7 @@ markupsafe==2.1.3 # jinja2 # mako # werkzeug -mercurial==6.4.4 +mercurial==7.2 # via -r requirements/static/ci/freebsd.in mock==5.1.0 # via -r requirements/pytest.txt @@ -276,15 +278,15 @@ msgpack==1.1.2 # -c requirements/static/pkg/py3.10/freebsd.txt # -r requirements/base.txt # pytest-salt-factories -multidict==6.7.1 +multidict==6.1.0 # via # -c requirements/static/pkg/py3.10/freebsd.txt # aiohttp # yarl -ncclient==0.6.13 ; sys_platform != 'win32' - # via junos-eznc -netaddr==0.8.0 ; sys_platform != 'win32' - # via junos-eznc +ncclient==0.7.0 ; sys_platform != 'win32' + # via + # -r requirements/static/ci/common.in + # junos-eznc oauthlib==3.3.1 # via requests-oauthlib oscrypto==1.3.0 ; sys_platform != 'win32' @@ -294,7 +296,7 @@ packaging==24.0 # -c requirements/static/pkg/py3.10/freebsd.txt # -r requirements/base.txt # pytest -paramiko==3.4.0 ; sys_platform != 'win32' +paramiko==4.0.0 ; sys_platform != 'win32' # via # -r requirements/static/ci/common.in # junos-eznc @@ -460,7 +462,7 @@ pyyaml==6.0.1 # pytest-salt-factories # responses # yamllint - # yamlordereddictloader + # yamlloader pyzmq==27.1.0 # via # -c requirements/static/pkg/py3.10/freebsd.txt @@ -523,7 +525,6 @@ six==1.16.0 # junos-eznc # kazoo # kubernetes - # ncclient # python-dateutil # pyvmomi # textfsm @@ -619,7 +620,7 @@ xmltodict==1.0.4 # moto yamllint==1.32.0 # via -r requirements/static/ci/freebsd.in -yamlordereddictloader==0.4.0 ; sys_platform != 'win32' +yamlloader==1.6.0 ; sys_platform != 'win32' # via junos-eznc yarl==1.23.0 # via diff --git a/requirements/static/ci/py3.10/lint.txt b/requirements/static/ci/py3.10/lint.txt index b9269590b1f2..c7af3d72f408 100644 --- a/requirements/static/ci/py3.10/lint.txt +++ b/requirements/static/ci/py3.10/lint.txt @@ -255,6 +255,10 @@ importlib-metadata==8.7.0 # -c requirements/static/pkg/py3.10/linux.txt # -r requirements/base.txt # -r requirements/static/pkg/linux.in +invoke==2.2.1 + # via + # -c requirements/static/ci/py3.10/linux.txt + # paramiko isort==4.3.21 # via pylint jaraco-collections==4.1.0 @@ -306,7 +310,7 @@ junit-xml==1.9 # via # -c requirements/static/ci/py3.10/linux.txt # -r requirements/static/ci/common.in -junos-eznc==2.6.7 +junos-eznc==2.7.6 # via # -c requirements/static/ci/py3.10/linux.txt # -r requirements/static/ci/common.in @@ -335,7 +339,7 @@ looseversion==1.3.0 # -c requirements/static/ci/py3.10/linux.txt # -c requirements/static/pkg/py3.10/linux.txt # -r requirements/base.txt -lxml==4.9.2 +lxml==6.0.2 # via # -c requirements/static/ci/py3.10/linux.txt # junos-eznc @@ -355,7 +359,7 @@ markupsafe==2.1.3 # werkzeug mccabe==0.6.1 # via pylint -mercurial==6.4.4 +mercurial==7.2 # via # -c requirements/static/ci/py3.10/linux.txt # -r requirements/static/ci/linux.in @@ -378,19 +382,16 @@ msgpack==1.0.7 # -c requirements/static/ci/py3.10/linux.txt # -c requirements/static/pkg/py3.10/linux.txt # -r requirements/base.txt -multidict==6.7.1 +multidict==6.1.0 # via # -c requirements/static/ci/py3.10/linux.txt # -c requirements/static/pkg/py3.10/linux.txt # aiohttp # yarl -ncclient==0.6.13 - # via - # -c requirements/static/ci/py3.10/linux.txt - # junos-eznc -netaddr==0.8.0 +ncclient==0.7.0 # via # -c requirements/static/ci/py3.10/linux.txt + # -r requirements/static/ci/common.in # junos-eznc oauthlib==3.3.1 # via @@ -406,7 +407,7 @@ packaging==24.0 # -c requirements/static/pkg/py3.10/linux.txt # -r requirements/base.txt # ansible-core -paramiko==3.4.0 +paramiko==4.0.0 # via # -c requirements/static/ci/py3.10/linux.txt # -r requirements/static/ci/common.in @@ -461,7 +462,7 @@ pycryptodomex==3.19.1 # -c requirements/static/ci/py3.10/linux.txt # -c requirements/static/pkg/py3.10/linux.txt # -r requirements/crypto.txt -pygit2==1.13.1 +pygit2==1.18.2 # via # -c requirements/static/ci/py3.10/linux.txt # -r requirements/static/ci/linux.in @@ -565,7 +566,7 @@ pyyaml==6.0.1 # kubernetes # responses # yamllint - # yamlordereddictloader + # yamlloader pyzmq==25.1.2 # via # -c requirements/static/ci/py3.10/linux.txt @@ -648,7 +649,6 @@ six==1.16.0 # junos-eznc # kazoo # kubernetes - # ncclient # python-consul # python-dateutil # pyvmomi @@ -791,7 +791,7 @@ yamllint==1.32.0 # via # -c requirements/static/ci/py3.10/linux.txt # -r requirements/static/ci/linux.in -yamlordereddictloader==0.4.0 +yamlloader==1.6.0 # via # -c requirements/static/ci/py3.10/linux.txt # junos-eznc diff --git a/requirements/static/ci/py3.10/linux.txt b/requirements/static/ci/py3.10/linux.txt index 5872ad58aeaf..a1dc06f238f9 100644 --- a/requirements/static/ci/py3.10/linux.txt +++ b/requirements/static/ci/py3.10/linux.txt @@ -197,6 +197,8 @@ importlib-metadata==8.7.0 # -r requirements/base.txt iniconfig==2.0.0 # via pytest +invoke==2.2.1 + # via paramiko jaraco-collections==4.1.0 # via # -c requirements/static/pkg/py3.10/linux.txt @@ -236,7 +238,7 @@ jsonschema==3.2.0 # via -r requirements/static/ci/common.in junit-xml==1.9 # via -r requirements/static/ci/common.in -junos-eznc==2.6.7 +junos-eznc==2.7.6 # via -r requirements/static/ci/common.in jxmlease==1.0.3 # via -r requirements/static/ci/common.in @@ -252,7 +254,7 @@ looseversion==1.3.0 # via # -c requirements/static/pkg/py3.10/linux.txt # -r requirements/base.txt -lxml==4.9.2 +lxml==6.0.2 # via # junos-eznc # ncclient @@ -266,7 +268,7 @@ markupsafe==2.1.3 # jinja2 # mako # werkzeug -mercurial==6.4.4 +mercurial==7.2 # via -r requirements/static/ci/linux.in mock==5.1.0 # via -r requirements/pytest.txt @@ -286,15 +288,15 @@ msgpack==1.0.7 # -c requirements/static/pkg/py3.10/linux.txt # -r requirements/base.txt # pytest-salt-factories -multidict==6.7.1 +multidict==6.1.0 # via # -c requirements/static/pkg/py3.10/linux.txt # aiohttp # yarl -ncclient==0.6.13 - # via junos-eznc -netaddr==0.8.0 - # via junos-eznc +ncclient==0.7.0 + # via + # -r requirements/static/ci/common.in + # junos-eznc oauthlib==3.3.1 # via requests-oauthlib oscrypto==1.3.0 @@ -305,7 +307,7 @@ packaging==24.0 # -r requirements/base.txt # ansible-core # pytest -paramiko==3.4.0 +paramiko==4.0.0 # via # -r requirements/static/ci/common.in # junos-eznc @@ -353,7 +355,7 @@ pycryptodomex==3.19.1 # -r requirements/crypto.txt pyfakefs==5.3.1 # via -r requirements/pytest.txt -pygit2==1.13.1 +pygit2==1.18.2 # via -r requirements/static/ci/linux.in pyiface==0.0.11 # via -r requirements/static/ci/linux.in @@ -458,7 +460,7 @@ pyyaml==6.0.1 # pytest-salt-factories # responses # yamllint - # yamlordereddictloader + # yamlloader pyzmq==25.1.2 # via # -c requirements/static/pkg/py3.10/linux.txt @@ -515,7 +517,6 @@ six==1.16.0 # junos-eznc # kazoo # kubernetes - # ncclient # python-consul # python-dateutil # pyvmomi @@ -615,7 +616,7 @@ xmltodict==0.13.0 # via moto yamllint==1.32.0 # via -r requirements/static/ci/linux.in -yamlordereddictloader==0.4.0 +yamlloader==1.6.0 # via junos-eznc yarl==1.23.0 # via diff --git a/requirements/static/ci/py3.10/windows.txt b/requirements/static/ci/py3.10/windows.txt index 235bdf6522cb..d1406271dadd 100644 --- a/requirements/static/ci/py3.10/windows.txt +++ b/requirements/static/ci/py3.10/windows.txt @@ -260,7 +260,7 @@ msgpack==1.1.2 # -c requirements/static/pkg/py3.10/windows.txt # -r requirements/base.txt # pytest-salt-factories -multidict==6.7.1 +multidict==6.1.0 # via # -c requirements/static/pkg/py3.10/windows.txt # aiohttp @@ -316,7 +316,7 @@ pycryptodomex==3.23.0 # -r requirements/crypto.txt pyfakefs==5.3.1 # via -r requirements/pytest.txt -pygit2==1.13.1 +pygit2==1.18.2 # via -r requirements/static/ci/windows.in pygments==2.19.2 # via diff --git a/requirements/static/ci/py3.11/cloud.txt b/requirements/static/ci/py3.11/cloud.txt index 6c740b8bf15d..75ea3a318a40 100644 --- a/requirements/static/ci/py3.11/cloud.txt +++ b/requirements/static/ci/py3.11/cloud.txt @@ -221,6 +221,10 @@ iniconfig==2.0.0 # via # -c requirements/static/ci/py3.11/linux.txt # pytest +invoke==2.2.1 + # via + # -c requirements/static/ci/py3.11/linux.txt + # paramiko jaraco-collections==4.1.0 # via # -c requirements/static/ci/py3.11/linux.txt @@ -269,7 +273,7 @@ junit-xml==1.9 # via # -c requirements/static/ci/py3.11/linux.txt # -r requirements/static/ci/common.in -junos-eznc==2.6.7 +junos-eznc==2.7.6 # via # -c requirements/static/ci/py3.11/linux.txt # -r requirements/static/ci/common.in @@ -298,7 +302,7 @@ looseversion==1.3.0 # -c requirements/static/ci/py3.11/linux.txt # -c requirements/static/pkg/py3.11/linux.txt # -r requirements/base.txt -lxml==4.9.2 +lxml==6.0.2 # via # -c requirements/static/ci/py3.11/linux.txt # junos-eznc @@ -341,21 +345,19 @@ msgpack==1.0.7 # -c requirements/static/pkg/py3.11/linux.txt # -r requirements/base.txt # pytest-salt-factories -multidict==6.0.4 +multidict==6.1.0 # via # -c requirements/static/ci/py3.11/linux.txt # -c requirements/static/pkg/py3.11/linux.txt # aiohttp # yarl -ncclient==0.6.13 +ncclient==0.7.0 # via # -c requirements/static/ci/py3.11/linux.txt + # -r requirements/static/ci/common.in # junos-eznc netaddr==0.8.0 - # via - # -c requirements/static/ci/py3.11/linux.txt - # -r requirements/static/ci/cloud.in - # junos-eznc + # via -r requirements/static/ci/cloud.in oauthlib==3.3.1 # via # -c requirements/static/ci/py3.11/linux.txt @@ -370,7 +372,7 @@ packaging==24.0 # -c requirements/static/pkg/py3.11/linux.txt # -r requirements/base.txt # pytest -paramiko==3.4.0 +paramiko==4.0.0 # via # -c requirements/static/ci/py3.11/linux.txt # -r requirements/static/ci/common.in @@ -570,7 +572,7 @@ pyyaml==6.0.1 # kubernetes # pytest-salt-factories # responses - # yamlordereddictloader + # yamlloader pyzmq==25.1.2 # via # -c requirements/static/ci/py3.11/linux.txt @@ -643,7 +645,6 @@ six==1.16.0 # junos-eznc # kazoo # kubernetes - # ncclient # profitbricks # python-dateutil # pyvmomi @@ -766,7 +767,7 @@ xmltodict==0.13.0 # -c requirements/static/ci/py3.11/linux.txt # moto # pywinrm -yamlordereddictloader==0.4.0 +yamlloader==1.6.0 # via # -c requirements/static/ci/py3.11/linux.txt # junos-eznc diff --git a/requirements/static/ci/py3.11/darwin.txt b/requirements/static/ci/py3.11/darwin.txt index 0c73963ce52b..4a402e3f66e4 100644 --- a/requirements/static/ci/py3.11/darwin.txt +++ b/requirements/static/ci/py3.11/darwin.txt @@ -169,6 +169,8 @@ importlib-metadata==8.7.0 # -r requirements/base.txt iniconfig==2.0.0 # via pytest +invoke==2.2.1 + # via paramiko jaraco-collections==4.1.0 # via # -c requirements/static/pkg/py3.11/darwin.txt @@ -207,7 +209,7 @@ jsonschema==3.2.0 # via -r requirements/static/ci/common.in junit-xml==1.9 # via -r requirements/static/ci/common.in -junos-eznc==2.6.7 +junos-eznc==2.7.6 # via -r requirements/static/ci/common.in jxmlease==1.0.3 # via -r requirements/static/ci/common.in @@ -219,7 +221,7 @@ looseversion==1.3.0 # via # -c requirements/static/pkg/py3.11/darwin.txt # -r requirements/base.txt -lxml==4.9.2 +lxml==6.0.2 # via # junos-eznc # ncclient @@ -233,7 +235,7 @@ markupsafe==2.1.3 # jinja2 # mako # werkzeug -mercurial==6.0.1 +mercurial==7.2 # via -r requirements/static/ci/darwin.in mock==5.1.0 # via -r requirements/pytest.txt @@ -253,15 +255,15 @@ msgpack==1.0.7 # -c requirements/static/pkg/py3.11/darwin.txt # -r requirements/base.txt # pytest-salt-factories -multidict==6.0.4 +multidict==6.1.0 # via # -c requirements/static/pkg/py3.11/darwin.txt # aiohttp # yarl -ncclient==0.6.13 - # via junos-eznc -netaddr==0.8.0 - # via junos-eznc +ncclient==0.7.0 + # via + # -r requirements/static/ci/common.in + # junos-eznc oauthlib==3.3.1 # via requests-oauthlib oscrypto==1.3.0 @@ -271,7 +273,7 @@ packaging==24.0 # -c requirements/static/pkg/py3.11/darwin.txt # -r requirements/base.txt # pytest -paramiko==3.4.0 +paramiko==4.0.0 # via # junos-eznc # ncclient @@ -318,7 +320,7 @@ pycryptodomex==3.19.1 # -r requirements/crypto.txt pyfakefs==5.3.1 # via -r requirements/pytest.txt -pygit2==1.13.1 +pygit2==1.19.1 # via -r requirements/static/ci/darwin.in pynacl==1.5.0 # via @@ -409,7 +411,7 @@ pyyaml==6.0.1 # pytest-salt-factories # responses # yamllint - # yamlordereddictloader + # yamlloader pyzmq==25.1.2 # via # -c requirements/static/pkg/py3.11/darwin.txt @@ -453,7 +455,6 @@ six==1.16.0 # junit-xml # junos-eznc # kubernetes - # ncclient # python-dateutil # pyvmomi # textfsm @@ -536,7 +537,7 @@ xmltodict==0.13.0 # via moto yamllint==1.32.0 # via -r requirements/static/ci/darwin.in -yamlordereddictloader==0.4.0 +yamlloader==1.6.0 # via junos-eznc yarl==1.20.1 # via diff --git a/requirements/static/ci/py3.11/docs.txt b/requirements/static/ci/py3.11/docs.txt index 7e41a185b70b..4425a0a23b77 100644 --- a/requirements/static/ci/py3.11/docs.txt +++ b/requirements/static/ci/py3.11/docs.txt @@ -169,7 +169,7 @@ msgpack==1.0.7 # via # -c requirements/static/ci/py3.11/linux.txt # -r requirements/base.txt -multidict==6.0.4 +multidict==6.1.0 # via # -c requirements/static/ci/py3.11/linux.txt # aiohttp diff --git a/requirements/static/ci/py3.11/freebsd.txt b/requirements/static/ci/py3.11/freebsd.txt index 2d3e3b711873..b319ab1b9a7c 100644 --- a/requirements/static/ci/py3.11/freebsd.txt +++ b/requirements/static/ci/py3.11/freebsd.txt @@ -179,6 +179,8 @@ importlib-metadata==8.7.0 # -r requirements/static/pkg/freebsd.in iniconfig==2.0.0 # via pytest +invoke==2.2.1 ; sys_platform != 'win32' + # via paramiko jaraco-collections==4.1.0 # via # -c requirements/static/pkg/py3.11/freebsd.txt @@ -217,7 +219,7 @@ jsonschema==3.2.0 # via -r requirements/static/ci/common.in junit-xml==1.9 # via -r requirements/static/ci/common.in -junos-eznc==2.6.7 ; sys_platform != 'win32' +junos-eznc==2.7.6 ; sys_platform != 'win32' # via -r requirements/static/ci/common.in jxmlease==1.0.3 ; sys_platform != 'win32' # via -r requirements/static/ci/common.in @@ -249,7 +251,7 @@ markupsafe==2.1.3 # jinja2 # mako # werkzeug -mercurial==6.0.1 +mercurial==7.2 # via -r requirements/static/ci/freebsd.in mock==5.1.0 # via -r requirements/pytest.txt @@ -269,15 +271,15 @@ msgpack==1.1.2 # -c requirements/static/pkg/py3.11/freebsd.txt # -r requirements/base.txt # pytest-salt-factories -multidict==6.0.4 +multidict==6.1.0 # via # -c requirements/static/pkg/py3.11/freebsd.txt # aiohttp # yarl -ncclient==0.6.13 ; sys_platform != 'win32' - # via junos-eznc -netaddr==0.8.0 ; sys_platform != 'win32' - # via junos-eznc +ncclient==0.7.0 ; sys_platform != 'win32' + # via + # -r requirements/static/ci/common.in + # junos-eznc oauthlib==3.3.1 # via requests-oauthlib oscrypto==1.3.0 ; sys_platform != 'win32' @@ -287,7 +289,7 @@ packaging==24.0 # -c requirements/static/pkg/py3.11/freebsd.txt # -r requirements/base.txt # pytest -paramiko==3.4.0 ; sys_platform != 'win32' +paramiko==4.0.0 ; sys_platform != 'win32' # via # -r requirements/static/ci/common.in # junos-eznc @@ -449,7 +451,7 @@ pyyaml==6.0.1 # pytest-salt-factories # responses # yamllint - # yamlordereddictloader + # yamlloader pyzmq==27.1.0 # via # -c requirements/static/pkg/py3.11/freebsd.txt @@ -499,7 +501,6 @@ six==1.16.0 # junos-eznc # kazoo # kubernetes - # ncclient # python-dateutil # pyvmomi # textfsm @@ -590,7 +591,7 @@ xmltodict==1.0.4 # moto yamllint==1.32.0 # via -r requirements/static/ci/freebsd.in -yamlordereddictloader==0.4.0 ; sys_platform != 'win32' +yamlloader==1.6.0 ; sys_platform != 'win32' # via junos-eznc yarl==1.20.1 # via diff --git a/requirements/static/ci/py3.11/lint.txt b/requirements/static/ci/py3.11/lint.txt index 02f477da4f74..146e23a375df 100644 --- a/requirements/static/ci/py3.11/lint.txt +++ b/requirements/static/ci/py3.11/lint.txt @@ -246,6 +246,10 @@ importlib-metadata==8.7.0 # -c requirements/static/pkg/py3.11/linux.txt # -r requirements/base.txt # -r requirements/static/pkg/linux.in +invoke==2.2.1 + # via + # -c requirements/static/ci/py3.11/linux.txt + # paramiko isort==4.3.21 # via pylint jaraco-collections==4.1.0 @@ -297,7 +301,7 @@ junit-xml==1.9 # via # -c requirements/static/ci/py3.11/linux.txt # -r requirements/static/ci/common.in -junos-eznc==2.6.7 +junos-eznc==2.7.6 # via # -c requirements/static/ci/py3.11/linux.txt # -r requirements/static/ci/common.in @@ -326,7 +330,7 @@ looseversion==1.3.0 # -c requirements/static/ci/py3.11/linux.txt # -c requirements/static/pkg/py3.11/linux.txt # -r requirements/base.txt -lxml==4.9.2 +lxml==6.0.2 # via # -c requirements/static/ci/py3.11/linux.txt # junos-eznc @@ -346,7 +350,7 @@ markupsafe==2.1.3 # werkzeug mccabe==0.6.1 # via pylint -mercurial==6.0.1 +mercurial==7.2 # via # -c requirements/static/ci/py3.11/linux.txt # -r requirements/static/ci/linux.in @@ -369,19 +373,16 @@ msgpack==1.0.7 # -c requirements/static/ci/py3.11/linux.txt # -c requirements/static/pkg/py3.11/linux.txt # -r requirements/base.txt -multidict==6.0.4 +multidict==6.1.0 # via # -c requirements/static/ci/py3.11/linux.txt # -c requirements/static/pkg/py3.11/linux.txt # aiohttp # yarl -ncclient==0.6.13 - # via - # -c requirements/static/ci/py3.11/linux.txt - # junos-eznc -netaddr==0.8.0 +ncclient==0.7.0 # via # -c requirements/static/ci/py3.11/linux.txt + # -r requirements/static/ci/common.in # junos-eznc oauthlib==3.3.1 # via @@ -397,7 +398,7 @@ packaging==24.0 # -c requirements/static/pkg/py3.11/linux.txt # -r requirements/base.txt # ansible-core -paramiko==3.4.0 +paramiko==4.0.0 # via # -c requirements/static/ci/py3.11/linux.txt # -r requirements/static/ci/common.in @@ -452,7 +453,7 @@ pycryptodomex==3.19.1 # -c requirements/static/ci/py3.11/linux.txt # -c requirements/static/pkg/py3.11/linux.txt # -r requirements/crypto.txt -pygit2==1.13.1 +pygit2==1.19.1 # via # -c requirements/static/ci/py3.11/linux.txt # -r requirements/static/ci/linux.in @@ -556,7 +557,7 @@ pyyaml==6.0.1 # kubernetes # responses # yamllint - # yamlordereddictloader + # yamlloader pyzmq==25.1.2 # via # -c requirements/static/ci/py3.11/linux.txt @@ -639,7 +640,6 @@ six==1.16.0 # junos-eznc # kazoo # kubernetes - # ncclient # python-consul # python-dateutil # pyvmomi @@ -774,7 +774,7 @@ yamllint==1.32.0 # via # -c requirements/static/ci/py3.11/linux.txt # -r requirements/static/ci/linux.in -yamlordereddictloader==0.4.0 +yamlloader==1.6.0 # via # -c requirements/static/ci/py3.11/linux.txt # junos-eznc diff --git a/requirements/static/ci/py3.11/linux.txt b/requirements/static/ci/py3.11/linux.txt index 582578864518..fad5a3f421f9 100644 --- a/requirements/static/ci/py3.11/linux.txt +++ b/requirements/static/ci/py3.11/linux.txt @@ -188,6 +188,8 @@ importlib-metadata==8.7.0 # -r requirements/base.txt iniconfig==2.0.0 # via pytest +invoke==2.2.1 + # via paramiko jaraco-collections==4.1.0 # via # -c requirements/static/pkg/py3.11/linux.txt @@ -227,7 +229,7 @@ jsonschema==3.2.0 # via -r requirements/static/ci/common.in junit-xml==1.9 # via -r requirements/static/ci/common.in -junos-eznc==2.6.7 +junos-eznc==2.7.6 # via -r requirements/static/ci/common.in jxmlease==1.0.3 # via -r requirements/static/ci/common.in @@ -243,7 +245,7 @@ looseversion==1.3.0 # via # -c requirements/static/pkg/py3.11/linux.txt # -r requirements/base.txt -lxml==4.9.2 +lxml==6.0.2 # via # junos-eznc # ncclient @@ -257,7 +259,7 @@ markupsafe==2.1.3 # jinja2 # mako # werkzeug -mercurial==6.0.1 +mercurial==7.2 # via -r requirements/static/ci/linux.in mock==5.1.0 # via -r requirements/pytest.txt @@ -277,15 +279,15 @@ msgpack==1.0.7 # -c requirements/static/pkg/py3.11/linux.txt # -r requirements/base.txt # pytest-salt-factories -multidict==6.0.4 +multidict==6.1.0 # via # -c requirements/static/pkg/py3.11/linux.txt # aiohttp # yarl -ncclient==0.6.13 - # via junos-eznc -netaddr==0.8.0 - # via junos-eznc +ncclient==0.7.0 + # via + # -r requirements/static/ci/common.in + # junos-eznc oauthlib==3.3.1 # via requests-oauthlib oscrypto==1.3.0 @@ -296,7 +298,7 @@ packaging==24.0 # -r requirements/base.txt # ansible-core # pytest -paramiko==3.4.0 +paramiko==4.0.0 # via # -r requirements/static/ci/common.in # junos-eznc @@ -344,7 +346,7 @@ pycryptodomex==3.19.1 # -r requirements/crypto.txt pyfakefs==5.3.1 # via -r requirements/pytest.txt -pygit2==1.13.1 +pygit2==1.19.1 # via -r requirements/static/ci/linux.in pyiface==0.0.11 # via -r requirements/static/ci/linux.in @@ -449,7 +451,7 @@ pyyaml==6.0.1 # pytest-salt-factories # responses # yamllint - # yamlordereddictloader + # yamlloader pyzmq==25.1.2 # via # -c requirements/static/pkg/py3.11/linux.txt @@ -506,7 +508,6 @@ six==1.16.0 # junos-eznc # kazoo # kubernetes - # ncclient # python-consul # python-dateutil # pyvmomi @@ -601,7 +602,7 @@ xmltodict==0.13.0 # via moto yamllint==1.32.0 # via -r requirements/static/ci/linux.in -yamlordereddictloader==0.4.0 +yamlloader==1.6.0 # via junos-eznc yarl==1.20.1 # via diff --git a/requirements/static/ci/py3.11/windows.txt b/requirements/static/ci/py3.11/windows.txt index 28bf09af259f..545c6a203511 100644 --- a/requirements/static/ci/py3.11/windows.txt +++ b/requirements/static/ci/py3.11/windows.txt @@ -253,7 +253,7 @@ msgpack==1.1.2 # -c requirements/static/pkg/py3.11/windows.txt # -r requirements/base.txt # pytest-salt-factories -multidict==6.7.1 +multidict==6.1.0 # via # -c requirements/static/pkg/py3.11/windows.txt # aiohttp @@ -309,7 +309,7 @@ pycryptodomex==3.23.0 # -r requirements/crypto.txt pyfakefs==5.3.1 # via -r requirements/pytest.txt -pygit2==1.13.1 +pygit2==1.19.1 # via -r requirements/static/ci/windows.in pygments==2.19.2 # via diff --git a/requirements/static/ci/py3.12/cloud.txt b/requirements/static/ci/py3.12/cloud.txt index 5a4dbfe58f58..7aa86f4c1904 100644 --- a/requirements/static/ci/py3.12/cloud.txt +++ b/requirements/static/ci/py3.12/cloud.txt @@ -216,6 +216,10 @@ iniconfig==2.0.0 # via # -c requirements/static/ci/py3.12/linux.txt # pytest +invoke==2.2.1 + # via + # -c requirements/static/ci/py3.12/linux.txt + # paramiko jaraco-collections==4.1.0 # via # -c requirements/static/ci/py3.12/linux.txt @@ -264,7 +268,7 @@ junit-xml==1.9 # via # -c requirements/static/ci/py3.12/linux.txt # -r requirements/static/ci/common.in -junos-eznc==2.6.7 +junos-eznc==2.7.6 # via # -c requirements/static/ci/py3.12/linux.txt # -r requirements/static/ci/common.in @@ -293,7 +297,7 @@ looseversion==1.3.0 # -c requirements/static/ci/py3.12/linux.txt # -c requirements/static/pkg/py3.12/linux.txt # -r requirements/base.txt -lxml==4.9.2 +lxml==6.0.2 # via # -c requirements/static/ci/py3.12/linux.txt # junos-eznc @@ -336,21 +340,19 @@ msgpack==1.0.7 # -c requirements/static/pkg/py3.12/linux.txt # -r requirements/base.txt # pytest-salt-factories -multidict==6.0.4 +multidict==6.1.0 # via # -c requirements/static/ci/py3.12/linux.txt # -c requirements/static/pkg/py3.12/linux.txt # aiohttp # yarl -ncclient==0.6.13 +ncclient==0.7.0 # via # -c requirements/static/ci/py3.12/linux.txt + # -r requirements/static/ci/common.in # junos-eznc netaddr==0.8.0 - # via - # -c requirements/static/ci/py3.12/linux.txt - # -r requirements/static/ci/cloud.in - # junos-eznc + # via -r requirements/static/ci/cloud.in oauthlib==3.3.1 # via # -c requirements/static/ci/py3.12/linux.txt @@ -365,7 +367,7 @@ packaging==24.0 # -c requirements/static/pkg/py3.12/linux.txt # -r requirements/base.txt # pytest -paramiko==3.4.0 +paramiko==4.0.0 # via # -c requirements/static/ci/py3.12/linux.txt # -r requirements/static/ci/common.in @@ -565,7 +567,7 @@ pyyaml==6.0.1 # kubernetes # pytest-salt-factories # responses - # yamlordereddictloader + # yamlloader pyzmq==25.1.2 # via # -c requirements/static/ci/py3.12/linux.txt @@ -638,7 +640,6 @@ six==1.16.0 # junos-eznc # kazoo # kubernetes - # ncclient # profitbricks # python-dateutil # pyvmomi @@ -761,7 +762,7 @@ xmltodict==0.13.0 # -c requirements/static/ci/py3.12/linux.txt # moto # pywinrm -yamlordereddictloader==0.4.0 +yamlloader==1.6.0 # via # -c requirements/static/ci/py3.12/linux.txt # junos-eznc diff --git a/requirements/static/ci/py3.12/darwin.txt b/requirements/static/ci/py3.12/darwin.txt index 04495d5eda4b..4bcbf1d47c41 100644 --- a/requirements/static/ci/py3.12/darwin.txt +++ b/requirements/static/ci/py3.12/darwin.txt @@ -165,6 +165,8 @@ importlib-metadata==8.7.0 # -r requirements/base.txt iniconfig==2.0.0 # via pytest +invoke==2.2.1 + # via paramiko jaraco-collections==4.1.0 # via # -c requirements/static/pkg/py3.12/darwin.txt @@ -203,7 +205,7 @@ jsonschema==3.2.0 # via -r requirements/static/ci/common.in junit-xml==1.9 # via -r requirements/static/ci/common.in -junos-eznc==2.6.7 +junos-eznc==2.7.6 # via -r requirements/static/ci/common.in jxmlease==1.0.3 # via -r requirements/static/ci/common.in @@ -215,7 +217,7 @@ looseversion==1.3.0 # via # -c requirements/static/pkg/py3.12/darwin.txt # -r requirements/base.txt -lxml==4.9.2 +lxml==6.0.2 # via # junos-eznc # ncclient @@ -229,7 +231,7 @@ markupsafe==2.1.3 # jinja2 # mako # werkzeug -mercurial==6.0.1 +mercurial==7.2 # via -r requirements/static/ci/darwin.in mock==5.1.0 # via -r requirements/pytest.txt @@ -249,15 +251,15 @@ msgpack==1.0.7 # -c requirements/static/pkg/py3.12/darwin.txt # -r requirements/base.txt # pytest-salt-factories -multidict==6.0.4 +multidict==6.1.0 # via # -c requirements/static/pkg/py3.12/darwin.txt # aiohttp # yarl -ncclient==0.6.13 - # via junos-eznc -netaddr==0.8.0 - # via junos-eznc +ncclient==0.7.0 + # via + # -r requirements/static/ci/common.in + # junos-eznc oauthlib==3.3.1 # via requests-oauthlib oscrypto==1.3.0 @@ -267,7 +269,7 @@ packaging==24.0 # -c requirements/static/pkg/py3.12/darwin.txt # -r requirements/base.txt # pytest -paramiko==3.4.0 +paramiko==4.0.0 # via # junos-eznc # ncclient @@ -314,7 +316,7 @@ pycryptodomex==3.19.1 # -r requirements/crypto.txt pyfakefs==5.3.1 # via -r requirements/pytest.txt -pygit2==1.13.1 +pygit2==1.19.1 # via -r requirements/static/ci/darwin.in pynacl==1.5.0 # via @@ -405,7 +407,7 @@ pyyaml==6.0.1 # pytest-salt-factories # responses # yamllint - # yamlordereddictloader + # yamlloader pyzmq==25.1.2 # via # -c requirements/static/pkg/py3.12/darwin.txt @@ -449,7 +451,6 @@ six==1.16.0 # junit-xml # junos-eznc # kubernetes - # ncclient # python-dateutil # pyvmomi # textfsm @@ -532,7 +533,7 @@ xmltodict==0.13.0 # via moto yamllint==1.32.0 # via -r requirements/static/ci/darwin.in -yamlordereddictloader==0.4.0 +yamlloader==1.6.0 # via junos-eznc yarl==1.20.1 # via diff --git a/requirements/static/ci/py3.12/docs.txt b/requirements/static/ci/py3.12/docs.txt index 4ccb967d5125..aff76b0f242f 100644 --- a/requirements/static/ci/py3.12/docs.txt +++ b/requirements/static/ci/py3.12/docs.txt @@ -165,7 +165,7 @@ msgpack==1.0.7 # via # -c requirements/static/ci/py3.12/linux.txt # -r requirements/base.txt -multidict==6.0.4 +multidict==6.1.0 # via # -c requirements/static/ci/py3.12/linux.txt # aiohttp diff --git a/requirements/static/ci/py3.12/freebsd.txt b/requirements/static/ci/py3.12/freebsd.txt index 87d254484423..b2e48a617832 100644 --- a/requirements/static/ci/py3.12/freebsd.txt +++ b/requirements/static/ci/py3.12/freebsd.txt @@ -175,6 +175,8 @@ importlib-metadata==8.7.0 # -r requirements/static/pkg/freebsd.in iniconfig==2.0.0 # via pytest +invoke==2.2.1 ; sys_platform != 'win32' + # via paramiko jaraco-collections==4.1.0 # via # -c requirements/static/pkg/py3.12/freebsd.txt @@ -213,7 +215,7 @@ jsonschema==3.2.0 # via -r requirements/static/ci/common.in junit-xml==1.9 # via -r requirements/static/ci/common.in -junos-eznc==2.6.7 ; sys_platform != 'win32' +junos-eznc==2.7.6 ; sys_platform != 'win32' # via -r requirements/static/ci/common.in jxmlease==1.0.3 ; sys_platform != 'win32' # via -r requirements/static/ci/common.in @@ -245,7 +247,7 @@ markupsafe==2.1.3 # jinja2 # mako # werkzeug -mercurial==6.0.1 +mercurial==7.2 # via -r requirements/static/ci/freebsd.in mock==5.1.0 # via -r requirements/pytest.txt @@ -265,15 +267,15 @@ msgpack==1.1.2 # -c requirements/static/pkg/py3.12/freebsd.txt # -r requirements/base.txt # pytest-salt-factories -multidict==6.0.4 +multidict==6.1.0 # via # -c requirements/static/pkg/py3.12/freebsd.txt # aiohttp # yarl -ncclient==0.6.13 ; sys_platform != 'win32' - # via junos-eznc -netaddr==0.8.0 ; sys_platform != 'win32' - # via junos-eznc +ncclient==0.7.0 ; sys_platform != 'win32' + # via + # -r requirements/static/ci/common.in + # junos-eznc oauthlib==3.3.1 # via requests-oauthlib oscrypto==1.3.0 ; sys_platform != 'win32' @@ -283,7 +285,7 @@ packaging==24.0 # -c requirements/static/pkg/py3.12/freebsd.txt # -r requirements/base.txt # pytest -paramiko==3.4.0 ; sys_platform != 'win32' +paramiko==4.0.0 ; sys_platform != 'win32' # via # -r requirements/static/ci/common.in # junos-eznc @@ -445,7 +447,7 @@ pyyaml==6.0.1 # pytest-salt-factories # responses # yamllint - # yamlordereddictloader + # yamlloader pyzmq==27.1.0 # via # -c requirements/static/pkg/py3.12/freebsd.txt @@ -495,7 +497,6 @@ six==1.16.0 # junos-eznc # kazoo # kubernetes - # ncclient # python-dateutil # pyvmomi # textfsm @@ -586,7 +587,7 @@ xmltodict==1.0.4 # moto yamllint==1.32.0 # via -r requirements/static/ci/freebsd.in -yamlordereddictloader==0.4.0 ; sys_platform != 'win32' +yamlloader==1.6.0 ; sys_platform != 'win32' # via junos-eznc yarl==1.20.1 # via diff --git a/requirements/static/ci/py3.12/lint.txt b/requirements/static/ci/py3.12/lint.txt index f8e2658e3166..0d19f8def12e 100644 --- a/requirements/static/ci/py3.12/lint.txt +++ b/requirements/static/ci/py3.12/lint.txt @@ -241,6 +241,10 @@ importlib-metadata==8.7.0 # -c requirements/static/pkg/py3.12/linux.txt # -r requirements/base.txt # -r requirements/static/pkg/linux.in +invoke==2.2.1 + # via + # -c requirements/static/ci/py3.12/linux.txt + # paramiko isort==4.3.21 # via pylint jaraco-collections==4.1.0 @@ -292,7 +296,7 @@ junit-xml==1.9 # via # -c requirements/static/ci/py3.12/linux.txt # -r requirements/static/ci/common.in -junos-eznc==2.6.7 +junos-eznc==2.7.6 # via # -c requirements/static/ci/py3.12/linux.txt # -r requirements/static/ci/common.in @@ -321,7 +325,7 @@ looseversion==1.3.0 # -c requirements/static/ci/py3.12/linux.txt # -c requirements/static/pkg/py3.12/linux.txt # -r requirements/base.txt -lxml==4.9.2 +lxml==6.0.2 # via # -c requirements/static/ci/py3.12/linux.txt # junos-eznc @@ -341,7 +345,7 @@ markupsafe==2.1.3 # werkzeug mccabe==0.6.1 # via pylint -mercurial==6.0.1 +mercurial==7.2 # via # -c requirements/static/ci/py3.12/linux.txt # -r requirements/static/ci/linux.in @@ -364,19 +368,16 @@ msgpack==1.0.7 # -c requirements/static/ci/py3.12/linux.txt # -c requirements/static/pkg/py3.12/linux.txt # -r requirements/base.txt -multidict==6.0.4 +multidict==6.1.0 # via # -c requirements/static/ci/py3.12/linux.txt # -c requirements/static/pkg/py3.12/linux.txt # aiohttp # yarl -ncclient==0.6.13 - # via - # -c requirements/static/ci/py3.12/linux.txt - # junos-eznc -netaddr==0.8.0 +ncclient==0.7.0 # via # -c requirements/static/ci/py3.12/linux.txt + # -r requirements/static/ci/common.in # junos-eznc oauthlib==3.3.1 # via @@ -392,7 +393,7 @@ packaging==24.0 # -c requirements/static/pkg/py3.12/linux.txt # -r requirements/base.txt # ansible-core -paramiko==3.4.0 +paramiko==4.0.0 # via # -c requirements/static/ci/py3.12/linux.txt # -r requirements/static/ci/common.in @@ -447,7 +448,7 @@ pycryptodomex==3.19.1 # -c requirements/static/ci/py3.12/linux.txt # -c requirements/static/pkg/py3.12/linux.txt # -r requirements/crypto.txt -pygit2==1.13.1 +pygit2==1.19.1 # via # -c requirements/static/ci/py3.12/linux.txt # -r requirements/static/ci/linux.in @@ -551,7 +552,7 @@ pyyaml==6.0.1 # kubernetes # responses # yamllint - # yamlordereddictloader + # yamlloader pyzmq==25.1.2 # via # -c requirements/static/ci/py3.12/linux.txt @@ -634,7 +635,6 @@ six==1.16.0 # junos-eznc # kazoo # kubernetes - # ncclient # python-consul # python-dateutil # pyvmomi @@ -769,7 +769,7 @@ yamllint==1.32.0 # via # -c requirements/static/ci/py3.12/linux.txt # -r requirements/static/ci/linux.in -yamlordereddictloader==0.4.0 +yamlloader==1.6.0 # via # -c requirements/static/ci/py3.12/linux.txt # junos-eznc diff --git a/requirements/static/ci/py3.12/linux.txt b/requirements/static/ci/py3.12/linux.txt index 94948773e8b3..0e5f8a66ca40 100644 --- a/requirements/static/ci/py3.12/linux.txt +++ b/requirements/static/ci/py3.12/linux.txt @@ -184,6 +184,8 @@ importlib-metadata==8.7.0 # -r requirements/base.txt iniconfig==2.0.0 # via pytest +invoke==2.2.1 + # via paramiko jaraco-collections==4.1.0 # via # -c requirements/static/pkg/py3.12/linux.txt @@ -223,7 +225,7 @@ jsonschema==3.2.0 # via -r requirements/static/ci/common.in junit-xml==1.9 # via -r requirements/static/ci/common.in -junos-eznc==2.6.7 +junos-eznc==2.7.6 # via -r requirements/static/ci/common.in jxmlease==1.0.3 # via -r requirements/static/ci/common.in @@ -239,7 +241,7 @@ looseversion==1.3.0 # via # -c requirements/static/pkg/py3.12/linux.txt # -r requirements/base.txt -lxml==4.9.2 +lxml==6.0.2 # via # junos-eznc # ncclient @@ -253,7 +255,7 @@ markupsafe==2.1.3 # jinja2 # mako # werkzeug -mercurial==6.0.1 +mercurial==7.2 # via -r requirements/static/ci/linux.in mock==5.1.0 # via -r requirements/pytest.txt @@ -273,15 +275,15 @@ msgpack==1.0.7 # -c requirements/static/pkg/py3.12/linux.txt # -r requirements/base.txt # pytest-salt-factories -multidict==6.0.4 +multidict==6.1.0 # via # -c requirements/static/pkg/py3.12/linux.txt # aiohttp # yarl -ncclient==0.6.13 - # via junos-eznc -netaddr==0.8.0 - # via junos-eznc +ncclient==0.7.0 + # via + # -r requirements/static/ci/common.in + # junos-eznc oauthlib==3.3.1 # via requests-oauthlib oscrypto==1.3.0 @@ -292,7 +294,7 @@ packaging==24.0 # -r requirements/base.txt # ansible-core # pytest -paramiko==3.4.0 +paramiko==4.0.0 # via # -r requirements/static/ci/common.in # junos-eznc @@ -340,7 +342,7 @@ pycryptodomex==3.19.1 # -r requirements/crypto.txt pyfakefs==5.3.1 # via -r requirements/pytest.txt -pygit2==1.13.1 +pygit2==1.19.1 # via -r requirements/static/ci/linux.in pyiface==0.0.11 # via -r requirements/static/ci/linux.in @@ -445,7 +447,7 @@ pyyaml==6.0.1 # pytest-salt-factories # responses # yamllint - # yamlordereddictloader + # yamlloader pyzmq==25.1.2 # via # -c requirements/static/pkg/py3.12/linux.txt @@ -502,7 +504,6 @@ six==1.16.0 # junos-eznc # kazoo # kubernetes - # ncclient # python-consul # python-dateutil # pyvmomi @@ -597,7 +598,7 @@ xmltodict==0.13.0 # via moto yamllint==1.32.0 # via -r requirements/static/ci/linux.in -yamlordereddictloader==0.4.0 +yamlloader==1.6.0 # via junos-eznc yarl==1.20.1 # via diff --git a/requirements/static/ci/py3.12/windows.txt b/requirements/static/ci/py3.12/windows.txt index 397f9e083d05..e93997fe0904 100644 --- a/requirements/static/ci/py3.12/windows.txt +++ b/requirements/static/ci/py3.12/windows.txt @@ -247,7 +247,7 @@ msgpack==1.1.2 # -c requirements/static/pkg/py3.12/windows.txt # -r requirements/base.txt # pytest-salt-factories -multidict==6.7.1 +multidict==6.1.0 # via # -c requirements/static/pkg/py3.12/windows.txt # aiohttp @@ -303,7 +303,7 @@ pycryptodomex==3.23.0 # -r requirements/crypto.txt pyfakefs==5.3.1 # via -r requirements/pytest.txt -pygit2==1.13.1 +pygit2==1.19.1 # via -r requirements/static/ci/windows.in pygments==2.19.2 # via diff --git a/requirements/static/ci/py3.13/cloud.txt b/requirements/static/ci/py3.13/cloud.txt index f05a5ca8a6d0..421578fcb3e1 100644 --- a/requirements/static/ci/py3.13/cloud.txt +++ b/requirements/static/ci/py3.13/cloud.txt @@ -299,7 +299,7 @@ looseversion==1.3.0 # -c requirements/static/ci/py3.13/linux.txt # -c requirements/static/pkg/py3.13/linux.txt # -r requirements/base.txt -lxml==5.3.0 +lxml==6.0.2 # via # -c requirements/static/ci/py3.13/linux.txt # junos-eznc @@ -351,6 +351,7 @@ multidict==6.1.0 ncclient==0.6.16 # via # -c requirements/static/ci/py3.13/linux.txt + # -r requirements/static/ci/common.in # junos-eznc netaddr==1.3.0 # via -r requirements/static/ci/cloud.in diff --git a/requirements/static/ci/py3.13/darwin.txt b/requirements/static/ci/py3.13/darwin.txt index 9685edcea1d5..5679cfc44737 100644 --- a/requirements/static/ci/py3.13/darwin.txt +++ b/requirements/static/ci/py3.13/darwin.txt @@ -219,7 +219,7 @@ looseversion==1.3.0 # via # -c requirements/static/pkg/py3.13/darwin.txt # -r requirements/base.txt -lxml==5.3.0 +lxml==6.0.2 # via # junos-eznc # ncclient @@ -259,7 +259,9 @@ multidict==6.1.0 # aiohttp # yarl ncclient==0.6.16 - # via junos-eznc + # via + # -r requirements/static/ci/common.in + # junos-eznc oauthlib==3.3.1 # via requests-oauthlib oscrypto==1.3.0 diff --git a/requirements/static/ci/py3.13/freebsd.txt b/requirements/static/ci/py3.13/freebsd.txt index 7e5fca466c97..7bb5a25c1d43 100644 --- a/requirements/static/ci/py3.13/freebsd.txt +++ b/requirements/static/ci/py3.13/freebsd.txt @@ -270,7 +270,9 @@ multidict==6.1.0 # aiohttp # yarl ncclient==0.6.16 ; sys_platform != 'win32' - # via junos-eznc + # via + # -r requirements/static/ci/common.in + # junos-eznc oauthlib==3.3.1 # via requests-oauthlib oscrypto==1.3.0 ; sys_platform != 'win32' diff --git a/requirements/static/ci/py3.13/lint.txt b/requirements/static/ci/py3.13/lint.txt index f4d99db1356c..39590e04abb4 100644 --- a/requirements/static/ci/py3.13/lint.txt +++ b/requirements/static/ci/py3.13/lint.txt @@ -326,7 +326,7 @@ looseversion==1.3.0 # -c requirements/static/ci/py3.13/linux.txt # -c requirements/static/pkg/py3.13/linux.txt # -r requirements/base.txt -lxml==5.3.0 +lxml==6.0.2 # via # -c requirements/static/ci/py3.13/linux.txt # junos-eznc @@ -378,6 +378,7 @@ multidict==6.1.0 ncclient==0.6.16 # via # -c requirements/static/ci/py3.13/linux.txt + # -r requirements/static/ci/common.in # junos-eznc oauthlib==3.3.1 # via diff --git a/requirements/static/ci/py3.13/linux.txt b/requirements/static/ci/py3.13/linux.txt index f345c9f6c4cc..602ae3a5ef6f 100644 --- a/requirements/static/ci/py3.13/linux.txt +++ b/requirements/static/ci/py3.13/linux.txt @@ -243,7 +243,7 @@ looseversion==1.3.0 # via # -c requirements/static/pkg/py3.13/linux.txt # -r requirements/base.txt -lxml==5.3.0 +lxml==6.0.2 # via # junos-eznc # ncclient @@ -283,7 +283,9 @@ multidict==6.1.0 # aiohttp # yarl ncclient==0.6.16 - # via junos-eznc + # via + # -r requirements/static/ci/common.in + # junos-eznc oauthlib==3.3.1 # via requests-oauthlib oscrypto==1.3.0 diff --git a/requirements/static/ci/py3.13/windows.txt b/requirements/static/ci/py3.13/windows.txt index 391c24099ed6..812d6d802383 100644 --- a/requirements/static/ci/py3.13/windows.txt +++ b/requirements/static/ci/py3.13/windows.txt @@ -246,7 +246,7 @@ msgpack==1.1.2 # -c requirements/static/pkg/py3.13/windows.txt # -r requirements/base.txt # pytest-salt-factories -multidict==6.7.1 +multidict==6.1.0 # via # -c requirements/static/pkg/py3.13/windows.txt # aiohttp diff --git a/requirements/static/ci/py3.8/freebsd.txt b/requirements/static/ci/py3.8/freebsd.txt index 9921ec097cb8..af1c8b06e326 100644 --- a/requirements/static/ci/py3.8/freebsd.txt +++ b/requirements/static/ci/py3.8/freebsd.txt @@ -269,7 +269,7 @@ msgpack==1.0.7 ; python_version < "3.13" # -c requirements/static/ci/../pkg/py3.8/freebsd.txt # -r requirements/base.txt # pytest-salt-factories -multidict==6.0.4 +multidict==6.1.0 # via # -c requirements/static/ci/../pkg/py3.8/freebsd.txt # aiohttp diff --git a/requirements/static/ci/py3.8/linux.txt b/requirements/static/ci/py3.8/linux.txt index 5a20445803f1..733d1fbddc0e 100644 --- a/requirements/static/ci/py3.8/linux.txt +++ b/requirements/static/ci/py3.8/linux.txt @@ -288,7 +288,7 @@ msgpack==1.0.7 ; python_version < "3.13" # -c requirements/static/ci/../pkg/py3.8/linux.txt # -r requirements/base.txt # pytest-salt-factories -multidict==6.0.4 +multidict==6.1.0 # via # -c requirements/static/ci/../pkg/py3.8/linux.txt # aiohttp diff --git a/requirements/static/ci/py3.8/windows.txt b/requirements/static/ci/py3.8/windows.txt index 15ab3ff63767..c1596a3be20d 100644 --- a/requirements/static/ci/py3.8/windows.txt +++ b/requirements/static/ci/py3.8/windows.txt @@ -252,7 +252,7 @@ msgpack==1.0.7 ; python_version < "3.13" # -c requirements/static/ci/../pkg/py3.8/windows.txt # -r requirements/base.txt # pytest-salt-factories -multidict==6.0.4 +multidict==6.1.0 # via # -c requirements/static/ci/../pkg/py3.8/windows.txt # aiohttp diff --git a/requirements/static/ci/py3.9/cloud.txt b/requirements/static/ci/py3.9/cloud.txt index e651184fe2ad..041ffa9d05f9 100644 --- a/requirements/static/ci/py3.9/cloud.txt +++ b/requirements/static/ci/py3.9/cloud.txt @@ -241,6 +241,10 @@ iniconfig==2.0.0 # via # -c requirements/static/ci/py3.9/linux.txt # pytest +invoke==2.2.1 + # via + # -c requirements/static/ci/py3.9/linux.txt + # paramiko jaraco-collections==4.1.0 # via # -c requirements/static/ci/py3.9/linux.txt @@ -290,7 +294,7 @@ junit-xml==1.9 # via # -c requirements/static/ci/py3.9/linux.txt # -r requirements/static/ci/common.in -junos-eznc==2.6.7 +junos-eznc==2.7.6 # via # -c requirements/static/ci/py3.9/linux.txt # -r requirements/static/ci/common.in @@ -320,7 +324,7 @@ looseversion==1.3.0 # -c requirements/static/ci/py3.9/linux.txt # -c requirements/static/pkg/py3.9/linux.txt # -r requirements/base.txt -lxml==4.9.2 +lxml==6.0.2 # via # -c requirements/static/ci/py3.9/linux.txt # junos-eznc @@ -364,7 +368,7 @@ msgpack==1.0.7 # -c requirements/static/pkg/py3.9/linux.txt # -r requirements/base.txt # pytest-salt-factories -multidict==6.7.1 +multidict==6.1.0 # via # -c requirements/static/ci/py3.9/linux.txt # -c requirements/static/pkg/py3.9/linux.txt @@ -374,16 +378,16 @@ napalm==4.1.0 # via # -c requirements/static/ci/py3.9/linux.txt # -r requirements/static/ci/common.in -ncclient==0.6.13 +ncclient==0.7.0 # via # -c requirements/static/ci/py3.9/linux.txt + # -r requirements/static/ci/common.in # junos-eznc # napalm netaddr==0.8.0 # via # -c requirements/static/ci/py3.9/linux.txt # -r requirements/static/ci/cloud.in - # junos-eznc # napalm # pyeapi netmiko==4.2.0 @@ -412,7 +416,7 @@ packaging==24.0 # -c requirements/static/pkg/py3.9/linux.txt # -r requirements/base.txt # pytest -paramiko==3.4.0 +paramiko==4.0.0 # via # -c requirements/static/ci/py3.9/linux.txt # -r requirements/static/ci/common.in @@ -628,7 +632,7 @@ pyyaml==6.0.1 # netmiko # pytest-salt-factories # responses - # yamlordereddictloader + # yamlloader pyzmq==25.1.2 # via # -c requirements/static/ci/py3.9/linux.txt @@ -708,7 +712,6 @@ six==1.16.0 # junos-eznc # kazoo # kubernetes - # ncclient # profitbricks # python-dateutil # pyvmomi @@ -849,7 +852,7 @@ xmltodict==0.13.0 # -c requirements/static/ci/py3.9/linux.txt # moto # pywinrm -yamlordereddictloader==0.4.0 +yamlloader==1.6.0 # via # -c requirements/static/ci/py3.9/linux.txt # junos-eznc diff --git a/requirements/static/ci/py3.9/darwin.txt b/requirements/static/ci/py3.9/darwin.txt index 6684a383c374..33ce91d1a6b4 100644 --- a/requirements/static/ci/py3.9/darwin.txt +++ b/requirements/static/ci/py3.9/darwin.txt @@ -183,6 +183,8 @@ importlib-metadata==8.7.0 # -r requirements/base.txt iniconfig==2.0.0 # via pytest +invoke==2.2.1 + # via paramiko jaraco-collections==4.1.0 # via # -c requirements/static/pkg/py3.9/darwin.txt @@ -222,7 +224,7 @@ jsonschema==3.2.0 # via -r requirements/static/ci/common.in junit-xml==1.9 # via -r requirements/static/ci/common.in -junos-eznc==2.6.7 +junos-eznc==2.7.6 # via # -r requirements/static/ci/common.in # napalm @@ -236,7 +238,7 @@ looseversion==1.3.0 # via # -c requirements/static/pkg/py3.9/darwin.txt # -r requirements/base.txt -lxml==4.9.2 +lxml==6.0.2 # via # junos-eznc # napalm @@ -251,7 +253,7 @@ markupsafe==2.1.3 # jinja2 # mako # werkzeug -mercurial==6.4.4 +mercurial==7.2 # via -r requirements/static/ci/darwin.in mock==5.1.0 # via -r requirements/pytest.txt @@ -271,20 +273,20 @@ msgpack==1.0.7 # -c requirements/static/pkg/py3.9/darwin.txt # -r requirements/base.txt # pytest-salt-factories -multidict==6.7.1 +multidict==6.1.0 # via # -c requirements/static/pkg/py3.9/darwin.txt # aiohttp # yarl napalm==4.1.0 # via -r requirements/static/ci/common.in -ncclient==0.6.13 +ncclient==0.7.0 # via + # -r requirements/static/ci/common.in # junos-eznc # napalm netaddr==0.8.0 # via - # junos-eznc # napalm # pyeapi netmiko==4.2.0 @@ -302,7 +304,7 @@ packaging==24.0 # -c requirements/static/pkg/py3.9/darwin.txt # -r requirements/base.txt # pytest -paramiko==3.4.0 +paramiko==4.0.0 # via # junos-eznc # napalm @@ -359,7 +361,7 @@ pyeapi==1.0.0 # via napalm pyfakefs==5.3.1 # via -r requirements/pytest.txt -pygit2==1.13.1 +pygit2==1.15.1 # via -r requirements/static/ci/darwin.in pynacl==1.5.0 # via @@ -454,7 +456,7 @@ pyyaml==6.0.1 # pytest-salt-factories # responses # yamllint - # yamlordereddictloader + # yamlloader pyzmq==25.1.2 # via # -c requirements/static/pkg/py3.9/darwin.txt @@ -504,7 +506,6 @@ six==1.16.0 # junit-xml # junos-eznc # kubernetes - # ncclient # python-dateutil # pyvmomi # textfsm @@ -605,7 +606,7 @@ xmltodict==0.13.0 # via moto yamllint==1.32.0 # via -r requirements/static/ci/darwin.in -yamlordereddictloader==0.4.0 +yamlloader==1.6.0 # via junos-eznc yarl==1.22.0 # via diff --git a/requirements/static/ci/py3.9/docs.txt b/requirements/static/ci/py3.9/docs.txt index 0cb79d1ba033..9a8dcfc40d87 100644 --- a/requirements/static/ci/py3.9/docs.txt +++ b/requirements/static/ci/py3.9/docs.txt @@ -174,7 +174,7 @@ msgpack==1.0.7 # via # -c requirements/static/ci/py3.9/linux.txt # -r requirements/base.txt -multidict==6.7.1 +multidict==6.1.0 # via # -c requirements/static/ci/py3.9/linux.txt # aiohttp diff --git a/requirements/static/ci/py3.9/freebsd.txt b/requirements/static/ci/py3.9/freebsd.txt index f8f737f2926a..f273798423a6 100644 --- a/requirements/static/ci/py3.9/freebsd.txt +++ b/requirements/static/ci/py3.9/freebsd.txt @@ -210,6 +210,8 @@ importlib-metadata==8.7.0 # -r requirements/static/pkg/freebsd.in iniconfig==2.0.0 # via pytest +invoke==2.2.1 ; sys_platform != 'win32' + # via paramiko jaraco-collections==4.1.0 # via # -c requirements/static/pkg/py3.9/freebsd.txt @@ -249,7 +251,7 @@ jsonschema==3.2.0 # via -r requirements/static/ci/common.in junit-xml==1.9 # via -r requirements/static/ci/common.in -junos-eznc==2.6.7 ; sys_platform != 'win32' +junos-eznc==2.7.6 ; sys_platform != 'win32' # via # -r requirements/static/ci/common.in # napalm @@ -284,7 +286,7 @@ markupsafe==2.1.3 # jinja2 # mako # werkzeug -mercurial==6.4.4 +mercurial==7.2 # via -r requirements/static/ci/freebsd.in mock==5.1.0 # via -r requirements/pytest.txt @@ -304,20 +306,20 @@ msgpack==1.1.2 # -c requirements/static/pkg/py3.9/freebsd.txt # -r requirements/base.txt # pytest-salt-factories -multidict==6.7.1 +multidict==6.1.0 # via # -c requirements/static/pkg/py3.9/freebsd.txt # aiohttp # yarl napalm==4.1.0 ; python_full_version < '3.10' and sys_platform != 'win32' # via -r requirements/static/ci/common.in -ncclient==0.6.13 ; sys_platform != 'win32' +ncclient==0.7.0 ; sys_platform != 'win32' # via + # -r requirements/static/ci/common.in # junos-eznc # napalm -netaddr==0.8.0 ; sys_platform != 'win32' +netaddr==0.8.0 ; python_full_version < '3.10' and sys_platform != 'win32' # via - # junos-eznc # napalm # pyeapi netmiko==4.2.0 ; python_full_version < '3.10' and sys_platform != 'win32' @@ -335,7 +337,7 @@ packaging==24.0 # -c requirements/static/pkg/py3.9/freebsd.txt # -r requirements/base.txt # pytest -paramiko==3.4.0 ; sys_platform != 'win32' +paramiko==4.0.0 ; sys_platform != 'win32' # via # -r requirements/static/ci/common.in # junos-eznc @@ -525,7 +527,7 @@ pyyaml==6.0.1 # pytest-salt-factories # responses # yamllint - # yamlordereddictloader + # yamlloader pyzmq==27.1.0 # via # -c requirements/static/pkg/py3.9/freebsd.txt @@ -594,7 +596,6 @@ six==1.16.0 # junos-eznc # kazoo # kubernetes - # ncclient # python-dateutil # pyvmomi # textfsm @@ -713,7 +714,7 @@ xmltodict==1.0.4 # moto yamllint==1.32.0 # via -r requirements/static/ci/freebsd.in -yamlordereddictloader==0.4.0 ; sys_platform != 'win32' +yamlloader==1.6.0 ; sys_platform != 'win32' # via junos-eznc yarl==1.22.0 ; python_full_version < '3.10' # via diff --git a/requirements/static/ci/py3.9/lint.txt b/requirements/static/ci/py3.9/lint.txt index fdcdae808574..e27e6a924967 100644 --- a/requirements/static/ci/py3.9/lint.txt +++ b/requirements/static/ci/py3.9/lint.txt @@ -269,6 +269,10 @@ importlib-resources==5.0.7 # via # -c requirements/static/ci/py3.9/linux.txt # ansible-core +invoke==2.2.1 + # via + # -c requirements/static/ci/py3.9/linux.txt + # paramiko isort==4.3.21 # via pylint jaraco-collections==4.1.0 @@ -321,7 +325,7 @@ junit-xml==1.9 # via # -c requirements/static/ci/py3.9/linux.txt # -r requirements/static/ci/common.in -junos-eznc==2.6.7 +junos-eznc==2.7.6 # via # -c requirements/static/ci/py3.9/linux.txt # -r requirements/static/ci/common.in @@ -351,7 +355,7 @@ looseversion==1.3.0 # -c requirements/static/ci/py3.9/linux.txt # -c requirements/static/pkg/py3.9/linux.txt # -r requirements/base.txt -lxml==4.9.2 +lxml==6.0.2 # via # -c requirements/static/ci/py3.9/linux.txt # junos-eznc @@ -372,7 +376,7 @@ markupsafe==2.1.3 # werkzeug mccabe==0.6.1 # via pylint -mercurial==6.4.4 +mercurial==7.2 # via # -c requirements/static/ci/py3.9/linux.txt # -r requirements/static/ci/linux.in @@ -395,7 +399,7 @@ msgpack==1.0.7 # -c requirements/static/ci/py3.9/linux.txt # -c requirements/static/pkg/py3.9/linux.txt # -r requirements/base.txt -multidict==6.7.1 +multidict==6.1.0 # via # -c requirements/static/ci/py3.9/linux.txt # -c requirements/static/pkg/py3.9/linux.txt @@ -405,15 +409,15 @@ napalm==4.1.0 # via # -c requirements/static/ci/py3.9/linux.txt # -r requirements/static/ci/common.in -ncclient==0.6.13 +ncclient==0.7.0 # via # -c requirements/static/ci/py3.9/linux.txt + # -r requirements/static/ci/common.in # junos-eznc # napalm netaddr==0.8.0 # via # -c requirements/static/ci/py3.9/linux.txt - # junos-eznc # napalm # pyeapi netmiko==4.2.0 @@ -442,7 +446,7 @@ packaging==24.0 # -c requirements/static/pkg/py3.9/linux.txt # -r requirements/base.txt # ansible-core -paramiko==3.4.0 +paramiko==4.0.0 # via # -c requirements/static/ci/py3.9/linux.txt # -r requirements/static/ci/common.in @@ -510,7 +514,7 @@ pyeapi==1.0.0 # via # -c requirements/static/ci/py3.9/linux.txt # napalm -pygit2==1.13.1 +pygit2==1.15.1 # via # -c requirements/static/ci/py3.9/linux.txt # -r requirements/static/ci/linux.in @@ -617,7 +621,7 @@ pyyaml==6.0.1 # netmiko # responses # yamllint - # yamlordereddictloader + # yamlloader pyzmq==25.1.2 # via # -c requirements/static/ci/py3.9/linux.txt @@ -707,7 +711,6 @@ six==1.16.0 # junos-eznc # kazoo # kubernetes - # ncclient # python-consul # python-dateutil # pyvmomi @@ -861,7 +864,7 @@ yamllint==1.32.0 # via # -c requirements/static/ci/py3.9/linux.txt # -r requirements/static/ci/linux.in -yamlordereddictloader==0.4.0 +yamlloader==1.6.0 # via # -c requirements/static/ci/py3.9/linux.txt # junos-eznc diff --git a/requirements/static/ci/py3.9/linux.txt b/requirements/static/ci/py3.9/linux.txt index cb7b1eea8a6c..a1ffe3cdfa80 100644 --- a/requirements/static/ci/py3.9/linux.txt +++ b/requirements/static/ci/py3.9/linux.txt @@ -206,6 +206,8 @@ importlib-resources==5.0.7 # via ansible-core iniconfig==2.0.0 # via pytest +invoke==2.2.1 + # via paramiko jaraco-collections==4.1.0 # via # -c requirements/static/pkg/py3.9/linux.txt @@ -246,7 +248,7 @@ jsonschema==3.2.0 # via -r requirements/static/ci/common.in junit-xml==1.9 # via -r requirements/static/ci/common.in -junos-eznc==2.6.7 +junos-eznc==2.7.6 # via # -r requirements/static/ci/common.in # napalm @@ -264,7 +266,7 @@ looseversion==1.3.0 # via # -c requirements/static/pkg/py3.9/linux.txt # -r requirements/base.txt -lxml==4.9.2 +lxml==6.0.2 # via # junos-eznc # napalm @@ -279,7 +281,7 @@ markupsafe==2.1.3 # jinja2 # mako # werkzeug -mercurial==6.4.4 +mercurial==7.2 # via -r requirements/static/ci/linux.in mock==5.1.0 # via -r requirements/pytest.txt @@ -299,20 +301,20 @@ msgpack==1.0.7 # -c requirements/static/pkg/py3.9/linux.txt # -r requirements/base.txt # pytest-salt-factories -multidict==6.7.1 +multidict==6.1.0 # via # -c requirements/static/pkg/py3.9/linux.txt # aiohttp # yarl napalm==4.1.0 # via -r requirements/static/ci/common.in -ncclient==0.6.13 +ncclient==0.7.0 # via + # -r requirements/static/ci/common.in # junos-eznc # napalm netaddr==0.8.0 # via - # junos-eznc # napalm # pyeapi netmiko==4.2.0 @@ -331,7 +333,7 @@ packaging==24.0 # -r requirements/base.txt # ansible-core # pytest -paramiko==3.4.0 +paramiko==4.0.0 # via # -r requirements/static/ci/common.in # junos-eznc @@ -389,7 +391,7 @@ pyeapi==1.0.0 # via napalm pyfakefs==5.3.1 # via -r requirements/pytest.txt -pygit2==1.13.1 +pygit2==1.15.1 # via -r requirements/static/ci/linux.in pyiface==0.0.11 # via -r requirements/static/ci/linux.in @@ -498,7 +500,7 @@ pyyaml==6.0.1 # pytest-salt-factories # responses # yamllint - # yamlordereddictloader + # yamlloader pyzmq==25.1.2 # via # -c requirements/static/pkg/py3.9/linux.txt @@ -561,7 +563,6 @@ six==1.16.0 # junos-eznc # kazoo # kubernetes - # ncclient # python-consul # python-dateutil # pyvmomi @@ -672,7 +673,7 @@ xmltodict==0.13.0 # via moto yamllint==1.32.0 # via -r requirements/static/ci/linux.in -yamlordereddictloader==0.4.0 +yamlloader==1.6.0 # via junos-eznc yarl==1.22.0 # via diff --git a/requirements/static/ci/py3.9/windows.txt b/requirements/static/ci/py3.9/windows.txt index 54f85e264efd..b3ad6ad2fa85 100644 --- a/requirements/static/ci/py3.9/windows.txt +++ b/requirements/static/ci/py3.9/windows.txt @@ -262,7 +262,7 @@ msgpack==1.1.2 # -c requirements/static/pkg/py3.9/windows.txt # -r requirements/base.txt # pytest-salt-factories -multidict==6.7.1 +multidict==6.1.0 # via # -c requirements/static/pkg/py3.9/windows.txt # aiohttp @@ -324,7 +324,7 @@ pycryptodomex==3.23.0 # -r requirements/crypto.txt pyfakefs==5.3.1 # via -r requirements/pytest.txt -pygit2==1.13.1 +pygit2==1.15.1 # via -r requirements/static/ci/windows.in pygments==2.19.2 # via diff --git a/requirements/static/ci/windows.in b/requirements/static/ci/windows.in index 23eb32effcce..e9f317cb00b8 100644 --- a/requirements/static/ci/windows.in +++ b/requirements/static/ci/windows.in @@ -1,6 +1,6 @@ dmidecode patch -pygit2>=1.10.1 +pygit2>=1.14.0 sed pywinrm>=0.4.1 yamllint diff --git a/requirements/static/pkg/py3.10/darwin.txt b/requirements/static/pkg/py3.10/darwin.txt index dd95fbfa212f..d4c4989fb0fb 100644 --- a/requirements/static/pkg/py3.10/darwin.txt +++ b/requirements/static/pkg/py3.10/darwin.txt @@ -97,7 +97,7 @@ more-itertools==9.1.0 # jaraco-text msgpack==1.0.7 # via -r requirements/base.txt -multidict==6.7.1 +multidict==6.1.0 # via # aiohttp # yarl diff --git a/requirements/static/pkg/py3.10/freebsd.txt b/requirements/static/pkg/py3.10/freebsd.txt index e8641c351c26..dd8edb20dbef 100644 --- a/requirements/static/pkg/py3.10/freebsd.txt +++ b/requirements/static/pkg/py3.10/freebsd.txt @@ -111,7 +111,7 @@ more-itertools==9.1.0 # jaraco-text msgpack==1.1.2 # via -r requirements/base.txt -multidict==6.7.1 +multidict==6.1.0 # via # aiohttp # yarl diff --git a/requirements/static/pkg/py3.10/linux.txt b/requirements/static/pkg/py3.10/linux.txt index c5afab08f892..80cf2f25c96a 100644 --- a/requirements/static/pkg/py3.10/linux.txt +++ b/requirements/static/pkg/py3.10/linux.txt @@ -104,7 +104,7 @@ more-itertools==9.1.0 # jaraco-text msgpack==1.0.7 # via -r requirements/base.txt -multidict==6.7.1 +multidict==6.1.0 # via # aiohttp # yarl diff --git a/requirements/static/pkg/py3.10/windows.txt b/requirements/static/pkg/py3.10/windows.txt index 2d4322e895a4..dff68d1012c2 100644 --- a/requirements/static/pkg/py3.10/windows.txt +++ b/requirements/static/pkg/py3.10/windows.txt @@ -108,7 +108,7 @@ more-itertools==10.8.0 # jaraco-text msgpack==1.1.2 # via -r requirements/base.txt -multidict==6.7.1 +multidict==6.1.0 # via # aiohttp # yarl diff --git a/requirements/static/pkg/py3.11/darwin.txt b/requirements/static/pkg/py3.11/darwin.txt index e6e4a0b2201c..2cb0ee0f024f 100644 --- a/requirements/static/pkg/py3.11/darwin.txt +++ b/requirements/static/pkg/py3.11/darwin.txt @@ -95,7 +95,7 @@ more-itertools==10.7.0 # jaraco-text msgpack==1.0.7 # via -r requirements/base.txt -multidict==6.0.4 +multidict==6.1.0 # via # aiohttp # yarl diff --git a/requirements/static/pkg/py3.11/freebsd.txt b/requirements/static/pkg/py3.11/freebsd.txt index f0a65831b05d..3a3b4d6aae5f 100644 --- a/requirements/static/pkg/py3.11/freebsd.txt +++ b/requirements/static/pkg/py3.11/freebsd.txt @@ -109,7 +109,7 @@ more-itertools==10.8.0 # jaraco-text msgpack==1.1.2 # via -r requirements/base.txt -multidict==6.0.4 +multidict==6.1.0 # via # aiohttp # yarl diff --git a/requirements/static/pkg/py3.11/linux.txt b/requirements/static/pkg/py3.11/linux.txt index de2a3b7af93d..0a8a2f43bdfa 100644 --- a/requirements/static/pkg/py3.11/linux.txt +++ b/requirements/static/pkg/py3.11/linux.txt @@ -102,7 +102,7 @@ more-itertools==10.8.0 # jaraco-text msgpack==1.0.7 # via -r requirements/base.txt -multidict==6.0.4 +multidict==6.1.0 # via # aiohttp # yarl diff --git a/requirements/static/pkg/py3.11/windows.txt b/requirements/static/pkg/py3.11/windows.txt index 76ab7378f36e..30b59c3db980 100644 --- a/requirements/static/pkg/py3.11/windows.txt +++ b/requirements/static/pkg/py3.11/windows.txt @@ -106,7 +106,7 @@ more-itertools==10.8.0 # jaraco-text msgpack==1.1.2 # via -r requirements/base.txt -multidict==6.7.1 +multidict==6.1.0 # via # aiohttp # yarl diff --git a/requirements/static/pkg/py3.12/darwin.txt b/requirements/static/pkg/py3.12/darwin.txt index 807ad7190aba..86cfda7a1793 100644 --- a/requirements/static/pkg/py3.12/darwin.txt +++ b/requirements/static/pkg/py3.12/darwin.txt @@ -93,7 +93,7 @@ more-itertools==10.7.0 # jaraco-text msgpack==1.0.7 # via -r requirements/base.txt -multidict==6.0.4 +multidict==6.1.0 # via # aiohttp # yarl diff --git a/requirements/static/pkg/py3.12/freebsd.txt b/requirements/static/pkg/py3.12/freebsd.txt index 4529b020edf9..40cb7dcb0f1d 100644 --- a/requirements/static/pkg/py3.12/freebsd.txt +++ b/requirements/static/pkg/py3.12/freebsd.txt @@ -107,7 +107,7 @@ more-itertools==10.8.0 # jaraco-text msgpack==1.1.2 # via -r requirements/base.txt -multidict==6.0.4 +multidict==6.1.0 # via # aiohttp # yarl diff --git a/requirements/static/pkg/py3.12/linux.txt b/requirements/static/pkg/py3.12/linux.txt index 6b243f7ada08..01434571abe1 100644 --- a/requirements/static/pkg/py3.12/linux.txt +++ b/requirements/static/pkg/py3.12/linux.txt @@ -100,7 +100,7 @@ more-itertools==10.8.0 # jaraco-text msgpack==1.0.7 # via -r requirements/base.txt -multidict==6.0.4 +multidict==6.1.0 # via # aiohttp # yarl diff --git a/requirements/static/pkg/py3.12/windows.txt b/requirements/static/pkg/py3.12/windows.txt index f66df9f0bd89..467a8ea8747b 100644 --- a/requirements/static/pkg/py3.12/windows.txt +++ b/requirements/static/pkg/py3.12/windows.txt @@ -104,7 +104,7 @@ more-itertools==10.8.0 # jaraco-text msgpack==1.1.2 # via -r requirements/base.txt -multidict==6.7.1 +multidict==6.1.0 # via # aiohttp # yarl diff --git a/requirements/static/pkg/py3.13/windows.txt b/requirements/static/pkg/py3.13/windows.txt index 576be68231d1..be41261a2c59 100644 --- a/requirements/static/pkg/py3.13/windows.txt +++ b/requirements/static/pkg/py3.13/windows.txt @@ -101,7 +101,7 @@ more-itertools==10.8.0 # jaraco-text msgpack==1.1.2 # via -r requirements/base.txt -multidict==6.7.1 +multidict==6.1.0 # via # aiohttp # yarl diff --git a/requirements/static/pkg/py3.8/freebsd.txt b/requirements/static/pkg/py3.8/freebsd.txt index dac0a509f06f..ee5c306ec16f 100644 --- a/requirements/static/pkg/py3.8/freebsd.txt +++ b/requirements/static/pkg/py3.8/freebsd.txt @@ -83,7 +83,7 @@ more-itertools==9.1.0 # jaraco.text msgpack==1.0.7 ; python_version < "3.13" # via -r requirements/base.txt -multidict==6.0.4 +multidict==6.1.0 # via # aiohttp # yarl diff --git a/requirements/static/pkg/py3.8/linux.txt b/requirements/static/pkg/py3.8/linux.txt index f068a74d3819..81fb120ccc49 100644 --- a/requirements/static/pkg/py3.8/linux.txt +++ b/requirements/static/pkg/py3.8/linux.txt @@ -83,7 +83,7 @@ more-itertools==9.1.0 # jaraco.text msgpack==1.0.7 ; python_version < "3.13" # via -r requirements/base.txt -multidict==6.0.4 +multidict==6.1.0 # via # aiohttp # yarl diff --git a/requirements/static/pkg/py3.8/windows.txt b/requirements/static/pkg/py3.8/windows.txt index 567997bc57b4..b31704c9c9e2 100644 --- a/requirements/static/pkg/py3.8/windows.txt +++ b/requirements/static/pkg/py3.8/windows.txt @@ -91,7 +91,7 @@ more-itertools==9.1.0 # jaraco.text msgpack==1.0.7 ; python_version < "3.13" # via -r requirements/base.txt -multidict==6.0.4 +multidict==6.1.0 # via # aiohttp # yarl diff --git a/requirements/static/pkg/py3.9/darwin.txt b/requirements/static/pkg/py3.9/darwin.txt index 589956fe12cc..97534ba7773f 100644 --- a/requirements/static/pkg/py3.9/darwin.txt +++ b/requirements/static/pkg/py3.9/darwin.txt @@ -97,7 +97,7 @@ more-itertools==9.1.0 # jaraco-text msgpack==1.0.7 # via -r requirements/base.txt -multidict==6.7.1 +multidict==6.1.0 # via # aiohttp # yarl diff --git a/requirements/static/pkg/py3.9/freebsd.txt b/requirements/static/pkg/py3.9/freebsd.txt index ec4056ec1eab..c0f120c39edb 100644 --- a/requirements/static/pkg/py3.9/freebsd.txt +++ b/requirements/static/pkg/py3.9/freebsd.txt @@ -121,7 +121,7 @@ more-itertools==9.1.0 # jaraco-text msgpack==1.1.2 # via -r requirements/base.txt -multidict==6.7.1 +multidict==6.1.0 # via # aiohttp # yarl diff --git a/requirements/static/pkg/py3.9/linux.txt b/requirements/static/pkg/py3.9/linux.txt index e8fa138fbbb4..94fe7db43f85 100644 --- a/requirements/static/pkg/py3.9/linux.txt +++ b/requirements/static/pkg/py3.9/linux.txt @@ -104,7 +104,7 @@ more-itertools==9.1.0 # jaraco-text msgpack==1.0.7 # via -r requirements/base.txt -multidict==6.7.1 +multidict==6.1.0 # via # aiohttp # yarl diff --git a/requirements/static/pkg/py3.9/windows.txt b/requirements/static/pkg/py3.9/windows.txt index d7acd24e8f8d..3535b8bc4abf 100644 --- a/requirements/static/pkg/py3.9/windows.txt +++ b/requirements/static/pkg/py3.9/windows.txt @@ -108,7 +108,7 @@ more-itertools==10.8.0 # jaraco-text msgpack==1.1.2 # via -r requirements/base.txt -multidict==6.7.1 +multidict==6.1.0 # via # aiohttp # yarl diff --git a/salt/__init__.py b/salt/__init__.py index 4468a442d459..5b024ab2fe6a 100644 --- a/salt/__init__.py +++ b/salt/__init__.py @@ -110,6 +110,18 @@ def exec_module(self, module): category=DeprecationWarning, ) +# Filter dateutil's deprecated datetime calls in Python 3.12 +warnings.filterwarnings( + "ignore", + message="datetime.datetime.utcfromtimestamp\\(\\) is deprecated and scheduled for removal.*", + category=DeprecationWarning, +) +warnings.filterwarnings( + "ignore", + message="datetime.datetime.utcnow\\(\\) is deprecated and scheduled for removal.*", + category=DeprecationWarning, +) + def __define_global_system_encoding_variable__(): import builtins diff --git a/salt/beacons/status.py b/salt/beacons/status.py index 8c1210e7dbc7..cfb17715f3da 100644 --- a/salt/beacons/status.py +++ b/salt/beacons/status.py @@ -88,12 +88,12 @@ """ -import datetime import logging import salt.exceptions import salt.utils.beacons import salt.utils.platform +import salt.utils.timeutil log = logging.getLogger(__name__) @@ -118,7 +118,7 @@ def beacon(config): Return status for requested information """ log.debug(config) - ctime = datetime.datetime.utcnow().isoformat() + ctime = salt.utils.timeutil.utcnow().isoformat() whitelist = [] config = salt.utils.beacons.remove_hidden_options(config, whitelist) diff --git a/salt/channel/client.py b/salt/channel/client.py index f567c60be792..98faf969ad69 100644 --- a/salt/channel/client.py +++ b/salt/channel/client.py @@ -9,9 +9,6 @@ import time import uuid -import tornado.gen -import tornado.ioloop - import salt.crypt import salt.exceptions import salt.payload @@ -107,7 +104,7 @@ def factory(cls, opts, **kwargs): opts["master_uri"] = kwargs["master_uri"] io_loop = kwargs.get("io_loop") if io_loop is None: - io_loop = tornado.ioloop.IOLoop.current() + io_loop = salt.utils.asynchronous.get_ioloop() timeout = opts.get("request_channel_timeout", REQUEST_CHANNEL_TIMEOUT) tries = opts.get("request_channel_tries", REQUEST_CHANNEL_TRIES) @@ -412,7 +409,7 @@ def factory(cls, opts, **kwargs): io_loop = kwargs.get("io_loop") if io_loop is None: - io_loop = tornado.ioloop.IOLoop.current() + io_loop = salt.utils.asynchronous.get_ioloop() auth = salt.crypt.AsyncAuth(opts, io_loop=io_loop) host = opts.get("master_ip", "127.0.0.1") diff --git a/salt/client/ssh/__init__.py b/salt/client/ssh/__init__.py index 634e924f805e..cd2d2af945a6 100644 --- a/salt/client/ssh/__init__.py +++ b/salt/client/ssh/__init__.py @@ -46,6 +46,7 @@ import salt.utils.relenv import salt.utils.stringutils import salt.utils.thin +import salt.utils.timeutil import salt.utils.url import salt.utils.verify from salt._logging import LOG_LEVELS @@ -512,7 +513,7 @@ def _update_roster(self): '# Automatically added by "{s_user}" at {s_time}\n{hostname}:\n' " host: {hostname}\n user: {user}\n passwd: {passwd}\n".format( s_user=getpass.getuser(), - s_time=datetime.datetime.utcnow().isoformat(), + s_time=salt.utils.timeutil.utcnow().isoformat(), hostname=self.opts.get("tgt", ""), user=self.opts.get("ssh_user", ""), passwd=self.opts.get("ssh_passwd", ""), diff --git a/salt/crypt.py b/salt/crypt.py index d66ac3afd120..40470a06d4cd 100644 --- a/salt/crypt.py +++ b/salt/crypt.py @@ -719,7 +719,7 @@ def __new__(cls, opts, io_loop=None): Only create one instance of AsyncAuth per __key() """ # do we have any mapping for this io_loop - io_loop = io_loop or tornado.ioloop.IOLoop.current() + io_loop = io_loop or salt.utils.asynchronous.get_ioloop() if io_loop not in AsyncAuth.instance_map: AsyncAuth.instance_map[io_loop] = weakref.WeakValueDictionary() loop_instance_map = AsyncAuth.instance_map[io_loop] @@ -769,7 +769,7 @@ def __singleton_init__(self, opts, io_loop=None): self.get_keys() if io_loop is None: self.io_loop = salt.utils.asynchronous.aioloop( - tornado.ioloop.IOLoop.current() + salt.utils.asynchronous.get_ioloop() ) else: self.io_loop = salt.utils.asynchronous.aioloop(io_loop) diff --git a/salt/daemons/masterapi.py b/salt/daemons/masterapi.py index eabc934308ad..29f2991cab6f 100644 --- a/salt/daemons/masterapi.py +++ b/salt/daemons/masterapi.py @@ -1052,6 +1052,8 @@ def minion_publish(self, load): pub_load["raw"] = True ret = {} for minion in self.local.cmd_iter(**pub_load): + if not minion: + continue if load.get("form", "") == "full": data = minion if "jid" in minion: @@ -1062,11 +1064,13 @@ def minion_publish(self, load): ret[minion["id"]] = minion["return"] if "jid" in minion: ret["__jid__"] = minion["jid"] - for key, val in self.local.get_cache_returns(ret["__jid__"]).items(): - if key not in ret: - ret[key] = val - if load.get("form", "") != "full": - ret.pop("__jid__") + + if "__jid__" in ret: + for key, val in self.local.get_cache_returns(ret["__jid__"]).items(): + if key not in ret: + ret[key] = val + if load.get("form", "") != "full": + ret.pop("__jid__") return ret def revoke_auth(self, load): diff --git a/salt/master.py b/salt/master.py index 73e596050004..a2225fd8bd53 100644 --- a/salt/master.py +++ b/salt/master.py @@ -36,6 +36,7 @@ import salt.serializers.msgpack import salt.state import salt.utils.args +import salt.utils.asynchronous import salt.utils.atomicfile import salt.utils.ctx import salt.utils.event @@ -996,8 +997,7 @@ async def handle_event(self, package): log.trace("Ignore tag %s", tag) def run(self): - io_loop = asyncio.new_event_loop() - asyncio.set_event_loop(io_loop) + io_loop = salt.utils.asynchronous.get_event_loop() with salt.utils.event.get_master_event( self.opts, self.opts["sock_dir"], io_loop=io_loop, listen=True ) as event_bus: @@ -1169,8 +1169,7 @@ def __bind(self): """ Bind to the local port """ - self.io_loop = asyncio.new_event_loop() - asyncio.set_event_loop(self.io_loop) + self.io_loop = salt.utils.asynchronous.get_event_loop() for req_channel in self.req_channels: req_channel.post_fork( self._handle_payload, io_loop=self.io_loop diff --git a/salt/minion.py b/salt/minion.py index 45e326949398..a9e88fbeb15a 100644 --- a/salt/minion.py +++ b/salt/minion.py @@ -946,7 +946,7 @@ def __init__(self, opts, context=None): if self.opts.get("file_client", "remote") == "remote" or self.opts.get( "use_master_when_local", False ): - io_loop = tornado.ioloop.IOLoop.current() + io_loop = salt.utils.asynchronous.get_ioloop() async def eval_master(): """ @@ -1058,11 +1058,7 @@ def __init__(self, opts): self.max_auth_wait = self.opts["acceptance_wait_time_max"] self.minions = [] self.jid_queue = [] - try: - self.io_loop = asyncio.get_running_loop() - except RuntimeError: - self.io_loop = asyncio.new_event_loop() - asyncio.set_event_loop(self.io_loop) + self.io_loop = salt.utils.asynchronous.get_event_loop() self.process_manager = ProcessManager(name="MultiMinionProcessManager") self.io_loop.create_task(self.process_manager.run(asynchronous=True)) self.event_publisher = None @@ -1343,11 +1339,7 @@ def __init__( self._system_resource_limit_hit_timestamp = 0 if io_loop is None: - try: - self.io_loop = asyncio.get_running_loop() - except RuntimeError: - self.io_loop = asyncio.new_event_loop() - asyncio.set_event_loop(self.io_loop) + self.io_loop = salt.utils.asynchronous.get_event_loop() else: # Accept either asyncio loop or Tornado IOLoop (extract asyncio loop) if isinstance(io_loop, asyncio.AbstractEventLoop): @@ -4431,11 +4423,7 @@ def __init__(self, opts, io_loop=None): self.jid_forward_cache = set() if io_loop is None: - try: - self.io_loop = asyncio.get_running_loop() - except RuntimeError: - self.io_loop = asyncio.new_event_loop() - asyncio.set_event_loop(self.io_loop) + self.io_loop = salt.utils.asynchronous.get_event_loop() else: # Accept either asyncio loop or Tornado IOLoop (extract asyncio loop) if isinstance(io_loop, asyncio.AbstractEventLoop): diff --git a/salt/modules/aptpkg.py b/salt/modules/aptpkg.py index d24eec77c0b1..4f5b8a59b2be 100644 --- a/salt/modules/aptpkg.py +++ b/salt/modules/aptpkg.py @@ -9,7 +9,6 @@ """ import copy -import datetime import fnmatch import logging import os @@ -33,6 +32,7 @@ import salt.utils.pkg.deb import salt.utils.stringutils import salt.utils.systemd +import salt.utils.timeutil import salt.utils.versions import salt.utils.yaml from salt.exceptions import ( @@ -3280,7 +3280,7 @@ def list_downloaded(root=None, **kwargs): "path": package_path, "size": os.path.getsize(package_path), "creation_date_time_t": pkg_timestamp, - "creation_date_time": datetime.datetime.utcfromtimestamp( + "creation_date_time": salt.utils.timeutil.utcfromtimestamp( pkg_timestamp ).isoformat(), } diff --git a/salt/modules/dpkg_lowpkg.py b/salt/modules/dpkg_lowpkg.py index 3a4058621630..322d651db4da 100644 --- a/salt/modules/dpkg_lowpkg.py +++ b/salt/modules/dpkg_lowpkg.py @@ -2,7 +2,6 @@ Support for DEB packages """ -import datetime import logging import os import re @@ -12,6 +11,7 @@ import salt.utils.files import salt.utils.path import salt.utils.stringutils +import salt.utils.timeutil from salt.exceptions import CommandExecutionError, SaltInvocationError log = logging.getLogger(__name__) @@ -338,7 +338,7 @@ def _get_pkg_install_time(pkg): location = f"/var/lib/dpkg/info/{pkg}.list" if os.path.exists(location): iso_time = ( - datetime.datetime.utcfromtimestamp( + salt.utils.timeutil.utcfromtimestamp( int(os.path.getmtime(location)) ).isoformat() + "Z" diff --git a/salt/modules/rpm_lowpkg.py b/salt/modules/rpm_lowpkg.py index cfd0c650bfd0..a41c7f4d2a0d 100644 --- a/salt/modules/rpm_lowpkg.py +++ b/salt/modules/rpm_lowpkg.py @@ -2,7 +2,6 @@ Support for rpm """ -import datetime import logging import os import re @@ -11,6 +10,7 @@ import salt.utils.itertools import salt.utils.path import salt.utils.pkg.rpm +import salt.utils.timeutil from salt.exceptions import CommandExecutionError, SaltInvocationError from salt.utils.versions import LooseVersion @@ -634,7 +634,8 @@ def info(*packages, **kwargs): if key in ["build_date", "install_date"]: try: pkg_data[key] = ( - datetime.datetime.utcfromtimestamp(int(value)).isoformat() + "Z" + salt.utils.timeutil.utcfromtimestamp(int(value)).isoformat() + + "Z" ) except ValueError: log.warning('Could not convert "%s" into Unix time', value) diff --git a/salt/modules/status.py b/salt/modules/status.py index 09f4d0cca491..2e5d4fba4749 100644 --- a/salt/modules/status.py +++ b/salt/modules/status.py @@ -22,6 +22,7 @@ import salt.utils.path import salt.utils.platform import salt.utils.stringutils +import salt.utils.timeutil from salt.exceptions import CommandExecutionError log = logging.getLogger(__file__) @@ -255,8 +256,8 @@ def uptime(): return __salt__["cmd.run"]("uptime") # Setup datetime and timedelta objects - boot_time = datetime.datetime.utcfromtimestamp(curr_seconds - seconds) - curr_time = datetime.datetime.utcfromtimestamp(curr_seconds) + boot_time = salt.utils.timeutil.utcfromtimestamp(curr_seconds - seconds) + curr_time = salt.utils.timeutil.utcfromtimestamp(curr_seconds) up_time = curr_time - boot_time # Construct return information diff --git a/salt/modules/system.py b/salt/modules/system.py index 059c4c26ba8e..1899742f2ba2 100644 --- a/salt/modules/system.py +++ b/salt/modules/system.py @@ -20,6 +20,7 @@ import salt.utils.files import salt.utils.path import salt.utils.platform +import salt.utils.timeutil from salt.exceptions import CommandExecutionError, SaltInvocationError from salt.utils.decorators import depends @@ -258,7 +259,7 @@ def _get_offset_time(utc_offset): if utc_offset is not None: minutes = _offset_to_min(utc_offset) offset = timedelta(minutes=minutes) - offset_time = datetime.utcnow() + offset + offset_time = salt.utils.timeutil.utcnow() + offset offset_time = offset_time.replace(tzinfo=_FixedOffset(minutes)) else: offset_time = datetime.now() diff --git a/salt/modules/tls.py b/salt/modules/tls.py index 85e599cccf36..3d20897fe37e 100644 --- a/salt/modules/tls.py +++ b/salt/modules/tls.py @@ -110,6 +110,7 @@ import salt.utils.data import salt.utils.files import salt.utils.stringutils +import salt.utils.timeutil from salt.exceptions import CommandExecutionError from salt.utils.versions import Version @@ -365,7 +366,7 @@ def maybe_fix_ssl_version(ca_name, cacert_path=None, ca_filename=None): try: days = ( datetime.strptime(cert.get_notAfter(), "%Y%m%d%H%M%SZ") - - datetime.utcnow() + - salt.utils.timeutil.utcnow() ).days except (ValueError, TypeError): days = 365 @@ -593,8 +594,10 @@ def validate(cert, ca_name, crl_file): builder = x509.CertificateRevocationListBuilder() builder = builder.issuer_name(ca_x509.subject) - builder = builder.last_update(datetime.utcnow()) - builder = builder.next_update(datetime.utcnow() + timedelta(days=36500)) + builder = builder.last_update(salt.utils.timeutil.utcnow()) + builder = builder.next_update( + salt.utils.timeutil.utcnow() + timedelta(days=36500) + ) # Load existing revocations from index file if it exists index_file = f"{ca_dir}/index.txt" @@ -845,7 +848,7 @@ def create_ca( err, ) bck = "{}.unloadable.{}".format( - ca_keyp, datetime.utcnow().strftime("%Y%m%d%H%M%S") + ca_keyp, salt.utils.timeutil.utcnow().strftime("%Y%m%d%H%M%S") ) log.info("Saving unloadable CA ssl key in %s", bck) os.rename(ca_keyp, bck) @@ -903,7 +906,9 @@ def create_ca( keycontent = OpenSSL.crypto.dump_privatekey(OpenSSL.crypto.FILETYPE_PEM, key) write_key = True if os.path.exists(ca_keyp): - bck = "{}.{}".format(ca_keyp, datetime.utcnow().strftime("%Y%m%d%H%M%S")) + bck = "{}.{}".format( + ca_keyp, salt.utils.timeutil.utcnow().strftime("%Y%m%d%H%M%S") + ) with salt.utils.files.fopen(ca_keyp) as fic: old_key = salt.utils.stringutils.to_unicode(fic.read()).strip() if old_key.strip() == keycontent.strip(): @@ -1905,8 +1910,10 @@ def create_empty_crl( builder = x509.CertificateRevocationListBuilder() builder = builder.issuer_name(ca_x509.subject) - builder = builder.last_update(datetime.utcnow()) - builder = builder.next_update(datetime.utcnow() + timedelta(days=36500)) + builder = builder.last_update(salt.utils.timeutil.utcnow()) + builder = builder.next_update( + salt.utils.timeutil.utcnow() + timedelta(days=36500) + ) # Mapping digest strings to cryptography hashes hash_algo = getattr(hashes, digest.upper(), hashes.SHA256)() @@ -2021,7 +2028,7 @@ def revoke_cert( ) index_r_data = "R\t{}\t{}\t{}".format( expire_date, - _four_digit_year_to_two_digit(datetime.utcnow()), + _four_digit_year_to_two_digit(salt.utils.timeutil.utcnow()), index_serial_subject, ) @@ -2063,8 +2070,10 @@ def revoke_cert( builder = x509.CertificateRevocationListBuilder() builder = builder.issuer_name(ca_x509.subject) - builder = builder.last_update(datetime.utcnow()) - builder = builder.next_update(datetime.utcnow() + timedelta(days=36500)) + builder = builder.last_update(salt.utils.timeutil.utcnow()) + builder = builder.next_update( + salt.utils.timeutil.utcnow() + timedelta(days=36500) + ) with salt.utils.files.fopen(index_file) as fp_: for line in fp_: diff --git a/salt/modules/virtualenv_mod.py b/salt/modules/virtualenv_mod.py index cd52435e6f51..d3abd597d857 100644 --- a/salt/modules/virtualenv_mod.py +++ b/salt/modules/virtualenv_mod.py @@ -382,8 +382,14 @@ def get_distribution_path(venv, distribution): ret = __salt__["cmd.exec_code_all"]( bin_path, - "import pkg_resources; " - "print(pkg_resources.get_distribution('{}').location)".format(distribution), + "try:\n" + " import importlib.metadata, pathlib\n" + " print(str(pathlib.Path(importlib.metadata.distribution('{dist}').locate_file('.')).resolve()))\n" + "except Exception:\n" + " import pkg_resources\n" + " print(pkg_resources.get_distribution('{dist}').location)\n".format( + dist=distribution + ), ) if ret["retcode"] != 0: diff --git a/salt/modules/vsphere.py b/salt/modules/vsphere.py index ff62e1ca3c65..c2eb7535326e 100644 --- a/salt/modules/vsphere.py +++ b/salt/modules/vsphere.py @@ -181,7 +181,6 @@ 6500 """ -import datetime import logging import sys from functools import wraps @@ -191,6 +190,7 @@ import salt.utils.http import salt.utils.path import salt.utils.pbm +import salt.utils.timeutil import salt.utils.vmware import salt.utils.vsan from salt.config.schemas.esxcluster import ( @@ -3877,7 +3877,7 @@ def update_host_datetime( host_ref = _get_host_ref(service_instance, host, host_name=host_name) date_time_manager = _get_date_time_mgr(host_ref) try: - date_time_manager.UpdateDateTime(datetime.datetime.utcnow()) + date_time_manager.UpdateDateTime(salt.utils.timeutil.utcnow()) except vim.fault.HostConfigFault as err: msg = "'vsphere.update_date_time' failed for host {}: {}".format( host_name, err diff --git a/salt/modules/win_timezone.py b/salt/modules/win_timezone.py index 85807a7503d0..da00c1d01c21 100644 --- a/salt/modules/win_timezone.py +++ b/salt/modules/win_timezone.py @@ -3,8 +3,8 @@ """ import logging -from datetime import datetime +import salt.utils.timeutil from salt.exceptions import CommandExecutionError try: @@ -242,7 +242,7 @@ def get_offset(): """ # http://craigglennie.com/programming/python/2013/07/21/working-with-timezones-using-Python-and-pytz-localize-vs-normalize/ tz_object = pytz.timezone(get_zone()) - utc_time = pytz.utc.localize(datetime.utcnow()) + utc_time = pytz.utc.localize(salt.utils.timeutil.utcnow()) loc_time = utc_time.astimezone(tz_object) norm_time = tz_object.normalize(loc_time) return norm_time.strftime("%z") @@ -262,7 +262,7 @@ def get_zonecode(): salt '*' timezone.get_zonecode """ tz_object = pytz.timezone(get_zone()) - loc_time = tz_object.localize(datetime.utcnow()) + loc_time = tz_object.localize(salt.utils.timeutil.utcnow()) return loc_time.tzname() diff --git a/salt/modules/x509.py b/salt/modules/x509.py index 0e68d38116be..baf8c2a65880 100644 --- a/salt/modules/x509.py +++ b/salt/modules/x509.py @@ -37,6 +37,7 @@ import salt.utils.path import salt.utils.platform import salt.utils.stringutils +import salt.utils.timeutil import salt.utils.versions from salt.state import STATE_INTERNAL_KEYWORDS as _STATE_INTERNAL_KEYWORDS @@ -1963,7 +1964,7 @@ def expired(certificate): ret["path"] = certificate cert = _get_certificate_obj(certificate) - _now = datetime.datetime.utcnow() + _now = salt.utils.timeutil.utcnow() _expiration_date = cert.get_not_after().get_datetime() ret["cn"] = _parse_subject(cert.get_subject())["CN"] @@ -2007,7 +2008,7 @@ def will_expire(certificate, days): cert = _get_certificate_obj(certificate) - _check_time = datetime.datetime.utcnow() + datetime.timedelta(days=days) + _check_time = salt.utils.timeutil.utcnow() + datetime.timedelta(days=days) _expiration_date = cert.get_not_after().get_datetime() ret["cn"] = _parse_subject(cert.get_subject())["CN"] diff --git a/salt/runners/winrepo.py b/salt/runners/winrepo.py index 0da7d57d8062..94ab49478922 100644 --- a/salt/runners/winrepo.py +++ b/salt/runners/winrepo.py @@ -224,7 +224,9 @@ def update_git_repos(opts=None, clean=False, masterless=False): # one level down. key = next(iter(result)) result = result[key] - winrepo_result[result["name"]] = result["result"] + # Store the target path (gittarget) not the boolean result, + # to match the behavior of the non-legacy gitfs code + winrepo_result[result["name"]] = gittarget ret.update(winrepo_result) else: # New winrepo code utilizing salt.utils.gitfs diff --git a/salt/spm/pkgdb/sqlite3.py b/salt/spm/pkgdb/sqlite3.py index c6c0fb1384f1..83a127cbf1b5 100644 --- a/salt/spm/pkgdb/sqlite3.py +++ b/salt/spm/pkgdb/sqlite3.py @@ -4,12 +4,13 @@ .. versionadded:: 2015.8.0 """ -import datetime import logging import os import sqlite3 from sqlite3 import OperationalError +import salt.utils.timeutil + # Get logging started log = logging.getLogger(__name__) @@ -166,7 +167,7 @@ def register_pkg(name, formula_def, conn=None): name, formula_def["version"], formula_def["release"], - datetime.datetime.utcnow().strftime("%a, %d %b %Y %H:%M:%S GMT"), + salt.utils.timeutil.utcnow().strftime("%a, %d %b %Y %H:%M:%S GMT"), formula_def.get("os", None), formula_def.get("os_family", None), formula_def.get("dependencies", None), diff --git a/salt/states/ssh_auth.py b/salt/states/ssh_auth.py index dc9ac913f35d..83cf82e1ff4a 100644 --- a/salt/states/ssh_auth.py +++ b/salt/states/ssh_auth.py @@ -98,7 +98,9 @@ def _present_test( ) else: # check if this is of form {options} {enc} {key} {comment} - sshre = re.compile(r"^(.*?)\s?((?:sk-)?(?:ssh\-|ecds)[\w@.-]+\s.+)$") + sshre = re.compile( + r"^(.*?)\s?((?:sk-)?(?:ssh\-|ecds)[\w@.-]+\s[^\s]+(?:\s.*)?)$" + ) fullkey = sshre.search(name) # if it is {key} [comment] if not fullkey: @@ -171,7 +173,9 @@ def _absent_test( return (True, f"All host keys in file {source} are already absent") else: # check if this is of form {options} {enc} {key} {comment} - sshre = re.compile(r"^(.*?)\s?((?:sk-)?(?:ssh\-|ecds)[\w@.-]+\s.+)$") + sshre = re.compile( + r"^(.*?)\s?((?:sk-)?(?:ssh\-|ecds)[\w@.-]+\s[^\s]+(?:\s.*)?)$" + ) fullkey = sshre.search(name) # if it is {key} [comment] if not fullkey: @@ -269,7 +273,9 @@ def present( if source == "": # check if this is of form {options} {enc} {key} {comment} - sshre = re.compile(r"^(.*?)\s?((?:sk-)?(?:ssh\-|ecds)[\w@.-]+\s.+)$") + sshre = re.compile( + r"^(.*?)\s?((?:sk-)?(?:ssh\-|ecds)[\w@.-]+\s[^\s]+(?:\s.*)?)$" + ) fullkey = sshre.search(name) # if it is {key} [comment] if not fullkey: @@ -455,7 +461,9 @@ def absent( ) else: # Get just the key - sshre = re.compile(r"^(.*?)\s?((?:sk-)?(?:ssh\-|ecds)[\w@.-]+\s.+)$") + sshre = re.compile( + r"^(.*?)\s?((?:sk-)?(?:ssh\-|ecds)[\w@.-]+\s[^\s]+(?:\s.*)?)$" + ) fullkey = sshre.search(name) # if it is {key} [comment] if not fullkey: @@ -548,10 +556,18 @@ def manage( ret = {"name": "", "changes": {}, "result": True, "comment": ""} all_potential_keys = [] + sshre = re.compile(r"^(.*?)\s?((?:sk-)?(?:ssh\-|ecds)[\w@.-]+\s[^\s]+(?:\s.*)?)$") for ssh_key in ssh_keys: - # gather list potential ssh keys for removal comparison - # options, enc, and comments could be in the mix - all_potential_keys.extend(ssh_key.split(" ")) + # check if this is of form {options} {enc} {key} {comment} + fullkey = sshre.search(ssh_key) + # if it is {key} [comment] + if not fullkey: + key_and_comment = ssh_key.split(None, 1) + all_potential_keys.append(key_and_comment[0]) + else: + # key is of format: {enc} {key} [comment] + comps = fullkey.group(2).split(None, 2) + all_potential_keys.append(comps[1]) existing_keys = __salt__["ssh.auth_keys"]( user=user, config=config, fingerprint_hash_type=fingerprint_hash_type diff --git a/salt/transport/ipc.py b/salt/transport/ipc.py index 0f264a112187..2573115d160c 100644 --- a/salt/transport/ipc.py +++ b/salt/transport/ipc.py @@ -13,13 +13,13 @@ import tornado.gen import tornado.ioloop import tornado.netutil -from tornado.ioloop import IOLoop from tornado.ioloop import TimeoutError as TornadoTimeoutError from tornado.iostream import IOStream, StreamClosedError from tornado.locks import Lock import salt.defaults import salt.transport.frame +import salt.utils.asynchronous import salt.utils.msgpack from salt.utils.versions import warn_until @@ -121,7 +121,7 @@ def __init__(self, socket_path, io_loop=None, payload_handler=None): # Placeholders for attributes to be populated by method calls self.sock = None - self.io_loop = io_loop or tornado.ioloop.IOLoop.current() + self.io_loop = io_loop or salt.utils.asynchronous.get_ioloop() self._closing = False def start(self): @@ -274,7 +274,7 @@ def __init__(self, socket_path, io_loop=None): to the server. """ - self.io_loop = io_loop or tornado.ioloop.IOLoop.current() + self.io_loop = io_loop or salt.utils.asynchronous.get_ioloop() self.socket_path = socket_path self._closing = False self.stream = None @@ -296,7 +296,7 @@ def connect(self, callback=None, timeout=None): self._connecting_future.exception() # pylint: disable=E0203 future = tornado.concurrent.Future() self._connecting_future = future - self._connect(timeout) + self.io_loop.add_callback(self._connect, timeout) if callback is not None: @@ -329,8 +329,8 @@ def _connect(self, timeout=None): break if self.stream is None: - # with salt.utils.asynchronous.current_ioloop(self.io_loop): - self.stream = IOStream(socket.socket(sock_type, socket.SOCK_STREAM)) + with salt.utils.asynchronous.current_ioloop(self.io_loop): + self.stream = IOStream(socket.socket(sock_type, socket.SOCK_STREAM)) try: log.trace("IPCClient: Connecting to socket: %s", self.socket_path) yield self.stream.connect(sock_addr) @@ -403,7 +403,7 @@ class IPCMessageClient(IPCClient): import salt.config import salt.transport.ipc - io_loop = tornado.ioloop.IOLoop.current() + io_loop = salt.utils.asynchronous.get_ioloop() ipc_server_socket_path = '/var/run/ipc_server.ipc' @@ -458,7 +458,7 @@ class IPCMessageServer(IPCServer): # Import Salt libs import salt.transport.ipc - io_loop = tornado.ioloop.IOLoop.current() + io_loop = salt.utils.asynchronous.get_ioloop() ipc_server_socket_path = '/var/run/ipc_server.ipc' ipc_server = salt.transport.ipc.IPCMessageServer(ipc_server_socket_path, io_loop=io_loop, payload_handler=print_to_console) @@ -502,7 +502,7 @@ def __init__(self, opts, socket_path, io_loop=None): # Placeholders for attributes to be populated by method calls self.sock = None - self.io_loop = io_loop or IOLoop.current() + self.io_loop = io_loop or salt.utils.asynchronous.get_ioloop() self._closing = False self.streams = set() diff --git a/salt/transport/tcp.py b/salt/transport/tcp.py index 862928ce18c0..ff378a7aa5ce 100644 --- a/salt/transport/tcp.py +++ b/salt/transport/tcp.py @@ -413,14 +413,25 @@ async def recv(self, timeout=None): async with self._read_in_progress: try: byts = await self._stream.read_bytes(4096, partial=True) - except tornado.iostream.StreamClosedError: - log.trace("Stream closed, reconnecting.") + except ( + tornado.iostream.StreamClosedError, + RuntimeError, + ) as exc: + if isinstance( + exc, RuntimeError + ) and "Event loop is closed" not in str(exc): + raise + log.trace( + "Stream closed or loop closed, reconnecting: %s", exc + ) stream = self._stream self._stream = None - stream.close() + if stream: + stream.close() if self.disconnect_callback: - self.disconnect_callback() - await self.connect() + await self.disconnect_callback() + if not self._closing: + await self.connect() return self.unpacker.feed(byts) for msg in self.unpacker: @@ -443,14 +454,20 @@ async def recv(self, timeout=None): async with self._read_in_progress: try: byts = await self._stream.read_bytes(4096, partial=True) - except tornado.iostream.StreamClosedError: - log.trace("Stream closed, reconnecting.") + except (tornado.iostream.StreamClosedError, RuntimeError) as exc: + if isinstance( + exc, RuntimeError + ) and "Event loop is closed" not in str(exc): + raise + log.trace("Stream closed or loop closed, reconnecting: %s", exc) stream = self._stream self._stream = None - stream.close() + if stream: + stream.close() if self.disconnect_callback: await self.disconnect_callback() - await self.connect() + if not self._closing: + await self.connect() log.debug("Re-connected - continue") continue self.unpacker.feed(byts) @@ -650,7 +667,7 @@ class SaltMessageServer(tornado.tcpserver.TCPServer): """ def __init__(self, message_handler, *args, **kwargs): - io_loop = kwargs.pop("io_loop", None) or tornado.ioloop.IOLoop.current() + io_loop = kwargs.pop("io_loop", None) or salt.utils.asynchronous.get_ioloop() self._closing = False super().__init__(*args, **kwargs) self.io_loop = io_loop @@ -758,9 +775,17 @@ def socket_queue_thread(self): # Schedule handling the connection using the event loop. # Must use call_soon_threadsafe since we're in a background thread aio_loop = salt.utils.asynchronous.aioloop(self.io_loop) - aio_loop.call_soon_threadsafe( - self._handle_connection, client_socket, address - ) + try: + aio_loop.call_soon_threadsafe( + self._handle_connection, client_socket, address + ) + except RuntimeError as exc: + if "Event loop is closed" not in str(exc): + raise + log.trace( + "Loop closed while scheduling connection in LoadBalancerWorker." + ) + break except (KeyboardInterrupt, SystemExit): pass @@ -821,7 +846,7 @@ def __init__( self.connect_callback = connect_callback self.disconnect_callback = disconnect_callback if io_loop is None: - io_loop = tornado.ioloop.IOLoop.current() + io_loop = salt.utils.asynchronous.get_ioloop() self.io_loop = io_loop self.asyncio_loop = salt.utils.asynchronous.aioloop(io_loop) self._tcp_client = TCPClientKeepAlive(opts, resolver=resolver) @@ -1095,7 +1120,7 @@ def __init__( super().__init__(ssl_options=ssl) if io_loop is None: self.io_loop = salt.utils.asynchronous.aioloop( - tornado.ioloop.IOLoop.current() + salt.utils.asynchronous.get_ioloop() ) else: self.io_loop = salt.utils.asynchronous.aioloop(io_loop) @@ -1148,6 +1173,10 @@ async def _stream_read( self.remove_presence_callback(client) self.clients.discard(client) break + except RuntimeError as exc: + if "Event loop is closed" not in str(exc): + raise + break except Exception as e: # pylint: disable=broad-except log.error( "Exception parsing response from %s", client.address, exc_info=True @@ -1305,7 +1334,7 @@ def __init__( self.sock = None if io_loop is None: self.io_loop = salt.utils.asynchronous.aioloop( - tornado.ioloop.IOLoop.current() + salt.utils.asynchronous.get_ioloop() ) else: self.io_loop = salt.utils.asynchronous.aioloop(io_loop) @@ -1523,7 +1552,7 @@ async def publisher( io_loop=None, ): if io_loop is None: - io_loop = tornado.ioloop.IOLoop.current() + io_loop = salt.utils.asynchronous.get_ioloop() # Spin up the publisher ctx = None if self.ssl is not None: @@ -1673,7 +1702,7 @@ class _TCPPubServerPublisher: import salt.config import salt.transport.ipc - io_loop = tornado.ioloop.IOLoop.current() + io_loop = salt.utils.asynchronous.get_ioloop() ipc_server_socket_path = '/var/run/ipc_server.ipc' @@ -1706,7 +1735,7 @@ def __init__(self, host, port, path, io_loop=None): """ if io_loop is None: self.io_loop = salt.utils.asynchronous.aioloop( - tornado.ioloop.IOLoop.current() + salt.utils.asynchronous.get_ioloop() ) else: self.io_loop = salt.utils.asynchronous.aioloop(io_loop) diff --git a/salt/transport/ws.py b/salt/transport/ws.py index 0826dea3b648..2daab9fb742f 100644 --- a/salt/transport/ws.py +++ b/salt/transport/ws.py @@ -45,7 +45,7 @@ class PublishClient(salt.transport.base.PublishClient): def __init__(self, opts, io_loop, **kwargs): # pylint: disable=W0231 self.opts = opts if io_loop is None: - io_loop = tornado.ioloop.IOLoop.current() + io_loop = salt.utils.asynchronous.get_ioloop() self.io_loop = io_loop self.asyncio_loop = salt.utils.asynchronous.aioloop(io_loop) @@ -143,7 +143,9 @@ async def getstream(self, **kwargs): else: url = "http://ipc.saltproject.io/ws" log.debug("pub client connect %r %r", url, ctx) - ws = await asyncio.wait_for(session.ws_connect(url, ssl=ctx), 3) + ws = await asyncio.wait_for( + session.ws_connect(url, ssl=ctx if ctx is not None else False), 3 + ) # For SSL connections, give handshake time to complete and fail if invalid if ws and self.ssl: await asyncio.sleep(0.1) @@ -372,7 +374,7 @@ async def publisher( io_loop=None, ): if io_loop is None: - io_loop = tornado.ioloop.IOLoop.current() + io_loop = salt.utils.asynchronous.get_ioloop() if self._run is None: self._run = asyncio.Event() @@ -635,7 +637,9 @@ async def connect(self): # pylint: disable=invalid-overridden-method self.session = aiohttp.ClientSession() URL = self.get_master_uri(self.opts) log.debug("Connect to %s %s", URL, ctx) - self.ws = await self.session.ws_connect(URL, ssl=ctx) + self.ws = await self.session.ws_connect( + URL, ssl=ctx if ctx is not None else False + ) async def send(self, load, timeout=60): if self.sending or self._closing: diff --git a/salt/transport/zeromq.py b/salt/transport/zeromq.py index 65c165c897a2..3dc0267b66c6 100644 --- a/salt/transport/zeromq.py +++ b/salt/transport/zeromq.py @@ -573,6 +573,11 @@ async def request_handler(self): continue except asyncio.exceptions.TimeoutError: continue + except RuntimeError as exc: + if "Event loop is closed" not in str(exc): + raise + log.trace("Loop closed while handling request in request_handler.") + break except Exception as exc: # pylint: disable=broad-except log.error( "Exception in request handler", @@ -661,7 +666,7 @@ def __init__(self, opts, addr, linger=0, io_loop=None): self.addr = addr self.linger = linger if io_loop is None: - self.io_loop = tornado.ioloop.IOLoop.current() + self.io_loop = salt.utils.asynchronous.get_ioloop() else: self.io_loop = io_loop self.context = zmq.eventloop.future.Context() @@ -1112,7 +1117,7 @@ async def publisher( io_loop=None, ): if io_loop is None: - io_loop = tornado.ioloop.IOLoop.current() + io_loop = salt.utils.asynchronous.get_ioloop() self.daemon_context = zmq.asyncio.Context() ( self.daemon_pull_sock, @@ -1124,6 +1129,11 @@ async def publisher( try: package = await self.daemon_pull_sock.recv() await publish_payload(package) + except RuntimeError as exc: + if "Event loop is closed" not in str(exc): + raise + log.trace("Loop closed while receiving package in publisher.") + break except Exception as exc: # pylint: disable=broad-except log.error( "Exception in publisher %s %s", @@ -1242,7 +1252,7 @@ def __init__(self, opts, io_loop, linger=0): # pylint: disable=W0231 self.linger = linger if io_loop is None: self.io_loop = salt.utils.asynchronous.aioloop( - tornado.ioloop.IOLoop.current() + salt.utils.asynchronous.get_ioloop() ) else: self.io_loop = salt.utils.asynchronous.aioloop(io_loop) @@ -1410,6 +1420,12 @@ async def _send_recv(self, socket, queue, _TimeoutError=tornado.gen.TimeoutError # The ioloop was closed before polling finished. send_recv_running = False break + except RuntimeError as exc: + if "Event loop is closed" not in str(exc): + raise + log.trace("Loop closed while polling send socket.") + send_recv_running = False + break except zmq.ZMQError: log.trace("Send socket closed while polling.") send_recv_running = False @@ -1422,13 +1438,14 @@ async def _send_recv(self, socket, queue, _TimeoutError=tornado.gen.TimeoutError break try: await socket.send(message) - except asyncio.CancelledError as exc: + except (asyncio.CancelledError, zmq.eventloop.future.CancelledError) as exc: log.trace("Loop closed while sending.") send_recv_running = False future.set_exception(exc) - except zmq.eventloop.future.CancelledError as exc: + except RuntimeError as exc: + if "Event loop is closed" not in str(exc): + raise log.trace("Loop closed while sending.") - # The ioloop was closed before polling finished. send_recv_running = False future.set_exception(exc) except zmq.ZMQError as exc: @@ -1469,11 +1486,16 @@ async def _send_recv(self, socket, queue, _TimeoutError=tornado.gen.TimeoutError try: # Time is in milliseconds. ready = await socket.poll(300, zmq.POLLIN) - except asyncio.CancelledError as exc: + except ( + asyncio.CancelledError, + zmq.eventloop.future.CancelledError, + ) as exc: log.trace("Loop closed while polling receive socket.") send_recv_running = False future.set_exception(exc) - except zmq.eventloop.future.CancelledError as exc: + except RuntimeError as exc: + if "Event loop is closed" not in str(exc): + raise log.trace("Loop closed while polling receive socket.") send_recv_running = False future.set_exception(exc) @@ -1486,11 +1508,16 @@ async def _send_recv(self, socket, queue, _TimeoutError=tornado.gen.TimeoutError try: recv = await socket.recv() received = True - except asyncio.CancelledError as exc: + except ( + asyncio.CancelledError, + zmq.eventloop.future.CancelledError, + ) as exc: log.trace("Loop closed while receiving.") send_recv_running = False future.set_exception(exc) - except zmq.eventloop.future.CancelledError as exc: + except RuntimeError as exc: + if "Event loop is closed" not in str(exc): + raise log.trace("Loop closed while receiving.") send_recv_running = False future.set_exception(exc) diff --git a/salt/utils/asynchronous.py b/salt/utils/asynchronous.py index 328be0adfd30..06815c4217a6 100644 --- a/salt/utils/asynchronous.py +++ b/salt/utils/asynchronous.py @@ -30,13 +30,52 @@ def aioloop(io_loop, warn=False): raise RuntimeError("Loop must be AbstractEventLoop (prefered) or IOLoop") +def get_event_loop(): + """ + Get the current event loop. If one is not set, create one and set it. + """ + import warnings + + try: + return asyncio.get_running_loop() + except RuntimeError: + pass + + try: + with warnings.catch_warnings(): + warnings.simplefilter("ignore", DeprecationWarning) + return asyncio.get_event_loop() + except RuntimeError: + loop = asyncio.new_event_loop() + asyncio.set_event_loop(loop) + return loop + + +def get_ioloop(): + """ + Get the current IOLoop. If one is not set, create one and set it. + """ + import warnings + + try: + # We try to get the current asyncio loop first + asyncio.get_running_loop() + except RuntimeError: + # No running loop, create/set one to avoid tornado triggering warning + get_event_loop() + + with warnings.catch_warnings(): + warnings.simplefilter("ignore", DeprecationWarning) + return tornado.ioloop.IOLoop.current() + + @contextlib.contextmanager def current_ioloop(io_loop): """ A context manager that will set the current ioloop to io_loop for the context """ try: - orig_loop = tornado.ioloop.IOLoop.current() + orig_loop = get_ioloop() except RuntimeError: orig_loop = None @@ -172,9 +211,10 @@ def wrap(*args, **kwargs): def _target(self, key, args, kwargs, results, asyncio_loop): asyncio.set_event_loop(asyncio_loop) - io_loop = tornado.ioloop.IOLoop.current() try: - result = io_loop.run_sync(lambda: getattr(self.obj, key)(*args, **kwargs)) + result = self.io_loop.run_sync( + lambda: getattr(self.obj, key)(*args, **kwargs) + ) results.append(True) results.append(result) except Exception: # pylint: disable=broad-except diff --git a/salt/utils/aws.py b/salt/utils/aws.py index 615aee19040c..086329edafcf 100644 --- a/salt/utils/aws.py +++ b/salt/utils/aws.py @@ -18,12 +18,12 @@ import time import urllib.parse import xml.etree.ElementTree as ET -from datetime import datetime import requests import salt.config import salt.utils.hashutils +import salt.utils.timeutil import salt.utils.xmlutil as xml log = logging.getLogger(__name__) @@ -121,7 +121,7 @@ def creds(provider): ## if needed if provider["id"] == IROLE_CODE or provider["key"] == IROLE_CODE: # Check to see if we have cache credentials that are still good - if not __Expiration__ or __Expiration__ < datetime.utcnow().strftime( + if not __Expiration__ or __Expiration__ < salt.utils.timeutil.utcnow().strftime( "%Y-%m-%dT%H:%M:%SZ" ): # We don't have any cached credentials, or they are expired, get them @@ -164,7 +164,7 @@ def sig2(method, endpoint, params, provider, aws_api_version): http://docs.aws.amazon.com/general/latest/gr/signature-version-2.html """ - timenow = datetime.utcnow() + timenow = salt.utils.timeutil.utcnow() timestamp = timenow.strftime("%Y-%m-%dT%H:%M:%SZ") # Retrieve access credentials from meta-data, or use provided @@ -201,7 +201,7 @@ def assumed_creds(prov_dict, role_arn, location=None): valid_session_name_re = re.compile("[^a-z0-9A-Z+=,.@-]") # current time in epoch seconds - now = time.mktime(datetime.utcnow().timetuple()) + now = time.mktime(salt.utils.timeutil.utcnow().timetuple()) for key, creds in copy.deepcopy(__AssumeCache__).items(): if (creds["Expiration"] - now) <= 120: @@ -281,7 +281,7 @@ def sig4( http://docs.aws.amazon.com/general/latest/gr/sigv4-signed-request-examples.html http://docs.aws.amazon.com/general/latest/gr/sigv4-create-canonical-request.html """ - timenow = datetime.utcnow() + timenow = salt.utils.timeutil.utcnow() # Retrieve access credentials from meta-data, or use provided if role_arn is None: diff --git a/salt/utils/event.py b/salt/utils/event.py index 8b6aae6caeef..dfb3f006daaa 100644 --- a/salt/utils/event.py +++ b/salt/utils/event.py @@ -75,6 +75,7 @@ import salt.utils.platform import salt.utils.process import salt.utils.stringutils +import salt.utils.timeutil import salt.utils.zeromq from salt.exceptions import SaltDeserializationError, SaltInvocationError from salt.utils.versions import warn_until @@ -782,7 +783,7 @@ async def fire_event_async(self, data, tag, cb=None, timeout=1000): if not self.connect_pull(timeout=timeout_s): return False - data["_stamp"] = datetime.datetime.now(datetime.timezone.utc).isoformat() + data["_stamp"] = salt.utils.timeutil.utcnow().isoformat() event = self.pack(tag, data, max_size=self.opts["max_event_size"]) msg = salt.utils.stringutils.to_bytes(event, "utf-8") self.pusher.publish(msg) @@ -817,7 +818,7 @@ def fire_event(self, data, tag, timeout=1000): if not self.connect_pull(timeout=timeout_s): return False - data["_stamp"] = datetime.datetime.now(datetime.timezone.utc).isoformat() + data["_stamp"] = salt.utils.timeutil.utcnow().isoformat() event = self.pack(tag, data, max_size=self.opts["max_event_size"]) msg = salt.utils.stringutils.to_bytes(event, "utf-8") if self._run_io_loop_sync: @@ -1059,9 +1060,8 @@ class AsyncEventPublisher: def __init__(self, opts, io_loop=None): warn_until( - 3008, - "salt.utils.event.AsyncEventPublisher is deprecated. " - "Please use salt.transport.publish_server instead.", + 3009, + "salt.utils.event.AsyncEventPublisher is deprecated. Please use salt.transport.publish_server instead.", ) import salt.transport.ipc @@ -1069,7 +1069,7 @@ def __init__(self, opts, io_loop=None): default_minion_sock_dir = self.opts["sock_dir"] self.opts.update(opts) - self.io_loop = io_loop or tornado.ioloop.IOLoop.current() + self.io_loop = io_loop or salt.utils.asynchronous.get_ioloop() self._closing = False self.publisher = None self.puller = None @@ -1166,9 +1166,8 @@ class EventPublisher(salt.utils.process.SignalHandlingProcess): def __init__(self, opts, **kwargs): warn_until( - 3008, - "salt.utils.event.EventPublisher is deprecated. " - "Please use salt.transport.publish_server instead.", + 3009, + "salt.utils.event.EventPublisher is deprecated. Please use salt.transport.publish_server instead.", ) super().__init__(**kwargs) self.opts = salt.config.DEFAULT_MASTER_OPTS.copy() @@ -1257,7 +1256,15 @@ def close(self): self.puller.close() self.puller = None if self.io_loop is not None: - self.io_loop.close() + # We can only close the loop if it is not running + try: + if not salt.utils.asynchronous.aioloop(self.io_loop).is_running(): + self.io_loop.close() + else: + self.io_loop.stop() + except RuntimeError: + # If we're already closing or the loop is in a weird state + pass self.io_loop = None def _handle_signals(self, signum, sigframe): diff --git a/salt/utils/nacl.py b/salt/utils/nacl.py index 63d97e6f9abb..199d970cdf7c 100644 --- a/salt/utils/nacl.py +++ b/salt/utils/nacl.py @@ -4,6 +4,8 @@ import base64 import os +import sys +import threading import salt.syspaths import salt.utils.files @@ -14,14 +16,21 @@ import salt.utils.win_functions REQ_ERROR = None -try: - import nacl.public # pylint: disable=no-name-in-module - import nacl.secret # pylint: disable=no-name-in-module -except ImportError: +if sys.version_info >= (3, 12) and "zmq" in sys.modules: REQ_ERROR = ( - "PyNaCl import error, perhaps missing python PyNaCl package or should update." + "nacl module is currently incompatible with zmq in Python 3.12+ " + "due to segmentation faults in libsodium/pyzmq interaction." ) +if REQ_ERROR is None: + try: + import nacl.public as pynacl_public # pylint: disable=no-name-in-module + import nacl.secret as pynacl_secret # pylint: disable=no-name-in-module + except ImportError: + REQ_ERROR = "PyNaCl import error, perhaps missing python PyNaCl package or should update." + +NACL_LOCK = threading.RLock() + __virtualname__ = "nacl" @@ -42,6 +51,9 @@ def _get_config(**kwargs): """ Return configuration """ + success, error = check_requirements() + if not success: + raise Exception(error) sk_file = kwargs.get("sk_file") if not sk_file: sk_file = os.path.join(kwargs["opts"].get("pki_dir"), "master/nacl") @@ -138,19 +150,25 @@ def keygen(sk_file=None, pk_file=None, **kwargs): if "keyfile" in kwargs: sk_file = kwargs["keyfile"] + success, error = check_requirements() + if not success: + raise Exception(error) + if sk_file is None: - kp = nacl.public.PrivateKey.generate() - return { - "sk": base64.b64encode(kp.encode()), - "pk": base64.b64encode(kp.public_key.encode()), - } + with NACL_LOCK: + kp = pynacl_public.PrivateKey.generate() + return { + "sk": base64.b64encode(kp.encode()), + "pk": base64.b64encode(kp.public_key.encode()), + } if pk_file is None: pk_file = f"{sk_file}.pub" if sk_file and pk_file is None: if not os.path.isfile(sk_file): - kp = nacl.public.PrivateKey.generate() + with NACL_LOCK: + kp = pynacl_public.PrivateKey.generate() with salt.utils.files.fopen(sk_file, "wb") as keyf: keyf.write(base64.b64encode(kp.encode())) if salt.utils.platform.is_windows(): @@ -182,14 +200,18 @@ def keygen(sk_file=None, pk_file=None, **kwargs): with salt.utils.files.fopen(sk_file, "rb") as keyf: sk = salt.utils.stringutils.to_unicode(keyf.read()).rstrip("\n") sk = base64.b64decode(sk) - kp = nacl.public.PrivateKey(sk) + with NACL_LOCK: + kp = pynacl_public.PrivateKey(sk) + pk_encoded = base64.b64encode(kp.public_key.encode()) with salt.utils.files.fopen(pk_file, "wb") as keyf: - keyf.write(base64.b64encode(kp.public_key.encode())) + keyf.write(pk_encoded) return f"saved pk_file: {pk_file}" - kp = nacl.public.PrivateKey.generate() + with NACL_LOCK: + kp = pynacl_public.PrivateKey.generate() + kp_encoded = base64.b64encode(kp.encode()) with salt.utils.files.fopen(sk_file, "wb") as keyf: - keyf.write(base64.b64encode(kp.encode())) + keyf.write(kp_encoded) if salt.utils.platform.is_windows(): cur_user = salt.utils.win_functions.get_current_user() salt.utils.win_dacl.set_owner(sk_file, cur_user) @@ -364,9 +386,9 @@ def sealedbox_encrypt(data, **kwargs): data = salt.utils.stringutils.to_bytes(data) pk = _get_pk(**kwargs) - keypair = nacl.public.PublicKey(pk) - b = nacl.public.SealedBox(keypair) - return base64.b64encode(b.encrypt(data)) + with NACL_LOCK: + b = pynacl_public.SealedBox(pynacl_public.PublicKey(pk)) + return base64.b64encode(b.encrypt(data)) def sealedbox_decrypt(data, **kwargs): @@ -388,44 +410,45 @@ def sealedbox_decrypt(data, **kwargs): data = salt.utils.stringutils.to_bytes(data) sk = _get_sk(**kwargs) - keypair = nacl.public.PrivateKey(sk) - b = nacl.public.SealedBox(keypair) - return b.decrypt(base64.b64decode(data)) + with NACL_LOCK: + b = pynacl_public.SealedBox(pynacl_public.PrivateKey(sk)) + return b.decrypt(base64.b64decode(data)) def secretbox_encrypt(data, **kwargs): """ Encrypt data using a secret key generated from `nacl.keygen`. - The same secret key can be used to decrypt the data using `nacl.secretbox_decrypt`. + The same secret key can be used to decrypt the data using `pynacl_secretbox_decrypt`. CLI Examples: .. code-block:: bash - salt-run nacl.secretbox_encrypt datatoenc - salt-call --local nacl.secretbox_encrypt datatoenc sk_file=/etc/salt/pki/master/nacl - salt-call --local nacl.secretbox_encrypt datatoenc sk='YmFkcGFzcwo=' + salt-run pynacl_secretbox_encrypt datatoenc + salt-call --local pynacl_secretbox_encrypt datatoenc sk_file=/etc/salt/pki/master/nacl + salt-call --local pynacl_secretbox_encrypt datatoenc sk='YmFkcGFzcwo=' """ # ensure data is in bytes data = salt.utils.stringutils.to_bytes(data) sk = _get_sk(**kwargs) - b = nacl.secret.SecretBox(sk) - return base64.b64encode(b.encrypt(data)) + with NACL_LOCK: + b = pynacl_secret.SecretBox(sk) + return base64.b64encode(b.encrypt(data)) def secretbox_decrypt(data, **kwargs): """ - Decrypt data that was encrypted using `nacl.secretbox_encrypt` using the secret key + Decrypt data that was encrypted using `pynacl_secretbox_encrypt` using the secret key that was generated from `nacl.keygen`. CLI Examples: .. code-block:: bash - salt-call nacl.secretbox_decrypt pEXHQM6cuaF7A= - salt-call --local nacl.secretbox_decrypt data='pEXHQM6cuaF7A=' sk_file=/etc/salt/pki/master/nacl - salt-call --local nacl.secretbox_decrypt data='pEXHQM6cuaF7A=' sk='YmFkcGFzcwo=' + salt-call pynacl_secretbox_decrypt pEXHQM6cuaF7A= + salt-call --local pynacl_secretbox_decrypt data='pEXHQM6cuaF7A=' sk_file=/etc/salt/pki/master/nacl + salt-call --local pynacl_secretbox_decrypt data='pEXHQM6cuaF7A=' sk='YmFkcGFzcwo=' """ if data is None: return None @@ -433,6 +456,7 @@ def secretbox_decrypt(data, **kwargs): # ensure data is in bytes data = salt.utils.stringutils.to_bytes(data) - key = _get_sk(**kwargs) - b = nacl.secret.SecretBox(key=key) - return b.decrypt(base64.b64decode(data)) + sk = _get_sk(**kwargs) + with NACL_LOCK: + b = pynacl_secret.SecretBox(sk) + return b.decrypt(base64.b64decode(data)) diff --git a/salt/utils/optsdict.py b/salt/utils/optsdict.py index 37a0e9089e5d..18366e1dff43 100644 --- a/salt/utils/optsdict.py +++ b/salt/utils/optsdict.py @@ -63,11 +63,14 @@ class DictProxy(dict): def __init__(self, target: dict, parent_optsdict: OptsDict, key: str): # Initialize underlying dict with target data AND keep _target # We need both: underlying dict for C code, _target for our logic - super().__init__(target) + # Initialize empty first to avoid triggering COW during init + super().__init__() object.__setattr__(self, "_target", target) object.__setattr__(self, "_parent", parent_optsdict) object.__setattr__(self, "_key", key) object.__setattr__(self, "_copied", False) + # Sync underlying storage using C-level update to avoid COW + dict.update(self, target) def _ensure_copied(self): """Copy target to parent's _local on first mutation.""" @@ -181,11 +184,14 @@ class ListProxy(list): def __init__(self, target: list, parent_optsdict: OptsDict, key: str): # Initialize underlying list with target data AND keep _target # We need both: underlying list for C code, _target for our logic - super().__init__(target) + # Initialize empty first to avoid triggering COW during init + super().__init__() object.__setattr__(self, "_target", target) object.__setattr__(self, "_parent", parent_optsdict) object.__setattr__(self, "_key", key) object.__setattr__(self, "_copied", False) + # Sync underlying storage using C-level extend to avoid COW + list.extend(self, target) def _ensure_copied(self): """Copy target to parent's _local on first mutation.""" @@ -964,9 +970,14 @@ def __deepcopy__(self, memo): more memory efficient. When the copied OptsDict is modified, only the modified keys are copied, not the entire dict. """ + if id(self) in memo: + return memo[id(self)] + # Use copy-on-write by creating a child OptsDict # This shares data with parent until mutations occur child = OptsDict.from_parent(self, name=f"{self._name}_deepcopy") + memo[id(self)] = child + # Sync underlying dict to support C-level iteration (e.g., JSON serialization) # This ensures json.dumps() works without needing to call __iter__() first list(child) # Triggers __iter__() which syncs the underlying dict diff --git a/salt/utils/thin.py b/salt/utils/thin.py index 3f31945aa990..c46cad8ee0be 100644 --- a/salt/utils/thin.py +++ b/salt/utils/thin.py @@ -699,8 +699,8 @@ def _discover_saltexts(allowlist=None, blocklist=None): dist_name, ) continue - if entry_point.dist.name not in loaded_saltexts: - loaded_saltexts[entry_point.dist.name] = { + if dist_name not in loaded_saltexts: + loaded_saltexts[dist_name] = { "name": dist_name, "entrypoints": {}, } @@ -711,9 +711,7 @@ def _discover_saltexts(allowlist=None, blocklist=None): if ctx.exception_caught: continue - loaded_saltexts[entry_point.dist.name]["entrypoints"][ - entry_point.name - ] = entry_point.value + loaded_saltexts[dist_name]["entrypoints"][entry_point.name] = entry_point.value _add_dependency(mods, root_mod, namespace=namespace) # We need the mods to be in a deterministic order for the hash digest later diff --git a/salt/utils/timeutil.py b/salt/utils/timeutil.py index 0985ec504be6..462faff45f42 100644 --- a/salt/utils/timeutil.py +++ b/salt/utils/timeutil.py @@ -5,14 +5,48 @@ # Import Python import logging import re +import sys import time -from datetime import datetime, timedelta +from datetime import datetime, timedelta, timezone # Import Salt modules log = logging.getLogger(__name__) +def utcnow(): + """ + Return current UTC time as a naive datetime object. + + In Python 3.12+, datetime.utcnow() is deprecated in favor of + datetime.now(timezone.utc). This function provides compatibility + by returning a naive datetime (without timezone info) to match + the behavior of the deprecated datetime.utcnow(). + """ + if sys.version_info >= (3, 12): + return datetime.now(timezone.utc).replace(tzinfo=None) + else: + return datetime.utcnow() + + +def utcfromtimestamp(timestamp): + """ + Return a naive datetime from a POSIX timestamp. + + In Python 3.12+, datetime.utcfromtimestamp() is deprecated in favor of + datetime.fromtimestamp(timestamp, tz=timezone.utc). This function provides + compatibility by returning a naive datetime (without timezone info) to match + the behavior of the deprecated datetime.utcfromtimestamp(). + + Args: + timestamp: POSIX timestamp (seconds since epoch) + """ + if sys.version_info >= (3, 12): + return datetime.fromtimestamp(timestamp, tz=timezone.utc).replace(tzinfo=None) + else: + return datetime.utcfromtimestamp(timestamp) + + def get_timestamp_at(time_in=None, time_at=None): """ Computes the timestamp for a future event that may occur in ``time_in`` time @@ -34,7 +68,7 @@ def get_timestamp_at(time_in=None, time_at=None): minutes = 0 hours, minutes = int(hours), int(minutes) dt = timedelta(hours=hours, minutes=minutes) - time_now = datetime.utcnow() + time_now = utcnow() time_at = time_now + dt return time.mktime(time_at.timetuple()) elif time_at: diff --git a/salt/utils/versions.py b/salt/utils/versions.py index d64d2d66f3fd..9f535c91bd86 100644 --- a/salt/utils/versions.py +++ b/salt/utils/versions.py @@ -244,7 +244,7 @@ def warn_until_date( # Attribute the warning to the calling function, not to warn_until_date() stacklevel = 2 - today = _current_date or datetime.datetime.utcnow().date() + today = _current_date or datetime.datetime.now(datetime.timezone.utc).date() if today >= date: caller = inspect.getframeinfo(sys._getframe(stacklevel - 1)) deprecated_message = ( diff --git a/tests/conftest.py b/tests/conftest.py index 807ee5118858..d6f6fdff2937 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1345,20 +1345,27 @@ def bridge_pytest_and_runtests( RUNTIME_VARS.TMP_SYNDIC_MINION_CONF_DIR = os.path.dirname( salt_syndic_factory.config["conf_file"] ) - RUNTIME_VARS.TMP_SSH_CONF_DIR = str(sshd_config_dir) + if sshd_config_dir: + RUNTIME_VARS.TMP_SSH_CONF_DIR = str(sshd_config_dir) with reap_stray_processes(): yield @pytest.fixture(scope="session") def sshd_config_dir(salt_factories): + if not shutil.which("sshd"): + yield None + return config_dir = salt_factories.get_root_dir_for_daemon("sshd") + yield config_dir shutil.rmtree(str(config_dir), ignore_errors=True) @pytest.fixture(scope="module") def sshd_server(salt_factories, sshd_config_dir, salt_master, grains): + if not shutil.which("sshd"): + pytest.skip("The 'sshd' binary was not found. Skipping salt-ssh tests.") sshd_config_dict = { "Protocol": "2", # Turn strict modes off so that we can operate in /tmp diff --git a/tests/integration/modules/test_saltcheck.py b/tests/integration/modules/test_saltcheck.py index 914b046fdd71..05dbb392e126 100644 --- a/tests/integration/modules/test_saltcheck.py +++ b/tests/integration/modules/test_saltcheck.py @@ -25,7 +25,7 @@ def test_saltcheck_run(self): "args": ["This works!"], } ret = self.run_function("saltcheck.run_test", test=saltcheck_test) - self.assertDictContainsSubset({"status": "Pass"}, ret) + self.assertEqual(ret.get("status"), "Pass") @pytest.mark.slow_test def test_saltcheck_state(self): @@ -34,10 +34,10 @@ def test_saltcheck_state(self): """ saltcheck_test = "validate-saltcheck" ret = self.run_function("saltcheck.run_state_tests", [saltcheck_test]) - self.assertDictContainsSubset( - {"status": "Pass"}, ret[0]["validate-saltcheck"]["echo_test_hello"] + self.assertEqual( + ret[0]["validate-saltcheck"]["echo_test_hello"].get("status"), "Pass" ) - self.assertDictContainsSubset({"Failed": 0}, ret[1]["TEST RESULTS"]) + self.assertEqual(ret[1]["TEST RESULTS"].get("Failed"), 0) @pytest.mark.slow_test def test_topfile_validation(self): @@ -61,11 +61,11 @@ def test_saltcheck_checkall(self): ret = self.run_function( "saltcheck.run_state_tests", [saltcheck_test], check_all=True ) - self.assertDictContainsSubset( - {"status": "Pass"}, ret[0]["validate-saltcheck"]["echo_test_hello"] + self.assertEqual( + ret[0]["validate-saltcheck"]["echo_test_hello"].get("status"), "Pass" ) - self.assertDictContainsSubset( - {"status": "Pass"}, ret[0]["validate-saltcheck"]["check_all_validate"] + self.assertEqual( + ret[0]["validate-saltcheck"]["check_all_validate"].get("status"), "Pass" ) @pytest.mark.slow_test @@ -82,11 +82,12 @@ def test_saltcheck_checkall_saltenv(self): saltenv="prod", check_all=True, ) - self.assertDictContainsSubset( - {"status": "Pass"}, ret[0]["validate-saltcheck"]["echo_test_prod_env"] + self.assertEqual( + ret[0]["validate-saltcheck"]["echo_test_prod_env"].get("status"), "Pass" ) - self.assertDictContainsSubset( - {"status": "Pass"}, ret[0]["validate-saltcheck"]["check_all_validate_prod"] + self.assertEqual( + ret[0]["validate-saltcheck"]["check_all_validate_prod"].get("status"), + "Pass", ) @pytest.mark.slow_test @@ -98,6 +99,6 @@ def test_saltcheck_saltenv(self): ret = self.run_function( "saltcheck.run_state_tests", [saltcheck_test], saltenv="prod" ) - self.assertDictContainsSubset( - {"status": "Pass"}, ret[0]["validate-saltcheck"]["echo_test_prod_env"] + self.assertEqual( + ret[0]["validate-saltcheck"]["echo_test_prod_env"].get("status"), "Pass" ) diff --git a/tests/pytests/functional/modules/test_pip.py b/tests/pytests/functional/modules/test_pip.py index 0537e0ca68d0..e7b621aefdd0 100644 --- a/tests/pytests/functional/modules/test_pip.py +++ b/tests/pytests/functional/modules/test_pip.py @@ -74,8 +74,20 @@ def _pip_successful_install( reason="'pip==9.0.3' is not available on Py >= 3.10", ), ), - "pip<20.0", - "pip<21.0", + pytest.param( + "pip<20.0", + marks=pytest.mark.skipif( + sys.version_info >= (3, 12), + reason="pip < 20.0 is not compatible with Python >= 3.12", + ), + ), + pytest.param( + "pip<21.0", + marks=pytest.mark.skipif( + sys.version_info >= (3, 12), + reason="pip < 21.0 is not compatible with Python >= 3.12", + ), + ), "pip>=21.0", ), ) @@ -92,17 +104,33 @@ def test_list_available_packages(pip, pip_version, tmp_path): @pytest.mark.parametrize( "pip_version", ( - "pip==9.0.3", - "pip<20.0", - "pip<21.0", + pytest.param( + "pip==9.0.3", + marks=pytest.mark.skipif( + sys.version_info >= (3, 10), + reason="'pip==9.0.3' is not available on Py >= 3.10", + ), + ), + pytest.param( + "pip<20.0", + marks=pytest.mark.skipif( + sys.version_info >= (3, 12), + reason="pip < 20.0 is not compatible with Python >= 3.12", + ), + ), + pytest.param( + "pip<21.0", + marks=pytest.mark.skipif( + sys.version_info >= (3, 12), + reason="pip < 21.0 is not compatible with Python >= 3.12", + ), + ), "pip>=21.0", ), ) def test_list_available_packages_with_index_url(pip, pip_version, tmp_path): if sys.version_info < (3, 6) and pip_version == "pip>=21.0": pytest.skip(f"{pip_version} is not available on Py3.5") - if sys.version_info >= (3, 10) and pip_version == "pip==9.0.3": - pytest.skip(f"{pip_version} is not available on Py3.10") with VirtualEnv(venv_dir=tmp_path, pip_requirement=pip_version) as virtualenv: virtualenv.install("-U", pip_version) package_name = "pep8" diff --git a/tests/pytests/functional/modules/test_pkg.py b/tests/pytests/functional/modules/test_pkg.py index ccbe5452b007..575efafbc317 100644 --- a/tests/pytests/functional/modules/test_pkg.py +++ b/tests/pytests/functional/modules/test_pkg.py @@ -218,9 +218,9 @@ def test_owner(modules, grains): test finding the package owning a file """ binary = "/bin/ls" - if grains["os"] == "Ubuntu" and grains["osmajorrelease"] >= 24: + if grains["os"] == "Ubuntu" and grains.get("osmajorrelease", 0) >= 24: binary = "/usr/bin/ls" - if grains["os"] == "Debian" and grains["osmajorrelease"] >= 13: + if grains["os"] == "Debian" and grains.get("osmajorrelease", 0) >= 13: binary = "/usr/bin/ls" ret = modules.pkg.owner(binary) @@ -235,9 +235,9 @@ def test_which(modules, grains): test finding the package owning a file """ binary = "/bin/ls" - if grains["os"] == "Ubuntu" and grains["osmajorrelease"] >= 24: + if grains["os"] == "Ubuntu" and grains.get("osmajorrelease", 0) >= 24: binary = "/usr/bin/ls" - elif grains["os"] == "Debian" and grains["osmajorrelease"] >= 13: + elif grains["os"] == "Debian" and grains.get("osmajorrelease", 0) >= 13: binary = "/usr/bin/ls" ret = modules.pkg.which(binary) assert len(ret) != 0 diff --git a/tests/pytests/functional/modules/test_system.py b/tests/pytests/functional/modules/test_system.py index 6f9e5b19d894..56ea99840ce1 100644 --- a/tests/pytests/functional/modules/test_system.py +++ b/tests/pytests/functional/modules/test_system.py @@ -10,6 +10,7 @@ import pytest import salt.utils.files +import salt.utils.timeutil from salt.exceptions import CommandExecutionError pytestmark = [ @@ -82,7 +83,7 @@ def fmt_str(): @pytest.fixture(scope="function") def setup_teardown_vars(file, service, system): _systemd_timesyncd_available_ = None - _orig_time = datetime.datetime.utcnow() + _orig_time = salt.utils.timeutil.utcnow() if os.path.isfile("/etc/machine-info"): with salt.utils.files.fopen("/etc/machine-info", "r") as mach_info: @@ -232,7 +233,7 @@ def test_get_system_date_time_utc(setup_teardown_vars, system, fmt_str): """ Test we are able to get the correct time with utc """ - t1 = datetime.datetime.utcnow() + t1 = salt.utils.timeutil.utcnow() res = system.get_system_date_time("+0000") t2 = datetime.datetime.strptime(res, fmt_str) msg = f"Difference in times is too large. Now: {t1} Fake: {t2}" @@ -268,10 +269,10 @@ def test_set_system_date_time_utc(setup_teardown_vars, system, hwclock_has_compa Test changing the system clock. We are only able to set it up to a resolution of a second so this test may appear to run in negative time. """ - cmp_time = datetime.datetime.utcnow() - datetime.timedelta(days=7) + cmp_time = salt.utils.timeutil.utcnow() - datetime.timedelta(days=7) result = _set_time(system, cmp_time, offset="+0000") - time_now = datetime.datetime.utcnow() + time_now = salt.utils.timeutil.utcnow() msg = "Difference in times is too large. Now: {} Fake: {}".format( time_now, cmp_time @@ -291,11 +292,11 @@ def test_set_system_date_time_utcoffset_east( Test changing the system clock. We are only able to set it up to a resolution of a second so this test may appear to run in negative time. """ - cmp_time = datetime.datetime.utcnow() - datetime.timedelta(days=7) + cmp_time = salt.utils.timeutil.utcnow() - datetime.timedelta(days=7) # 25200 seconds = 7 hours time_to_set = cmp_time - datetime.timedelta(seconds=25200) result = _set_time(system, time_to_set, offset="-0700") - time_now = datetime.datetime.utcnow() + time_now = salt.utils.timeutil.utcnow() msg = "Difference in times is too large. Now: {} Fake: {}".format( time_now, cmp_time @@ -315,11 +316,11 @@ def test_set_system_date_time_utcoffset_west( Test changing the system clock. We are only able to set it up to a resolution of a second so this test may appear to run in negative time. """ - cmp_time = datetime.datetime.utcnow() - datetime.timedelta(days=7) + cmp_time = salt.utils.timeutil.utcnow() - datetime.timedelta(days=7) # 7200 seconds = 2 hours time_to_set = cmp_time + datetime.timedelta(seconds=7200) result = _set_time(system, time_to_set, offset="+0200") - time_now = datetime.datetime.utcnow() + time_now = salt.utils.timeutil.utcnow() msg = "Difference in times is too large. Now: {} Fake: {}".format( time_now, cmp_time diff --git a/tests/pytests/functional/states/test_pip_state.py b/tests/pytests/functional/states/test_pip_state.py index 04db04c87b06..597b5fe7192b 100644 --- a/tests/pytests/functional/states/test_pip_state.py +++ b/tests/pytests/functional/states/test_pip_state.py @@ -448,17 +448,29 @@ def test_issue_6833_pip_upgrade_pip(tmp_path, create_virtualenv, modules, states wheels_dir = tmp_path / "wheels" wheels_dir.mkdir() - pip_22_0_4_url = "https://files.pythonhosted.org/packages/4d/16/0a14ca596f30316efd412a60bdfac02a7259bf8673d4d917dc60b9a21812/pip-22.0.4-py3-none-any.whl" - pip_22_1_2_url = "https://files.pythonhosted.org/packages/96/2f/caec18213f6a67852f6997fb0673ae08d2e93d1b81573edb93ba4ef06970/pip-22.1.2-py3-none-any.whl" + pip_version_url = "https://files.pythonhosted.org/packages/4d/16/0a14ca596f30316efd412a60bdfac02a7259bf8673d4d917dc60b9a21812/pip-22.0.4-py3-none-any.whl" + pip_upgrade_url = "https://files.pythonhosted.org/packages/96/2f/caec18213f6a67852f6997fb0673ae08d2e93d1b81573edb93ba4ef06970/pip-22.1.2-py3-none-any.whl" + + if sys.version_info >= (3, 12): + # Python 3.12+ requires pip >= 23.2 to avoid distutils dependency + pip_version = "23.2.1" + pip_upgrade = "23.3.2" + pip_version_url = "https://files.pythonhosted.org/packages/50/c2/e06851e8cc28dcad7c155f4753da8833ac06a5c704c109313b8d5a62968a/pip-23.2.1-py3-none-any.whl" + pip_upgrade_url = "https://files.pythonhosted.org/packages/15/aa/3f4c7bcee2057a76562a5b33ecbd199be08cdb4443a02e26bd2c3cf6fc39/pip-23.3.2-py3-none-any.whl" + else: + + pip_version = "22.0.4" + pip_upgrade = "22.1.2" - for url in (pip_22_0_4_url, pip_22_1_2_url): - subprocess.check_call(["curl", "-L", "-O", url], cwd=str(wheels_dir)) + for url in (pip_version_url, pip_upgrade_url): + filename = url.rsplit("/", maxsplit=1)[-1] + subprocess.check_call(["curl", "-L", "-o", filename, url], cwd=str(wheels_dir)) # Use local wheels with patched_environ(PIP_NO_INDEX="1", PIP_FIND_LINKS=str(wheels_dir)): # Let's install a fixed version pip over whatever pip was # previously installed - ret = modules.pip.install("pip==22.0.4", upgrade=True, bin_env=venv_dir) + ret = modules.pip.install(f"pip=={pip_version}", upgrade=True, bin_env=venv_dir) if not isinstance(ret, dict): pytest.fail( @@ -469,11 +481,13 @@ def test_issue_6833_pip_upgrade_pip(tmp_path, create_virtualenv, modules, states assert ret["retcode"] == 0 assert "Successfully installed pip" in ret["stdout"] - # Let's make sure we have pip 22.0.4 installed - assert modules.pip.list("pip", bin_env=venv_dir) == {"pip": "22.0.4"} + # Let's make sure we have pip installed + assert modules.pip.list("pip", bin_env=venv_dir) == {"pip": pip_version} # Now the actual pip upgrade pip test - ret = states.pip.installed(name="pip==22.1.2", upgrade=True, bin_env=venv_dir) + ret = states.pip.installed( + name=f"pip=={pip_upgrade}", upgrade=True, bin_env=venv_dir + ) if not isinstance(ret.raw, dict): pytest.fail( @@ -482,7 +496,7 @@ def test_issue_6833_pip_upgrade_pip(tmp_path, create_virtualenv, modules, states ) assert ret.result is True - assert ret.changes == {"pip==22.1.2": "Installed"} + assert ret.changes == {f"pip=={pip_upgrade}": "Installed"} @pytest.mark.slow_test diff --git a/tests/pytests/functional/states/test_ssh_auth.py b/tests/pytests/functional/states/test_ssh_auth.py index fea9a29df6c9..456e40aaeb10 100644 --- a/tests/pytests/functional/states/test_ssh_auth.py +++ b/tests/pytests/functional/states/test_ssh_auth.py @@ -4,6 +4,7 @@ import pytest import salt.states.ssh_auth as ssh_auth_state +import salt.utils.asynchronous import salt.utils.files log = logging.getLogger(__name__) @@ -11,7 +12,13 @@ @pytest.fixture def configure_loader_modules(modules, minion_opts): - loader = {"__salt__": modules, "__opts__": minion_opts, "__env__": "base"} + io_loop = salt.utils.asynchronous.get_ioloop() + loader = { + "__salt__": modules, + "__opts__": minion_opts, + "__env__": "base", + "io_loop": io_loop, + } return {ssh_auth_state: loader} @@ -35,11 +42,11 @@ def test_ssh_auth_config(tmp_path, system_user, state_tree): ret = ssh_auth_state.manage( name="test", user=system_user.username, - ssh_keys=["ssh-dss AAAAB3NzaCL0sQ9fJ5bYTEyY== root@domain"], + ssh_keys=["ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC6G9ID root@domain"], ) with salt.utils.files.fopen(user_ssh_dir / "authorized_keys") as fp: pre_data = fp.read() - file_contents = "ssh-dss AAAAB3NzaCL0sQ9fJ5bYTEyY== root@domain" + file_contents = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC6G9ID root@domain" new_auth_file = tmp_path / "authorized_keys3" with pytest.helpers.temp_file("authorized", file_contents, state_tree): ssh_auth_state.manage( @@ -47,7 +54,7 @@ def test_ssh_auth_config(tmp_path, system_user, state_tree): user=system_user.username, source="salt://authorized", config=str(new_auth_file), - ssh_keys=[""], + ssh_keys=["ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC6G9ID root@domain"], ) with salt.utils.files.fopen(user_ssh_dir / "authorized_keys") as fp: post_data = fp.read() diff --git a/tests/pytests/functional/transport/zeromq/test_request_client.py b/tests/pytests/functional/transport/zeromq/test_request_client.py index e165a09cbec1..3ef30076bc5d 100644 --- a/tests/pytests/functional/transport/zeromq/test_request_client.py +++ b/tests/pytests/functional/transport/zeromq/test_request_client.py @@ -151,6 +151,8 @@ def test_request_client_send_recv_loop_closed(minion_opts, port, caplog): serve_socket.bind(minion_opts["master_uri"]) minion_opts["master_uri"] = f"tcp://127.0.0.1:{port}" request_client = salt.transport.zeromq.RequestClient(minion_opts, io_loop) + # Initialize the socket before trying to access it + request_client._init_socket() def poll(*args, **kwargs): """ @@ -208,7 +210,7 @@ async def send(*args, **kwargs): if errno == zmq.EFSM: assert "Socket was found in invalid state." in caplog.messages elif errno != 321: - assert "Recieve socket closed while polling." in caplog.messages + assert "Receive socket closed while polling." in caplog.messages else: assert ( "Unhandled Zeromq error durring send/receive: Unknown error 321" @@ -315,7 +317,7 @@ def poll(*args, **kwargs): try: await request_client.send("meh") await asyncio.sleep(0.3) - assert "Recieve socket closed while polling." in caplog.messages + assert "Receive socket closed while polling." in caplog.messages assert f"Send and receive coroutine ending {socket}" in caplog.messages finally: request_client.close() diff --git a/tests/pytests/integration/cli/test_salt_key.py b/tests/pytests/integration/cli/test_salt_key.py index 73b19e2b1c40..8b6209bfe7d7 100644 --- a/tests/pytests/integration/cli/test_salt_key.py +++ b/tests/pytests/integration/cli/test_salt_key.py @@ -160,13 +160,8 @@ def test_list_all(salt_key_cli, salt_minion, salt_sub_minion): """ ret = salt_key_cli.run("-L") assert ret.returncode == 0 - expected = { - "minions_rejected": [], - "minions_denied": [], - "minions_pre": [], - "minions": [salt_minion.id, salt_sub_minion.id], - } - assert ret.data == expected + assert salt_minion.id in ret.data["minions"] + assert salt_sub_minion.id in ret.data["minions"] def test_list_all_no_check_files( @@ -191,13 +186,8 @@ def test_list_all_no_check_files( "-L", ) assert ret.returncode == 0 - expected = { - "minions_rejected": [], - "minions_denied": [], - "minions_pre": [], - "minions": [salt_minion.id, salt_sub_minion.id], - } - assert ret.data == expected + assert salt_minion.id in ret.data["minions"] + assert salt_sub_minion.id in ret.data["minions"] bad_key = pki_dir / "minions" / "dir1" bad_key.mkdir() @@ -207,7 +197,8 @@ def test_list_all_no_check_files( "-L", ) assert ret.returncode == 0 - assert ret.data == expected + assert salt_minion.id in ret.data["minions"] + assert salt_sub_minion.id in ret.data["minions"] def test_list_all_yaml_out(salt_key_cli, salt_minion, salt_sub_minion): @@ -217,13 +208,8 @@ def test_list_all_yaml_out(salt_key_cli, salt_minion, salt_sub_minion): ret = salt_key_cli.run("-L", "--out=yaml") assert ret.returncode == 0 output = salt.utils.yaml.safe_load(str(ret.stdout)) - expected = { - "minions_rejected": [], - "minions_denied": [], - "minions_pre": [], - "minions": [salt_minion.id, salt_sub_minion.id], - } - assert output == expected + assert salt_minion.id in output["minions"] + assert salt_sub_minion.id in output["minions"] def test_list_all_raw_out(salt_key_cli, salt_minion, salt_sub_minion): @@ -233,13 +219,8 @@ def test_list_all_raw_out(salt_key_cli, salt_minion, salt_sub_minion): ret = salt_key_cli.run("-L", "--out=raw") assert ret.returncode == 0 output = ast.literal_eval(ret.stdout) - expected = { - "minions_rejected": [], - "minions_denied": [], - "minions_pre": [], - "minions": [salt_minion.id, salt_sub_minion.id], - } - assert output == expected + assert salt_minion.id in output["minions"] + assert salt_sub_minion.id in output["minions"] def test_list_acc(salt_key_cli, salt_minion, salt_sub_minion): @@ -248,8 +229,8 @@ def test_list_acc(salt_key_cli, salt_minion, salt_sub_minion): """ ret = salt_key_cli.run("-l", "acc") assert ret.returncode == 0 - expected = {"minions": [salt_minion.id, salt_sub_minion.id]} - assert ret.data == expected + assert salt_minion.id in ret.data["minions"] + assert salt_sub_minion.id in ret.data["minions"] @pytest.mark.skip_if_not_root @@ -270,8 +251,8 @@ def test_list_acc_eauth(salt_key_cli, salt_minion, salt_sub_minion, salt_eauth_a salt_eauth_account.password, ) assert ret.returncode == 0 - expected = {"minions": [salt_minion.id, salt_sub_minion.id]} - assert ret.data == expected + assert salt_minion.id in ret.data["minions"] + assert salt_sub_minion.id in ret.data["minions"] @pytest.mark.skip_if_not_root diff --git a/tests/pytests/integration/minion/test_process_name.py b/tests/pytests/integration/minion/test_process_name.py index 54c859217fbf..cc32486e9d3a 100644 --- a/tests/pytests/integration/minion/test_process_name.py +++ b/tests/pytests/integration/minion/test_process_name.py @@ -2,6 +2,10 @@ Test process name behavior with multiprocessing enabled and disabled. """ +import pytest + +import salt.utils.process + def test_process_name_no_pollution_when_multiprocessing_disabled( salt_master_factory, @@ -112,6 +116,9 @@ def test_process_name_normal_when_multiprocessing_enabled( ) +@pytest.mark.skipif( + not salt.utils.process.HAS_SETPROCTITLE, reason="setproctitle not installed" +) def test_process_name_includes_minion_process_manager( salt_master_factory, ): @@ -145,17 +152,21 @@ def test_process_name_includes_minion_process_manager( ret = cli.run("ps.proc_info", minion_pid, minion_tgt=minion.id) assert ret.returncode == 0, f"Failed to get process info for PID {minion_pid}" - # Get the process command line + # Get the process command line and name proc_info = ret.data cmdline = " ".join(proc_info.get("cmdline", [])) + name = proc_info.get("name", "") # The process title should include either MinionProcessManager or MultiMinionProcessManager # This validates the fix for minion process managers to append their name # even when running in MainProcess has_minion_pm = ( - "MinionProcessManager" in cmdline or "MultiMinionProcessManager" in cmdline + "MinionProcessManager" in cmdline + or "MultiMinionProcessManager" in cmdline + or "MinionProcessManager" in name + or "MultiMinionProcessManager" in name ) assert has_minion_pm, ( - f"Process cmdline should contain 'MinionProcessManager' or " - f"'MultiMinionProcessManager', but got: {cmdline}" + f"Process cmdline or name should contain 'MinionProcessManager' or " + f"'MultiMinionProcessManager', but got cmdline: {cmdline}, name: {name}" ) diff --git a/tests/pytests/integration/states/test_pip_state.py b/tests/pytests/integration/states/test_pip_state.py index ad7f52582760..34e32bdd410f 100644 --- a/tests/pytests/integration/states/test_pip_state.py +++ b/tests/pytests/integration/states/test_pip_state.py @@ -1,5 +1,6 @@ import os import subprocess +import sys import pytest @@ -35,11 +36,29 @@ def _extra_requirements(): "pip_contraint", [ # Latest pip 18 - "<19.0", + pytest.param( + "<19.0", + marks=pytest.mark.skipif( + sys.version_info >= (3, 12), + reason="pip < 19.0 is not compatible with Python >= 3.12", + ), + ), # Latest pip 19 - "<20.0", + pytest.param( + "<20.0", + marks=pytest.mark.skipif( + sys.version_info >= (3, 12), + reason="pip < 20.0 is not compatible with Python >= 3.12", + ), + ), # Latest pip 20 - "<21.0", + pytest.param( + "<21.0", + marks=pytest.mark.skipif( + sys.version_info >= (3, 12), + reason="pip < 21.0 is not compatible with Python >= 3.12", + ), + ), # Latest pip None, ], diff --git a/tests/pytests/pkg/integration/test_pip.py b/tests/pytests/pkg/integration/test_pip.py index 6115ce6ba3a0..fa8f01c2df05 100644 --- a/tests/pytests/pkg/integration/test_pip.py +++ b/tests/pytests/pkg/integration/test_pip.py @@ -76,12 +76,8 @@ def test_pip_install(salt_call_cli, install_salt, shell): def extras_pypath(install_salt): # Handle both single-element (Path) and multi-element (path components) lists python_path = install_salt.binary_paths["python"] - if len(python_path) == 1: - python_bin = str(python_path[0]) - else: - python_bin = os.path.join(*python_path) - ret = subprocess.run([python_bin, "--version"], check=True, capture_output=True) - v = packaging.version.Version(ret.stdout.decode().split()[1]) + ret = install_salt.proc.run(*python_path, "--version") + v = packaging.version.Version(ret.stdout.strip().split()[1]) extras_dir = f"extras-{v.major}.{v.minor}" if platform.is_windows(): @@ -99,12 +95,12 @@ def extras_pypath_bin(extras_pypath): return extras_pypath / "bin" -def test_pip_install_extras(shell, install_salt, extras_pypath_bin): +def test_pip_install_extras(shell, install_salt, extras_pypath_bin, extras_pypath): """ Test salt-pip installs into the correct directory """ dep = "pep8" - extras_keyword = "extras-3" + extras_keyword = extras_pypath.name if platform.is_windows(): check_path = extras_pypath_bin / f"{dep}.exe" else: diff --git a/tests/pytests/pkg/integration/test_salt_minion.py b/tests/pytests/pkg/integration/test_salt_minion.py index 1a06db1b1f3b..e660e3c12be1 100644 --- a/tests/pytests/pkg/integration/test_salt_minion.py +++ b/tests/pytests/pkg/integration/test_salt_minion.py @@ -1,5 +1,7 @@ import pytest +import salt.utils.process + pytestmark = [ pytest.mark.skip_on_windows, ] @@ -16,6 +18,9 @@ def test_salt_minion_ping(salt_cli, salt_minion, salt_master): assert ret.data is True +@pytest.mark.skipif( + not salt.utils.process.HAS_SETPROCTITLE, reason="setproctitle not installed" +) def test_salt_minion_setproctitle(salt_cli, salt_minion, salt_master): """ Test that setproctitle is working diff --git a/tests/pytests/unit/beacons/test_log_beacon.py b/tests/pytests/unit/beacons/test_log_beacon.py index cff24d1cacde..e3b36088d89c 100644 --- a/tests/pytests/unit/beacons/test_log_beacon.py +++ b/tests/pytests/unit/beacons/test_log_beacon.py @@ -42,7 +42,9 @@ def test_empty_config(): def test_log_match(stub_log_entry, caplog): with patch("salt.utils.files.fopen", mock_open(read_data=stub_log_entry)): - with caplog.at_level(logging.TRACE, logger="salt.beacons.log_beacon"): + with caplog.at_level( + getattr(logging, "TRACE", 5), logger="salt.beacons.log_beacon" + ): config = [ {"file": "/var/log/auth.log", "tags": {"sshd": {"regex": ".*sshd.*"}}} ] diff --git a/tests/pytests/unit/client/ssh/test_single.py b/tests/pytests/unit/client/ssh/test_single.py index 87ce0bd39f32..903d6aaf9653 100644 --- a/tests/pytests/unit/client/ssh/test_single.py +++ b/tests/pytests/unit/client/ssh/test_single.py @@ -474,7 +474,7 @@ def test_run_ssh_pre_flight_no_connect(opts, target, tmp_path, caplog, mock_bin_ send_mock = MagicMock(return_value=ret_send) patch_send = patch("salt.client.ssh.shell.Shell.send", send_mock) - with caplog.at_level(logging.TRACE, logger="salt.client.ssh"): + with caplog.at_level(5, logger="salt.client.ssh"): with patch_send, patch_exec_cmd, patch_tmp: ret = single.run_ssh_pre_flight() @@ -569,7 +569,7 @@ def test_run_ssh_pre_flight_connect(opts, target, tmp_path, caplog, mock_bin_pat send_mock = MagicMock(return_value=ret_send) patch_send = patch("salt.client.ssh.shell.Shell.send", send_mock) - with caplog.at_level(logging.TRACE, logger="salt.client.ssh"): + with caplog.at_level(5, logger="salt.client.ssh"): with patch_send, patch_exec_cmd, patch_tmp: ret = single.run_ssh_pre_flight() diff --git a/tests/pytests/unit/modules/test_nacl.py b/tests/pytests/unit/modules/test_nacl.py index 2906ebc5419a..b179b975701e 100644 --- a/tests/pytests/unit/modules/test_nacl.py +++ b/tests/pytests/unit/modules/test_nacl.py @@ -4,14 +4,10 @@ import pytest +import salt.modules.nacl as nacl import salt.utils.stringutils from tests.support.mock import patch -pytest.importorskip("nacl.public") -pytest.importorskip("nacl.secret") - -import salt.modules.nacl as nacl - @pytest.fixture def configure_loader_modules(minion_opts): @@ -51,51 +47,62 @@ def test_fips_mode(): assert ret == (False, "nacl module not available in FIPS mode") -def test_keygen(test_keys): - """ - Test keygen - """ - test_pk, test_sk = test_keys - assert len(test_pk) == 44 - assert len(test_sk) == 44 - - -def test_enc_dec(test_data, test_keys): - """ - Generate keys, encrypt, then decrypt. - """ - # Encrypt with pk - test_pk, test_sk = test_keys - encrypted_data = nacl.enc(data=test_data, pk=test_pk) - - # Decrypt with sk - decrypted_data = nacl.dec(data=encrypted_data, sk=test_sk) - assert test_data == decrypted_data - - -def test_sealedbox_enc_dec(test_data, test_keys): - """ - Generate keys, encrypt, then decrypt. - """ - # Encrypt with pk - test_pk, test_sk = test_keys - encrypted_data = nacl.sealedbox_encrypt(data=test_data, pk=test_pk) - - # Decrypt with sk - decrypted_data = nacl.sealedbox_decrypt(data=encrypted_data, sk=test_sk) - - assert test_data == decrypted_data - - -def test_secretbox_enc_dec(test_data, test_keys): +class TestNaclModule: """ - Generate keys, encrypt, then decrypt. + Test the nacl module. These tests are skipped if the module + fails to load (e.g. due to Python 3.12 + ZMQ incompatibility). """ - # Encrypt with sk - test_pk, test_sk = test_keys - encrypted_data = nacl.secretbox_encrypt(data=test_data, sk=test_sk) - - # Decrypt with sk - decrypted_data = nacl.secretbox_decrypt(data=encrypted_data, sk=test_sk) - assert test_data == decrypted_data + @pytest.fixture(autouse=True) + def _check_nacl(self): + # We mock __opts__ to avoid the FIPS check since that is tested separately. + with patch("salt.modules.nacl.__opts__", {"fips_mode": False}, create=True): + success, reason = nacl.__virtual__() + if success is False: + pytest.skip(reason) + + def test_keygen(self, test_keys): + """ + Test keygen + """ + test_pk, test_sk = test_keys + assert len(test_pk) == 44 + assert len(test_sk) == 44 + + def test_enc_dec(self, test_data, test_keys): + """ + Generate keys, encrypt, then decrypt. + """ + # Encrypt with pk + test_pk, test_sk = test_keys + encrypted_data = nacl.enc(data=test_data, pk=test_pk) + + # Decrypt with sk + decrypted_data = nacl.dec(data=encrypted_data, sk=test_sk) + assert test_data == decrypted_data + + def test_sealedbox_enc_dec(self, test_data, test_keys): + """ + Generate keys, encrypt, then decrypt. + """ + # Encrypt with pk + test_pk, test_sk = test_keys + encrypted_data = nacl.sealedbox_encrypt(data=test_data, pk=test_pk) + + # Decrypt with sk + decrypted_data = nacl.sealedbox_decrypt(data=encrypted_data, sk=test_sk) + + assert test_data == decrypted_data + + def test_secretbox_enc_dec(self, test_data, test_keys): + """ + Generate keys, encrypt, then decrypt. + """ + # Encrypt with sk + test_pk, test_sk = test_keys + encrypted_data = nacl.secretbox_encrypt(data=test_data, sk=test_sk) + + # Decrypt with sk + decrypted_data = nacl.secretbox_decrypt(data=encrypted_data, sk=test_sk) + + assert test_data == decrypted_data diff --git a/tests/pytests/unit/states/file/test_tidied.py b/tests/pytests/unit/states/file/test_tidied.py index 0139cd3ac76b..e1d9123cdb4c 100644 --- a/tests/pytests/unit/states/file/test_tidied.py +++ b/tests/pytests/unit/states/file/test_tidied.py @@ -8,6 +8,7 @@ import salt.utils.files import salt.utils.json import salt.utils.platform +import salt.utils.timeutil import salt.utils.win_functions import salt.utils.yaml from tests.support.mock import MagicMock, PropertyMock, patch @@ -30,7 +31,7 @@ def test__tidied(): (os.path.join("test", "test2"), ["test3"], ["file2"]), ("test", ["test1", "test2"], ["file3"]), ] - today_delta = datetime.today() - datetime.utcfromtimestamp(0) + today_delta = datetime.today() - salt.utils.timeutil.utcfromtimestamp(0) remove = MagicMock(name="file.remove") mystat = MagicMock() @@ -140,7 +141,7 @@ def test_tidied_with_exclude(): (os.path.join("test", "test2"), ["test3"], ["file2"]), ("test", ["test1", "test2"], ["file3"]), ] - today_delta = datetime.today() - datetime.utcfromtimestamp(0) + today_delta = datetime.today() - salt.utils.timeutil.utcfromtimestamp(0) mystat = MagicMock() mystat.st_atime = today_delta.total_seconds() @@ -272,7 +273,7 @@ def test_tidied_with_full_path_exclude(): (os.path.join("test", "test2"), ["test3"], ["file2"]), ("test", ["test1", "test2"], ["file3"]), ] - today_delta = datetime.today() - datetime.utcfromtimestamp(0) + today_delta = datetime.today() - salt.utils.timeutil.utcfromtimestamp(0) mystat = MagicMock() mystat.st_atime = today_delta.total_seconds() @@ -411,7 +412,9 @@ def test_tidied_age_size_args_AND_operator_age_not_size(): (os.path.join("test", "test2"), ["test3"], ["file2"]), ("test", ["test1", "test2"], ["file3"]), ] - today_delta = (datetime.today() - timedelta(days=14)) - datetime.utcfromtimestamp(0) + today_delta = ( + datetime.today() - timedelta(days=14) + ) - salt.utils.timeutil.utcfromtimestamp(0) remove = MagicMock(name="file.remove") with patch("os.walk", return_value=walker), patch( "os.path.islink", return_value=False @@ -452,7 +455,9 @@ def test_tidied_age_size_args_AND_operator_age_not_size_age_only(): (os.path.join("test", "test2"), ["test3"], ["file2"]), ("test", ["test1", "test2"], ["file3"]), ] - today_delta = (datetime.today() - timedelta(days=14)) - datetime.utcfromtimestamp(0) + today_delta = ( + datetime.today() - timedelta(days=14) + ) - salt.utils.timeutil.utcfromtimestamp(0) mystat = MagicMock() mystat.st_atime = today_delta.total_seconds() @@ -516,7 +521,9 @@ def test_tidied_age_size_args_AND_operator_size_not_age(): (os.path.join("test", "test2"), ["test3"], ["file2"]), ("test", ["test1", "test2"], ["file3"]), ] - today_delta = (datetime.today() - timedelta(days=14)) - datetime.utcfromtimestamp(0) + today_delta = ( + datetime.today() - timedelta(days=14) + ) - salt.utils.timeutil.utcfromtimestamp(0) remove = MagicMock(name="file.remove") with patch("os.walk", return_value=walker), patch( "os.path.islink", return_value=False @@ -557,7 +564,9 @@ def test_tidied_age_size_args_AND_operator_size_not_age_size_only(): (os.path.join("test", "test2"), ["test3"], ["file2"]), ("test", ["test1", "test2"], ["file3"]), ] - today_delta = (datetime.today() - timedelta(days=14)) - datetime.utcfromtimestamp(0) + today_delta = ( + datetime.today() - timedelta(days=14) + ) - salt.utils.timeutil.utcfromtimestamp(0) mystat = MagicMock() mystat.st_atime = today_delta.total_seconds() @@ -621,7 +630,9 @@ def test_tidied_age_size_args_AND_operator_size_and_age(): (os.path.join("test", "test2"), ["test3"], ["file2"]), ("test", ["test1", "test2"], ["file3"]), ] - today_delta = (datetime.today() - timedelta(days=14)) - datetime.utcfromtimestamp(0) + today_delta = ( + datetime.today() - timedelta(days=14) + ) - salt.utils.timeutil.utcfromtimestamp(0) mystat = MagicMock() mystat.st_atime = today_delta.total_seconds() @@ -713,7 +724,9 @@ def test_tidied_rmlinks(): (os.path.join("test", "test2"), ["test3"], ["link1"]), ("test", ["test1", "test2"], ["file3"]), ] - today_delta = (datetime.today() - timedelta(days=14)) - datetime.utcfromtimestamp(0) + today_delta = ( + datetime.today() - timedelta(days=14) + ) - salt.utils.timeutil.utcfromtimestamp(0) mystat = MagicMock() mystat.st_atime = today_delta.total_seconds() diff --git a/tests/pytests/unit/states/test_winrepo.py b/tests/pytests/unit/states/test_winrepo.py index 352347dc74eb..e0b5c6553ba1 100644 --- a/tests/pytests/unit/states/test_winrepo.py +++ b/tests/pytests/unit/states/test_winrepo.py @@ -60,7 +60,9 @@ def test_genrepo(): mock_empty_list = MagicMock(return_value=[]) with patch.object(salt.config, "master_config", mock_config), patch.object( os, "stat", mock_stat - ), patch.object(salt.utils.path, "os_walk", mock_empty_list), patch.dict( + ), patch("os.path.exists", MagicMock(return_value=True)), patch.object( + salt.utils.path, "os_walk", mock_empty_list + ), patch.dict( winrepo.__opts__, {"test": True} ): # With test=True diff --git a/tests/pytests/unit/test_fileserver.py b/tests/pytests/unit/test_fileserver.py index 49be3967dc40..9ed0ee564fa4 100644 --- a/tests/pytests/unit/test_fileserver.py +++ b/tests/pytests/unit/test_fileserver.py @@ -4,6 +4,7 @@ import salt.fileserver import salt.utils.files +import salt.utils.timeutil def test_diff_with_diffent_keys(): @@ -52,7 +53,7 @@ def test_future_file_list_cache_file_ignored(tmp_path): _f.write(b"\x80") # Set modification time to file list cache file to 1 year in the future - now = datetime.datetime.utcnow() + now = salt.utils.timeutil.utcnow() future = now + datetime.timedelta(days=365) mod_time = time.mktime(future.timetuple()) os.utime(os.path.join(back_cachedir, "base.p"), (mod_time, mod_time)) diff --git a/tests/pytests/unit/utils/test_aws.py b/tests/pytests/unit/utils/test_aws.py index a7ab2710a427..d265c542d43f 100644 --- a/tests/pytests/unit/utils/test_aws.py +++ b/tests/pytests/unit/utils/test_aws.py @@ -8,13 +8,14 @@ import io import os import time -from datetime import datetime, timedelta +from datetime import timedelta import pytest import requests from pytest_timeout import DEFAULT_METHOD import salt.utils.aws as aws +import salt.utils.timeutil from tests.support.helpers import patched_environ from tests.support.mock import MagicMock, patch @@ -79,11 +80,11 @@ def handle_get_mock(_, **args): def test_assumed_creds_not_updating_dictionary_while_iterating(): mock_cache = { "expired": { - "Expiration": time.mktime(datetime.utcnow().timetuple()), + "Expiration": time.mktime(salt.utils.timeutil.utcnow().timetuple()), }, "not_expired_1": { "Expiration": time.mktime( - (datetime.utcnow() + timedelta(days=1)).timetuple() + (salt.utils.timeutil.utcnow() + timedelta(days=1)).timetuple() ), "AccessKeyId": "mock_AccessKeyId", "SecretAccessKey": "mock_SecretAccessKey", @@ -91,7 +92,7 @@ def test_assumed_creds_not_updating_dictionary_while_iterating(): }, "not_expired_2": { "Expiration": time.mktime( - (datetime.utcnow() + timedelta(seconds=300)).timetuple() + (salt.utils.timeutil.utcnow() + timedelta(seconds=300)).timetuple() ), }, } @@ -104,11 +105,11 @@ def test_assumed_creds_not_updating_dictionary_while_iterating(): def test_assumed_creds_deletes_expired_key(): mock_cache = { "expired": { - "Expiration": time.mktime(datetime.utcnow().timetuple()), + "Expiration": time.mktime(salt.utils.timeutil.utcnow().timetuple()), }, "not_expired_1": { "Expiration": time.mktime( - (datetime.utcnow() + timedelta(days=1)).timetuple() + (salt.utils.timeutil.utcnow() + timedelta(days=1)).timetuple() ), "AccessKeyId": "mock_AccessKeyId", "SecretAccessKey": "mock_SecretAccessKey", @@ -116,7 +117,7 @@ def test_assumed_creds_deletes_expired_key(): }, "not_expired_2": { "Expiration": time.mktime( - (datetime.utcnow() + timedelta(seconds=300)).timetuple() + (salt.utils.timeutil.utcnow() + timedelta(seconds=300)).timetuple() ), }, } @@ -153,7 +154,7 @@ def test_creds_with_role_arn_should_always_call_assumed_creds(): access_key_id = "mock_AccessKeyId" secret_access_key = "mock_SecretAccessKey" token = "mock_Token" - expiration = (datetime.utcnow() + timedelta(seconds=900)).strftime( + expiration = (salt.utils.timeutil.utcnow() + timedelta(seconds=900)).strftime( "%Y-%m-%dT%H:%M:%SZ" ) diff --git a/tests/pytests/unit/utils/test_thin.py b/tests/pytests/unit/utils/test_thin.py index b63811e7b8b2..c9cf7f0f01f7 100644 --- a/tests/pytests/unit/utils/test_thin.py +++ b/tests/pytests/unit/utils/test_thin.py @@ -513,7 +513,7 @@ def test_get_tops(thin_ctx): "urllib3", "charset_normalizer", ] - if sys.version_info < (3, 13): + if salt.utils.thin.backports is not None: base_tops.append("backports") if salt.utils.thin.has_immutables: base_tops.extend(["immutables"]) @@ -627,7 +627,7 @@ def test_get_tops_extra_mods(thin_ctx): "foo", "bar.py", ] - if sys.version_info < (3, 13): + if salt.utils.thin.backports is not None: base_tops.append("backports") if salt.utils.thin.has_immutables: base_tops.extend(["immutables"]) @@ -749,7 +749,7 @@ def test_get_tops_so_mods(thin_ctx): "foo.so", "bar.so", ] - if sys.version_info < (3, 13): + if salt.utils.thin.backports is not None: base_tops.append("backports") if salt.utils.thin.has_immutables: base_tops.extend(["immutables"]) diff --git a/tests/pytests/unit/utils/win_lgpo/test_netsh.py b/tests/pytests/unit/utils/win_lgpo/test_netsh.py index 814ca05d364f..d7339b32dcfe 100644 --- a/tests/pytests/unit/utils/win_lgpo/test_netsh.py +++ b/tests/pytests/unit/utils/win_lgpo/test_netsh.py @@ -94,10 +94,11 @@ def test_set_firewall_settings_inbound(store, inbound): )["Inbound"] assert new.lower() == inbound finally: - ret = win_lgpo_netsh.set_firewall_settings( - profile="domain", inbound=current, store=store - ) - assert ret is True + if not (current == "NotConfigured" and store == "local"): + ret = win_lgpo_netsh.set_firewall_settings( + profile="domain", inbound=current, store=store + ) + assert ret is True @pytest.mark.destructive_test @@ -128,10 +129,11 @@ def test_set_firewall_settings_outbound(store, outbound): )["Outbound"] assert new.lower() == outbound finally: - ret = win_lgpo_netsh.set_firewall_settings( - profile="domain", outbound=current, store=store - ) - assert ret is True + if not (current == "NotConfigured" and store == "local"): + ret = win_lgpo_netsh.set_firewall_settings( + profile="domain", outbound=current, store=store + ) + assert ret is True @pytest.mark.destructive_test @@ -169,13 +171,14 @@ def test_set_firewall_logging_connections(store, setting, value): )[setting_map[setting]] assert new.lower() == value finally: - ret = win_lgpo_netsh.set_logging_settings( - profile="domain", - setting=setting, - value=current, - store=store, - ) - assert ret is True + if not (str(current).lower() == "notconfigured" and store == "local"): + ret = win_lgpo_netsh.set_logging_settings( + profile="domain", + setting=setting, + value=current, + store=store, + ) + assert ret is True @pytest.mark.destructive_test @@ -231,10 +234,11 @@ def test_set_firewall_logging_maxfilesize(store, value): )["MaxFileSize"] assert new == int(value) finally: - ret = win_lgpo_netsh.set_logging_settings( - profile="domain", setting="maxfilesize", value=current, store=store - ) - assert ret is True + if str(current).lower() != "notconfigured": + ret = win_lgpo_netsh.set_logging_settings( + profile="domain", setting="maxfilesize", value=current, store=store + ) + assert ret is True @pytest.mark.destructive_test diff --git a/tests/support/helpers.py b/tests/support/helpers.py index 92b016391bf1..ecfd914e5489 100644 --- a/tests/support/helpers.py +++ b/tests/support/helpers.py @@ -1612,8 +1612,12 @@ class VirtualEnv: @pip_requirement.default def _default_pip_requirement(self): - if os.environ.get("ONEDIR_TESTRUN", "0") == "1": - return "pip>=22.3.1,<23.0" + if os.environ.get("ONEDIR_TESTRUN", "0") == "1" or sys.version_info >= (3, 12): + # pip < 23.2 vendors pkg_resources that uses pkgutil.ImpImporter, + # which was removed in Python 3.12. Require 23.2+ to avoid + # AttributeError: module 'pkgutil' has no attribute 'ImpImporter'. + # Also, pip < 23.0 tries to import distutils which was removed in Python 3.12. + return "pip>=23.2" return "pip>=20.2.4,<21.2" @setuptools_requirement.default diff --git a/tests/support/pytest/helpers.py b/tests/support/pytest/helpers.py index 5ffbc537e4b0..5ba4537448af 100644 --- a/tests/support/pytest/helpers.py +++ b/tests/support/pytest/helpers.py @@ -325,6 +325,15 @@ def _set_group(self, value): self._group = value def __enter__(self): + if salt.utils.platform.is_windows(): + import win32com.shell.shell as shell + + if not shell.IsUserAnAdmin(): + pytest.skip( + f"Not running as administrator, cannot create account {self.username}" + ) + elif os.getuid() != 0: + pytest.skip(f"Not running as root, cannot create account {self.username}") if not self.sminion.functions.user.info(self.username): log.debug("Creating system account: %s", self) ret = self.sminion.functions.user.add(self.username) diff --git a/tests/support/pytest/transport_ssl.py b/tests/support/pytest/transport_ssl.py index 6189e24482fd..968e3e2fdb80 100644 --- a/tests/support/pytest/transport_ssl.py +++ b/tests/support/pytest/transport_ssl.py @@ -11,6 +11,7 @@ import pytest import salt.utils.files +import salt.utils.timeutil try: from cryptography import x509 @@ -56,8 +57,8 @@ def _generate_ca_certificate(private_key, common_name="Test CA"): .issuer_name(issuer) .public_key(private_key.public_key()) .serial_number(x509.random_serial_number()) - .not_valid_before(datetime.datetime.utcnow()) - .not_valid_after(datetime.datetime.utcnow() + datetime.timedelta(days=365)) + .not_valid_before(salt.utils.timeutil.utcnow()) + .not_valid_after(salt.utils.timeutil.utcnow() + datetime.timedelta(days=365)) .add_extension( x509.BasicConstraints(ca=True, path_length=0), critical=True, @@ -116,8 +117,8 @@ def _generate_certificate( .issuer_name(ca_cert.subject) .public_key(private_key.public_key()) .serial_number(x509.random_serial_number()) - .not_valid_before(datetime.datetime.utcnow()) - .not_valid_after(datetime.datetime.utcnow() + datetime.timedelta(days=365)) + .not_valid_before(salt.utils.timeutil.utcnow()) + .not_valid_after(salt.utils.timeutil.utcnow() + datetime.timedelta(days=365)) .add_extension( x509.BasicConstraints(ca=False, path_length=None), critical=True, diff --git a/tests/support/unit.py b/tests/support/unit.py index 7e2aefb43aa5..c463992af8a9 100644 --- a/tests/support/unit.py +++ b/tests/support/unit.py @@ -209,6 +209,31 @@ def run(self, result=None): del self._prerun_instance_attributes return outcome + def assertDictContainsSubset(self, subset, dictionary, msg=None): + """ + Checks whether all key/value pairs in subset are found in dictionary. + This method was removed in Python 3.12. + """ + missing = [] + mismatched = [] + for key, value in subset.items(): + if key not in dictionary: + missing.append(key) + elif value != dictionary[key]: + mismatched.append( + "{!r}, expected: {!r}, actual: {!r}".format( + key, value, dictionary[key] + ) + ) + if missing or mismatched: + parts = [] + if missing: + parts.append("Missing: {}".format(", ".join(repr(m) for m in missing))) + if mismatched: + parts.append("Mismatched values: {}".format(", ".join(mismatched))) + standard_msg = "; ".join(parts) + self.fail(self._formatMessage(msg, standard_msg)) + def shortDescription(self): desc = _TestCase.shortDescription(self) if HAS_PSUTIL and SHOW_PROC: diff --git a/tests/unit/modules/test_saltcheck.py b/tests/unit/modules/test_saltcheck.py index 3d35fe2de5b2..8fa354eb38cf 100644 --- a/tests/unit/modules/test_saltcheck.py +++ b/tests/unit/modules/test_saltcheck.py @@ -24,9 +24,24 @@ def setup_loader_modules(self): ) local_opts["file_client"] = "local" local_opts["conf_file"] = "/etc/salt/minion" - patcher = patch("salt.config.minion_config", MagicMock(return_value=local_opts)) - patcher.start() - self.addCleanup(patcher.stop) + + # Mock salt.client.Caller to avoid initializing a real SMinion which tries to access /var/cache/salt + self.mock_caller = MagicMock() + + def mock_cmd(fun, *args, **kwargs): + if fun == "test.echo" and args: + return args[0] + return "This works!" + + self.mock_caller.cmd.side_effect = mock_cmd + + patchers = [ + patch("salt.config.minion_config", MagicMock(return_value=local_opts)), + patch("salt.client.Caller", MagicMock(return_value=self.mock_caller)), + ] + for patcher in patchers: + patcher.start() + self.addCleanup(patcher.stop) return {saltcheck: {"__opts__": local_opts}} @pytest.mark.slow_test diff --git a/tests/unit/modules/test_x509.py b/tests/unit/modules/test_x509.py index f1ca5bb45a3d..32be1ba3f6d4 100644 --- a/tests/unit/modules/test_x509.py +++ b/tests/unit/modules/test_x509.py @@ -22,6 +22,7 @@ import salt.utils.files import salt.utils.stringutils +import salt.utils.timeutil from salt.modules import x509 from tests.support.helpers import dedent from tests.support.mixins import LoaderModuleMockMixin @@ -185,7 +186,7 @@ def test_create_certificate_with_not_after(self): fmt = "%Y-%m-%d %H:%M:%S" # We also gonna use the current date in UTC format for verification - not_after = datetime.datetime.utcnow() + not_after = salt.utils.timeutil.utcnow() # And set the UTC timezone to the naive datetime resulting from parsing not_after = not_after.replace(tzinfo=M2Crypto.ASN1.UTC) not_after_str = datetime.datetime.strftime(not_after, fmt) @@ -226,7 +227,7 @@ def test_create_certificate_with_not_before(self): fmt = "%Y-%m-%d %H:%M:%S" # We also gonna use the current date in UTC format for verification - not_before = datetime.datetime.utcnow() + not_before = salt.utils.timeutil.utcnow() # And set the UTC timezone to the naive datetime resulting from parsing not_before = not_before.replace(tzinfo=M2Crypto.ASN1.UTC) not_before_str = datetime.datetime.strftime(not_before, fmt) @@ -319,7 +320,7 @@ def test_create_certificate_with_not_before_and_not_after(self): fmt = "%Y-%m-%d %H:%M:%S" # Here we gonna use the current date as the not_before date # First we again take the UTC for verification - not_before = datetime.datetime.utcnow() + not_before = salt.utils.timeutil.utcnow() # And set the UTC timezone to the naive datetime resulting from parsing not_before = not_before.replace(tzinfo=M2Crypto.ASN1.UTC) not_before_str = datetime.datetime.strftime(not_before, fmt) diff --git a/tests/unit/test_config.py b/tests/unit/test_config.py index a67ae52bbb9a..4a1c50a66c20 100644 --- a/tests/unit/test_config.py +++ b/tests/unit/test_config.py @@ -386,7 +386,7 @@ def test_load_client_config_from_environ_var(self, tempdir): with patched_environ( SALT_MASTER_CONFIG=master_config, SALT_CLIENT_CONFIG=env_fpath - ): + ), patch("os.path.expanduser", return_value="/tmp/non-existent-file"): # Should load from env variable, not the default configuration file config = salt.config.client_config(os.path.expanduser("~/.salt")) self.assertEqual(config["log_file"], env_fpath) diff --git a/tests/unit/transport/test_ipc.py b/tests/unit/transport/test_ipc.py index eb469d6efb46..73b545628eda 100644 --- a/tests/unit/transport/test_ipc.py +++ b/tests/unit/transport/test_ipc.py @@ -94,8 +94,8 @@ def test_multi_client_reading(self): def close_server(): if evt.wait(1): return - client2.close() - self.stop() + self.io_loop.add_callback(client2.close) + self.io_loop.add_callback(self.stop) watchdog = threading.Thread(target=close_server) watchdog.start() @@ -140,8 +140,8 @@ def test_async_reading_streamclosederror(self): def close_server(): if evt.wait(0.001): return - client1.close() - self.stop() + self.io_loop.add_callback(client1.close) + self.io_loop.add_callback(self.stop) watchdog = threading.Thread(target=close_server) watchdog.start() diff --git a/tests/unit/utils/test_boto3mod.py b/tests/unit/utils/test_boto3mod.py index 0a9509ab5987..4aae1a88a341 100644 --- a/tests/unit/utils/test_boto3mod.py +++ b/tests/unit/utils/test_boto3mod.py @@ -31,7 +31,7 @@ @pytest.mark.skipif(HAS_BOTO3 is False, reason="The boto module must be installed.") @pytest.mark.skipif( - Version(boto3.__version__) < Version(REQUIRED_BOTO3_VERSION), + HAS_BOTO3 and Version(boto3.__version__) < Version(REQUIRED_BOTO3_VERSION), reason="The boto3 module must be greater or equal to version {}".format( REQUIRED_BOTO3_VERSION ), diff --git a/tests/unit/utils/test_color.py b/tests/unit/utils/test_color.py index 741db780a23a..0e3f5ac042fb 100644 --- a/tests/unit/utils/test_color.py +++ b/tests/unit/utils/test_color.py @@ -12,7 +12,7 @@ def test_get_colors(self): self.assertEqual("\x1b[0;37m", str(ret["LIGHT_GRAY"])) ret = salt.utils.color.get_colors(use=False) - self.assertDictContainsSubset({"LIGHT_GRAY": ""}, ret) + self.assertEqual(ret.get("LIGHT_GRAY"), "") ret = salt.utils.color.get_colors(use="LIGHT_GRAY") # LIGHT_YELLOW now == LIGHT_GRAY diff --git a/tools/pkg/build.py b/tools/pkg/build.py index 36c6c838329e..6e193aa0961f 100644 --- a/tools/pkg/build.py +++ b/tools/pkg/build.py @@ -633,6 +633,10 @@ def onedir_dependencies( # Cryptography needs openssl dir set to link to the proper openssl libs. if platform == "macos": env["OPENSSL_DIR"] = f"{dest}" + # Apple Clang 16+ (Xcode 16, macOS 14+) treats pointer-to-integer + # conversions as hard errors. Suppress for packages with older C code + # (e.g. multidict 6.0.4) that predate stricter Clang defaults. + env["CFLAGS"] = env.get("CFLAGS", "") + " -Wno-int-conversion" if platform == "linux": # This installs the ppbt package. We'll remove it after installing all