Merge 3007.x into master

This commit is contained in:
Pedro Algarvio 2024-01-26 15:26:00 +00:00
commit d943669244
No known key found for this signature in database
GPG key ID: BB36BF6584A298FF
83 changed files with 1476 additions and 739 deletions

View file

@ -43,6 +43,7 @@ env:
PIP_INDEX_URL: https://pypi-proxy.saltstack.net/root/local/+simple/
PIP_EXTRA_INDEX_URL: https://pypi.org/simple
PIP_DISABLE_PIP_VERSION_CHECK: "1"
RAISE_DEPRECATIONS_RUNTIME_ERRORS: "1"
jobs:

View file

@ -19,6 +19,7 @@ env:
CACHE_SEED: SEED-4 # Bump the number to invalidate all caches
RELENV_DATA: "${{ github.workspace }}/.relenv"
PIP_DISABLE_PIP_VERSION_CHECK: "1"
RAISE_DEPRECATIONS_RUNTIME_ERRORS: "1"
permissions:
contents: read # for dorny/paths-filter to fetch a list of changed files

View file

@ -25,6 +25,7 @@ env:
CACHE_SEED: SEED-4 # Bump the number to invalidate all caches
RELENV_DATA: "${{ github.workspace }}/.relenv"
PIP_DISABLE_PIP_VERSION_CHECK: "1"
RAISE_DEPRECATIONS_RUNTIME_ERRORS: "1"
permissions:
contents: read # for dorny/paths-filter to fetch a list of changed files

View file

@ -24,6 +24,7 @@ env:
CACHE_SEED: SEED-4 # Bump the number to invalidate all caches
RELENV_DATA: "${{ github.workspace }}/.relenv"
PIP_DISABLE_PIP_VERSION_CHECK: "1"
RAISE_DEPRECATIONS_RUNTIME_ERRORS: "1"
permissions:
contents: write # To be able to publish the release

View file

@ -15,6 +15,7 @@ env:
CACHE_SEED: SEED-4 # Bump the number to invalidate all caches
RELENV_DATA: "${{ github.workspace }}/.relenv"
PIP_DISABLE_PIP_VERSION_CHECK: "1"
RAISE_DEPRECATIONS_RUNTIME_ERRORS: "1"
permissions:
contents: read # for dorny/paths-filter to fetch a list of changed files

View file

@ -40,6 +40,7 @@ env:
CACHE_SEED: SEED-4 # Bump the number to invalidate all caches
RELENV_DATA: "${{ github.workspace }}/.relenv"
PIP_DISABLE_PIP_VERSION_CHECK: "1"
RAISE_DEPRECATIONS_RUNTIME_ERRORS: "1"
permissions:
contents: read # for dorny/paths-filter to fetch a list of changed files

View file

@ -43,6 +43,7 @@ env:
PIP_INDEX_URL: https://pypi-proxy.saltstack.net/root/local/+simple/
PIP_EXTRA_INDEX_URL: https://pypi.org/simple
PIP_DISABLE_PIP_VERSION_CHECK: "1"
RAISE_DEPRECATIONS_RUNTIME_ERRORS: "1"
jobs:

View file

@ -37,6 +37,7 @@ env:
CACHE_SEED: SEED-4 # Bump the number to invalidate all caches
RELENV_DATA: "${{ github.workspace }}/.relenv"
PIP_DISABLE_PIP_VERSION_CHECK: "1"
RAISE_DEPRECATIONS_RUNTIME_ERRORS: "1"
<%- endblock env %>

View file

@ -51,6 +51,7 @@ env:
PIP_INDEX_URL: https://pypi-proxy.saltstack.net/root/local/+simple/
PIP_EXTRA_INDEX_URL: https://pypi.org/simple
PIP_DISABLE_PIP_VERSION_CHECK: "1"
RAISE_DEPRECATIONS_RUNTIME_ERRORS: "1"
jobs:
@ -128,22 +129,9 @@ jobs:
run: |
tools --timestamps vm decompress-dependencies ${{ matrix.distro-slug }}
- name: Show System Info & Test Plan
env:
SALT_RELEASE: "${{ inputs.salt-version }}"
SALT_REPO_ARCH: ${{ matrix.arch }}
SALT_REPO_TYPE: ${{ inputs.environment }}
SALT_REPO_USER: ${{ secrets.SALT_REPO_USER }}
SALT_REPO_PASS: ${{ secrets.SALT_REPO_PASS }}
SALT_REPO_DOMAIN_RELEASE: ${{ vars.SALT_REPO_DOMAIN_RELEASE || 'repo.saltproject.io' }}
SALT_REPO_DOMAIN_STAGING: ${{ vars.SALT_REPO_DOMAIN_STAGING || 'staging.repo.saltproject.io' }}
SKIP_CODE_COVERAGE: "${{ inputs.skip-code-coverage && '1' || '0' }}"
LATEST_SALT_RELEASE: "${{ inputs.latest-release }}"
DOWNLOAD_TEST_PACKAGE_TYPE: ${{ matrix.pkg-type }}
- name: Show System Info
run: |
tools --timestamps --timeout-secs=1800 vm testplan --skip-requirements-install \
-E SALT_RELEASE -E SALT_REPO_ARCH -E SALT_REPO_TYPE -E SALT_REPO_USER -E SALT_REPO_PASS \
-E SALT_REPO_DOMAIN_RELEASE -E SALT_REPO_DOMAIN_STAGING -E LATEST_SALT_RELEASE -E DOWNLOAD_TEST_PACKAGE_TYPE \
tools --timestamps --timeout-secs=1800 vm test --skip-requirements-install --print-system-information-only \
--nox-session=${{ inputs.nox-session }}-pkgs ${{ matrix.distro-slug }} -- download-pkgs
- name: Run Package Download Tests
@ -340,18 +328,10 @@ jobs:
run: |
nox --force-color -e decompress-dependencies -- macos ${{ matrix.arch }}
- name: Show System Info & Test Plan
- name: Show System Info
env:
SALT_RELEASE: "${{ inputs.salt-version }}"
SKIP_REQUIREMENTS_INSTALL: "1"
PRINT_TEST_SELECTION: "1"
PRINT_TEST_PLAN_ONLY: "1"
PRINT_SYSTEM_INFO: "1"
GITHUB_ACTIONS_PIPELINE: "1"
SKIP_INITIAL_GH_ACTIONS_FAILURES: "1"
SKIP_CODE_COVERAGE: "${{ inputs.skip-code-coverage && '1' || '0' }}"
LATEST_SALT_RELEASE: "${{ inputs.latest-release }}"
DOWNLOAD_TEST_PACKAGE_TYPE: ${{ matrix.pkg-type }}
PRINT_SYSTEM_INFO_ONLY: "1"
run: |
sudo -E nox --force-color -e ${{ inputs.nox-session }}-pkgs -- download-pkgs
@ -555,22 +535,9 @@ jobs:
run: |
tools --timestamps vm decompress-dependencies ${{ matrix.distro-slug }}
- name: Show System Info & Test Plan
env:
SALT_RELEASE: "${{ inputs.salt-version }}"
SALT_REPO_ARCH: ${{ matrix.arch }}
LATEST_SALT_RELEASE: "${{ inputs.latest-release }}"
SALT_REPO_TYPE: ${{ inputs.environment }}
SALT_REPO_USER: ${{ secrets.SALT_REPO_USER }}
SALT_REPO_PASS: ${{ secrets.SALT_REPO_PASS }}
SALT_REPO_DOMAIN_RELEASE: ${{ vars.SALT_REPO_DOMAIN_RELEASE || 'repo.saltproject.io' }}
SALT_REPO_DOMAIN_STAGING: ${{ vars.SALT_REPO_DOMAIN_STAGING || 'staging.repo.saltproject.io' }}
SKIP_CODE_COVERAGE: "${{ inputs.skip-code-coverage && '1' || '0' }}"
DOWNLOAD_TEST_PACKAGE_TYPE: ${{ matrix.pkg-type }}
- name: Show System Info
run: |
tools --timestamps --timeout-secs=1800 vm testplan --skip-requirements-install \
-E SALT_RELEASE -E SALT_REPO_ARCH -E SALT_REPO_TYPE -E SALT_REPO_USER -E SALT_REPO_PASS \
-E SALT_REPO_DOMAIN_RELEASE -E SALT_REPO_DOMAIN_STAGING -E LATEST_SALT_RELEASE -E DOWNLOAD_TEST_PACKAGE_TYPE \
tools --timestamps --timeout-secs=1800 vm test --skip-requirements-install --print-system-information-only \
--nox-session=${{ inputs.nox-session }}-pkgs ${{ matrix.distro-slug }} -- download-pkgs
- name: Run Package Download Tests

View file

@ -73,6 +73,7 @@ env:
PIP_INDEX_URL: https://pypi-proxy.saltstack.net/root/local/+simple/
PIP_EXTRA_INDEX_URL: https://pypi.org/simple
PIP_DISABLE_PIP_VERSION_CHECK: "1"
RAISE_DEPRECATIONS_RUNTIME_ERRORS: "1"
jobs:
@ -190,9 +191,9 @@ jobs:
run: |
tools --timestamps vm decompress-dependencies ${{ inputs.distro-slug }}
- name: Show System Info & Test Plan
- name: Show System Info
run: |
tools --timestamps --timeout-secs=1800 vm testplan --skip-requirements-install \
tools --timestamps --timeout-secs=1800 vm test --skip-requirements-install --print-system-information-only \
--nox-session=${{ inputs.nox-session }} ${{ inputs.distro-slug }} \
${{ matrix.tests-chunk }}

View file

@ -66,6 +66,7 @@ env:
PIP_INDEX_URL: "https://pypi-proxy.saltstack.net/root/local/+simple/"
PIP_EXTRA_INDEX_URL: "https://pypi.org/simple"
PIP_DISABLE_PIP_VERSION_CHECK: "1"
RAISE_DEPRECATIONS_RUNTIME_ERRORS: "1"
jobs:
@ -162,17 +163,12 @@ jobs:
with:
name: testrun-changed-files.txt
- name: Show System Info & Test Plan
- name: Show System Info
env:
SKIP_REQUIREMENTS_INSTALL: "1"
PRINT_TEST_SELECTION: "1"
PRINT_TEST_PLAN_ONLY: "1"
PRINT_SYSTEM_INFO: "1"
GITHUB_ACTIONS_PIPELINE: "1"
SKIP_INITIAL_GH_ACTIONS_FAILURES: "1"
SKIP_CODE_COVERAGE: "1"
PRINT_SYSTEM_INFO_ONLY: "1"
run: |
sudo -E nox --force-color -e ${{ inputs.nox-session }} -- ${{ matrix.tests-chunk }} -- -k "mac or darwin"
sudo -E nox --force-color -e ${{ inputs.nox-session }} -- ${{ matrix.tests-chunk }}
- name: Run Changed Tests
id: run-fast-changed-tests

View file

@ -73,6 +73,7 @@ env:
PIP_INDEX_URL: https://pypi-proxy.saltstack.net/root/local/+simple/
PIP_EXTRA_INDEX_URL: https://pypi.org/simple
PIP_DISABLE_PIP_VERSION_CHECK: "1"
RAISE_DEPRECATIONS_RUNTIME_ERRORS: "1"
jobs:
@ -190,9 +191,9 @@ jobs:
run: |
tools --timestamps vm decompress-dependencies ${{ inputs.distro-slug }}
- name: Show System Info & Test Plan
- name: Show System Info
run: |
tools --timestamps --timeout-secs=1800 vm testplan --skip-requirements-install \
tools --timestamps --timeout-secs=1800 vm test --skip-requirements-install --print-system-information-only \
--nox-session=${{ inputs.nox-session }} ${{ inputs.distro-slug }} \
${{ matrix.tests-chunk }}

View file

@ -51,6 +51,7 @@ env:
PIP_INDEX_URL: https://pypi-proxy.saltstack.net/root/local/+simple/
PIP_EXTRA_INDEX_URL: https://pypi.org/simple
PIP_DISABLE_PIP_VERSION_CHECK: "1"
RAISE_DEPRECATIONS_RUNTIME_ERRORS: "1"
jobs:
@ -273,22 +274,9 @@ jobs:
run: |
tools --timestamps vm decompress-dependencies ${{ matrix.distro-slug }}
- name: Show System Info & Test Plan
env:
SALT_RELEASE: "${{ inputs.salt-version }}"
SALT_REPO_ARCH: ${{ matrix.arch }}
SALT_REPO_TYPE: ${{ inputs.environment }}
SALT_REPO_USER: ${{ secrets.SALT_REPO_USER }}
SALT_REPO_PASS: ${{ secrets.SALT_REPO_PASS }}
SALT_REPO_DOMAIN_RELEASE: ${{ vars.SALT_REPO_DOMAIN_RELEASE || 'repo.saltproject.io' }}
SALT_REPO_DOMAIN_STAGING: ${{ vars.SALT_REPO_DOMAIN_STAGING || 'staging.repo.saltproject.io' }}
SKIP_CODE_COVERAGE: "${{ inputs.skip-code-coverage && '1' || '0' }}"
LATEST_SALT_RELEASE: "${{ inputs.latest-release }}"
DOWNLOAD_TEST_PACKAGE_TYPE: ${{ matrix.pkg-type }}
- name: Show System Info
run: |
tools --timestamps --timeout-secs=1800 vm testplan --skip-requirements-install \
-E SALT_RELEASE -E SALT_REPO_ARCH -E SALT_REPO_TYPE -E SALT_REPO_USER -E SALT_REPO_PASS \
-E SALT_REPO_DOMAIN_RELEASE -E SALT_REPO_DOMAIN_STAGING -E LATEST_SALT_RELEASE -E DOWNLOAD_TEST_PACKAGE_TYPE \
tools --timestamps --timeout-secs=1800 vm test --skip-requirements-install --print-system-information-only \
--nox-session=${{ inputs.nox-session }}-pkgs ${{ matrix.distro-slug }} -- download-pkgs
- name: Run Package Download Tests
@ -492,18 +480,10 @@ jobs:
run: |
nox --force-color -e decompress-dependencies -- macos ${{ matrix.arch }}
- name: Show System Info & Test Plan
- name: Show System Info
env:
SALT_RELEASE: "${{ inputs.salt-version }}"
SKIP_REQUIREMENTS_INSTALL: "1"
PRINT_TEST_SELECTION: "1"
PRINT_TEST_PLAN_ONLY: "1"
PRINT_SYSTEM_INFO: "1"
GITHUB_ACTIONS_PIPELINE: "1"
SKIP_INITIAL_GH_ACTIONS_FAILURES: "1"
SKIP_CODE_COVERAGE: "${{ inputs.skip-code-coverage && '1' || '0' }}"
LATEST_SALT_RELEASE: "${{ inputs.latest-release }}"
DOWNLOAD_TEST_PACKAGE_TYPE: ${{ matrix.pkg-type }}
PRINT_SYSTEM_INFO_ONLY: "1"
run: |
sudo -E nox --force-color -e ${{ inputs.nox-session }}-pkgs -- download-pkgs
@ -711,22 +691,9 @@ jobs:
run: |
tools --timestamps vm decompress-dependencies ${{ matrix.distro-slug }}
- name: Show System Info & Test Plan
env:
SALT_RELEASE: "${{ inputs.salt-version }}"
SALT_REPO_ARCH: ${{ matrix.arch }}
LATEST_SALT_RELEASE: "${{ inputs.latest-release }}"
SALT_REPO_TYPE: ${{ inputs.environment }}
SALT_REPO_USER: ${{ secrets.SALT_REPO_USER }}
SALT_REPO_PASS: ${{ secrets.SALT_REPO_PASS }}
SALT_REPO_DOMAIN_RELEASE: ${{ vars.SALT_REPO_DOMAIN_RELEASE || 'repo.saltproject.io' }}
SALT_REPO_DOMAIN_STAGING: ${{ vars.SALT_REPO_DOMAIN_STAGING || 'staging.repo.saltproject.io' }}
SKIP_CODE_COVERAGE: "${{ inputs.skip-code-coverage && '1' || '0' }}"
DOWNLOAD_TEST_PACKAGE_TYPE: ${{ matrix.pkg-type }}
- name: Show System Info
run: |
tools --timestamps --timeout-secs=1800 vm testplan --skip-requirements-install \
-E SALT_RELEASE -E SALT_REPO_ARCH -E SALT_REPO_TYPE -E SALT_REPO_USER -E SALT_REPO_PASS \
-E SALT_REPO_DOMAIN_RELEASE -E SALT_REPO_DOMAIN_STAGING -E LATEST_SALT_RELEASE -E DOWNLOAD_TEST_PACKAGE_TYPE \
tools --timestamps --timeout-secs=1800 vm test --skip-requirements-install --print-system-information-only \
--nox-session=${{ inputs.nox-session }}-pkgs ${{ matrix.distro-slug }} -- download-pkgs
- name: Run Package Download Tests

View file

@ -68,6 +68,7 @@ env:
PIP_INDEX_URL: https://pypi-proxy.saltstack.net/root/local/+simple/
PIP_EXTRA_INDEX_URL: https://pypi.org/simple
PIP_DISABLE_PIP_VERSION_CHECK: "1"
RAISE_DEPRECATIONS_RUNTIME_ERRORS: "1"
jobs:
@ -189,11 +190,10 @@ jobs:
# This step can go away once we stop testing classic packages upgrade/downgrades to/from 3005.x
tools --timestamps vm ssh ${{ inputs.distro-slug }} -- "sudo python3 -m pip install -U 'importlib-metadata<=4.13.0' 'virtualenv<=20.21.1'"
- name: Show System Info & Test Plan
- name: Show System Info
run: |
tools --timestamps --timeout-secs=1800 vm testplan --skip-requirements-install \
--nox-session=${{ inputs.nox-session }}-pkgs ${{ inputs.distro-slug }} -- ${{ matrix.tests-chunk }} \
${{ matrix.version && format('--prev-version {0}', matrix.version) || ''}}
tools --timestamps --timeout-secs=1800 vm test --skip-requirements-install --print-system-information-only \
--nox-session=${{ inputs.nox-session }}-pkgs ${{ inputs.distro-slug }} -- ${{ matrix.tests-chunk }}
- name: Run Package Tests
run: |

View file

@ -61,6 +61,7 @@ env:
PIP_INDEX_URL: https://pypi-proxy.saltstack.net/root/local/+simple/
PIP_EXTRA_INDEX_URL: https://pypi.org/simple
PIP_DISABLE_PIP_VERSION_CHECK: "1"
RAISE_DEPRECATIONS_RUNTIME_ERRORS: "1"
jobs:
@ -161,17 +162,12 @@ jobs:
run: |
nox --force-color -e decompress-dependencies -- macos ${{ inputs.arch }}
- name: Show System Info & Test Plan
- name: Show System Info
env:
SKIP_REQUIREMENTS_INSTALL: "1"
PRINT_TEST_SELECTION: "1"
PRINT_TEST_PLAN_ONLY: "1"
PRINT_SYSTEM_INFO: "1"
GITHUB_ACTIONS_PIPELINE: "1"
SKIP_INITIAL_GH_ACTIONS_FAILURES: "1"
PRINT_SYSTEM_INFO_ONLY: "1"
run: |
sudo -E nox --force-color -e ${{ inputs.nox-session }}-pkgs -- ${{ matrix.tests-chunk }} \
${{ matrix.version && format('--prev-version {0}', matrix.version) || ''}}
sudo -E nox --force-color -e ${{ inputs.nox-session }}-pkgs -- ${{ matrix.tests-chunk }}
- name: Run Package Tests
env:

View file

@ -68,6 +68,7 @@ env:
PIP_INDEX_URL: https://pypi-proxy.saltstack.net/root/local/+simple/
PIP_EXTRA_INDEX_URL: https://pypi.org/simple
PIP_DISABLE_PIP_VERSION_CHECK: "1"
RAISE_DEPRECATIONS_RUNTIME_ERRORS: "1"
jobs:
@ -189,11 +190,10 @@ jobs:
# This step can go away once we stop testing classic packages upgrade/downgrades to/from 3005.x
tools --timestamps vm ssh ${{ inputs.distro-slug }} -- "sudo python3 -m pip install -U 'importlib-metadata<=4.13.0' 'virtualenv<=20.21.1'"
- name: Show System Info & Test Plan
- name: Show System Info
run: |
tools --timestamps --timeout-secs=1800 vm testplan --skip-requirements-install \
--nox-session=${{ inputs.nox-session }}-pkgs ${{ inputs.distro-slug }} -- ${{ matrix.tests-chunk }} \
${{ matrix.version && format('--prev-version {0}', matrix.version) || ''}}
tools --timestamps --timeout-secs=1800 vm test --skip-requirements-install --print-system-information-only \
--nox-session=${{ inputs.nox-session }}-pkgs ${{ inputs.distro-slug }} -- ${{ matrix.tests-chunk }}
- name: Run Package Tests
run: |

1
changelog/65018.fixed.md Normal file
View file

@ -0,0 +1 @@
Use `send_multipart` instead of `send` when sending multipart message.

1
changelog/65777.fixed.md Normal file
View file

@ -0,0 +1 @@
Fixes an issue when reading/modifying ini files that contain unicode characters

1
changelog/65824.fixed.md Normal file
View file

@ -0,0 +1 @@
added https proxy to the list of proxies so that requests knows what to do with https based proxies

View file

@ -0,0 +1 @@
Salt no longer time bombs user installations on code using `salt.utils.versions.warn_until_date`

View file

@ -62,6 +62,7 @@ if PRINT_SYSTEM_INFO is None:
PRINT_SYSTEM_INFO = CI_RUN
else:
PRINT_SYSTEM_INFO = PRINT_SYSTEM_INFO == "1"
PRINT_SYSTEM_INFO_ONLY = os.environ.get("PRINT_SYSTEM_INFO_ONLY", "0") == "1"
SKIP_REQUIREMENTS_INSTALL = os.environ.get("SKIP_REQUIREMENTS_INSTALL", "0") == "1"
EXTRA_REQUIREMENTS_INSTALL = os.environ.get("EXTRA_REQUIREMENTS_INSTALL")
COVERAGE_REQUIREMENT = os.environ.get("COVERAGE_REQUIREMENT")
@ -1022,6 +1023,11 @@ def _pytest(session, coverage, cmd_args, env=None, on_rerun=False):
args.append(f"--log-file={RUNTESTS_LOGFILE}")
args.extend(cmd_args)
if PRINT_SYSTEM_INFO_ONLY and "--sys-info-and-exit" not in args:
args.append("--sys-info-and-exit")
session.run("python", "-m", "pytest", *args, env=env)
return
if PRINT_SYSTEM_INFO and "--sysinfo" not in args:
args.append("--sysinfo")

View file

@ -36,3 +36,4 @@ pythonnet>=3.0.1; sys_platform == 'win32'
pymssql>=2.2.1; sys_platform == 'win32'
pymysql>=1.0.2; sys_platform == 'win32'
lxml>=4.6.3; sys_platform == 'win32'
xmltodict>=0.13.0; sys_platform == 'win32'

View file

@ -2,7 +2,7 @@ mock >= 3.0.0
# PyTest
docker
pytest >= 7.2.0
pytest-salt-factories >= 1.0.0rc28
pytest-salt-factories >= 1.0.0rc29
pytest-helpers-namespace >= 2019.1.8
pytest-subtests
pytest-timeout
@ -11,3 +11,4 @@ pytest-custom-exit-code >= 0.3
flaky
more-itertools
pyfakefs
trustme

View file

@ -105,8 +105,9 @@ cryptography==41.0.7
# moto
# paramiko
# pyopenssl
# trustme
# vcert
distlib==0.3.7
distlib==0.3.8
# via virtualenv
distro==1.8.0
# via
@ -127,7 +128,7 @@ filelock==3.13.1
# via virtualenv
flaky==3.7.0
# via -r requirements/pytest.txt
frozenlist==1.4.0
frozenlist==1.4.1
# via
# -c requirements/static/ci/../pkg/py3.10/darwin.txt
# aiohttp
@ -144,7 +145,7 @@ gitdb==4.0.10
# via gitpython
gitpython==3.1.41
# via -r requirements/static/ci/common.in
google-auth==2.19.1
google-auth==2.27.0
# via kubernetes
hglib==2.6.2
# via -r requirements/static/ci/darwin.in
@ -153,6 +154,7 @@ idna==3.4
# -c requirements/static/ci/../pkg/py3.10/darwin.txt
# etcd3-py
# requests
# trustme
# yarl
immutables==0.15
# via
@ -312,7 +314,7 @@ psutil==5.9.6
# pytest-system-statistics
pyasn1-modules==0.3.0
# via google-auth
pyasn1==0.4.8
pyasn1==0.5.1
# via
# pyasn1-modules
# rsa
@ -360,7 +362,7 @@ pytest-helpers-namespace==2021.12.29
# pytest-shell-utilities
pytest-httpserver==1.0.8
# via -r requirements/pytest.txt
pytest-salt-factories==1.0.0rc28
pytest-salt-factories==1.0.0rc29
# via -r requirements/pytest.txt
pytest-shell-utilities==1.8.0
# via pytest-salt-factories
@ -464,7 +466,6 @@ six==1.16.0
# etcd3-py
# genshi
# geomet
# google-auth
# jsonschema
# junit-xml
# junos-eznc
@ -505,6 +506,8 @@ tornado==6.3.3
# -r requirements/base.txt
transitions==0.9.0
# via junos-eznc
trustme==1.1.0
# via -r requirements/pytest.txt
ttp-templates==0.3.5
# via napalm
ttp==0.9.5
@ -525,7 +528,6 @@ urllib3==1.26.18
# -c requirements/static/ci/../pkg/py3.10/darwin.txt
# botocore
# docker
# google-auth
# kubernetes
# python-etcd
# requests

View file

@ -104,8 +104,9 @@ cryptography==41.0.7
# moto
# paramiko
# pyopenssl
# trustme
# vcert
distlib==0.3.7
distlib==0.3.8
# via virtualenv
distro==1.8.0
# via
@ -126,7 +127,7 @@ filelock==3.13.1
# via virtualenv
flaky==3.7.0
# via -r requirements/pytest.txt
frozenlist==1.4.0
frozenlist==1.4.1
# via
# -c requirements/static/ci/../pkg/py3.10/freebsd.txt
# aiohttp
@ -143,7 +144,7 @@ gitdb==4.0.10
# via gitpython
gitpython==3.1.41
# via -r requirements/static/ci/common.in
google-auth==2.19.1
google-auth==2.27.0
# via kubernetes
hglib==2.6.2
# via -r requirements/static/ci/freebsd.in
@ -152,6 +153,7 @@ idna==3.4
# -c requirements/static/ci/../pkg/py3.10/freebsd.txt
# etcd3-py
# requests
# trustme
# yarl
immutables==0.15
# via
@ -316,7 +318,7 @@ psutil==5.9.6
# pytest-system-statistics
pyasn1-modules==0.3.0
# via google-auth
pyasn1==0.5.0
pyasn1==0.5.1
# via
# pyasn1-modules
# rsa
@ -364,7 +366,7 @@ pytest-helpers-namespace==2021.12.29
# pytest-shell-utilities
pytest-httpserver==1.0.8
# via -r requirements/pytest.txt
pytest-salt-factories==1.0.0rc28
pytest-salt-factories==1.0.0rc29
# via -r requirements/pytest.txt
pytest-shell-utilities==1.8.0
# via pytest-salt-factories
@ -468,7 +470,6 @@ six==1.16.0
# etcd3-py
# genshi
# geomet
# google-auth
# jsonschema
# junit-xml
# junos-eznc
@ -510,6 +511,8 @@ tornado==6.3.3
# -r requirements/base.txt
transitions==0.9.0
# via junos-eznc
trustme==1.1.0
# via -r requirements/pytest.txt
ttp-templates==0.3.5
# via napalm
ttp==0.9.5
@ -530,7 +533,6 @@ urllib3==1.26.18
# -c requirements/static/ci/../pkg/py3.10/freebsd.txt
# botocore
# docker
# google-auth
# kubernetes
# python-etcd
# requests

View file

@ -118,8 +118,9 @@ cryptography==41.0.7
# moto
# paramiko
# pyopenssl
# trustme
# vcert
distlib==0.3.7
distlib==0.3.8
# via virtualenv
distro==1.8.0
# via
@ -142,7 +143,7 @@ filelock==3.13.1
# via virtualenv
flaky==3.7.0
# via -r requirements/pytest.txt
frozenlist==1.4.0
frozenlist==1.4.1
# via
# -c requirements/static/ci/../pkg/py3.10/linux.txt
# aiohttp
@ -159,7 +160,7 @@ gitdb==4.0.10
# via gitpython
gitpython==3.1.41
# via -r requirements/static/ci/common.in
google-auth==2.19.1
google-auth==2.27.0
# via kubernetes
h11==0.14.0
# via httpcore
@ -176,6 +177,7 @@ idna==3.4
# etcd3-py
# httpx
# requests
# trustme
# yarl
immutables==0.15
# via
@ -342,7 +344,7 @@ psutil==5.9.6
# pytest-system-statistics
pyasn1-modules==0.3.0
# via google-auth
pyasn1==0.5.0
pyasn1==0.5.1
# via
# pyasn1-modules
# rsa
@ -398,7 +400,7 @@ pytest-helpers-namespace==2021.12.29
# pytest-shell-utilities
pytest-httpserver==1.0.8
# via -r requirements/pytest.txt
pytest-salt-factories==1.0.0rc28
pytest-salt-factories==1.0.0rc29
# via -r requirements/pytest.txt
pytest-shell-utilities==1.8.0
# via pytest-salt-factories
@ -520,7 +522,6 @@ six==1.16.0
# etcd3-py
# genshi
# geomet
# google-auth
# jsonschema
# junit-xml
# junos-eznc
@ -572,6 +573,8 @@ tornado==6.3.3
# -r requirements/base.txt
transitions==0.9.0
# via junos-eznc
trustme==1.1.0
# via -r requirements/pytest.txt
ttp-templates==0.3.5
# via napalm
ttp==0.9.5
@ -594,7 +597,6 @@ urllib3==1.26.18
# -c requirements/static/ci/../pkg/py3.10/linux.txt
# botocore
# docker
# google-auth
# kubernetes
# python-etcd
# requests

View file

@ -102,7 +102,8 @@ cryptography==41.0.7
# pyopenssl
# pyspnego
# requests-ntlm
distlib==0.3.7
# trustme
distlib==0.3.8
# via virtualenv
distro==1.8.0
# via
@ -125,7 +126,7 @@ filelock==3.13.1
# via virtualenv
flaky==3.7.0
# via -r requirements/pytest.txt
frozenlist==1.4.0
frozenlist==1.4.1
# via
# -c requirements/static/ci/../pkg/py3.10/windows.txt
# aiohttp
@ -134,17 +135,18 @@ genshi==0.7.7
# via -r requirements/static/ci/common.in
geomet==0.2.1.post1
# via cassandra-driver
gitdb==4.0.10
gitdb==4.0.11
# via gitpython
gitpython==3.1.41
# via -r requirements/static/ci/common.in
google-auth==2.19.1
google-auth==2.27.0
# via kubernetes
idna==3.4
# via
# -c requirements/static/ci/../pkg/py3.10/windows.txt
# etcd3-py
# requests
# trustme
# yarl
immutables==0.15
# via
@ -269,7 +271,7 @@ psutil==5.9.6
# pytest-system-statistics
pyasn1-modules==0.3.0
# via google-auth
pyasn1==0.4.8
pyasn1==0.5.1
# via
# pyasn1-modules
# rsa
@ -317,7 +319,7 @@ pytest-helpers-namespace==2021.12.29
# pytest-shell-utilities
pytest-httpserver==1.0.8
# via -r requirements/pytest.txt
pytest-salt-factories==1.0.0rc28
pytest-salt-factories==1.0.0rc29
# via -r requirements/pytest.txt
pytest-shell-utilities==1.8.0
# via pytest-salt-factories
@ -426,7 +428,6 @@ six==1.15.0
# etcd3-py
# genshi
# geomet
# google-auth
# jsonschema
# junit-xml
# kubernetes
@ -434,7 +435,7 @@ six==1.15.0
# pyvmomi
# pywinrm
# websocket-client
smmap==5.0.0
smmap==5.0.1
# via gitdb
sqlparse==0.4.4
# via -r requirements/static/ci/common.in
@ -456,6 +457,8 @@ tornado==6.3.3
# via
# -c requirements/static/ci/../pkg/py3.10/windows.txt
# -r requirements/base.txt
trustme==1.1.0
# via -r requirements/pytest.txt
types-pyyaml==6.0.1
# via responses
typing-extensions==4.8.0
@ -469,7 +472,6 @@ urllib3==1.26.18
# -c requirements/static/ci/../pkg/py3.10/windows.txt
# botocore
# docker
# google-auth
# kubernetes
# python-etcd
# requests
@ -496,8 +498,10 @@ wmi==1.5.1 ; sys_platform == "win32"
# -r requirements/base.txt
xmldiff==2.6.3
# via -r requirements/static/ci/common.in
xmltodict==0.13.0
xmltodict==0.13.0 ; sys_platform == "win32"
# via
# -c requirements/static/ci/../pkg/py3.10/windows.txt
# -r requirements/base.txt
# moto
# pywinrm
yamllint==1.32.0

View file

@ -105,8 +105,9 @@ cryptography==41.0.7
# moto
# paramiko
# pyopenssl
# trustme
# vcert
distlib==0.3.7
distlib==0.3.8
# via virtualenv
distro==1.8.0
# via
@ -125,7 +126,7 @@ filelock==3.13.1
# via virtualenv
flaky==3.7.0
# via -r requirements/pytest.txt
frozenlist==1.4.0
frozenlist==1.4.1
# via
# -c requirements/static/ci/../pkg/py3.11/darwin.txt
# aiohttp
@ -142,7 +143,7 @@ gitdb==4.0.10
# via gitpython
gitpython==3.1.41
# via -r requirements/static/ci/common.in
google-auth==2.19.1
google-auth==2.27.0
# via kubernetes
hglib==2.6.2
# via -r requirements/static/ci/darwin.in
@ -151,6 +152,7 @@ idna==3.4
# -c requirements/static/ci/../pkg/py3.11/darwin.txt
# etcd3-py
# requests
# trustme
# yarl
immutables==0.15
# via
@ -308,9 +310,9 @@ psutil==5.9.6
# pytest-salt-factories
# pytest-shell-utilities
# pytest-system-statistics
pyasn1-modules==0.2.4
pyasn1-modules==0.3.0
# via google-auth
pyasn1==0.4.8
pyasn1==0.5.1
# via
# pyasn1-modules
# rsa
@ -362,7 +364,7 @@ pytest-helpers-namespace==2021.12.29
# pytest-shell-utilities
pytest-httpserver==1.0.8
# via -r requirements/pytest.txt
pytest-salt-factories==1.0.0rc28
pytest-salt-factories==1.0.0rc29
# via -r requirements/pytest.txt
pytest-shell-utilities==1.8.0
# via pytest-salt-factories
@ -466,7 +468,6 @@ six==1.16.0
# etcd3-py
# genshi
# geomet
# google-auth
# jsonschema
# junit-xml
# junos-eznc
@ -505,6 +506,8 @@ tornado==6.3.3
# -r requirements/base.txt
transitions==0.9.0
# via junos-eznc
trustme==1.1.0
# via -r requirements/pytest.txt
ttp-templates==0.3.5
# via napalm
ttp==0.9.5
@ -527,7 +530,6 @@ urllib3==1.26.18
# -c requirements/static/ci/../pkg/py3.11/darwin.txt
# botocore
# docker
# google-auth
# kubernetes
# python-etcd
# requests

View file

@ -104,8 +104,9 @@ cryptography==41.0.7
# moto
# paramiko
# pyopenssl
# trustme
# vcert
distlib==0.3.7
distlib==0.3.8
# via virtualenv
distro==1.8.0
# via
@ -124,7 +125,7 @@ filelock==3.13.1
# via virtualenv
flaky==3.7.0
# via -r requirements/pytest.txt
frozenlist==1.4.0
frozenlist==1.4.1
# via
# -c requirements/static/ci/../pkg/py3.11/freebsd.txt
# aiohttp
@ -141,7 +142,7 @@ gitdb==4.0.10
# via gitpython
gitpython==3.1.41
# via -r requirements/static/ci/common.in
google-auth==2.19.1
google-auth==2.27.0
# via kubernetes
hglib==2.6.2
# via -r requirements/static/ci/freebsd.in
@ -150,6 +151,7 @@ idna==3.4
# -c requirements/static/ci/../pkg/py3.11/freebsd.txt
# etcd3-py
# requests
# trustme
# yarl
immutables==0.15
# via
@ -312,9 +314,9 @@ psutil==5.9.6
# pytest-salt-factories
# pytest-shell-utilities
# pytest-system-statistics
pyasn1-modules==0.2.4
pyasn1-modules==0.3.0
# via google-auth
pyasn1==0.4.8
pyasn1==0.5.1
# via
# pyasn1-modules
# rsa
@ -366,7 +368,7 @@ pytest-helpers-namespace==2021.12.29
# pytest-shell-utilities
pytest-httpserver==1.0.8
# via -r requirements/pytest.txt
pytest-salt-factories==1.0.0rc28
pytest-salt-factories==1.0.0rc29
# via -r requirements/pytest.txt
pytest-shell-utilities==1.8.0
# via pytest-salt-factories
@ -470,7 +472,6 @@ six==1.16.0
# etcd3-py
# genshi
# geomet
# google-auth
# jsonschema
# junit-xml
# junos-eznc
@ -511,6 +512,8 @@ tornado==6.3.3
# -r requirements/base.txt
transitions==0.9.0
# via junos-eznc
trustme==1.1.0
# via -r requirements/pytest.txt
ttp-templates==0.3.5
# via napalm
ttp==0.9.5
@ -533,7 +536,6 @@ urllib3==1.26.18
# -c requirements/static/ci/../pkg/py3.11/freebsd.txt
# botocore
# docker
# google-auth
# kubernetes
# python-etcd
# requests

View file

@ -118,8 +118,9 @@ cryptography==41.0.7
# moto
# paramiko
# pyopenssl
# trustme
# vcert
distlib==0.3.7
distlib==0.3.8
# via virtualenv
distro==1.8.0
# via
@ -138,7 +139,7 @@ filelock==3.13.1
# via virtualenv
flaky==3.7.0
# via -r requirements/pytest.txt
frozenlist==1.4.0
frozenlist==1.4.1
# via
# -c requirements/static/ci/../pkg/py3.11/linux.txt
# aiohttp
@ -155,7 +156,7 @@ gitdb==4.0.10
# via gitpython
gitpython==3.1.41
# via -r requirements/static/ci/common.in
google-auth==2.19.1
google-auth==2.27.0
# via kubernetes
h11==0.14.0
# via httpcore
@ -172,6 +173,7 @@ idna==3.4
# etcd3-py
# httpx
# requests
# trustme
# yarl
immutables==0.15
# via
@ -336,9 +338,9 @@ psutil==5.9.6
# pytest-salt-factories
# pytest-shell-utilities
# pytest-system-statistics
pyasn1-modules==0.2.4
pyasn1-modules==0.3.0
# via google-auth
pyasn1==0.4.8
pyasn1==0.5.1
# via
# pyasn1-modules
# rsa
@ -398,7 +400,7 @@ pytest-helpers-namespace==2021.12.29
# pytest-shell-utilities
pytest-httpserver==1.0.8
# via -r requirements/pytest.txt
pytest-salt-factories==1.0.0rc28
pytest-salt-factories==1.0.0rc29
# via -r requirements/pytest.txt
pytest-shell-utilities==1.8.0
# via pytest-salt-factories
@ -520,7 +522,6 @@ six==1.16.0
# etcd3-py
# genshi
# geomet
# google-auth
# jsonschema
# junit-xml
# junos-eznc
@ -571,6 +572,8 @@ tornado==6.3.3
# -r requirements/base.txt
transitions==0.9.0
# via junos-eznc
trustme==1.1.0
# via -r requirements/pytest.txt
ttp-templates==0.3.5
# via napalm
ttp==0.9.5
@ -595,7 +598,6 @@ urllib3==1.26.18
# -c requirements/static/ci/../pkg/py3.11/linux.txt
# botocore
# docker
# google-auth
# kubernetes
# python-etcd
# requests

View file

@ -102,7 +102,8 @@ cryptography==41.0.7
# pyopenssl
# pyspnego
# requests-ntlm
distlib==0.3.7
# trustme
distlib==0.3.8
# via virtualenv
distro==1.8.0
# via
@ -123,7 +124,7 @@ filelock==3.13.1
# via virtualenv
flaky==3.7.0
# via -r requirements/pytest.txt
frozenlist==1.4.0
frozenlist==1.4.1
# via
# -c requirements/static/ci/../pkg/py3.11/windows.txt
# aiohttp
@ -132,17 +133,18 @@ genshi==0.7.7
# via -r requirements/static/ci/common.in
geomet==0.2.1.post1
# via cassandra-driver
gitdb==4.0.10
gitdb==4.0.11
# via gitpython
gitpython==3.1.41
# via -r requirements/static/ci/common.in
google-auth==2.19.1
google-auth==2.27.0
# via kubernetes
idna==3.4
# via
# -c requirements/static/ci/../pkg/py3.11/windows.txt
# etcd3-py
# requests
# trustme
# yarl
immutables==0.15
# via
@ -265,9 +267,9 @@ psutil==5.9.6
# pytest-salt-factories
# pytest-shell-utilities
# pytest-system-statistics
pyasn1-modules==0.2.4
pyasn1-modules==0.3.0
# via google-auth
pyasn1==0.4.8
pyasn1==0.5.1
# via
# pyasn1-modules
# rsa
@ -319,7 +321,7 @@ pytest-helpers-namespace==2021.12.29
# pytest-shell-utilities
pytest-httpserver==1.0.8
# via -r requirements/pytest.txt
pytest-salt-factories==1.0.0rc28
pytest-salt-factories==1.0.0rc29
# via -r requirements/pytest.txt
pytest-shell-utilities==1.8.0
# via pytest-salt-factories
@ -428,7 +430,6 @@ six==1.15.0
# etcd3-py
# genshi
# geomet
# google-auth
# jsonschema
# junit-xml
# kubernetes
@ -436,7 +437,7 @@ six==1.15.0
# pyvmomi
# pywinrm
# websocket-client
smmap==5.0.0
smmap==5.0.1
# via gitdb
sqlparse==0.4.4
# via -r requirements/static/ci/common.in
@ -456,6 +457,8 @@ tornado==6.3.3
# via
# -c requirements/static/ci/../pkg/py3.11/windows.txt
# -r requirements/base.txt
trustme==1.1.0
# via -r requirements/pytest.txt
types-pyyaml==6.0.12.12
# via responses
typing-extensions==4.8.0
@ -471,7 +474,6 @@ urllib3==1.26.18
# -c requirements/static/ci/../pkg/py3.11/windows.txt
# botocore
# docker
# google-auth
# kubernetes
# python-etcd
# requests
@ -498,8 +500,10 @@ wmi==1.5.1 ; sys_platform == "win32"
# -r requirements/base.txt
xmldiff==2.6.3
# via -r requirements/static/ci/common.in
xmltodict==0.13.0
xmltodict==0.13.0 ; sys_platform == "win32"
# via
# -c requirements/static/ci/../pkg/py3.11/windows.txt
# -r requirements/base.txt
# moto
# pywinrm
yamllint==1.32.0

View file

@ -142,8 +142,9 @@ cryptography==41.0.7
# pyspnego
# requests-ntlm
# smbprotocol
# trustme
# vcert
distlib==0.3.7
distlib==0.3.8
# via
# -c requirements/static/ci/py3.12/linux.txt
# virtualenv
@ -174,7 +175,7 @@ flaky==3.7.0
# via
# -c requirements/static/ci/py3.12/linux.txt
# -r requirements/pytest.txt
frozenlist==1.4.0
frozenlist==1.4.1
# via
# -c requirements/static/ci/../pkg/py3.12/linux.txt
# -c requirements/static/ci/py3.12/linux.txt
@ -201,7 +202,7 @@ gitpython==3.1.41
# via
# -c requirements/static/ci/py3.12/linux.txt
# -r requirements/static/ci/common.in
google-auth==2.19.1
google-auth==2.27.0
# via
# -c requirements/static/ci/py3.12/linux.txt
# kubernetes
@ -211,6 +212,7 @@ idna==3.4
# -c requirements/static/ci/py3.12/linux.txt
# etcd3-py
# requests
# trustme
# yarl
immutables==0.15
# via
@ -434,11 +436,11 @@ psutil==5.9.6
# pytest-salt-factories
# pytest-shell-utilities
# pytest-system-statistics
pyasn1-modules==0.2.4
pyasn1-modules==0.3.0
# via
# -c requirements/static/ci/py3.12/linux.txt
# google-auth
pyasn1==0.4.8
pyasn1==0.5.1
# via
# -c requirements/static/ci/py3.12/linux.txt
# pyasn1-modules
@ -520,7 +522,7 @@ pytest-httpserver==1.0.8
# via
# -c requirements/static/ci/py3.12/linux.txt
# -r requirements/pytest.txt
pytest-salt-factories==1.0.0rc28
pytest-salt-factories==1.0.0rc29
# via
# -c requirements/static/ci/py3.12/linux.txt
# -r requirements/pytest.txt
@ -670,7 +672,6 @@ six==1.16.0
# etcd3-py
# genshi
# geomet
# google-auth
# jsonschema
# junit-xml
# junos-eznc
@ -731,6 +732,10 @@ transitions==0.9.0
# via
# -c requirements/static/ci/py3.12/linux.txt
# junos-eznc
trustme==1.1.0
# via
# -c requirements/static/ci/py3.12/linux.txt
# -r requirements/pytest.txt
ttp-templates==0.3.5
# via
# -c requirements/static/ci/py3.12/linux.txt
@ -760,7 +765,6 @@ urllib3==1.26.18
# -c requirements/static/ci/py3.12/linux.txt
# botocore
# docker
# google-auth
# kubernetes
# python-etcd
# requests

View file

@ -105,8 +105,9 @@ cryptography==41.0.7
# moto
# paramiko
# pyopenssl
# trustme
# vcert
distlib==0.3.7
distlib==0.3.8
# via virtualenv
distro==1.8.0
# via
@ -142,7 +143,7 @@ gitdb==4.0.10
# via gitpython
gitpython==3.1.41
# via -r requirements/static/ci/common.in
google-auth==2.19.1
google-auth==2.27.0
# via kubernetes
hglib==2.6.2
# via -r requirements/static/ci/darwin.in
@ -151,6 +152,7 @@ idna==3.4
# -c requirements/static/ci/../pkg/py3.12/darwin.txt
# etcd3-py
# requests
# trustme
# yarl
immutables==0.15
# via
@ -308,9 +310,9 @@ psutil==5.9.6
# pytest-salt-factories
# pytest-shell-utilities
# pytest-system-statistics
pyasn1-modules==0.2.4
pyasn1-modules==0.3.0
# via google-auth
pyasn1==0.4.8
pyasn1==0.5.1
# via
# pyasn1-modules
# rsa
@ -362,7 +364,7 @@ pytest-helpers-namespace==2021.12.29
# pytest-shell-utilities
pytest-httpserver==1.0.8
# via -r requirements/pytest.txt
pytest-salt-factories==1.0.0rc28
pytest-salt-factories==1.0.0rc29
# via -r requirements/pytest.txt
pytest-shell-utilities==1.8.0
# via pytest-salt-factories
@ -466,7 +468,6 @@ six==1.16.0
# etcd3-py
# genshi
# geomet
# google-auth
# jsonschema
# junit-xml
# junos-eznc
@ -505,6 +506,8 @@ tornado==6.3.3
# -r requirements/base.txt
transitions==0.9.0
# via junos-eznc
trustme==1.1.0
# via -r requirements/pytest.txt
ttp-templates==0.3.5
# via napalm
ttp==0.9.5
@ -527,7 +530,6 @@ urllib3==1.26.18
# -c requirements/static/ci/../pkg/py3.12/darwin.txt
# botocore
# docker
# google-auth
# kubernetes
# python-etcd
# requests

View file

@ -64,7 +64,7 @@ distro==1.8.0
# -r requirements/base.txt
docutils==0.20.1
# via sphinx
frozenlist==1.4.0
frozenlist==1.4.1
# via
# -c requirements/static/ci/py3.12/linux.txt
# aiohttp

View file

@ -104,8 +104,9 @@ cryptography==41.0.7
# moto
# paramiko
# pyopenssl
# trustme
# vcert
distlib==0.3.7
distlib==0.3.8
# via virtualenv
distro==1.8.0
# via
@ -124,7 +125,7 @@ filelock==3.13.1
# via virtualenv
flaky==3.7.0
# via -r requirements/pytest.txt
frozenlist==1.4.0
frozenlist==1.4.1
# via
# -c requirements/static/ci/../pkg/py3.12/freebsd.txt
# aiohttp
@ -141,7 +142,7 @@ gitdb==4.0.10
# via gitpython
gitpython==3.1.41
# via -r requirements/static/ci/common.in
google-auth==2.19.1
google-auth==2.27.0
# via kubernetes
hglib==2.6.2
# via -r requirements/static/ci/freebsd.in
@ -150,6 +151,7 @@ idna==3.4
# -c requirements/static/ci/../pkg/py3.12/freebsd.txt
# etcd3-py
# requests
# trustme
# yarl
immutables==0.15
# via
@ -312,9 +314,9 @@ psutil==5.9.6
# pytest-salt-factories
# pytest-shell-utilities
# pytest-system-statistics
pyasn1-modules==0.2.4
pyasn1-modules==0.3.0
# via google-auth
pyasn1==0.4.8
pyasn1==0.5.1
# via
# pyasn1-modules
# rsa
@ -366,7 +368,7 @@ pytest-helpers-namespace==2021.12.29
# pytest-shell-utilities
pytest-httpserver==1.0.8
# via -r requirements/pytest.txt
pytest-salt-factories==1.0.0rc28
pytest-salt-factories==1.0.0rc29
# via -r requirements/pytest.txt
pytest-shell-utilities==1.8.0
# via pytest-salt-factories
@ -470,7 +472,6 @@ six==1.16.0
# etcd3-py
# genshi
# geomet
# google-auth
# jsonschema
# junit-xml
# junos-eznc
@ -511,6 +512,8 @@ tornado==6.3.3
# -r requirements/base.txt
transitions==0.9.0
# via junos-eznc
trustme==1.1.0
# via -r requirements/pytest.txt
ttp-templates==0.3.5
# via napalm
ttp==0.9.5
@ -533,7 +536,6 @@ urllib3==1.26.18
# -c requirements/static/ci/../pkg/py3.12/freebsd.txt
# botocore
# docker
# google-auth
# kubernetes
# python-etcd
# requests

View file

@ -158,7 +158,7 @@ cryptography==41.0.7
# paramiko
# pyopenssl
# vcert
distlib==0.3.7
distlib==0.3.8
# via
# -c requirements/static/ci/py3.12/linux.txt
# virtualenv
@ -180,7 +180,7 @@ filelock==3.13.1
# via
# -c requirements/static/ci/py3.12/linux.txt
# virtualenv
frozenlist==1.4.0
frozenlist==1.4.1
# via
# -c requirements/static/ci/../pkg/py3.12/linux.txt
# -c requirements/static/ci/py3.12/linux.txt
@ -207,7 +207,7 @@ gitpython==3.1.41
# via
# -c requirements/static/ci/py3.12/linux.txt
# -r requirements/static/ci/common.in
google-auth==2.19.1
google-auth==2.27.0
# via
# -c requirements/static/ci/py3.12/linux.txt
# kubernetes
@ -454,11 +454,11 @@ psutil==5.9.6
# -c requirements/static/ci/../pkg/py3.12/linux.txt
# -c requirements/static/ci/py3.12/linux.txt
# -r requirements/base.txt
pyasn1-modules==0.2.4
pyasn1-modules==0.3.0
# via
# -c requirements/static/ci/py3.12/linux.txt
# google-auth
pyasn1==0.4.8
pyasn1==0.5.1
# via
# -c requirements/static/ci/py3.12/linux.txt
# pyasn1-modules
@ -667,7 +667,6 @@ six==1.16.0
# etcd3-py
# genshi
# geomet
# google-auth
# jsonschema
# junit-xml
# junos-eznc
@ -768,7 +767,6 @@ urllib3==1.26.18
# -c requirements/static/ci/../pkg/py3.12/linux.txt
# -c requirements/static/ci/py3.12/linux.txt
# botocore
# google-auth
# kubernetes
# python-etcd
# requests

View file

@ -118,8 +118,9 @@ cryptography==41.0.7
# moto
# paramiko
# pyopenssl
# trustme
# vcert
distlib==0.3.7
distlib==0.3.8
# via virtualenv
distro==1.8.0
# via
@ -138,7 +139,7 @@ filelock==3.13.1
# via virtualenv
flaky==3.7.0
# via -r requirements/pytest.txt
frozenlist==1.4.0
frozenlist==1.4.1
# via
# -c requirements/static/ci/../pkg/py3.12/linux.txt
# aiohttp
@ -155,7 +156,7 @@ gitdb==4.0.10
# via gitpython
gitpython==3.1.41
# via -r requirements/static/ci/common.in
google-auth==2.19.1
google-auth==2.27.0
# via kubernetes
h11==0.14.0
# via httpcore
@ -172,6 +173,7 @@ idna==3.4
# etcd3-py
# httpx
# requests
# trustme
# yarl
immutables==0.15
# via
@ -336,9 +338,9 @@ psutil==5.9.6
# pytest-salt-factories
# pytest-shell-utilities
# pytest-system-statistics
pyasn1-modules==0.2.4
pyasn1-modules==0.3.0
# via google-auth
pyasn1==0.4.8
pyasn1==0.5.1
# via
# pyasn1-modules
# rsa
@ -398,7 +400,7 @@ pytest-helpers-namespace==2021.12.29
# pytest-shell-utilities
pytest-httpserver==1.0.8
# via -r requirements/pytest.txt
pytest-salt-factories==1.0.0rc28
pytest-salt-factories==1.0.0rc29
# via -r requirements/pytest.txt
pytest-shell-utilities==1.8.0
# via pytest-salt-factories
@ -520,7 +522,6 @@ six==1.16.0
# etcd3-py
# genshi
# geomet
# google-auth
# jsonschema
# junit-xml
# junos-eznc
@ -571,6 +572,8 @@ tornado==6.3.3
# -r requirements/base.txt
transitions==0.9.0
# via junos-eznc
trustme==1.1.0
# via -r requirements/pytest.txt
ttp-templates==0.3.5
# via napalm
ttp==0.9.5
@ -595,7 +598,6 @@ urllib3==1.26.18
# -c requirements/static/ci/../pkg/py3.12/linux.txt
# botocore
# docker
# google-auth
# kubernetes
# python-etcd
# requests

View file

@ -102,7 +102,8 @@ cryptography==41.0.7
# pyopenssl
# pyspnego
# requests-ntlm
distlib==0.3.7
# trustme
distlib==0.3.8
# via virtualenv
distro==1.8.0
# via
@ -123,7 +124,7 @@ filelock==3.13.1
# via virtualenv
flaky==3.7.0
# via -r requirements/pytest.txt
frozenlist==1.4.0
frozenlist==1.4.1
# via
# -c requirements/static/ci/../pkg/py3.12/windows.txt
# aiohttp
@ -132,17 +133,18 @@ genshi==0.7.7
# via -r requirements/static/ci/common.in
geomet==0.2.1.post1
# via cassandra-driver
gitdb==4.0.10
gitdb==4.0.11
# via gitpython
gitpython==3.1.41
# via -r requirements/static/ci/common.in
google-auth==2.19.1
google-auth==2.27.0
# via kubernetes
idna==3.4
# via
# -c requirements/static/ci/../pkg/py3.12/windows.txt
# etcd3-py
# requests
# trustme
# yarl
immutables==0.15
# via
@ -265,9 +267,9 @@ psutil==5.9.6
# pytest-salt-factories
# pytest-shell-utilities
# pytest-system-statistics
pyasn1-modules==0.2.4
pyasn1-modules==0.3.0
# via google-auth
pyasn1==0.4.8
pyasn1==0.5.1
# via
# pyasn1-modules
# rsa
@ -319,7 +321,7 @@ pytest-helpers-namespace==2021.12.29
# pytest-shell-utilities
pytest-httpserver==1.0.8
# via -r requirements/pytest.txt
pytest-salt-factories==1.0.0rc28
pytest-salt-factories==1.0.0rc29
# via -r requirements/pytest.txt
pytest-shell-utilities==1.8.0
# via pytest-salt-factories
@ -428,7 +430,6 @@ six==1.15.0
# etcd3-py
# genshi
# geomet
# google-auth
# jsonschema
# junit-xml
# kubernetes
@ -436,7 +437,7 @@ six==1.15.0
# pyvmomi
# pywinrm
# websocket-client
smmap==5.0.0
smmap==5.0.1
# via gitdb
sqlparse==0.4.4
# via -r requirements/static/ci/common.in
@ -456,6 +457,8 @@ tornado==6.3.3
# via
# -c requirements/static/ci/../pkg/py3.12/windows.txt
# -r requirements/base.txt
trustme==1.1.0
# via -r requirements/pytest.txt
types-pyyaml==6.0.12.12
# via responses
typing-extensions==4.8.0
@ -471,7 +474,6 @@ urllib3==1.26.18
# -c requirements/static/ci/../pkg/py3.12/windows.txt
# botocore
# docker
# google-auth
# kubernetes
# python-etcd
# requests
@ -498,8 +500,10 @@ wmi==1.5.1 ; sys_platform == "win32"
# -r requirements/base.txt
xmldiff==2.6.3
# via -r requirements/static/ci/common.in
xmltodict==0.13.0
xmltodict==0.13.0 ; sys_platform == "win32"
# via
# -c requirements/static/ci/../pkg/py3.12/windows.txt
# -r requirements/base.txt
# moto
# pywinrm
yamllint==1.32.0

View file

@ -104,8 +104,9 @@ cryptography==41.0.7
# moto
# paramiko
# pyopenssl
# trustme
# vcert
distlib==0.3.7
distlib==0.3.8
# via virtualenv
distro==1.8.0
# via
@ -126,7 +127,7 @@ filelock==3.13.1
# via virtualenv
flaky==3.7.0
# via -r requirements/pytest.txt
frozenlist==1.4.0
frozenlist==1.4.1
# via
# -c requirements/static/ci/../pkg/py3.8/freebsd.txt
# aiohttp
@ -143,7 +144,7 @@ gitdb==4.0.10
# via gitpython
gitpython==3.1.41
# via -r requirements/static/ci/common.in
google-auth==2.19.1
google-auth==2.27.0
# via kubernetes
hglib==2.6.2
# via -r requirements/static/ci/freebsd.in
@ -152,6 +153,7 @@ idna==3.4
# -c requirements/static/ci/../pkg/py3.8/freebsd.txt
# etcd3-py
# requests
# trustme
# yarl
immutables==0.15
# via
@ -320,7 +322,7 @@ psutil==5.9.6
# pytest-system-statistics
pyasn1-modules==0.3.0
# via google-auth
pyasn1==0.5.0
pyasn1==0.5.1
# via
# pyasn1-modules
# rsa
@ -368,7 +370,7 @@ pytest-helpers-namespace==2021.12.29
# pytest-shell-utilities
pytest-httpserver==1.0.8
# via -r requirements/pytest.txt
pytest-salt-factories==1.0.0rc28
pytest-salt-factories==1.0.0rc29
# via -r requirements/pytest.txt
pytest-shell-utilities==1.8.0
# via pytest-salt-factories
@ -472,7 +474,6 @@ six==1.16.0
# etcd3-py
# genshi
# geomet
# google-auth
# jsonschema
# junit-xml
# junos-eznc
@ -514,6 +515,8 @@ tornado==6.3.3
# -r requirements/base.txt
transitions==0.9.0
# via junos-eznc
trustme==1.1.0
# via -r requirements/pytest.txt
ttp-templates==0.3.5
# via napalm
ttp==0.9.5
@ -534,7 +537,6 @@ urllib3==1.26.18
# -c requirements/static/ci/../pkg/py3.8/freebsd.txt
# botocore
# docker
# google-auth
# kubernetes
# python-etcd
# requests

View file

@ -113,8 +113,9 @@ cryptography==41.0.7
# moto
# paramiko
# pyopenssl
# trustme
# vcert
distlib==0.3.7
distlib==0.3.8
# via virtualenv
distro==1.8.0
# via
@ -137,7 +138,7 @@ filelock==3.13.1
# via virtualenv
flaky==3.7.0
# via -r requirements/pytest.txt
frozenlist==1.4.0
frozenlist==1.4.1
# via
# -c requirements/static/ci/../pkg/py3.8/linux.txt
# aiohttp
@ -154,7 +155,7 @@ gitdb==4.0.10
# via gitpython
gitpython==3.1.41
# via -r requirements/static/ci/common.in
google-auth==2.19.1
google-auth==2.27.0
# via kubernetes
h11==0.14.0
# via httpcore
@ -171,6 +172,7 @@ idna==3.4
# etcd3-py
# httpx
# requests
# trustme
# yarl
immutables==0.15
# via
@ -339,7 +341,7 @@ psutil==5.9.6
# pytest-system-statistics
pyasn1-modules==0.3.0
# via google-auth
pyasn1==0.5.0
pyasn1==0.5.1
# via
# pyasn1-modules
# rsa
@ -395,7 +397,7 @@ pytest-helpers-namespace==2021.12.29
# pytest-shell-utilities
pytest-httpserver==1.0.8
# via -r requirements/pytest.txt
pytest-salt-factories==1.0.0rc28
pytest-salt-factories==1.0.0rc29
# via -r requirements/pytest.txt
pytest-shell-utilities==1.8.0
# via pytest-salt-factories
@ -514,7 +516,6 @@ six==1.16.0
# etcd3-py
# genshi
# geomet
# google-auth
# jsonschema
# junit-xml
# junos-eznc
@ -566,6 +567,8 @@ tornado==6.3.3
# -r requirements/base.txt
transitions==0.9.0
# via junos-eznc
trustme==1.1.0
# via -r requirements/pytest.txt
ttp-templates==0.3.5
# via napalm
ttp==0.9.5
@ -586,7 +589,6 @@ urllib3==1.26.18
# -c requirements/static/ci/../pkg/py3.8/linux.txt
# botocore
# docker
# google-auth
# kubernetes
# python-etcd
# requests

View file

@ -102,7 +102,8 @@ cryptography==41.0.7
# pyopenssl
# pyspnego
# requests-ntlm
distlib==0.3.7
# trustme
distlib==0.3.8
# via virtualenv
distro==1.8.0
# via
@ -125,7 +126,7 @@ filelock==3.13.1
# via virtualenv
flaky==3.7.0
# via -r requirements/pytest.txt
frozenlist==1.4.0
frozenlist==1.4.1
# via
# -c requirements/static/ci/../pkg/py3.8/windows.txt
# aiohttp
@ -134,17 +135,18 @@ genshi==0.7.7
# via -r requirements/static/ci/common.in
geomet==0.2.1.post1
# via cassandra-driver
gitdb==4.0.10
gitdb==4.0.11
# via gitpython
gitpython==3.1.41
# via -r requirements/static/ci/common.in
google-auth==2.19.1
google-auth==2.27.0
# via kubernetes
idna==3.4
# via
# -c requirements/static/ci/../pkg/py3.8/windows.txt
# etcd3-py
# requests
# trustme
# yarl
immutables==0.15
# via
@ -273,7 +275,7 @@ psutil==5.9.6
# pytest-system-statistics
pyasn1-modules==0.3.0
# via google-auth
pyasn1==0.4.8
pyasn1==0.5.1
# via
# pyasn1-modules
# rsa
@ -321,7 +323,7 @@ pytest-helpers-namespace==2021.12.29
# pytest-shell-utilities
pytest-httpserver==1.0.8
# via -r requirements/pytest.txt
pytest-salt-factories==1.0.0rc28
pytest-salt-factories==1.0.0rc29
# via -r requirements/pytest.txt
pytest-shell-utilities==1.8.0
# via pytest-salt-factories
@ -431,7 +433,6 @@ six==1.15.0
# etcd3-py
# genshi
# geomet
# google-auth
# jsonschema
# junit-xml
# kubernetes
@ -439,7 +440,7 @@ six==1.15.0
# pyvmomi
# pywinrm
# websocket-client
smmap==5.0.0
smmap==5.0.1
# via gitdb
sqlparse==0.4.4
# via -r requirements/static/ci/common.in
@ -461,6 +462,8 @@ tornado==6.3.3
# via
# -c requirements/static/ci/../pkg/py3.8/windows.txt
# -r requirements/base.txt
trustme==1.1.0
# via -r requirements/pytest.txt
types-pyyaml==6.0.1
# via responses
typing-extensions==4.8.0
@ -474,7 +477,6 @@ urllib3==1.26.18
# -c requirements/static/ci/../pkg/py3.8/windows.txt
# botocore
# docker
# google-auth
# kubernetes
# python-etcd
# requests
@ -501,8 +503,10 @@ wmi==1.5.1 ; sys_platform == "win32"
# -r requirements/base.txt
xmldiff==2.6.3
# via -r requirements/static/ci/common.in
xmltodict==0.13.0
xmltodict==0.13.0 ; sys_platform == "win32"
# via
# -c requirements/static/ci/../pkg/py3.8/windows.txt
# -r requirements/base.txt
# moto
# pywinrm
yamllint==1.32.0

View file

@ -105,8 +105,9 @@ cryptography==41.0.7
# moto
# paramiko
# pyopenssl
# trustme
# vcert
distlib==0.3.7
distlib==0.3.8
# via virtualenv
distro==1.8.0
# via
@ -127,7 +128,7 @@ filelock==3.13.1
# via virtualenv
flaky==3.7.0
# via -r requirements/pytest.txt
frozenlist==1.4.0
frozenlist==1.4.1
# via
# -c requirements/static/ci/../pkg/py3.9/darwin.txt
# aiohttp
@ -144,7 +145,7 @@ gitdb==4.0.10
# via gitpython
gitpython==3.1.41
# via -r requirements/static/ci/common.in
google-auth==2.19.1
google-auth==2.27.0
# via kubernetes
hglib==2.6.2
# via -r requirements/static/ci/darwin.in
@ -153,6 +154,7 @@ idna==3.4
# -c requirements/static/ci/../pkg/py3.9/darwin.txt
# etcd3-py
# requests
# trustme
# yarl
immutables==0.15
# via
@ -312,7 +314,7 @@ psutil==5.9.6
# pytest-system-statistics
pyasn1-modules==0.3.0
# via google-auth
pyasn1==0.4.8
pyasn1==0.5.1
# via
# pyasn1-modules
# rsa
@ -360,7 +362,7 @@ pytest-helpers-namespace==2021.12.29
# pytest-shell-utilities
pytest-httpserver==1.0.8
# via -r requirements/pytest.txt
pytest-salt-factories==1.0.0rc28
pytest-salt-factories==1.0.0rc29
# via -r requirements/pytest.txt
pytest-shell-utilities==1.8.0
# via pytest-salt-factories
@ -464,7 +466,6 @@ six==1.16.0
# etcd3-py
# genshi
# geomet
# google-auth
# jsonschema
# junit-xml
# junos-eznc
@ -505,6 +506,8 @@ tornado==6.3.3
# -r requirements/base.txt
transitions==0.9.0
# via junos-eznc
trustme==1.1.0
# via -r requirements/pytest.txt
ttp-templates==0.3.5
# via napalm
ttp==0.9.5
@ -525,7 +528,6 @@ urllib3==1.26.18
# -c requirements/static/ci/../pkg/py3.9/darwin.txt
# botocore
# docker
# google-auth
# kubernetes
# python-etcd
# requests

View file

@ -104,8 +104,9 @@ cryptography==41.0.7
# moto
# paramiko
# pyopenssl
# trustme
# vcert
distlib==0.3.7
distlib==0.3.8
# via virtualenv
distro==1.8.0
# via
@ -126,7 +127,7 @@ filelock==3.13.1
# via virtualenv
flaky==3.7.0
# via -r requirements/pytest.txt
frozenlist==1.4.0
frozenlist==1.4.1
# via
# -c requirements/static/ci/../pkg/py3.9/freebsd.txt
# aiohttp
@ -143,7 +144,7 @@ gitdb==4.0.10
# via gitpython
gitpython==3.1.41
# via -r requirements/static/ci/common.in
google-auth==2.19.1
google-auth==2.27.0
# via kubernetes
hglib==2.6.2
# via -r requirements/static/ci/freebsd.in
@ -152,6 +153,7 @@ idna==3.4
# -c requirements/static/ci/../pkg/py3.9/freebsd.txt
# etcd3-py
# requests
# trustme
# yarl
immutables==0.15
# via
@ -316,7 +318,7 @@ psutil==5.9.6
# pytest-system-statistics
pyasn1-modules==0.3.0
# via google-auth
pyasn1==0.5.0
pyasn1==0.5.1
# via
# pyasn1-modules
# rsa
@ -364,7 +366,7 @@ pytest-helpers-namespace==2021.12.29
# pytest-shell-utilities
pytest-httpserver==1.0.8
# via -r requirements/pytest.txt
pytest-salt-factories==1.0.0rc28
pytest-salt-factories==1.0.0rc29
# via -r requirements/pytest.txt
pytest-shell-utilities==1.8.0
# via pytest-salt-factories
@ -468,7 +470,6 @@ six==1.16.0
# etcd3-py
# genshi
# geomet
# google-auth
# jsonschema
# junit-xml
# junos-eznc
@ -510,6 +511,8 @@ tornado==6.3.3
# -r requirements/base.txt
transitions==0.9.0
# via junos-eznc
trustme==1.1.0
# via -r requirements/pytest.txt
ttp-templates==0.3.5
# via napalm
ttp==0.9.5
@ -530,7 +533,6 @@ urllib3==1.26.18
# -c requirements/static/ci/../pkg/py3.9/freebsd.txt
# botocore
# docker
# google-auth
# kubernetes
# python-etcd
# requests

View file

@ -113,8 +113,9 @@ cryptography==41.0.7
# moto
# paramiko
# pyopenssl
# trustme
# vcert
distlib==0.3.7
distlib==0.3.8
# via virtualenv
distro==1.8.0
# via
@ -137,7 +138,7 @@ filelock==3.13.1
# via virtualenv
flaky==3.7.0
# via -r requirements/pytest.txt
frozenlist==1.4.0
frozenlist==1.4.1
# via
# -c requirements/static/ci/../pkg/py3.9/linux.txt
# aiohttp
@ -154,7 +155,7 @@ gitdb==4.0.10
# via gitpython
gitpython==3.1.41
# via -r requirements/static/ci/common.in
google-auth==2.19.1
google-auth==2.27.0
# via kubernetes
h11==0.14.0
# via httpcore
@ -171,6 +172,7 @@ idna==3.4
# etcd3-py
# httpx
# requests
# trustme
# yarl
immutables==0.15
# via
@ -335,7 +337,7 @@ psutil==5.9.6
# pytest-system-statistics
pyasn1-modules==0.3.0
# via google-auth
pyasn1==0.5.0
pyasn1==0.5.1
# via
# pyasn1-modules
# rsa
@ -391,7 +393,7 @@ pytest-helpers-namespace==2021.12.29
# pytest-shell-utilities
pytest-httpserver==1.0.8
# via -r requirements/pytest.txt
pytest-salt-factories==1.0.0rc28
pytest-salt-factories==1.0.0rc29
# via -r requirements/pytest.txt
pytest-shell-utilities==1.8.0
# via pytest-salt-factories
@ -510,7 +512,6 @@ six==1.16.0
# etcd3-py
# genshi
# geomet
# google-auth
# jsonschema
# junit-xml
# junos-eznc
@ -562,6 +563,8 @@ tornado==6.3.3
# -r requirements/base.txt
transitions==0.9.0
# via junos-eznc
trustme==1.1.0
# via -r requirements/pytest.txt
ttp-templates==0.3.5
# via napalm
ttp==0.9.5
@ -582,7 +585,6 @@ urllib3==1.26.18
# -c requirements/static/ci/../pkg/py3.9/linux.txt
# botocore
# docker
# google-auth
# kubernetes
# python-etcd
# requests

View file

@ -102,7 +102,8 @@ cryptography==41.0.7
# pyopenssl
# pyspnego
# requests-ntlm
distlib==0.3.7
# trustme
distlib==0.3.8
# via virtualenv
distro==1.8.0
# via
@ -125,7 +126,7 @@ filelock==3.13.1
# via virtualenv
flaky==3.7.0
# via -r requirements/pytest.txt
frozenlist==1.4.0
frozenlist==1.4.1
# via
# -c requirements/static/ci/../pkg/py3.9/windows.txt
# aiohttp
@ -134,17 +135,18 @@ genshi==0.7.7
# via -r requirements/static/ci/common.in
geomet==0.2.1.post1
# via cassandra-driver
gitdb==4.0.10
gitdb==4.0.11
# via gitpython
gitpython==3.1.41
# via -r requirements/static/ci/common.in
google-auth==2.19.1
google-auth==2.27.0
# via kubernetes
idna==3.4
# via
# -c requirements/static/ci/../pkg/py3.9/windows.txt
# etcd3-py
# requests
# trustme
# yarl
immutables==0.15
# via
@ -269,7 +271,7 @@ psutil==5.9.6
# pytest-system-statistics
pyasn1-modules==0.3.0
# via google-auth
pyasn1==0.4.8
pyasn1==0.5.1
# via
# pyasn1-modules
# rsa
@ -317,7 +319,7 @@ pytest-helpers-namespace==2021.12.29
# pytest-shell-utilities
pytest-httpserver==1.0.8
# via -r requirements/pytest.txt
pytest-salt-factories==1.0.0rc28
pytest-salt-factories==1.0.0rc29
# via -r requirements/pytest.txt
pytest-shell-utilities==1.8.0
# via pytest-salt-factories
@ -427,7 +429,6 @@ six==1.15.0
# etcd3-py
# genshi
# geomet
# google-auth
# jsonschema
# junit-xml
# kubernetes
@ -435,7 +436,7 @@ six==1.15.0
# pyvmomi
# pywinrm
# websocket-client
smmap==5.0.0
smmap==5.0.1
# via gitdb
sqlparse==0.4.4
# via -r requirements/static/ci/common.in
@ -457,6 +458,8 @@ tornado==6.3.3
# via
# -c requirements/static/ci/../pkg/py3.9/windows.txt
# -r requirements/base.txt
trustme==1.1.0
# via -r requirements/pytest.txt
types-pyyaml==6.0.1
# via responses
typing-extensions==4.8.0
@ -470,7 +473,6 @@ urllib3==1.26.18
# -c requirements/static/ci/../pkg/py3.9/windows.txt
# botocore
# docker
# google-auth
# kubernetes
# python-etcd
# requests
@ -497,8 +499,10 @@ wmi==1.5.1 ; sys_platform == "win32"
# -r requirements/base.txt
xmldiff==2.6.3
# via -r requirements/static/ci/common.in
xmltodict==0.13.0
xmltodict==0.13.0 ; sys_platform == "win32"
# via
# -c requirements/static/ci/../pkg/py3.9/windows.txt
# -r requirements/base.txt
# moto
# pywinrm
yamllint==1.32.0

View file

@ -32,7 +32,7 @@ cryptography==41.0.7
# pyopenssl
distro==1.8.0
# via -r requirements/base.txt
frozenlist==1.4.0
frozenlist==1.4.1
# via
# aiohttp
# aiosignal

View file

@ -32,7 +32,7 @@ cryptography==41.0.7
# pyopenssl
distro==1.8.0
# via -r requirements/base.txt
frozenlist==1.4.0
frozenlist==1.4.1
# via
# aiohttp
# aiosignal

View file

@ -32,7 +32,7 @@ cryptography==41.0.7
# pyopenssl
distro==1.8.0
# via -r requirements/base.txt
frozenlist==1.4.0
frozenlist==1.4.1
# via
# aiohttp
# aiosignal

View file

@ -36,7 +36,7 @@ cryptography==41.0.7
# pyopenssl
distro==1.8.0
# via -r requirements/base.txt
frozenlist==1.4.0
frozenlist==1.4.1
# via
# aiohttp
# aiosignal
@ -137,6 +137,8 @@ urllib3==1.26.18
# via requests
wmi==1.5.1 ; sys_platform == "win32"
# via -r requirements/base.txt
xmltodict==0.13.0 ; sys_platform == "win32"
# via -r requirements/base.txt
yarl==1.9.4
# via aiohttp
zc.lockfile==3.0.post1

View file

@ -32,7 +32,7 @@ cryptography==41.0.7
# pyopenssl
distro==1.8.0
# via -r requirements/base.txt
frozenlist==1.4.0
frozenlist==1.4.1
# via
# aiohttp
# aiosignal

View file

@ -32,7 +32,7 @@ cryptography==41.0.7
# pyopenssl
distro==1.8.0
# via -r requirements/base.txt
frozenlist==1.4.0
frozenlist==1.4.1
# via
# aiohttp
# aiosignal

View file

@ -32,7 +32,7 @@ cryptography==41.0.7
# pyopenssl
distro==1.8.0
# via -r requirements/base.txt
frozenlist==1.4.0
frozenlist==1.4.1
# via
# aiohttp
# aiosignal

View file

@ -36,7 +36,7 @@ cryptography==41.0.7
# pyopenssl
distro==1.8.0
# via -r requirements/base.txt
frozenlist==1.4.0
frozenlist==1.4.1
# via
# aiohttp
# aiosignal
@ -142,6 +142,8 @@ urllib3==1.26.18
# via requests
wmi==1.5.1 ; sys_platform == "win32"
# via -r requirements/base.txt
xmltodict==0.13.0 ; sys_platform == "win32"
# via -r requirements/base.txt
yarl==1.9.4
# via aiohttp
zc.lockfile==3.0.post1

View file

@ -32,7 +32,7 @@ cryptography==41.0.7
# pyopenssl
distro==1.8.0
# via -r requirements/base.txt
frozenlist==1.4.0
frozenlist==1.4.1
# via
# aiohttp
# aiosignal

View file

@ -32,7 +32,7 @@ cryptography==41.0.7
# pyopenssl
distro==1.8.0
# via -r requirements/base.txt
frozenlist==1.4.0
frozenlist==1.4.1
# via
# aiohttp
# aiosignal

View file

@ -36,7 +36,7 @@ cryptography==41.0.7
# pyopenssl
distro==1.8.0
# via -r requirements/base.txt
frozenlist==1.4.0
frozenlist==1.4.1
# via
# aiohttp
# aiosignal
@ -142,6 +142,8 @@ urllib3==1.26.18
# via requests
wmi==1.5.1 ; sys_platform == "win32"
# via -r requirements/base.txt
xmltodict==0.13.0 ; sys_platform == "win32"
# via -r requirements/base.txt
yarl==1.9.4
# via aiohttp
zc.lockfile==3.0.post1

View file

@ -32,7 +32,7 @@ cryptography==41.0.7
# pyopenssl
distro==1.8.0
# via -r requirements/base.txt
frozenlist==1.4.0
frozenlist==1.4.1
# via
# aiohttp
# aiosignal

View file

@ -32,7 +32,7 @@ cryptography==41.0.7
# pyopenssl
distro==1.8.0
# via -r requirements/base.txt
frozenlist==1.4.0
frozenlist==1.4.1
# via
# aiohttp
# aiosignal

View file

@ -36,7 +36,7 @@ cryptography==41.0.7
# pyopenssl
distro==1.8.0
# via -r requirements/base.txt
frozenlist==1.4.0
frozenlist==1.4.1
# via
# aiohttp
# aiosignal
@ -140,6 +140,8 @@ urllib3==1.26.18
# via requests
wmi==1.5.1 ; sys_platform == "win32"
# via -r requirements/base.txt
xmltodict==0.13.0 ; sys_platform == "win32"
# via -r requirements/base.txt
yarl==1.9.4
# via aiohttp
zc.lockfile==3.0.post1

View file

@ -32,7 +32,7 @@ cryptography==41.0.7
# pyopenssl
distro==1.8.0
# via -r requirements/base.txt
frozenlist==1.4.0
frozenlist==1.4.1
# via
# aiohttp
# aiosignal

View file

@ -32,7 +32,7 @@ cryptography==41.0.7
# pyopenssl
distro==1.8.0
# via -r requirements/base.txt
frozenlist==1.4.0
frozenlist==1.4.1
# via
# aiohttp
# aiosignal

View file

@ -32,7 +32,7 @@ cryptography==41.0.7
# pyopenssl
distro==1.8.0
# via -r requirements/base.txt
frozenlist==1.4.0
frozenlist==1.4.1
# via
# aiohttp
# aiosignal

View file

@ -36,7 +36,7 @@ cryptography==41.0.7
# pyopenssl
distro==1.8.0
# via -r requirements/base.txt
frozenlist==1.4.0
frozenlist==1.4.1
# via
# aiohttp
# aiosignal
@ -138,6 +138,8 @@ urllib3==1.26.18
# via requests
wmi==1.5.1 ; sys_platform == "win32"
# via -r requirements/base.txt
xmltodict==0.13.0 ; sys_platform == "win32"
# via -r requirements/base.txt
yarl==1.9.4
# via aiohttp
zc.lockfile==3.0.post1

View file

@ -110,52 +110,15 @@ warnings.filterwarnings(
def __define_global_system_encoding_variable__():
# This is the most trustworthy source of the system encoding, though, if
# salt is being imported after being daemonized, this information is lost
# and reset to None
encoding = None
if not sys.platform.startswith("win") and sys.stdin is not None:
# On linux we can rely on sys.stdin for the encoding since it
# most commonly matches the filesystem encoding. This however
# does not apply to windows
encoding = sys.stdin.encoding
if not encoding:
# If the system is properly configured this should return a valid
# encoding. MS Windows has problems with this and reports the wrong
# encoding
try:
encoding = locale.getencoding()
except AttributeError:
# Python < 3.11
encoding = locale.getpreferredencoding(do_setlocale=True)
if not encoding:
# This is most likely ascii which is not the best but we were
# unable to find a better encoding. If this fails, we fall all
# the way back to ascii
encoding = sys.getdefaultencoding()
if not encoding:
if sys.platform.startswith("darwin"):
# Mac OS X uses UTF-8
encoding = "utf-8"
elif sys.platform.startswith("win"):
# Windows uses a configurable encoding; on Windows, Python uses the name “mbcs”
# to refer to whatever the currently configured encoding is.
encoding = "mbcs"
else:
# On linux default to ascii as a last resort
encoding = "ascii"
import builtins
import sys
# Define the detected encoding as a built-in variable for ease of use
setattr(builtins, "__salt_system_encoding__", encoding)
setattr(builtins, "__salt_system_encoding__", sys.getdefaultencoding())
# This is now garbage collectable
del builtins
del encoding
del sys
__define_global_system_encoding_variable__()

View file

@ -75,6 +75,16 @@ structure::
More info here:
https://docs.aws.amazon.com/cli/latest/topic/s3-config.html
.. note:: This fileserver back-end will by default sync all buckets on every
fileserver update.
If you want files to be only populated in the cache when requested, you can
disable this in the master config:
.. code-block:: yaml
s3.s3_sync_on_update: False
"""
@ -94,9 +104,6 @@ import salt.utils.versions
log = logging.getLogger(__name__)
S3_CACHE_EXPIRE = 30 # cache for 30 seconds
S3_SYNC_ON_UPDATE = True # sync cache on update rather than jit
def envs():
"""
@ -116,7 +123,8 @@ def update():
metadata = _init()
if S3_SYNC_ON_UPDATE:
# sync cache on update rather than jit
if __opts__.get("s3.s3_sync_on_update", True):
# sync the buckets to the local cache
log.info("Syncing local cache from S3...")
for saltenv, env_meta in metadata.items():
@ -343,7 +351,7 @@ def _init():
specified and cache the data to disk.
"""
cache_file = _get_buckets_cache_filename()
exp = time.time() - S3_CACHE_EXPIRE
exp = time.time() - __opts__.get("s3.s3_cache_expire", 30)
# check mtime of the buckets files cache
metadata = None

View file

@ -290,9 +290,8 @@ def get_proc_dir(cachedir, **kwargs):
else:
mode = {"mode": mode}
if not os.path.isdir(fn_):
# proc_dir is not present, create it with mode settings
os.makedirs(fn_, **mode)
# proc_dir is not present, create it with mode settings
os.makedirs(fn_, **mode, exist_ok=True)
d_stat = os.stat(fn_)
@ -952,8 +951,7 @@ class SMinion(MinionBase):
import salt.utils.yaml
pdir = os.path.join(self.opts["cachedir"], "pillar")
if not os.path.isdir(pdir):
os.makedirs(pdir, 0o700)
os.makedirs(pdir, 0o700, exist_ok=True)
ptop = os.path.join(pdir, "top.sls")
if self.opts["saltenv"] is not None:
penv = self.opts["saltenv"]

View file

@ -37,26 +37,37 @@ COM_REGX = re.compile(r"^\s*(#|;)\s*(.*)")
INDENTED_REGX = re.compile(r"(\s+)(.*)")
def set_option(file_name, sections=None, separator="="):
def set_option(file_name, sections=None, separator="=", encoding=None):
"""
Edit an ini file, replacing one or more sections. Returns a dictionary
containing the changes made.
file_name
path of ini_file
Args:
sections : None
A dictionary representing the sections to be edited ini file
The keys are the section names and the values are the dictionary
containing the options
If the ini file does not contain sections the keys and values represent
the options
file_name (str):
The full path to the ini file.
separator : =
A character used to separate keys and values. Standard ini files use
the "=" character.
sections (dict):
A dictionary representing the sections to be edited in the ini file.
The keys are the section names and the values are a dictionary
containing the options. If the ini file does not contain sections
the keys and values represent the options. The default is ``None``.
.. versionadded:: 2016.11.0
separator (str):
The character used to separate keys and values. Standard ini files
use the "=" character. The default is ``=``.
.. versionadded:: 2016.11.0
encoding (str):
A string value representing encoding of the target ini file. If
``None`` is passed, it uses the system default which is likely
``utf-8``. Default is ``None``
.. versionadded:: 3006.6
Returns:
dict: A dictionary representing the changes made to the ini file
API Example:
@ -65,8 +76,7 @@ def set_option(file_name, sections=None, separator="="):
import salt.client
with salt.client.get_local_client() as sc:
sc.cmd(
'target', 'ini.set_option',
['path_to_ini_file', '{"section_to_change": {"key": "value"}}']
'target', 'ini.set_option', ['path_to_ini_file', '{"section_to_change": {"key": "value"}}']
)
CLI Example:
@ -74,36 +84,67 @@ def set_option(file_name, sections=None, separator="="):
.. code-block:: bash
salt '*' ini.set_option /path/to/ini '{section_foo: {key: value}}'
"""
sections = sections or {}
changes = {}
inifile = _Ini.get_ini_file(file_name, separator=separator)
inifile = _Ini.get_ini_file(file_name, separator=separator, encoding=encoding)
changes = inifile.update(sections)
inifile.flush()
return changes
def get_option(file_name, section, option, separator="="):
def get_option(file_name, section, option, separator="=", encoding=None):
"""
Get value of a key from a section in an ini file. Returns ``None`` if
no matching key was found.
Args:
file_name (str):
The full path to the ini file.
section (str):
A string value representing the section of the ini that the option
is in. If the option is not in a section, leave this empty.
option (str):
A string value representing the option to search for.
separator (str):
The character used to separate keys and values. Standard ini files
use the "=" character. The default is ``=``.
.. versionadded:: 2016.11.0
encoding (str):
A string value representing encoding of the target ini file. If
``None`` is passed, it uses the system default which is likely
``utf-8``. Default is ``None``
.. versionadded:: 3006.6
Returns:
str: The value as defined in the ini file, or ``None`` if empty or not
found
API Example:
.. code-block:: python
import salt.client
with salt.client.get_local_client() as sc:
sc.cmd('target', 'ini.get_option',
[path_to_ini_file, section_name, option])
sc.cmd('target', 'ini.get_option', [path_to_ini_file, section_name, option])
CLI Example:
.. code-block:: bash
salt '*' ini.get_option /path/to/ini section_name option_name
"""
inifile = _Ini.get_ini_file(file_name, separator=separator)
inifile = _Ini.get_ini_file(file_name, separator=separator, encoding=encoding)
if section:
try:
return inifile.get(section, {}).get(option, None)
@ -113,27 +154,57 @@ def get_option(file_name, section, option, separator="="):
return inifile.get(option, None)
def remove_option(file_name, section, option, separator="="):
def remove_option(file_name, section, option, separator="=", encoding=None):
"""
Remove a key/value pair from a section in an ini file. Returns the value of
the removed key, or ``None`` if nothing was removed.
Args:
file_name (str):
The full path to the ini file.
section (str):
A string value representing the section of the ini that the option
is in. If the option is not in a section, leave this empty.
option (str):
A string value representing the option to search for.
separator (str):
The character used to separate keys and values. Standard ini files
use the "=" character. The default is ``=``.
.. versionadded:: 2016.11.0
encoding (str):
A string value representing encoding of the target ini file. If
``None`` is passed, it uses the system default which is likely
``utf-8``. Default is ``None``
.. versionadded:: 3006.6
Returns:
str: A string value representing the option that was removed or ``None``
if nothing was removed
API Example:
.. code-block:: python
import salt
sc = salt.client.get_local_client()
sc.cmd('target', 'ini.remove_option',
[path_to_ini_file, section_name, option])
sc.cmd('target', 'ini.remove_option', [path_to_ini_file, section_name, option])
CLI Example:
.. code-block:: bash
salt '*' ini.remove_option /path/to/ini section_name option_name
"""
inifile = _Ini.get_ini_file(file_name, separator=separator)
inifile = _Ini.get_ini_file(file_name, separator=separator, encoding=encoding)
if isinstance(inifile.get(section), (dict, OrderedDict)):
value = inifile.get(section, {}).pop(option, None)
else:
@ -142,27 +213,54 @@ def remove_option(file_name, section, option, separator="="):
return value
def get_section(file_name, section, separator="="):
def get_section(file_name, section, separator="=", encoding=None):
"""
Retrieve a section from an ini file. Returns the section as dictionary. If
Retrieve a section from an ini file. Returns the section as a dictionary. If
the section is not found, an empty dictionary is returned.
Args:
file_name (str):
The full path to the ini file.
section (str):
A string value representing name of the section to search for.
separator (str):
The character used to separate keys and values. Standard ini files
use the "=" character. The default is ``=``.
.. versionadded:: 2016.11.0
encoding (str):
A string value representing encoding of the target ini file. If
``None`` is passed, it uses the system default which is likely
``utf-8``. Default is ``None``
.. versionadded:: 3006.6
Returns:
dict: A dictionary containing the names and values of all items in the
section of the ini file. If the section is not found, an empty
dictionary is returned
API Example:
.. code-block:: python
import salt.client
with salt.client.get_local_client() as sc:
sc.cmd('target', 'ini.get_section',
[path_to_ini_file, section_name])
sc.cmd('target', 'ini.get_section', [path_to_ini_file, section_name])
CLI Example:
.. code-block:: bash
salt '*' ini.get_section /path/to/ini section_name
"""
inifile = _Ini.get_ini_file(file_name, separator=separator)
inifile = _Ini.get_ini_file(file_name, separator=separator, encoding=encoding)
ret = {}
for key, value in inifile.get(section, {}).items():
if key[0] != "#":
@ -170,10 +268,35 @@ def get_section(file_name, section, separator="="):
return ret
def remove_section(file_name, section, separator="="):
def remove_section(file_name, section, separator="=", encoding=None):
"""
Remove a section in an ini file. Returns the removed section as dictionary,
or ``None`` if nothing was removed.
Remove a section in an ini file. Returns the removed section as a
dictionary, or ``None`` if nothing is removed.
Args:
file_name (str):
The full path to the ini file.
section (str):
A string value representing the name of the section search for.
separator (str):
The character used to separate keys and values. Standard ini files
use the "=" character. The default is ``=``.
.. versionadded:: 2016.11.0
encoding (str):
A string value representing encoding of the target ini file. If
``None`` is passed, it uses the system default which is likely
``utf-8``. Default is ``None``
.. versionadded:: 3006.6
Returns:
dict: A dictionary containing the names and values of all items in the
section that was removed or ``None`` if nothing was removed
API Example:
@ -181,16 +304,17 @@ def remove_section(file_name, section, separator="="):
import salt.client
with salt.client.get_local_client() as sc:
sc.cmd('target', 'ini.remove_section',
[path_to_ini_file, section_name])
sc.cmd('target', 'ini.remove_section', [path_to_ini_file, section_name])
CLI Example:
.. code-block:: bash
salt '*' ini.remove_section /path/to/ini section_name
"""
inifile = _Ini.get_ini_file(file_name, separator=separator)
inifile = _Ini.get_ini_file(file_name, separator=separator, encoding=encoding)
if section in inifile:
section = inifile.pop(section)
inifile.flush()
@ -201,24 +325,46 @@ def remove_section(file_name, section, separator="="):
return ret
def get_ini(file_name, separator="="):
def get_ini(file_name, separator="=", encoding=None):
"""
Retrieve whole structure from an ini file and return it as dictionary.
Retrieve the whole structure from an ini file and return it as a dictionary.
Args:
file_name (str):
The full path to the ini file.
separator (str):
The character used to separate keys and values. Standard ini files
use the "=" character. The default is ``=``.
.. versionadded:: 2016.11.0
encoding (str):
A string value representing encoding of the target ini file. If
``None`` is passed, it uses the system default which is likely
``utf-8``. Default is ``None``
.. versionadded:: 3006.6
Returns:
dict: A dictionary containing the sections along with the values and
names contained in each section
API Example:
.. code-block:: python
import salt.client
with salt.client.giet_local_client() as sc:
sc.cmd('target', 'ini.get_ini',
[path_to_ini_file])
with salt.client.get_local_client() as sc:
sc.cmd('target', 'ini.get_ini', [path_to_ini_file])
CLI Example:
.. code-block:: bash
salt '*' ini.get_ini /path/to/ini
"""
def ini_odict2dict(odict):
@ -227,6 +373,7 @@ def get_ini(file_name, separator="="):
:param odict: OrderedDict
:return: regular dict
"""
ret = {}
for key, val in odict.items():
if key[0] != "#":
@ -236,7 +383,7 @@ def get_ini(file_name, separator="="):
ret.update({key: val})
return ret
inifile = _Ini.get_ini_file(file_name, separator=separator)
inifile = _Ini.get_ini_file(file_name, separator=separator, encoding=encoding)
return ini_odict2dict(inifile)
@ -270,7 +417,7 @@ class _Section(OrderedDict):
# Match comments
com_match = COM_REGX.match(opt_str)
if com_match:
name = "#comment{}".format(comment_count)
name = f"#comment{comment_count}"
self.com = com_match.group(1)
comment_count += 1
self.update({name: opt_str})
@ -294,7 +441,7 @@ class _Section(OrderedDict):
self.update({name: value})
continue
# Anything remaining is a mystery.
name = "#unknown{}".format(unknown_count)
name = f"#unknown{unknown_count}"
self.update({name: opt_str})
unknown_count += 1
@ -365,7 +512,7 @@ class _Section(OrderedDict):
for name, value in self.items():
# Handle Comment Lines
if COM_REGX.match(name):
yield "{}{}".format(value, os.linesep)
yield f"{value}{os.linesep}"
# Handle Sections
elif isinstance(value, _Section):
sections_dict.update({name: value})
@ -374,7 +521,7 @@ class _Section(OrderedDict):
else:
yield "{}{}{}{}".format(
name,
" {} ".format(self.sep) if self.sep != " " else self.sep,
f" {self.sep} " if self.sep != " " else self.sep,
value,
os.linesep,
)
@ -409,19 +556,34 @@ class _Section(OrderedDict):
class _Ini(_Section):
def __init__(
self, name, inicontents="", separator="=", commenter="#", encoding=None
):
super().__init__(
self, inicontents=inicontents, separator=separator, commenter=commenter
)
self.name = name
if encoding is None:
encoding = __salt_system_encoding__
self.encoding = encoding
def refresh(self, inicontents=None):
if inicontents is None:
if not os.path.exists(self.name):
log.trace("File %s does not exist and will be created", self.name)
return
try:
with salt.utils.files.fopen(self.name) as rfh:
inicontents = salt.utils.stringutils.to_unicode(rfh.read())
# We need to set decode on open and not try to do it later with
# stringutils
with salt.utils.files.fopen(
self.name, "r", encoding=self.encoding
) as rfh:
inicontents = rfh.read()
inicontents = os.linesep.join(inicontents.splitlines())
except OSError as exc:
if __opts__["test"] is False:
raise CommandExecutionError(
"Unable to open file '{}'. Exception: {}".format(self.name, exc)
f"Unable to open file '{self.name}'. Exception: {exc}"
)
if not inicontents:
return
@ -443,22 +605,27 @@ class _Ini(_Section):
def flush(self):
try:
with salt.utils.files.fopen(self.name, "wb") as outfile:
# We need to encode in the fopen command instead of using
# data.encode in the writelines command. Using data.encode will
# cause a BoM to be placed on every line of the file
with salt.utils.files.fopen(
self.name, "w", encoding=self.encoding
) as outfile:
ini_gen = self.gen_ini()
next(ini_gen)
ini_gen_list = list(ini_gen)
# Avoid writing an initial line separator.
if ini_gen_list:
ini_gen_list[0] = ini_gen_list[0].lstrip(os.linesep)
outfile.writelines(salt.utils.data.encode(ini_gen_list))
outfile.writelines(ini_gen_list)
except OSError as exc:
raise CommandExecutionError(
"Unable to write file '{}'. Exception: {}".format(self.name, exc)
f"Unable to write file '{self.name}'. Exception: {exc}"
)
@staticmethod
def get_ini_file(file_name, separator="="):
inifile = _Ini(file_name, separator=separator)
def get_ini_file(file_name, separator="=", encoding=None):
inifile = _Ini(file_name, separator=separator, encoding=encoding)
inifile.refresh()
return inifile

View file

@ -12,7 +12,7 @@ Hives
This is the top level of the registry. They all begin with HKEY.
- HKEY_CLASSES_ROOT (HKCR)
- HKEY_CURRENT_USER(HKCU)
- HKEY_CURRENT_USER (HKCU)
- HKEY_LOCAL MACHINE (HKLM)
- HKEY_USER (HKU)
- HKEY_CURRENT_CONFIG
@ -139,7 +139,7 @@ def present(
A string value representing the full path of the key to include the
HIVE, Key, and all Subkeys. For example:
``HKEY_LOCAL_MACHINE\\SOFTWARE\\Salt``
``HKEY_LOCAL_MACHINE\SOFTWARE\Salt``
Valid hive values include:
@ -298,24 +298,24 @@ def present(
Example:
The following example will set the ``(Default)`` value for the
``SOFTWARE\\Salt`` key in the ``HKEY_CURRENT_USER`` hive to
``SOFTWARE\Salt`` key in the ``HKEY_CURRENT_USER`` hive to
``2016.3.1``:
.. code-block:: yaml
HKEY_CURRENT_USER\\SOFTWARE\\Salt:
HKEY_CURRENT_USER\SOFTWARE\Salt:
reg.present:
- vdata: 2016.3.1
Example:
The following example will set the value for the ``version`` entry under
the ``SOFTWARE\\Salt`` key in the ``HKEY_CURRENT_USER`` hive to
the ``SOFTWARE\Salt`` key in the ``HKEY_CURRENT_USER`` hive to
``2016.3.1``. The value will be reflected in ``Wow6432Node``:
.. code-block:: yaml
HKEY_CURRENT_USER\\SOFTWARE\\Salt:
HKEY_CURRENT_USER\SOFTWARE\Salt:
reg.present:
- vname: version
- vdata: 2016.3.1
@ -323,7 +323,7 @@ def present(
In the above example the path is interpreted as follows:
- ``HKEY_CURRENT_USER`` is the hive
- ``SOFTWARE\\Salt`` is the key
- ``SOFTWARE\Salt`` is the key
- ``vname`` is the value name ('version') that will be created under the key
- ``vdata`` is the data that will be assigned to 'version'
@ -423,7 +423,7 @@ def present(
)
add_change = {
"Key": r"{}\{}".format(hive, key),
"Key": rf"{hive}\{key}",
"Entry": "{}".format(
salt.utils.stringutils.to_unicode(vname, "utf-8") if vname else "(Default)"
),
@ -451,10 +451,10 @@ def present(
if not ret["result"]:
ret["changes"] = {}
ret["comment"] = r"Failed to add {} to {}\{}".format(vname, hive, key)
ret["comment"] = rf"Failed to add {vname} to {hive}\{key}"
else:
ret["changes"] = {"reg": {"Added": add_change}}
ret["comment"] = r"Added {} to {}\{}".format(vname, hive, key)
ret["comment"] = rf"Added {vname} to {hive}\{key}"
if ret["result"]:
ret = __utils__["dacl.check_perms"](
@ -480,7 +480,7 @@ def absent(name, vname=None, use_32bit_registry=False):
A string value representing the full path of the key to include the
HIVE, Key, and all Subkeys. For example:
``HKEY_LOCAL_MACHINE\\SOFTWARE\\Salt``
``HKEY_LOCAL_MACHINE\SOFTWARE\Salt``
Valid hive values include:
@ -504,7 +504,7 @@ def absent(name, vname=None, use_32bit_registry=False):
.. code-block:: yaml
'HKEY_CURRENT_USER\\SOFTWARE\\Salt':
'HKEY_CURRENT_USER\SOFTWARE\Salt':
reg.absent
- vname: version
@ -521,11 +521,11 @@ def absent(name, vname=None, use_32bit_registry=False):
hive=hive, key=key, vname=vname, use_32bit_registry=use_32bit_registry
)
if not reg_check["success"] or reg_check["vdata"] == "(value not set)":
ret["comment"] = "{} is already absent".format(name)
ret["comment"] = f"{name} is already absent"
return ret
remove_change = {
"Key": r"{}\{}".format(hive, key),
"Key": rf"{hive}\{key}",
"Entry": "{}".format(vname if vname else "(Default)"),
}
@ -541,10 +541,10 @@ def absent(name, vname=None, use_32bit_registry=False):
)
if not ret["result"]:
ret["changes"] = {}
ret["comment"] = r"Failed to remove {} from {}".format(key, hive)
ret["comment"] = rf"Failed to remove {key} from {hive}"
else:
ret["changes"] = {"reg": {"Removed": remove_change}}
ret["comment"] = r"Removed {} from {}".format(key, hive)
ret["comment"] = rf"Removed {key} from {hive}"
return ret
@ -598,10 +598,10 @@ def key_absent(name, use_32bit_registry=False):
if not __utils__["reg.read_value"](
hive=hive, key=key, use_32bit_registry=use_32bit_registry
)["success"]:
ret["comment"] = "{} is already absent".format(name)
ret["comment"] = f"{name} is already absent"
return ret
ret["changes"] = {"reg": {"Removed": {"Key": r"{}\{}".format(hive, key)}}}
ret["changes"] = {"reg": {"Removed": {"Key": rf"{hive}\{key}"}}}
# Check for test option
if __opts__["test"]:
@ -617,6 +617,6 @@ def key_absent(name, use_32bit_registry=False):
)["success"]:
ret["result"] = False
ret["changes"] = {}
ret["comment"] = "Failed to remove registry key {}".format(name)
ret["comment"] = f"Failed to remove registry key {name}"
return ret

View file

@ -968,21 +968,18 @@ class PublishServer(salt.transport.base.DaemonizedPublishServer):
htopic = salt.utils.stringutils.to_bytes(
hashlib.sha1(salt.utils.stringutils.to_bytes(topic)).hexdigest()
)
await self.dpub_sock.send(htopic, flags=zmq.SNDMORE)
await self.dpub_sock.send(payload)
await self.dpub_sock.send_multipart([htopic, payload])
log.trace("Filtered data has been sent")
# Syndic broadcast
if self.opts.get("order_masters"):
log.trace("Sending filtered data to syndic")
await self.dpub_sock.send(b"syndic", flags=zmq.SNDMORE)
await self.dpub_sock.send(payload)
await self.dpub_sock.send_multipart([b"syndic", payload])
log.trace("Filtered data has been sent to syndic")
# otherwise its a broadcast
else:
# TODO: constants file for "broadcast"
log.trace("Sending broadcasted data over publisher %s", self.pub_uri)
await self.dpub_sock.send(b"broadcast", flags=zmq.SNDMORE)
await self.dpub_sock.send(payload)
await self.dpub_sock.send_multipart([b"broadcast", payload])
log.trace("Broadcasted data has been sent")
else:
log.trace("Sending ZMQ-unfiltered data over publisher %s", self.pub_uri)

View file

@ -169,7 +169,7 @@ def _remove_circular_refs(ob, _seen=None):
This has been taken from author Martijn Pieters
https://stackoverflow.com/questions/44777369/
remove-circular-references-in-dicts-lists-tuples/44777477#44777477
:param ob: dict, list, typle, set, and frozenset
:param ob: dict, list, tuple, set, and frozenset
Standard python object
:param object _seen:
Object that has circular reference

View file

@ -363,7 +363,10 @@ def query(
sess_cookies = sess.cookies
sess.verify = verify_ssl
if http_proxy_url is not None:
sess.proxies = {"http": http_proxy_url}
sess.proxies = {
"http": http_proxy_url,
"https": http_proxy_url,
}
elif backend == "urllib2":
sess_cookies = None
else:

View file

@ -6,8 +6,6 @@
which works under python 3 because on python 3 you can no longer compare
strings against integers.
"""
import datetime
import inspect
import logging
@ -172,7 +170,7 @@ def warn_until(
if _version_ >= version:
caller = inspect.getframeinfo(sys._getframe(stacklevel - 1))
raise RuntimeError(
deprecated_message = (
"The warning triggered on filename '{filename}', line number "
"{lineno}, is supposed to be shown until version "
"{until_version} is released. Current version is now "
@ -181,8 +179,15 @@ def warn_until(
lineno=caller.lineno,
until_version=version.formatted_version,
salt_version=_version_.formatted_version,
),
)
)
if os.environ.get("RAISE_DEPRECATIONS_RUNTIME_ERRORS", "0") == "1":
# We don't raise RuntimeError by default since that can break
# users systems. We do however want to raise them in a CI context.
raise RuntimeError(deprecated_message)
# Otherwise, print the deprecated message to STDERR
sys.stderr.write(f"\n{deprecated_message}\n")
sys.stderr.flush()
if _dont_call_warnings is False and os.environ.get("PYTHONWARNINGS") != "ignore":
warnings.warn(
@ -240,7 +245,7 @@ def warn_until_date(
today = _current_date or datetime.datetime.utcnow().date()
if today >= date:
caller = inspect.getframeinfo(sys._getframe(stacklevel - 1))
raise RuntimeError(
deprecated_message = (
"{message} This warning(now exception) triggered on "
"filename '{filename}', line number {lineno}, is "
"supposed to be shown until {date}. Today is {today}. "
@ -252,6 +257,13 @@ def warn_until_date(
today=today.isoformat(),
),
)
if os.environ.get("RAISE_DEPRECATIONS_RUNTIME_ERRORS", "0") == "1":
# We don't raise RuntimeError by default since that can break
# users systems. We do however want to raise them in a CI context.
raise RuntimeError(deprecated_message)
# Otherwise, print the deprecated message to STDERR
sys.stderr.write(f"\n{deprecated_message}\n")
sys.stderr.flush()
if _dont_call_warnings is False and os.environ.get("PYTHONWARNINGS") != "ignore":
warnings.warn(

View file

@ -23,9 +23,8 @@ Values/Entries are name/data pairs. There can be many values in a key. The
(Default) value corresponds to the Key itself, the rest are their own name/value
pairs.
:depends: - PyWin32
:depends: PyWin32
"""
# When production windows installer is using Python 3, Python 2 code can be removed
import logging
@ -73,7 +72,7 @@ def __virtual__():
def _to_mbcs(vdata):
"""
Converts unicode to to current users character encoding. Use this for values
Converts unicode to current users character encoding. Use this for values
returned by reg functions
"""
return salt.utils.stringutils.to_unicode(vdata, "mbcs")
@ -186,7 +185,7 @@ def key_exists(hive, key, use_32bit_registry=False):
try:
hkey = registry.hkeys[local_hive]
except KeyError:
raise CommandExecutionError("Invalid Hive: {}".format(local_hive))
raise CommandExecutionError(f"Invalid Hive: {local_hive}")
access_mask = registry.registry_32[use_32bit_registry]
handle = None
@ -241,7 +240,7 @@ def value_exists(hive, key, vname, use_32bit_registry=False):
try:
hkey = registry.hkeys[local_hive]
except KeyError:
raise CommandExecutionError("Invalid Hive: {}".format(local_hive))
raise CommandExecutionError(f"Invalid Hive: {local_hive}")
access_mask = registry.registry_32[use_32bit_registry]
try:
@ -340,7 +339,7 @@ def list_keys(hive, key=None, use_32bit_registry=False):
try:
hkey = registry.hkeys[local_hive]
except KeyError:
raise CommandExecutionError("Invalid Hive: {}".format(local_hive))
raise CommandExecutionError(f"Invalid Hive: {local_hive}")
access_mask = registry.registry_32[use_32bit_registry]
subkeys = []
@ -355,10 +354,10 @@ def list_keys(hive, key=None, use_32bit_registry=False):
except win32api.error as exc:
if exc.winerror == 2:
log.debug(r"Cannot find key: %s\%s", hive, key, exc_info=True)
return False, r"Cannot find key: {}\{}".format(hive, key)
return False, rf"Cannot find key: {hive}\{key}"
if exc.winerror == 5:
log.debug(r"Access is denied: %s\%s", hive, key, exc_info=True)
return False, r"Access is denied: {}\{}".format(hive, key)
return False, rf"Access is denied: {hive}\{key}"
raise
finally:
@ -412,7 +411,7 @@ def list_values(hive, key=None, use_32bit_registry=False):
try:
hkey = registry.hkeys[local_hive]
except KeyError:
raise CommandExecutionError("Invalid Hive: {}".format(local_hive))
raise CommandExecutionError(f"Invalid Hive: {local_hive}")
access_mask = registry.registry_32[use_32bit_registry]
handle = None
values = list()
@ -445,10 +444,10 @@ def list_values(hive, key=None, use_32bit_registry=False):
except win32api.error as exc:
if exc.winerror == 2:
log.debug(r"Cannot find key: %s\%s", hive, key)
return False, r"Cannot find key: {}\{}".format(hive, key)
return False, rf"Cannot find key: {hive}\{key}"
elif exc.winerror == 5:
log.debug(r"Access is denied: %s\%s", hive, key)
return False, r"Access is denied: {}\{}".format(hive, key)
return False, rf"Access is denied: {hive}\{key}"
raise
finally:
@ -538,7 +537,7 @@ def read_value(hive, key, vname=None, use_32bit_registry=False):
try:
hkey = registry.hkeys[local_hive]
except KeyError:
raise CommandExecutionError("Invalid Hive: {}".format(local_hive))
raise CommandExecutionError(f"Invalid Hive: {local_hive}")
access_mask = registry.registry_32[use_32bit_registry]
handle = None
@ -574,13 +573,13 @@ def read_value(hive, key, vname=None, use_32bit_registry=False):
raise
except win32api.error as exc:
if exc.winerror == 2:
msg = "Cannot find key: {}\\{}".format(local_hive, local_key)
msg = f"Cannot find key: {local_hive}\\{local_key}"
log.trace(exc)
log.trace(msg)
ret["comment"] = msg
ret["success"] = False
elif exc.winerror == 5:
msg = "Access is denied: {}\\{}".format(local_hive, local_key)
msg = f"Access is denied: {local_hive}\\{local_key}"
log.trace(exc)
log.trace(msg)
ret["comment"] = msg
@ -733,7 +732,7 @@ def set_value(
try:
hkey = registry.hkeys[local_hive]
except KeyError:
raise CommandExecutionError("Invalid Hive: {}".format(local_hive))
raise CommandExecutionError(f"Invalid Hive: {local_hive}")
vtype_value = registry.vtype[local_vtype]
access_mask = registry.registry_32[use_32bit_registry] | win32con.KEY_ALL_ACCESS
@ -886,7 +885,7 @@ def delete_key_recursive(hive, key, use_32bit_registry=False):
try:
hkey = registry.hkeys[local_hive]
except KeyError:
raise CommandExecutionError("Invalid Hive: {}".format(local_hive))
raise CommandExecutionError(f"Invalid Hive: {local_hive}")
key_path = local_key
access_mask = registry.registry_32[use_32bit_registry] | win32con.KEY_ALL_ACCESS
@ -918,7 +917,7 @@ def delete_key_recursive(hive, key, use_32bit_registry=False):
"""
_key = win32api.RegOpenKeyEx(_hkey, _keypath, 0, _access_mask)
for subkeyname in _subkeys(_key):
subkeypath = "{}\\{}".format(_keypath, subkeyname)
subkeypath = f"{_keypath}\\{subkeyname}"
_ret = _traverse_registry_tree(_hkey, subkeypath, _ret, access_mask)
_ret.append(subkeypath)
return _ret
@ -938,13 +937,13 @@ def delete_key_recursive(hive, key, use_32bit_registry=False):
key_handle = win32api.RegOpenKeyEx(hkey, sub_key_path, 0, access_mask)
try:
win32api.RegDeleteKey(key_handle, "")
ret["Deleted"].append(r"{}\{}".format(hive, sub_key_path))
ret["Deleted"].append(rf"{hive}\{sub_key_path}")
except OSError as exc:
log.error(exc, exc_info=True)
ret["Failed"].append(r"{}\{} {}".format(hive, sub_key_path, exc))
ret["Failed"].append(rf"{hive}\{sub_key_path} {exc}")
except win32api.error as exc:
log.error(exc, exc_info=True)
ret["Failed"].append(r"{}\{} {}".format(hive, sub_key_path, exc.strerror))
ret["Failed"].append(rf"{hive}\{sub_key_path} {exc.strerror}")
finally:
if key_handle:
win32api.RegCloseKey(key_handle)
@ -998,7 +997,7 @@ def delete_value(hive, key, vname=None, use_32bit_registry=False):
try:
hkey = registry.hkeys[local_hive]
except KeyError:
raise CommandExecutionError("Invalid Hive: {}".format(local_hive))
raise CommandExecutionError(f"Invalid Hive: {local_hive}")
access_mask = registry.registry_32[use_32bit_registry] | win32con.KEY_ALL_ACCESS
handle = None

View file

@ -1,11 +1,17 @@
import asyncio
import copy
import logging
import os
import random
import time
from contextlib import contextmanager
import pytest
import tornado.ioloop
from saltfactories.utils import random_string
import salt.transport.zeromq
import salt.utils.process
from tests.support.mock import MagicMock, patch
from tests.support.pytest.transport import PubServerChannelProcess
@ -21,9 +27,169 @@ pytestmark = [
]
class PubServerChannelSender:
def __init__(self, pub_server_channel, payload_list):
self.pub_server_channel = pub_server_channel
self.payload_list = payload_list
def run(self):
loop = tornado.ioloop.IOLoop()
loop.add_callback(self._run, loop)
loop.start()
async def _run(self, loop):
for payload in self.payload_list:
await self.pub_server_channel.publish(payload)
await asyncio.sleep(2)
loop.stop()
def generate_msg_list(msg_cnt, minions_list, broadcast):
msg_list = []
for i in range(msg_cnt):
for idx, minion_id in enumerate(minions_list):
if broadcast:
msg_list.append(
{"tgt_type": "grain", "tgt": "id:*", "jid": msg_cnt * idx + i}
)
else:
msg_list.append(
{"tgt_type": "list", "tgt": [minion_id], "jid": msg_cnt * idx + i}
)
return msg_list
@contextmanager
def channel_publisher_manager(msg_list, p_cnt, pub_server_channel):
process_list = []
msg_list = copy.deepcopy(msg_list)
random.shuffle(msg_list)
batch_size = len(msg_list) // p_cnt
list_batch = [
[x * batch_size, x * batch_size + batch_size] for x in range(0, p_cnt)
]
list_batch[-1][1] = list_batch[-1][1] + 1
try:
for i, j in list_batch:
c = PubServerChannelSender(pub_server_channel, msg_list[i:j])
p = salt.utils.process.Process(target=c.run)
process_list.append(p)
for p in process_list:
p.start()
yield
finally:
for p in process_list:
p.join()
@pytest.mark.skip_on_windows
@pytest.mark.slow_test
def test_zeromq_filtering(salt_master, salt_minion):
def test_zeromq_filtering_minion(salt_master, salt_minion):
opts = dict(
salt_master.config.copy(),
ipc_mode="ipc",
pub_hwm=0,
zmq_filtering=True,
acceptance_wait_time=5,
)
minion_opts = dict(
salt_minion.config.copy(),
zmq_filtering=True,
)
messages = 200
workers = 5
minions = 3
expect = set(range(messages))
target_minion_id = salt_minion.id
minions_list = [target_minion_id]
for _ in range(minions - 1):
minions_list.append(random_string("zeromq-minion-"))
msg_list = generate_msg_list(messages, minions_list, False)
with patch(
"salt.utils.minions.CkMinions.check_minions",
MagicMock(
return_value={
"minions": minions_list,
"missing": [],
"ssh_minions": False,
}
),
):
with PubServerChannelProcess(opts, minion_opts) as server_channel:
with channel_publisher_manager(
msg_list, workers, server_channel.pub_server_channel
):
cnt = 0
last_results_len = 0
while cnt < 20:
time.sleep(2)
results_len = len(server_channel.collector.results)
if last_results_len == results_len:
break
last_results_len = results_len
cnt += 1
results = set(server_channel.collector.results)
assert (
results == expect
), f"{len(results)}, != {len(expect)}, difference: {expect.difference(results)} {results}"
@pytest.mark.skip_on_windows
@pytest.mark.slow_test
def test_zeromq_filtering_syndic(salt_master, salt_minion):
opts = dict(
salt_master.config.copy(),
ipc_mode="ipc",
pub_hwm=0,
zmq_filtering=True,
acceptance_wait_time=5,
order_masters=True,
)
minion_opts = dict(
salt_minion.config.copy(),
zmq_filtering=True,
__role="syndic",
)
messages = 200
workers = 5
minions = 3
expect = set(range(messages * minions))
minions_list = []
for _ in range(minions):
minions_list.append(random_string("zeromq-minion-"))
msg_list = generate_msg_list(messages, minions_list, False)
with patch(
"salt.utils.minions.CkMinions.check_minions",
MagicMock(
return_value={
"minions": minions_list,
"missing": [],
"ssh_minions": False,
}
),
):
with PubServerChannelProcess(opts, minion_opts) as server_channel:
with channel_publisher_manager(
msg_list, workers, server_channel.pub_server_channel
):
cnt = 0
last_results_len = 0
while cnt < 20:
time.sleep(2)
results_len = len(server_channel.collector.results)
if last_results_len == results_len:
break
last_results_len = results_len
cnt += 1
results = set(server_channel.collector.results)
assert (
results == expect
), f"{len(results)}, != {len(expect)}, difference: {expect.difference(results)} {results}"
@pytest.mark.skip_on_windows
@pytest.mark.slow_test
def test_zeromq_filtering_broadcast(salt_master, salt_minion):
"""
Test sending messages to publisher using UDP with zeromq_filtering enabled
"""
@ -34,28 +200,46 @@ def test_zeromq_filtering(salt_master, salt_minion):
zmq_filtering=True,
acceptance_wait_time=5,
)
send_num = 1
expect = []
minion_opts = dict(
salt_minion.config.copy(),
zmq_filtering=True,
)
messages = 200
workers = 5
minions = 3
expect = set(range(messages * minions))
target_minion_id = salt_minion.id
minions_list = [target_minion_id]
for _ in range(minions - 1):
minions_list.append(random_string("zeromq-minion-"))
msg_list = generate_msg_list(messages, minions_list, True)
with patch(
"salt.utils.minions.CkMinions.check_minions",
MagicMock(
return_value={
"minions": [salt_minion.id],
"minions": minions_list,
"missing": [],
"ssh_minions": False,
}
),
):
with PubServerChannelProcess(
opts, salt_minion.config.copy(), zmq_filtering=True
) as server_channel:
expect.append(send_num)
load = {"tgt_type": "glob", "tgt": "*", "jid": send_num}
server_channel.publish(load)
results = server_channel.collector.results
assert len(results) == send_num, "{} != {}, difference: {}".format(
len(results), send_num, set(expect).difference(results)
)
with PubServerChannelProcess(opts, minion_opts) as server_channel:
with channel_publisher_manager(
msg_list, workers, server_channel.pub_server_channel
):
cnt = 0
last_results_len = 0
while cnt < 20:
time.sleep(2)
results_len = len(server_channel.collector.results)
if last_results_len == results_len:
break
last_results_len = results_len
cnt += 1
results = set(server_channel.collector.results)
assert (
results == expect
), f"{len(results)}, != {len(expect)}, difference: {expect.difference(results)} {results}"
async def test_pub_channel(master_opts, io_loop):

View file

@ -1,4 +1,5 @@
import shutil
import ssl
import tarfile
import pytest
@ -7,6 +8,11 @@ from saltfactories.utils import random_string
import salt.utils.http
pytestmark = [
pytest.mark.slow_test,
pytest.mark.skip_if_binaries_missing("docker", "dockerd", check_all=False),
]
@pytest.mark.parametrize("backend", ["requests", "urllib2", "tornado"])
def test_decode_body(webserver, integration_files_dir, backend):
@ -19,12 +25,6 @@ def test_decode_body(webserver, integration_files_dir, backend):
assert isinstance(ret["body"], bytes)
pytestmark = [
pytest.mark.slow_test,
pytest.mark.skip_if_binaries_missing("docker", "dockerd", check_all=False),
]
@pytest.fixture(scope="module")
def tinyproxy_port():
return ports.get_unused_localhost_port()
@ -40,6 +40,26 @@ def tinyproxy_pass():
return random_string("tinyproxy-pass-")
@pytest.fixture(scope="session")
def ca():
trustme = pytest.importorskip("trustme")
return trustme.CA()
@pytest.fixture(scope="session")
def httpserver_ssl_context(ca):
context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
localhost_cert = ca.issue_cert("127.0.0.1")
localhost_cert.configure_cert(context)
return context
@pytest.fixture(scope="session")
def httpclient_ssl_context(ca):
with ca.cert_pem.tempfile() as ca_temp_path:
return ssl.create_default_context(cafile=ca_temp_path)
@pytest.fixture(params=[True, False], ids=lambda x: "basic-auth" if x else "no-auth")
def tinyproxy_basic_auth(request):
return request.param
@ -107,6 +127,7 @@ def tinyproxy_container(
def test_real_proxy(
tinyproxy_container,
httpserver,
ca,
tinyproxy_port,
tinyproxy_user,
tinyproxy_pass,
@ -137,18 +158,19 @@ def test_real_proxy(
else:
httpserver.expect_request(
"/real_proxy_test",
headers={"X-Tinyproxy-Header": "Test custom tinyproxy header"},
).respond_with_data(data, content_type="application/octet-stream")
url = httpserver.url_for("/real_proxy_test").replace("localhost", "127.0.0.1")
# We just want to be sure that it's using the proxy
ret = salt.utils.http.query(
url,
method=http_method,
data=data,
backend=backend,
opts=opts,
decode_body=False,
)
with ca.cert_pem.tempfile() as ca_temp_path:
ret = salt.utils.http.query(
url,
method=http_method,
data=data,
backend=backend,
opts=opts,
decode_body=False,
verify_ssl=ca_temp_path,
)
body = ret.get("body", "")
assert body == data

View file

@ -4,6 +4,10 @@ Integration tests for the ini_manage state
import pytest
pytestmark = [
pytest.mark.windows_whitelisted,
]
def test_options_present(salt_master, salt_call_cli):
"""

View file

@ -15,6 +15,7 @@ log = logging.getLogger(__name__)
CHECK_IMPORTS_SLS_CONTENTS = """
#!py
import importlib
import sys
def run():
config = {}
@ -81,7 +82,12 @@ def run():
]
}
for import_name in ["telnetlib"]:
# Import required for all OS'es
for import_name in [
"jinja2",
"telnetlib",
"yaml",
]:
try:
importlib.import_module(import_name)
config[import_name] = {
@ -101,6 +107,40 @@ def run():
}
]
}
# Windows specific requirements (I think, there may be some for other OSes in here)
if sys.platform == "win32":
for import_name in [
"cffi",
"clr_loader",
"lxml",
"pythonnet",
"pytz",
"pywintypes",
"timelib",
"win32",
"wmi",
"xmltodict",
]:
try:
importlib.import_module(import_name)
config[import_name] = {
'test.succeed_without_changes': [
{
"name": import_name,
'comment': "The '{}' import succeeded.".format(import_name)
}
]
}
except ModuleNotFoundError as err:
config[import_name] = {
'test.fail_without_changes': [
{
"name": import_name,
'comment': "The '{}' import failed. The error was: {}".format(import_name, err)
}
]
}
return config
"""

View file

@ -1,11 +1,508 @@
import os
import sys
import salt.modules.ini_manage
import pytest
import salt.modules.ini_manage as ini
import salt.utils.files
import salt.utils.stringutils
@pytest.fixture
def ini_content():
return [
"# Comment on the first line",
"",
"# First main option",
"option1=main1",
"",
"# Second main option",
"option2=main2",
"",
"",
"[main]",
"# Another comment",
"test1=value 1",
"",
"test2=value 2",
"",
"[SectionB]",
"test1=value 1B",
"",
"# Blank line should be above",
"test3 = value 3B",
"",
"[SectionC]",
"# The following option is empty",
"empty_option=",
]
@pytest.fixture(scope="function")
def ini_file(tmp_path, ini_content):
file_path = tmp_path / "file.ini"
yield file_path
@pytest.fixture
def unicode_content():
return [
"# An ini file with some unicode characters",
"",
"[Ascii]",
"de = Deutsch",
"en_GB = English (UK)",
"en_US = English (US)",
"fi = Suomi",
"hu = Magyar",
"it = Italiano",
"nl = Dutch",
"pt = Portuguese",
"sv = Svenska",
"",
"[Юникод]",
"# This means unicode in Russian",
"es = Español",
"es_ES = Español (ES)",
"fr = Français",
"hi = हिंदी",
"ja = 日本語",
"ko = :한국어",
"zh = 简体中文",
"繁體中文 = zh_TW",
]
def test_section_req():
"""
Test the __repr__ in the _Section class
"""
expected = "_Section(){}{{}}".format(os.linesep)
assert repr(salt.modules.ini_manage._Section("test")) == expected
expected = f"_Section(){os.linesep}{{}}"
assert repr(ini._Section("test")) == expected
@pytest.mark.parametrize("linesep", ["\r", "\n", "\r\n"])
@pytest.mark.parametrize(
"encoding", [None, "cp1252" if sys.platform == "win32" else "ISO-2022-JP"]
)
def test_get_option(encoding, linesep, ini_file, ini_content):
"""
Test get_option method.
"""
content = salt.utils.stringutils.to_bytes(
linesep.join(ini_content), encoding=encoding
)
ini_file.write_bytes(content)
assert (
ini.get_option(str(ini_file), "main", "test1", encoding=encoding) == "value 1"
)
assert (
ini.get_option(str(ini_file), "main", "test2", encoding=encoding) == "value 2"
)
assert (
ini.get_option(str(ini_file), "SectionB", "test1", encoding=encoding)
== "value 1B"
)
assert (
ini.get_option(str(ini_file), "SectionB", "test3", encoding=encoding)
== "value 3B"
)
assert (
ini.get_option(str(ini_file), "SectionC", "empty_option", encoding=encoding)
== ""
)
@pytest.mark.parametrize("linesep", ["\r", "\n", "\r\n"])
@pytest.mark.parametrize(
"encoding", [None, "cp1252" if sys.platform == "win32" else "ISO-2022-JP"]
)
def test_get_section(encoding, linesep, ini_file, ini_content):
"""
Test get_section method.
"""
content = salt.utils.stringutils.to_bytes(
linesep.join(ini_content), encoding=encoding
)
ini_file.write_bytes(content)
expected = {"test1": "value 1B", "test3": "value 3B"}
assert ini.get_section(str(ini_file), "SectionB", encoding=encoding) == expected
@pytest.mark.parametrize("linesep", ["\r", "\n", "\r\n"])
@pytest.mark.parametrize(
"encoding", [None, "cp1252" if sys.platform == "win32" else "ISO-2022-JP"]
)
def test_remove_option(encoding, linesep, ini_file, ini_content):
"""
Test remove_option method.
"""
content = salt.utils.stringutils.to_bytes(
linesep.join(ini_content), encoding=encoding
)
ini_file.write_bytes(content)
assert (
ini.remove_option(str(ini_file), "SectionB", "test1", encoding=encoding)
== "value 1B"
)
assert ini.get_option(str(ini_file), "SectionB", "test1", encoding=encoding) is None
@pytest.mark.parametrize("linesep", ["\r", "\n", "\r\n"])
@pytest.mark.parametrize(
"encoding", [None, "cp1252" if sys.platform == "win32" else "ISO-2022-JP"]
)
def test_remove_section(encoding, linesep, ini_file, ini_content):
"""
Test remove_section method.
"""
content = salt.utils.stringutils.to_bytes(
linesep.join(ini_content), encoding=encoding
)
ini_file.write_bytes(content)
expected = {"test1": "value 1B", "test3": "value 3B"}
assert ini.remove_section(str(ini_file), "SectionB", encoding=encoding) == expected
assert ini.get_section(str(ini_file), "SectionB", encoding=encoding) == {}
@pytest.mark.parametrize("linesep", ["\r", "\n", "\r\n"])
@pytest.mark.parametrize(
"encoding", [None, "cp1252" if sys.platform == "win32" else "ISO-2022-JP"]
)
def test_get_ini(encoding, linesep, ini_file, ini_content):
"""
Test get_ini method.
"""
content = salt.utils.stringutils.to_bytes(
linesep.join(ini_content), encoding=encoding
)
ini_file.write_bytes(content)
expected = {
"SectionC": {
"empty_option": "",
},
"SectionB": {
"test1": "value 1B",
"test3": "value 3B",
},
"main": {
"test1": "value 1",
"test2": "value 2",
},
"option2": "main2",
"option1": "main1",
}
assert dict(ini.get_ini(str(ini_file), encoding=encoding)) == expected
@pytest.mark.parametrize("linesep", ["\r", "\n", "\r\n"])
@pytest.mark.parametrize(
"encoding", [None, "cp1252" if sys.platform == "win32" else "ISO-2022-JP"]
)
def test_set_option(encoding, linesep, ini_file, ini_content):
"""
Test set_option method.
"""
content = salt.utils.stringutils.to_bytes(
linesep.join(ini_content), encoding=encoding
)
ini_file.write_bytes(content)
result = ini.set_option(
str(ini_file),
{
"SectionB": {
"test3": "new value 3B",
"test_set_option": "test_set_value",
},
"SectionD": {"test_set_option2": "test_set_value1"},
},
encoding=encoding,
)
expected = {
"SectionB": {
"test3": {"after": "new value 3B", "before": "value 3B"},
"test_set_option": {"after": "test_set_value", "before": None},
},
"SectionD": {
"after": {"test_set_option2": "test_set_value1"},
"before": None,
},
}
assert result == expected
# Check existing option updated
assert (
ini.get_option(str(ini_file), "SectionB", "test3", encoding=encoding)
== "new value 3B"
)
# Check new section and option added
assert (
ini.get_option(str(ini_file), "SectionD", "test_set_option2", encoding=encoding)
== "test_set_value1"
)
@pytest.mark.parametrize("linesep", ["\r", "\n", "\r\n"])
@pytest.mark.parametrize(
"encoding", [None, "cp1252" if sys.platform == "win32" else "ISO-2022-JP"]
)
def test_empty_value(encoding, linesep, ini_file, ini_content):
"""
Test empty value preserved after edit
"""
content = salt.utils.stringutils.to_bytes(
linesep.join(ini_content), encoding=encoding
)
ini_file.write_bytes(content)
ini.set_option(
str(ini_file), {"SectionB": {"test3": "new value 3B"}}, encoding=encoding
)
with salt.utils.files.fopen(str(ini_file), "r") as fp_:
file_content = salt.utils.stringutils.to_unicode(fp_.read(), encoding=encoding)
expected = "{0}{1}{0}".format(os.linesep, "empty_option = ")
assert expected in file_content, "empty_option was not preserved"
@pytest.mark.parametrize("linesep", ["\r", "\n", "\r\n"])
@pytest.mark.parametrize(
"encoding", [None, "cp1252" if sys.platform == "win32" else "ISO-2022-JP"]
)
def test_empty_lines(encoding, linesep, ini_file, ini_content):
"""
Test empty lines preserved after edit
"""
content = salt.utils.stringutils.to_bytes(
linesep.join(ini_content), encoding=encoding
)
ini_file.write_bytes(content)
expected = os.linesep.join(
[
"# Comment on the first line",
"",
"# First main option",
"option1 = main1",
"",
"# Second main option",
"option2 = main2",
"",
"[main]",
"# Another comment",
"test1 = value 1",
"",
"test2 = value 2",
"",
"[SectionB]",
"test1 = value 1B",
"",
"# Blank line should be above",
"test3 = new value 3B",
"",
"[SectionC]",
"# The following option is empty",
"empty_option = ",
"",
]
)
ini.set_option(
str(ini_file), {"SectionB": {"test3": "new value 3B"}}, encoding=encoding
)
with salt.utils.files.fopen(str(ini_file), "r") as fp_:
file_content = fp_.read()
assert expected == file_content
@pytest.mark.parametrize("linesep", ["\r", "\n", "\r\n"])
@pytest.mark.parametrize(
"encoding", [None, "cp1252" if sys.platform == "win32" else "ISO-2022-JP"]
)
def test_empty_lines_multiple_edits(encoding, linesep, ini_file, ini_content):
"""
Test empty lines preserved after multiple edits
"""
content = salt.utils.stringutils.to_bytes(
linesep.join(ini_content), encoding=encoding
)
ini_file.write_bytes(content)
ini.set_option(
str(ini_file),
{"SectionB": {"test3": "this value will be edited two times"}},
encoding=encoding,
)
expected = os.linesep.join(
[
"# Comment on the first line",
"",
"# First main option",
"option1 = main1",
"",
"# Second main option",
"option2 = main2",
"",
"[main]",
"# Another comment",
"test1 = value 1",
"",
"test2 = value 2",
"",
"[SectionB]",
"test1 = value 1B",
"",
"# Blank line should be above",
"test3 = new value 3B",
"",
"[SectionC]",
"# The following option is empty",
"empty_option = ",
"",
]
)
ini.set_option(
str(ini_file), {"SectionB": {"test3": "new value 3B"}}, encoding=encoding
)
with salt.utils.files.fopen(str(ini_file), "r") as fp_:
file_content = fp_.read()
assert expected == file_content
@pytest.mark.parametrize("linesep", ["\r", "\n", "\r\n"])
@pytest.mark.parametrize("encoding", [None, "utf-16", "utf-32-le"])
def test_unicode_get_option(encoding, linesep, ini_file, unicode_content):
"""
Test ability to get an option from a file that contains unicode characters
We can't encode the file with something that doesn't support unicode
Ie: cp1252
"""
content = salt.utils.stringutils.to_bytes(
linesep.join(unicode_content), encoding=encoding
)
ini_file.write_bytes(content)
# Get a non-unicode value
assert ini.get_option(str(ini_file), "Ascii", "de", encoding=encoding) == "Deutsch"
# Get a unicode value
assert ini.get_option(str(ini_file), "Юникод", "hi", encoding=encoding) == "हिंदी"
@pytest.mark.parametrize("linesep", ["\r", "\n", "\r\n"])
@pytest.mark.parametrize("encoding", [None, "utf-16", "utf-16-le", "utf-32-le"])
def test_unicode_set_option(encoding, linesep, ini_file, unicode_content):
"""
Test ability to set an option in a file that contains unicode characters.
The option itself may be unicode
We can't encode the file with something that doesn't support unicode
Ie: cp1252
"""
content = salt.utils.stringutils.to_bytes(
linesep.join(unicode_content), encoding=encoding
)
ini_file.write_bytes(content)
result = ini.set_option(
str(ini_file),
{
"Ascii": {"ay": "Aymar"},
"Юникод": {"dv": "ދިވެހިބަސް"},
},
encoding=encoding,
)
expected = {
"Ascii": {
"ay": {
"before": None,
"after": "Aymar",
},
},
"Юникод": {
"dv": {
"before": None,
"after": "ދިވެހިބަސް",
},
},
}
assert result == expected
# Check existing option updated
assert ini.get_option(str(ini_file), "Ascii", "ay", encoding=encoding) == "Aymar"
# Check new section and option added
assert (
ini.get_option(str(ini_file), "Юникод", "dv", encoding=encoding) == "ދިވެހިބަސް"
)
@pytest.mark.parametrize("linesep", ["\r", "\n", "\r\n"])
@pytest.mark.parametrize("encoding", [None, "utf-16", "utf-16-le", "utf-32-le"])
def test_unicode_get_section(encoding, linesep, ini_file, unicode_content):
"""
Test get_section method.
"""
content = salt.utils.stringutils.to_bytes(
linesep.join(unicode_content), encoding=encoding
)
ini_file.write_bytes(content)
expected = {
"es": "Español",
"es_ES": "Español (ES)",
"fr": "Français",
"hi": "हिंदी",
"ja": "日本語",
"ko": ":한국어",
"zh": "简体中文",
"繁體中文": "zh_TW",
}
assert ini.get_section(str(ini_file), "Юникод", encoding=encoding) == expected
@pytest.mark.parametrize("linesep", ["\r", "\n", "\r\n"])
@pytest.mark.parametrize("encoding", [None, "utf-16", "utf-16-le", "utf-32-le"])
def test_unicode_remove_option(encoding, linesep, ini_file, unicode_content):
"""
Test remove_option method.
"""
content = salt.utils.stringutils.to_bytes(
linesep.join(unicode_content), encoding=encoding
)
ini_file.write_bytes(content)
assert (
ini.remove_option(str(ini_file), "Юникод", "繁體中文", encoding=encoding) == "zh_TW"
)
assert ini.get_option(str(ini_file), "Юникод", "繁體中文", encoding=encoding) is None
@pytest.mark.parametrize("linesep", ["\r", "\n", "\r\n"])
@pytest.mark.parametrize("encoding", [None, "utf-16", "utf-16-le", "utf-32-le"])
def test_unicode_remove_section(encoding, linesep, ini_file, unicode_content):
"""
Test remove_section method.
"""
content = salt.utils.stringutils.to_bytes(
linesep.join(unicode_content), encoding=encoding
)
ini_file.write_bytes(content)
expected = {
"es": "Español",
"es_ES": "Español (ES)",
"fr": "Français",
"hi": "हिंदी",
"ja": "日本語",
"ko": ":한국어",
"zh": "简体中文",
"繁體中文": "zh_TW",
}
assert ini.remove_section(str(ini_file), "Юникод", encoding=encoding) == expected
assert ini.get_section(str(ini_file), "Юникод", encoding=encoding) == {}

View file

@ -0,0 +1,6 @@
import sys
def test_salt_system_encoding():
encoding = sys.getdefaultencoding()
assert __salt_system_encoding__ == encoding

View file

@ -250,7 +250,8 @@ def test_query_proxy(httpserver):
)
assert mock_session.return_value.proxies == {
"http": "http://salt_test:super_secret@127.0.0.1:88"
"http": "http://salt_test:super_secret@127.0.0.1:88",
"https": "http://salt_test:super_secret@127.0.0.1:88",
}
opts["no_proxy"] = [httpserver.host]

View file

@ -1,4 +1,5 @@
import ctypes
import hashlib
import logging
import multiprocessing
import queue
@ -6,15 +7,16 @@ import socket
import time
import pytest
import tornado.gen
import tornado.ioloop
import tornado.iostream
import zmq
from pytestshellutils.utils.processes import terminate_process
import salt.channel.server
import salt.crypt
import salt.exceptions
import salt.master
import salt.payload
import salt.utils.msgpack
import salt.utils.process
import salt.utils.stringutils
@ -37,10 +39,12 @@ class Collector(salt.utils.process.SignalHandlingProcess):
port,
aes_key,
timeout=300,
zmq_filtering=False,
):
super().__init__()
self.minion_config = minion_config
self.hexid = hashlib.sha1(
salt.utils.stringutils.to_bytes(self.minion_config["id"])
).hexdigest()
self.interface = interface
self.port = port
self.aes_key = aes_key
@ -49,10 +53,11 @@ class Collector(salt.utils.process.SignalHandlingProcess):
self.hard_timeout = time.time() + timeout + 120
self.manager = multiprocessing.Manager()
self.results = self.manager.list()
self.zmq_filtering = zmq_filtering
self.zmq_filtering = minion_config["zmq_filtering"]
self.stopped = multiprocessing.Event()
self.started = multiprocessing.Event()
self.running = multiprocessing.Event()
self.stop_running = multiprocessing.Event()
self.unpacker = salt.utils.msgpack.Unpacker(raw=False)
@property
@ -86,9 +91,17 @@ class Collector(salt.utils.process.SignalHandlingProcess):
self.ctx = zmq.Context()
self.sock = self.ctx.socket(zmq.SUB)
self.sock.setsockopt(zmq.LINGER, -1)
self.sock.setsockopt(zmq.SUBSCRIBE, b"")
if self.zmq_filtering:
self.sock.setsockopt(zmq.SUBSCRIBE, b"broadcast")
if self.minion_config.get("__role") == "syndic":
self.sock.setsockopt(zmq.SUBSCRIBE, b"syndic")
else:
self.sock.setsockopt(
zmq.SUBSCRIBE, salt.utils.stringutils.to_bytes(self.hexid)
)
else:
self.sock.setsockopt(zmq.SUBSCRIBE, b"")
pub_uri = f"tcp://{self.interface}:{self.port}"
log.info("Collector listen %s", pub_uri)
self.sock.connect(pub_uri)
else:
end = time.time() + 120
@ -104,30 +117,44 @@ class Collector(salt.utils.process.SignalHandlingProcess):
break
self.sock = tornado.iostream.IOStream(sock)
@tornado.gen.coroutine
def _recv(self):
async def _recv(self):
if self.transport == "zeromq":
# test_zeromq_filtering requires catching the
# SaltDeserializationError in order to pass.
try:
payload = self.sock.recv(zmq.NOBLOCK)
serial_payload = salt.payload.loads(payload)
raise tornado.gen.Return(serial_payload)
messages = self.sock.recv_multipart(flags=zmq.NOBLOCK, copy=True)
messages_len = len(messages)
if messages_len == 1:
serial_payload = salt.payload.loads(messages[0])
elif messages_len == 2:
message_target = salt.utils.stringutils.to_str(messages[0])
is_syndic = self.minion_config.get("__role") == "syndic"
if (
not is_syndic
and message_target not in ("broadcast", self.hexid)
) or (is_syndic and message_target not in ("broadcast", "syndic")):
log.debug(
"Publish received for not this minion: %s", message_target
)
return
serial_payload = salt.payload.loads(messages[1])
else:
raise Exception("Invalid number of messages")
return serial_payload
except (zmq.ZMQError, salt.exceptions.SaltDeserializationError):
raise RecvError("ZMQ Error")
else:
for msg in self.unpacker:
serial_payload = salt.payload.loads(msg["body"])
raise tornado.gen.Return(serial_payload)
byts = yield self.sock.read_bytes(8096, partial=True)
return serial_payload
byts = await self.sock.read_bytes(8096, partial=True)
self.unpacker.feed(byts)
for msg in self.unpacker:
serial_payload = salt.payload.loads(msg["body"])
raise tornado.gen.Return(serial_payload)
return serial_payload
raise RecvError("TCP Error")
@tornado.gen.coroutine
def _run(self, loop):
async def _run(self, loop):
try:
self._setup_listener()
except Exception: # pylint: disable=broad-except
@ -149,7 +176,7 @@ class Collector(salt.utils.process.SignalHandlingProcess):
log.error("Receive timeout reached in test collector!")
break
try:
payload = yield self._recv()
payload = await self._recv()
except RecvError:
time.sleep(0.03)
else:
@ -164,6 +191,7 @@ class Collector(salt.utils.process.SignalHandlingProcess):
continue
if "stop" in payload:
log.info("Collector stopped")
self.stop_running.set()
break
last_msg = time.time()
self.results.append(payload["jid"])
@ -250,13 +278,14 @@ class PubServerChannelProcess(salt.utils.process.SignalHandlingProcess):
)
def run(self):
ioloop = tornado.ioloop.IOLoop()
try:
while True:
try:
payload = self.queue.get(False)
except queue.Empty:
if self._closing is True:
break
time.sleep(0.03)
continue
if payload is None:
@ -297,6 +326,7 @@ class PubServerChannelProcess(salt.utils.process.SignalHandlingProcess):
self.publish({"tgt_type": "glob", "tgt": "*", "jid": -1, "start": True})
if self.collector.running.wait(1) is True:
break
time.sleep(0.5)
attempts -= 1
else:
pytest.fail("Failed to confirm the collector has started")
@ -304,7 +334,15 @@ class PubServerChannelProcess(salt.utils.process.SignalHandlingProcess):
def __exit__(self, *args):
# Publish a payload to tell the collection it's done processing
self.publish({"tgt_type": "glob", "tgt": "*", "jid": -1, "stop": True})
attempts = 300
while attempts > 0:
self.publish({"tgt_type": "glob", "tgt": "*", "jid": -1, "stop": True})
if self.collector.stop_running.wait(1) is True:
break
time.sleep(0.5)
attempts -= 1
else:
pytest.fail("Failed to confirm the collector has stopped")
# Now trigger the collector to also exit
self.collector.__exit__(*args)
# We can safely wait here without a timeout because the Collector instance has a

View file

@ -1,232 +0,0 @@
"""
Testing ini_manage exec module.
"""
import os
import tempfile
import salt.modules.ini_manage as ini
import salt.utils.files
import salt.utils.stringutils
from tests.support.unit import TestCase
class IniManageTestCase(TestCase):
"""
Testing ini_manage exec module.
"""
TEST_FILE_CONTENT = [
"# Comment on the first line",
"",
"# First main option",
"option1=main1",
"",
"# Second main option",
"option2=main2",
"",
"",
"[main]",
"# Another comment",
"test1=value 1",
"",
"test2=value 2",
"",
"[SectionB]",
"test1=value 1B",
"",
"# Blank line should be above",
"test3 = value 3B",
"",
"[SectionC]",
"# The following option is empty",
"empty_option=",
]
maxDiff = None
def _setUp(self, linesep):
self.tfile = tempfile.NamedTemporaryFile(delete=False, mode="w+b")
self.tfile.write(
salt.utils.stringutils.to_bytes(linesep.join(self.TEST_FILE_CONTENT))
)
self.tfile.close()
def setUp(self):
self._setUp(os.linesep)
def tearDown(self):
os.remove(self.tfile.name)
def test_get_option(self):
"""
Test get_option method.
"""
self.assertEqual(ini.get_option(self.tfile.name, "main", "test1"), "value 1")
self.assertEqual(ini.get_option(self.tfile.name, "main", "test2"), "value 2")
self.assertEqual(
ini.get_option(self.tfile.name, "SectionB", "test1"), "value 1B"
)
self.assertEqual(
ini.get_option(self.tfile.name, "SectionB", "test3"), "value 3B"
)
self.assertEqual(
ini.get_option(self.tfile.name, "SectionC", "empty_option"), ""
)
def test_get_section(self):
"""
Test get_section method.
"""
self.assertEqual(
ini.get_section(self.tfile.name, "SectionB"),
{"test1": "value 1B", "test3": "value 3B"},
)
def test_remove_option(self):
"""
Test remove_option method.
"""
self.assertEqual(
ini.remove_option(self.tfile.name, "SectionB", "test1"), "value 1B"
)
self.assertIsNone(ini.get_option(self.tfile.name, "SectionB", "test1"))
def test_remove_section(self):
"""
Test remove_section method.
"""
self.assertEqual(
ini.remove_section(self.tfile.name, "SectionB"),
{"test1": "value 1B", "test3": "value 3B"},
)
self.assertEqual(ini.get_section(self.tfile.name, "SectionB"), {})
def test_get_ini(self):
"""
Test get_ini method.
"""
self.assertEqual(
dict(ini.get_ini(self.tfile.name)),
{
"SectionC": {"empty_option": ""},
"SectionB": {"test1": "value 1B", "test3": "value 3B"},
"main": {"test1": "value 1", "test2": "value 2"},
"option2": "main2",
"option1": "main1",
},
)
def test_set_option(self):
"""
Test set_option method.
"""
result = ini.set_option(
self.tfile.name,
{
"SectionB": {
"test3": "new value 3B",
"test_set_option": "test_set_value",
},
"SectionD": {"test_set_option2": "test_set_value1"},
},
)
self.assertEqual(
result,
{
"SectionB": {
"test3": {"after": "new value 3B", "before": "value 3B"},
"test_set_option": {"after": "test_set_value", "before": None},
},
"SectionD": {
"after": {"test_set_option2": "test_set_value1"},
"before": None,
},
},
)
# Check existing option updated
self.assertEqual(
ini.get_option(self.tfile.name, "SectionB", "test3"), "new value 3B"
)
# Check new section and option added
self.assertEqual(
ini.get_option(self.tfile.name, "SectionD", "test_set_option2"),
"test_set_value1",
)
def test_empty_value(self):
"""
Test empty value preserved after edit
"""
ini.set_option(self.tfile.name, {"SectionB": {"test3": "new value 3B"}})
with salt.utils.files.fopen(self.tfile.name, "r") as fp_:
file_content = salt.utils.stringutils.to_unicode(fp_.read())
expected = "{0}{1}{0}".format(os.linesep, "empty_option = ")
self.assertIn(expected, file_content, "empty_option was not preserved")
def test_empty_lines(self):
"""
Test empty lines preserved after edit
"""
ini.set_option(self.tfile.name, {"SectionB": {"test3": "new value 3B"}})
expected = os.linesep.join(
[
"# Comment on the first line",
"",
"# First main option",
"option1 = main1",
"",
"# Second main option",
"option2 = main2",
"",
"[main]",
"# Another comment",
"test1 = value 1",
"",
"test2 = value 2",
"",
"[SectionB]",
"test1 = value 1B",
"",
"# Blank line should be above",
"test3 = new value 3B",
"",
"[SectionC]",
"# The following option is empty",
"empty_option = ",
"",
]
)
with salt.utils.files.fopen(self.tfile.name, "r") as fp_:
file_content = salt.utils.stringutils.to_unicode(fp_.read())
self.assertEqual(expected, file_content)
def test_empty_lines_multiple_edits(self):
"""
Test empty lines preserved after multiple edits
"""
ini.set_option(
self.tfile.name,
{"SectionB": {"test3": "this value will be edited two times"}},
)
self.test_empty_lines()
def test_newline_characters(self):
"""
Test newline characters
"""
for c in ["\n", "\r", "\r\n"]:
for test in [
self.test_get_option,
self.test_get_section,
self.test_remove_option,
self.test_remove_section,
self.test_get_ini,
self.test_set_option,
self.test_empty_value,
self.test_empty_lines,
self.test_empty_lines_multiple_edits,
]:
self.tearDown()
self._setUp(c)
test()

View file

@ -263,6 +263,22 @@ def rsync(ctx: Context, name: str, download: bool = False):
"--print-tests-selection",
],
},
"print_system_info": {
"help": "Print the system information",
"action": "store_true",
"flags": [
"--psi",
"--print-system-information",
],
},
"print_system_info_only": {
"help": "Print the system information and exit",
"action": "store_true",
"flags": [
"--psio",
"--print-system-information-only",
],
},
"skip_code_coverage": {
"help": "Skip tracking code coverage",
"action": "store_true",
@ -293,6 +309,7 @@ def test(
skip_requirements_install: bool = False,
print_tests_selection: bool = False,
print_system_info: bool = False,
print_system_info_only: bool = False,
skip_code_coverage: bool = False,
envvars: list[str] = None,
fips: bool = False,
@ -323,6 +340,10 @@ def test(
env["PRINT_SYSTEM_INFO"] = "1"
else:
env["PRINT_SYSTEM_INFO"] = "0"
if print_system_info_only:
env["PRINT_SYSTEM_INFO_ONLY"] = "1"
else:
env["PRINT_SYSTEM_INFO_ONLY"] = "0"
if (
skip_requirements_install
or os.environ.get("SKIP_REQUIREMENTS_INSTALL", "0") == "1"
@ -1438,6 +1459,7 @@ class VM:
env["PYTHONUTF8"] = "1"
env["OUTPUT_COLUMNS"] = str(self.ctx.console.width)
env["GITHUB_ACTIONS_PIPELINE"] = "1"
env["RAISE_DEPRECATIONS_RUNTIME_ERRORS"] = "1"
self.write_and_upload_dot_env(env)
if self.is_windows is False and self.config.ssh_username != "root":
sudo = True