Merge branch 'master' into 65080_require_included_sls

This commit is contained in:
Gareth J. Greenaway 2023-10-09 17:22:17 -07:00 committed by GitHub
commit 2fed2efa0f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
117 changed files with 2500 additions and 857 deletions

View file

@ -1,7 +1,7 @@
{
"repoOwner": "saltstack",
"repoName": "salt",
"targetBranchChoices": ["master", "3006.x", "3005.x"],
"targetBranchChoices": ["master", "3006.x", "3005.x", "freeze"],
"autoMerge": false,
"autoMergeMethod": "rebase",
"branchLabelMapping": {

View file

@ -33,7 +33,7 @@ jobs:
)
steps:
- name: Backport Action
uses: sqren/backport-github-action@v9.2.1
uses: sqren/backport-github-action@v8.9.7
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
auto_backport_label_prefix: "backport:"

View file

@ -19,14 +19,12 @@ on:
type: string
description: Seed used to invalidate caches
relenv-version:
required: false
required: true
type: string
default: 0.13.2
description: The version of relenv to use
python-version:
required: false
required: true
type: string
default: 3.10.12
description: The version of python to use with relenv
env:

View file

@ -110,6 +110,7 @@ jobs:
DEV_APP_CERT: "${{ secrets.MAC_SIGN_DEV_APP_CERT }}"
DEV_INSTALL_CERT: "${{ secrets.MAC_SIGN_DEV_INSTALL_CERT }}"
APPLE_ACCT: "${{ secrets.MAC_SIGN_APPLE_ACCT }}"
APPLE_TEAM_ID: "${{ secrets.MAC_SIGN_APPLE_TEAM_ID }}"
APP_SPEC_PWD: "${{ secrets.MAC_SIGN_APP_SPEC_PWD }}"
run: |
tools pkg build macos --relenv-version=${{ inputs.relenv-version }} --python-version=${{ inputs.python-version }} ${{

View file

@ -19,14 +19,12 @@ on:
type: string
description: Seed used to invalidate caches
relenv-version:
required: false
required: true
type: string
default: 0.13.2
description: The version of relenv to use
python-version:
required: false
required: true
type: string
default: 3.10.12
description: The version of python to use with relenv
env:

View file

@ -701,6 +701,25 @@ jobs:
skip-junit-reports: ${{ github.event_name == 'pull_request' }}
testing-releases: ${{ needs.prepare-workflow.outputs.testing-releases }}
photonos-4-arm64-pkg-tests:
name: Photon OS 4 Arm64 Package Tests
if: ${{ fromJSON(needs.prepare-workflow.outputs.jobs)['test-pkg'] && fromJSON(needs.prepare-workflow.outputs.runners)['self-hosted'] }}
needs:
- prepare-workflow
- build-rpm-pkgs
uses: ./.github/workflows/test-packages-action.yml
with:
distro-slug: photonos-4-arm64
platform: linux
arch: aarch64
salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}"
pkg-type: rpm
nox-version: 2022.8.7
cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.13
skip-code-coverage: ${{ fromJSON(needs.prepare-workflow.outputs.testrun)['skip_code_coverage'] }}
skip-junit-reports: ${{ github.event_name == 'pull_request' }}
testing-releases: ${{ needs.prepare-workflow.outputs.testing-releases }}
ubuntu-2004-pkg-tests:
name: Ubuntu 20.04 Package Tests
if: ${{ fromJSON(needs.prepare-workflow.outputs.jobs)['test-pkg'] && fromJSON(needs.prepare-workflow.outputs.runners)['self-hosted'] }}
@ -1271,6 +1290,25 @@ jobs:
skip-code-coverage: ${{ fromJSON(needs.prepare-workflow.outputs.testrun)['skip_code_coverage'] }}
skip-junit-reports: ${{ github.event_name == 'pull_request' }}
photonos-4-arm64:
name: Photon OS 4 Arm64
if: ${{ fromJSON(needs.prepare-workflow.outputs.jobs)['test'] && fromJSON(needs.prepare-workflow.outputs.runners)['self-hosted'] }}
needs:
- prepare-workflow
- build-salt-onedir
uses: ./.github/workflows/test-action.yml
with:
distro-slug: photonos-4-arm64
nox-session: ci-test-onedir
platform: linux
arch: aarch64
nox-version: 2022.8.7
testrun: ${{ needs.prepare-workflow.outputs.testrun }}
salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}"
cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.13
skip-code-coverage: ${{ fromJSON(needs.prepare-workflow.outputs.testrun)['skip_code_coverage'] }}
skip-junit-reports: ${{ github.event_name == 'pull_request' }}
ubuntu-2004:
name: Ubuntu 20.04
if: ${{ fromJSON(needs.prepare-workflow.outputs.jobs)['test'] && fromJSON(needs.prepare-workflow.outputs.runners)['self-hosted'] }}
@ -1372,6 +1410,7 @@ jobs:
- opensuse-15
- photonos-3
- photonos-4
- photonos-4-arm64
- ubuntu-2004
- ubuntu-2004-arm64
- ubuntu-2204
@ -1448,6 +1487,7 @@ jobs:
- opensuse-15
- photonos-3
- photonos-4
- photonos-4-arm64
- ubuntu-2004
- ubuntu-2004-arm64
- ubuntu-2204
@ -1461,6 +1501,7 @@ jobs:
- debian-11-arm64-pkg-tests
- photonos-3-pkg-tests
- photonos-4-pkg-tests
- photonos-4-arm64-pkg-tests
- ubuntu-2004-pkg-tests
- ubuntu-2004-arm64-pkg-tests
- ubuntu-2204-pkg-tests

View file

@ -751,6 +751,25 @@ jobs:
skip-junit-reports: false
testing-releases: ${{ needs.prepare-workflow.outputs.testing-releases }}
photonos-4-arm64-pkg-tests:
name: Photon OS 4 Arm64 Package Tests
if: ${{ fromJSON(needs.prepare-workflow.outputs.jobs)['test-pkg'] && fromJSON(needs.prepare-workflow.outputs.runners)['self-hosted'] }}
needs:
- prepare-workflow
- build-rpm-pkgs
uses: ./.github/workflows/test-packages-action.yml
with:
distro-slug: photonos-4-arm64
platform: linux
arch: aarch64
salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}"
pkg-type: rpm
nox-version: 2022.8.7
cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.13
skip-code-coverage: false
skip-junit-reports: false
testing-releases: ${{ needs.prepare-workflow.outputs.testing-releases }}
ubuntu-2004-pkg-tests:
name: Ubuntu 20.04 Package Tests
if: ${{ fromJSON(needs.prepare-workflow.outputs.jobs)['test-pkg'] && fromJSON(needs.prepare-workflow.outputs.runners)['self-hosted'] }}
@ -1321,6 +1340,25 @@ jobs:
skip-code-coverage: false
skip-junit-reports: false
photonos-4-arm64:
name: Photon OS 4 Arm64
if: ${{ fromJSON(needs.prepare-workflow.outputs.jobs)['test'] && fromJSON(needs.prepare-workflow.outputs.runners)['self-hosted'] }}
needs:
- prepare-workflow
- build-salt-onedir
uses: ./.github/workflows/test-action.yml
with:
distro-slug: photonos-4-arm64
nox-session: ci-test-onedir
platform: linux
arch: aarch64
nox-version: 2022.8.7
testrun: ${{ needs.prepare-workflow.outputs.testrun }}
salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}"
cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.13
skip-code-coverage: false
skip-junit-reports: false
ubuntu-2004:
name: Ubuntu 20.04
if: ${{ fromJSON(needs.prepare-workflow.outputs.jobs)['test'] && fromJSON(needs.prepare-workflow.outputs.runners)['self-hosted'] }}
@ -1422,6 +1460,7 @@ jobs:
- opensuse-15
- photonos-3
- photonos-4
- photonos-4-arm64
- ubuntu-2004
- ubuntu-2004-arm64
- ubuntu-2204
@ -2129,6 +2168,7 @@ jobs:
- opensuse-15
- photonos-3
- photonos-4
- photonos-4-arm64
- ubuntu-2004
- ubuntu-2004-arm64
- ubuntu-2204
@ -2195,6 +2235,7 @@ jobs:
- debian-11-arm64-pkg-tests
- photonos-3-pkg-tests
- photonos-4-pkg-tests
- photonos-4-arm64-pkg-tests
- ubuntu-2004-pkg-tests
- ubuntu-2004-arm64-pkg-tests
- ubuntu-2204-pkg-tests

View file

@ -664,6 +664,27 @@ jobs:
pkg-type: package
secrets: inherit
photonos-4-arm64-package-download-tests:
name: Test Photon OS 4 Arm64 package Downloads
if: ${{ inputs.skip-salt-pkg-download-test-suite == false }}
needs:
- prepare-workflow
- publish-repositories
- download-onedir-artifact
uses: ./.github/workflows/test-package-downloads-action-linux.yml
with:
distro-slug: photonos-4-arm64
platform: linux
arch: aarch64
cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.13
salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}"
environment: release
nox-version: 2022.8.7
skip-code-coverage: true
latest-release: "${{ needs.prepare-workflow.outputs.latest-release }}"
pkg-type: package
secrets: inherit
ubuntu-2004-package-download-tests:
name: Test Ubuntu 20.04 package Downloads
if: ${{ inputs.skip-salt-pkg-download-test-suite == false }}
@ -927,6 +948,7 @@ jobs:
- fedora-38-arm64-package-download-tests
- photonos-3-package-download-tests
- photonos-4-package-download-tests
- photonos-4-arm64-package-download-tests
- ubuntu-2004-package-download-tests
- ubuntu-2004-arm64-package-download-tests
- ubuntu-2204-package-download-tests

View file

@ -735,6 +735,25 @@ jobs:
skip-junit-reports: false
testing-releases: ${{ needs.prepare-workflow.outputs.testing-releases }}
photonos-4-arm64-pkg-tests:
name: Photon OS 4 Arm64 Package Tests
if: ${{ fromJSON(needs.prepare-workflow.outputs.jobs)['test-pkg'] && fromJSON(needs.prepare-workflow.outputs.runners)['self-hosted'] }}
needs:
- prepare-workflow
- build-rpm-pkgs
uses: ./.github/workflows/test-packages-action.yml
with:
distro-slug: photonos-4-arm64
platform: linux
arch: aarch64
salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}"
pkg-type: rpm
nox-version: 2022.8.7
cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.13
skip-code-coverage: false
skip-junit-reports: false
testing-releases: ${{ needs.prepare-workflow.outputs.testing-releases }}
ubuntu-2004-pkg-tests:
name: Ubuntu 20.04 Package Tests
if: ${{ fromJSON(needs.prepare-workflow.outputs.jobs)['test-pkg'] && fromJSON(needs.prepare-workflow.outputs.runners)['self-hosted'] }}
@ -1305,6 +1324,25 @@ jobs:
skip-code-coverage: false
skip-junit-reports: false
photonos-4-arm64:
name: Photon OS 4 Arm64
if: ${{ fromJSON(needs.prepare-workflow.outputs.jobs)['test'] && fromJSON(needs.prepare-workflow.outputs.runners)['self-hosted'] }}
needs:
- prepare-workflow
- build-salt-onedir
uses: ./.github/workflows/test-action.yml
with:
distro-slug: photonos-4-arm64
nox-session: ci-test-onedir
platform: linux
arch: aarch64
nox-version: 2022.8.7
testrun: ${{ needs.prepare-workflow.outputs.testrun }}
salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}"
cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.13
skip-code-coverage: false
skip-junit-reports: false
ubuntu-2004:
name: Ubuntu 20.04
if: ${{ fromJSON(needs.prepare-workflow.outputs.jobs)['test'] && fromJSON(needs.prepare-workflow.outputs.runners)['self-hosted'] }}
@ -1406,6 +1444,7 @@ jobs:
- opensuse-15
- photonos-3
- photonos-4
- photonos-4-arm64
- ubuntu-2004
- ubuntu-2004-arm64
- ubuntu-2204
@ -1484,6 +1523,7 @@ jobs:
- opensuse-15
- photonos-3
- photonos-4
- photonos-4-arm64
- ubuntu-2004
- ubuntu-2004-arm64
- ubuntu-2204
@ -1497,6 +1537,7 @@ jobs:
- debian-11-arm64-pkg-tests
- photonos-3-pkg-tests
- photonos-4-pkg-tests
- photonos-4-arm64-pkg-tests
- ubuntu-2004-pkg-tests
- ubuntu-2004-arm64-pkg-tests
- ubuntu-2204-pkg-tests

View file

@ -751,6 +751,25 @@ jobs:
skip-junit-reports: true
testing-releases: ${{ needs.prepare-workflow.outputs.testing-releases }}
photonos-4-arm64-pkg-tests:
name: Photon OS 4 Arm64 Package Tests
if: ${{ fromJSON(needs.prepare-workflow.outputs.jobs)['test-pkg'] && fromJSON(needs.prepare-workflow.outputs.runners)['self-hosted'] }}
needs:
- prepare-workflow
- build-rpm-pkgs
uses: ./.github/workflows/test-packages-action.yml
with:
distro-slug: photonos-4-arm64
platform: linux
arch: aarch64
salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}"
pkg-type: rpm
nox-version: 2022.8.7
cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.13
skip-code-coverage: true
skip-junit-reports: true
testing-releases: ${{ needs.prepare-workflow.outputs.testing-releases }}
ubuntu-2004-pkg-tests:
name: Ubuntu 20.04 Package Tests
if: ${{ fromJSON(needs.prepare-workflow.outputs.jobs)['test-pkg'] && fromJSON(needs.prepare-workflow.outputs.runners)['self-hosted'] }}
@ -1321,6 +1340,25 @@ jobs:
skip-code-coverage: true
skip-junit-reports: true
photonos-4-arm64:
name: Photon OS 4 Arm64
if: ${{ fromJSON(needs.prepare-workflow.outputs.jobs)['test'] && fromJSON(needs.prepare-workflow.outputs.runners)['self-hosted'] }}
needs:
- prepare-workflow
- build-salt-onedir
uses: ./.github/workflows/test-action.yml
with:
distro-slug: photonos-4-arm64
nox-session: ci-test-onedir
platform: linux
arch: aarch64
nox-version: 2022.8.7
testrun: ${{ needs.prepare-workflow.outputs.testrun }}
salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}"
cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.13
skip-code-coverage: true
skip-junit-reports: true
ubuntu-2004:
name: Ubuntu 20.04
if: ${{ fromJSON(needs.prepare-workflow.outputs.jobs)['test'] && fromJSON(needs.prepare-workflow.outputs.runners)['self-hosted'] }}
@ -2564,6 +2602,26 @@ jobs:
pkg-type: package
secrets: inherit
photonos-4-arm64-package-download-tests:
name: Test Photon OS 4 Arm64 package Downloads
if: ${{ fromJSON(needs.prepare-workflow.outputs.jobs)['test-pkg-download'] && fromJSON(needs.prepare-workflow.outputs.runners)['self-hosted'] }}
needs:
- prepare-workflow
- publish-repositories
uses: ./.github/workflows/test-package-downloads-action-linux.yml
with:
distro-slug: photonos-4-arm64
platform: linux
arch: aarch64
cache-prefix: ${{ needs.prepare-workflow.outputs.cache-seed }}|3.10.13
salt-version: "${{ needs.prepare-workflow.outputs.salt-version }}"
environment: staging
nox-version: 2022.8.7
skip-code-coverage: true
latest-release: "${{ needs.prepare-workflow.outputs.latest-release }}"
pkg-type: package
secrets: inherit
ubuntu-2004-package-download-tests:
name: Test Ubuntu 20.04 package Downloads
if: ${{ fromJSON(needs.prepare-workflow.outputs.jobs)['test-pkg-download'] && fromJSON(needs.prepare-workflow.outputs.runners)['self-hosted'] }}
@ -2809,6 +2867,7 @@ jobs:
- opensuse-15
- photonos-3
- photonos-4
- photonos-4-arm64
- ubuntu-2004
- ubuntu-2004-arm64
- ubuntu-2204
@ -2822,6 +2881,7 @@ jobs:
- debian-11-arm64-pkg-tests
- photonos-3-pkg-tests
- photonos-4-pkg-tests
- photonos-4-arm64-pkg-tests
- ubuntu-2004-pkg-tests
- ubuntu-2004-arm64-pkg-tests
- ubuntu-2204-pkg-tests
@ -2854,6 +2914,7 @@ jobs:
- fedora-38-arm64-package-download-tests
- photonos-3-package-download-tests
- photonos-4-package-download-tests
- photonos-4-arm64-package-download-tests
- ubuntu-2004-package-download-tests
- ubuntu-2004-arm64-package-download-tests
- ubuntu-2204-package-download-tests

View file

@ -21,6 +21,7 @@
("fedora-38-arm64", "Fedora 38 Arm64", "aarch64", "package"),
("photonos-3", "Photon OS 3", "x86_64", "package"),
("photonos-4", "Photon OS 4", "x86_64", "package"),
("photonos-4-arm64", "Photon OS 4 Arm64", "aarch64", "package"),
("ubuntu-20.04", "Ubuntu 20.04", "x86_64", "package"),
("ubuntu-20.04-arm64", "Ubuntu 20.04 Arm64", "aarch64", "package"),
("ubuntu-22.04", "Ubuntu 22.04", "x86_64", "package"),

View file

@ -27,6 +27,7 @@
("debian-11-arm64", "Debian 11 Arm64", "aarch64", "deb"),
("photonos-3", "Photon OS 3", "x86_64", "rpm"),
("photonos-4", "Photon OS 4", "x86_64", "rpm"),
("photonos-4-arm64", "Photon OS 4 Arm64", "aarch64", "rpm"),
("ubuntu-20.04", "Ubuntu 20.04", "x86_64", "deb"),
("ubuntu-20.04-arm64", "Ubuntu 20.04 Arm64", "aarch64", "deb"),
("ubuntu-22.04", "Ubuntu 22.04", "x86_64", "deb"),

View file

@ -64,6 +64,7 @@
("opensuse-15", "Opensuse 15", "x86_64"),
("photonos-3", "Photon OS 3", "x86_64"),
("photonos-4", "Photon OS 4", "x86_64"),
("photonos-4-arm64", "Photon OS 4 Arm64", "aarch64"),
("ubuntu-20.04", "Ubuntu 20.04", "x86_64"),
("ubuntu-20.04-arm64", "Ubuntu 20.04 Arm64", "aarch64"),
("ubuntu-22.04", "Ubuntu 22.04", "x86_64"),

View file

@ -22,7 +22,7 @@ jobs:
issues: write
pull-requests: read # for dawidd6/action-download-artifact to query commit hash
name: Triage New Issue
runs-on: ubuntu-latest
runs-on: ${{ github.event.repository.private && fromJSON('["self-hosted", "linux", "x86_64"]') || 'ubuntu-latest' }}
steps:
- uses: actions/checkout@v3

View file

@ -7,6 +7,18 @@ Versions are `MAJOR.PATCH`.
# Changelog
## Salt v3005.3 (2023-09-14)
### Fixed
- Fix __env__ and improve cache cleaning see more info at pull #65017. (#65002)
### Security
- Update to `gitpython>=3.1.35` due to https://github.com/advisories/GHSA-wfm5-v35h-vwf4 and https://github.com/advisories/GHSA-cwvm-v4w8-q58c (#65167)
## 3006.3 (2023-09-06)

View file

@ -578,6 +578,9 @@ commit message, it's usually a good idea to add other information, such as
This will also help you out, because when you go to create the PR it
will automatically insert the body of your commit messages.
See the `changelog <https://docs.saltproject.io/en/latest/topics/development/changelog.html>`__
docs for more information.
Pull request time!
------------------

View file

@ -121,7 +121,7 @@ Security advisories
Keep an eye on the Salt Project
`Security Announcements <https://saltproject.io/security-announcements/>`_
landing page. Salt Project recommends subscribing to the
`Salt Project Security RSS feed <https://saltproject.io/feed/?post_type=security>`_
`Salt Project Security RSS feed <https://saltproject.io/security-announcements/index.xml>`_
to receive notification when new information is available regarding security
announcements.

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

@ -0,0 +1 @@
Allow all primitive grain types for autosign_grains

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

@ -0,0 +1 @@
Allow all primitive grain types for autosign_grains

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

@ -0,0 +1 @@
Fix salt user login shell path in Debian packages

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

@ -0,0 +1 @@
Add follow_symlinks to file.symlink exec module to switch to os.path.lexists when False

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

@ -0,0 +1 @@
Fixed grp.getgrall() in utils/user.py causing performance issues

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

@ -0,0 +1 @@
Fix user.list_groups omits remote groups via sssd, etc.

View file

@ -0,0 +1 @@
Tech Debt - support for pysss removed due to functionality addition in Python 3.3

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

@ -0,0 +1 @@
Only attempt to create a keys directory when `--gen-keys` is passed to the `salt-key` CLI

View file

@ -0,0 +1 @@
Update to `gitpython>=3.1.35` due to https://github.com/advisories/GHSA-wfm5-v35h-vwf4 and https://github.com/advisories/GHSA-cwvm-v4w8-q58c

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

@ -0,0 +1 @@
Ensure __kwarg__ is preserved when checking for kwargs. This change affects proxy minions when used with Deltaproxy, which had kwargs popped when targeting multiple minions id.

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

@ -0,0 +1 @@
Fixes traceback when state id is an int in a reactor SLS file.

View file

@ -0,0 +1 @@
Bump to `cryptography==41.0.4` due to https://github.com/advisories/GHSA-v8gr-m533-ghj9

View file

@ -1 +1 @@
centosstream-9-x86_64: ami-0bd92f4dca5d74017
centosstream-9-x86_64: ami-0dfa940714a95b497

View file

@ -1,8 +1,8 @@
{
"almalinux-8-arm64": {
"ami": "ami-05c1d3dbdeeb94bc6",
"ami": "ami-09017a2c26bb6cf37",
"ami_description": "CI Image of AlmaLinux 8 arm64",
"ami_name": "salt-project/ci/almalinux/8/arm64/20230522.0606",
"ami_name": "salt-project/ci/almalinux/8/arm64/20230912.1532",
"arch": "arm64",
"cloudwatch-agent-available": "true",
"instance_type": "m6g.large",
@ -10,9 +10,9 @@
"ssh_username": "ec2-user"
},
"almalinux-8": {
"ami": "ami-0ec1cbc531f10105b",
"ami": "ami-0da7449d7f17dca6d",
"ami_description": "CI Image of AlmaLinux 8 x86_64",
"ami_name": "salt-project/ci/almalinux/8/x86_64/20230522.0606",
"ami_name": "salt-project/ci/almalinux/8/x86_64/20230912.1532",
"arch": "x86_64",
"cloudwatch-agent-available": "true",
"instance_type": "t3a.large",
@ -20,9 +20,9 @@
"ssh_username": "ec2-user"
},
"almalinux-9-arm64": {
"ami": "ami-036c495af9dfcf852",
"ami": "ami-0b45894ce343176b0",
"ami_description": "CI Image of AlmaLinux 9 arm64",
"ami_name": "salt-project/ci/almalinux/9/arm64/20230522.0606",
"ami_name": "salt-project/ci/almalinux/9/arm64/20230912.1532",
"arch": "arm64",
"cloudwatch-agent-available": "true",
"instance_type": "m6g.large",
@ -30,9 +30,9 @@
"ssh_username": "ec2-user"
},
"almalinux-9": {
"ami": "ami-0dbc7030666419671",
"ami": "ami-0c8a554820c140d45",
"ami_description": "CI Image of AlmaLinux 9 x86_64",
"ami_name": "salt-project/ci/almalinux/9/x86_64/20230522.0606",
"ami_name": "salt-project/ci/almalinux/9/x86_64/20230912.1532",
"arch": "x86_64",
"cloudwatch-agent-available": "true",
"instance_type": "t3a.large",
@ -40,9 +40,9 @@
"ssh_username": "ec2-user"
},
"amazonlinux-2-arm64": {
"ami": "ami-022232915c2a5f2d0",
"ami": "ami-0aac44852e96fb156",
"ami_description": "CI Image of AmazonLinux 2 arm64",
"ami_name": "salt-project/ci/amazonlinux/2/arm64/20230522.0621",
"ami_name": "salt-project/ci/amazonlinux/2/arm64/20230912.1532",
"arch": "arm64",
"cloudwatch-agent-available": "true",
"instance_type": "m6g.large",
@ -50,9 +50,29 @@
"ssh_username": "ec2-user"
},
"amazonlinux-2": {
"ami": "ami-0695f87baa5b5ce15",
"ami": "ami-04bf06c280f2957e0",
"ami_description": "CI Image of AmazonLinux 2 x86_64",
"ami_name": "salt-project/ci/amazonlinux/2/x86_64/20230522.0620",
"ami_name": "salt-project/ci/amazonlinux/2/x86_64/20230912.1532",
"arch": "x86_64",
"cloudwatch-agent-available": "true",
"instance_type": "t3a.large",
"is_windows": "false",
"ssh_username": "ec2-user"
},
"amazonlinux-2023.1-arm64": {
"ami": "ami-0430562e1dc073734",
"ami_description": "CI Image of AmazonLinux 2023.1 arm64",
"ami_name": "salt-project/ci/amazonlinux/2023.1/arm64/20230912.1532",
"arch": "arm64",
"cloudwatch-agent-available": "true",
"instance_type": "m6g.large",
"is_windows": "false",
"ssh_username": "ec2-user"
},
"amazonlinux-2023.1": {
"ami": "ami-09b7ab6b9bb5ceca3",
"ami_description": "CI Image of AmazonLinux 2023.1 x86_64",
"ami_name": "salt-project/ci/amazonlinux/2023.1/x86_64/20230912.1532",
"arch": "x86_64",
"cloudwatch-agent-available": "true",
"instance_type": "t3a.large",
@ -60,9 +80,9 @@
"ssh_username": "ec2-user"
},
"archlinux-lts": {
"ami": "ami-0f6424847f98afc04",
"ami": "ami-08ecb254b10e24bca",
"ami_description": "CI Image of ArchLinux lts x86_64",
"ami_name": "salt-project/ci/archlinux/lts/x86_64/20230522.0606",
"ami_name": "salt-project/ci/archlinux/lts/x86_64/20230912.1532",
"arch": "x86_64",
"cloudwatch-agent-available": "false",
"instance_type": "t3a.large",
@ -70,9 +90,9 @@
"ssh_username": "arch"
},
"centos-7-arm64": {
"ami": "ami-0908831c364e33a37",
"ami": "ami-0facb0416e994c2d4",
"ami_description": "CI Image of CentOS 7 arm64",
"ami_name": "salt-project/ci/centos/7/arm64/20230522.0606",
"ami_name": "salt-project/ci/centos/7/arm64/20230912.1553",
"arch": "arm64",
"cloudwatch-agent-available": "true",
"instance_type": "m6g.large",
@ -80,9 +100,9 @@
"ssh_username": "centos"
},
"centos-7": {
"ami": "ami-0ace33028ada62ddb",
"ami": "ami-04e695ebbac38868e",
"ami_description": "CI Image of CentOS 7 x86_64",
"ami_name": "salt-project/ci/centos/7/x86_64/20230522.0606",
"ami_name": "salt-project/ci/centos/7/x86_64/20230912.1553",
"arch": "x86_64",
"cloudwatch-agent-available": "true",
"instance_type": "t3a.large",
@ -90,9 +110,9 @@
"ssh_username": "centos"
},
"centosstream-8-arm64": {
"ami": "ami-0b30827dc592b2695",
"ami": "ami-02b1e24269822d3fc",
"ami_description": "CI Image of CentOSStream 8 arm64",
"ami_name": "salt-project/ci/centosstream/8/arm64/20230522.0618",
"ami_name": "salt-project/ci/centosstream/8/arm64/20230912.1532",
"arch": "arm64",
"cloudwatch-agent-available": "true",
"instance_type": "m6g.large",
@ -100,9 +120,9 @@
"ssh_username": "centos"
},
"centosstream-8": {
"ami": "ami-0929882a7e5cfba5f",
"ami": "ami-0706ab643607236c0",
"ami_description": "CI Image of CentOSStream 8 x86_64",
"ami_name": "salt-project/ci/centosstream/8/x86_64/20230522.0618",
"ami_name": "salt-project/ci/centosstream/8/x86_64/20230912.1532",
"arch": "x86_64",
"cloudwatch-agent-available": "true",
"instance_type": "t3a.large",
@ -110,9 +130,9 @@
"ssh_username": "centos"
},
"centosstream-9-arm64": {
"ami": "ami-00700fb8821b8b8c7",
"ami": "ami-032abe3ace927c296",
"ami_description": "CI Image of CentOSStream 9 arm64",
"ami_name": "salt-project/ci/centosstream/9/arm64/20230522.0619",
"ami_name": "salt-project/ci/centosstream/9/arm64/20230912.1532",
"arch": "arm64",
"cloudwatch-agent-available": "true",
"instance_type": "m6g.large",
@ -120,9 +140,9 @@
"ssh_username": "ec2-user"
},
"centosstream-9": {
"ami": "ami-0bd92f4dca5d74017",
"ami": "ami-091986d83f4c0bdd7",
"ami_description": "CI Image of CentOSStream 9 x86_64",
"ami_name": "salt-project/ci/centosstream/9/x86_64/20230522.0619",
"ami_name": "salt-project/ci/centosstream/9/x86_64/20230912.1532",
"arch": "x86_64",
"cloudwatch-agent-available": "true",
"instance_type": "t3a.large",
@ -130,9 +150,9 @@
"ssh_username": "ec2-user"
},
"debian-10-arm64": {
"ami": "ami-0f681fc9d5de0c3df",
"ami": "ami-08b7b9fb74d7c58f2",
"ami_description": "CI Image of Debian 10 arm64",
"ami_name": "salt-project/ci/debian/10/arm64/20230522.0606",
"ami_name": "salt-project/ci/debian/10/arm64/20230912.1546",
"arch": "arm64",
"cloudwatch-agent-available": "false",
"instance_type": "m6g.large",
@ -140,9 +160,9 @@
"ssh_username": "admin"
},
"debian-10": {
"ami": "ami-0dcf5610590139238",
"ami": "ami-0002ea04be195948e",
"ami_description": "CI Image of Debian 10 x86_64",
"ami_name": "salt-project/ci/debian/10/x86_64/20230522.0606",
"ami_name": "salt-project/ci/debian/10/x86_64/20230912.1548",
"arch": "x86_64",
"cloudwatch-agent-available": "true",
"instance_type": "t3a.large",
@ -150,9 +170,9 @@
"ssh_username": "admin"
},
"debian-11-arm64": {
"ami": "ami-062b4bf11a864825c",
"ami": "ami-0e14ec1b2a5553f96",
"ami_description": "CI Image of Debian 11 arm64",
"ami_name": "salt-project/ci/debian/11/arm64/20230522.0606",
"ami_name": "salt-project/ci/debian/11/arm64/20230912.1548",
"arch": "arm64",
"cloudwatch-agent-available": "false",
"instance_type": "m6g.large",
@ -160,9 +180,29 @@
"ssh_username": "admin"
},
"debian-11": {
"ami": "ami-0f400e5fa6806bbca",
"ami": "ami-06c5ea0d19a5773d7",
"ami_description": "CI Image of Debian 11 x86_64",
"ami_name": "salt-project/ci/debian/11/x86_64/20230522.0606",
"ami_name": "salt-project/ci/debian/11/x86_64/20230912.1549",
"arch": "x86_64",
"cloudwatch-agent-available": "true",
"instance_type": "t3a.large",
"is_windows": "false",
"ssh_username": "admin"
},
"debian-12-arm64": {
"ami": "ami-055b0a6d5bb3e9ecd",
"ami_description": "CI Image of Debian 12 arm64",
"ami_name": "salt-project/ci/debian/12/arm64/20230912.1550",
"arch": "arm64",
"cloudwatch-agent-available": "false",
"instance_type": "m6g.large",
"is_windows": "false",
"ssh_username": "admin"
},
"debian-12": {
"ami": "ami-0eada119571a913fd",
"ami_description": "CI Image of Debian 12 x86_64",
"ami_name": "salt-project/ci/debian/12/x86_64/20230912.1550",
"arch": "x86_64",
"cloudwatch-agent-available": "true",
"instance_type": "t3a.large",
@ -170,9 +210,9 @@
"ssh_username": "admin"
},
"fedora-37-arm64": {
"ami": "ami-0d71d6f2b0869842f",
"ami": "ami-02b916b21581ead5a",
"ami_description": "CI Image of Fedora 37 arm64",
"ami_name": "salt-project/ci/fedora/37/arm64/20230522.0606",
"ami_name": "salt-project/ci/fedora/37/arm64/20230912.1533",
"arch": "arm64",
"cloudwatch-agent-available": "true",
"instance_type": "m6g.large",
@ -180,9 +220,9 @@
"ssh_username": "fedora"
},
"fedora-37": {
"ami": "ami-026f494dd4b9d40e8",
"ami": "ami-01e0becc3552ad2f6",
"ami_description": "CI Image of Fedora 37 x86_64",
"ami_name": "salt-project/ci/fedora/37/x86_64/20230522.0606",
"ami_name": "salt-project/ci/fedora/37/x86_64/20230912.1533",
"arch": "x86_64",
"cloudwatch-agent-available": "true",
"instance_type": "t3a.large",
@ -190,9 +230,9 @@
"ssh_username": "fedora"
},
"fedora-38-arm64": {
"ami": "ami-01ba8a7951daf68fb",
"ami": "ami-01f4a3bdee88da9f3",
"ami_description": "CI Image of Fedora 38 arm64",
"ami_name": "salt-project/ci/fedora/38/arm64/20230522.0606",
"ami_name": "salt-project/ci/fedora/38/arm64/20230912.1533",
"arch": "arm64",
"cloudwatch-agent-available": "true",
"instance_type": "m6g.large",
@ -200,9 +240,9 @@
"ssh_username": "fedora"
},
"fedora-38": {
"ami": "ami-0699dbe70b69e96aa",
"ami": "ami-0c38a1907f5b55077",
"ami_description": "CI Image of Fedora 38 x86_64",
"ami_name": "salt-project/ci/fedora/38/x86_64/20230522.0606",
"ami_name": "salt-project/ci/fedora/38/x86_64/20230912.1543",
"arch": "x86_64",
"cloudwatch-agent-available": "true",
"instance_type": "t3a.large",
@ -210,29 +250,69 @@
"ssh_username": "fedora"
},
"opensuse-15": {
"ami": "ami-0c594da84f6e1cd96",
"ami": "ami-0ecfb817deee506a9",
"ami_description": "CI Image of Opensuse 15 x86_64",
"ami_name": "salt-project/ci/opensuse/15/x86_64/20230522.0619",
"ami_name": "salt-project/ci/opensuse/15/x86_64/20230912.1533",
"arch": "x86_64",
"cloudwatch-agent-available": "true",
"instance_type": "t3a.large",
"is_windows": "false",
"ssh_username": "ec2-user"
},
"photonos-3-arm64": {
"ami": "ami-0383031c08217b13e",
"ami_description": "CI Image of PhotonOS 3 arm64",
"ami_name": "salt-project/ci/photonos/3/arm64/20230924.0913",
"arch": "arm64",
"cloudwatch-agent-available": "true",
"instance_type": "m6g.large",
"is_windows": "false",
"ssh_username": "root"
},
"photonos-3": {
"ami": "ami-0db2ebdb9bc3400ef",
"ami": "ami-06004a7d856e94355",
"ami_description": "CI Image of PhotonOS 3 x86_64",
"ami_name": "salt-project/ci/photonos/3/x86_64/20230522.0617",
"ami_name": "salt-project/ci/photonos/3/x86_64/20230924.0913",
"arch": "x86_64",
"cloudwatch-agent-available": "true",
"instance_type": "t3a.large",
"is_windows": "false",
"ssh_username": "root"
},
"photonos-4-arm64": {
"ami": "ami-08808bcf97f824036",
"ami_description": "CI Image of PhotonOS 4 arm64",
"ami_name": "salt-project/ci/photonos/4/arm64/20230924.0924",
"arch": "arm64",
"cloudwatch-agent-available": "true",
"instance_type": "m6g.large",
"is_windows": "false",
"ssh_username": "root"
},
"photonos-4": {
"ami": "ami-08a6b6bbf6779a538",
"ami": "ami-0fd7a6ed4c61ee312",
"ami_description": "CI Image of PhotonOS 4 x86_64",
"ami_name": "salt-project/ci/photonos/4/x86_64/20230522.0606",
"ami_name": "salt-project/ci/photonos/4/x86_64/20230924.0925",
"arch": "x86_64",
"cloudwatch-agent-available": "true",
"instance_type": "t3a.large",
"is_windows": "false",
"ssh_username": "root"
},
"photonos-5-arm64": {
"ami": "ami-0c85ad72d107ec4b8",
"ami_description": "CI Image of PhotonOS 5 arm64",
"ami_name": "salt-project/ci/photonos/5/arm64/20230924.0927",
"arch": "arm64",
"cloudwatch-agent-available": "true",
"instance_type": "m6g.large",
"is_windows": "false",
"ssh_username": "root"
},
"photonos-5": {
"ami": "ami-0732ce03b2ab6fad2",
"ami_description": "CI Image of PhotonOS 5 x86_64",
"ami_name": "salt-project/ci/photonos/5/x86_64/20230924.0927",
"arch": "x86_64",
"cloudwatch-agent-available": "true",
"instance_type": "t3a.large",
@ -240,9 +320,9 @@
"ssh_username": "root"
},
"ubuntu-20.04-arm64": {
"ami": "ami-0dccc0de7a38cca90",
"ami": "ami-05aeb3d5bf0a16369",
"ami_description": "CI Image of Ubuntu 20.04 arm64",
"ami_name": "salt-project/ci/ubuntu/20.04/arm64/20230522.0606",
"ami_name": "salt-project/ci/ubuntu/20.04/arm64/20230912.1551",
"arch": "arm64",
"cloudwatch-agent-available": "true",
"instance_type": "m6g.large",
@ -250,9 +330,9 @@
"ssh_username": "ubuntu"
},
"ubuntu-20.04": {
"ami": "ami-05e51f893a626b579",
"ami": "ami-00cec0054fd71d281",
"ami_description": "CI Image of Ubuntu 20.04 x86_64",
"ami_name": "salt-project/ci/ubuntu/20.04/x86_64/20230522.0606",
"ami_name": "salt-project/ci/ubuntu/20.04/x86_64/20230912.1550",
"arch": "x86_64",
"cloudwatch-agent-available": "true",
"instance_type": "t3a.large",
@ -260,9 +340,9 @@
"ssh_username": "ubuntu"
},
"ubuntu-22.04-arm64": {
"ami": "ami-0c958272da6c09ca6",
"ami": "ami-0f7dc3333620d58fd",
"ami_description": "CI Image of Ubuntu 22.04 arm64",
"ami_name": "salt-project/ci/ubuntu/22.04/arm64/20230522.0606",
"ami_name": "salt-project/ci/ubuntu/22.04/arm64/20230912.1551",
"arch": "arm64",
"cloudwatch-agent-available": "true",
"instance_type": "m6g.large",
@ -270,9 +350,29 @@
"ssh_username": "ubuntu"
},
"ubuntu-22.04": {
"ami": "ami-09e45f31ccafcdcec",
"ami": "ami-0bc7c1824a6b0752f",
"ami_description": "CI Image of Ubuntu 22.04 x86_64",
"ami_name": "salt-project/ci/ubuntu/22.04/x86_64/20230522.0606",
"ami_name": "salt-project/ci/ubuntu/22.04/x86_64/20230912.1552",
"arch": "x86_64",
"cloudwatch-agent-available": "true",
"instance_type": "t3a.large",
"is_windows": "false",
"ssh_username": "ubuntu"
},
"ubuntu-23.04-arm64": {
"ami": "ami-0e8818777218efeeb",
"ami_description": "CI Image of Ubuntu 23.04 arm64",
"ami_name": "salt-project/ci/ubuntu/23.04/arm64/20230912.1552",
"arch": "arm64",
"cloudwatch-agent-available": "true",
"instance_type": "m6g.large",
"is_windows": "false",
"ssh_username": "ubuntu"
},
"ubuntu-23.04": {
"ami": "ami-0813a38bf6a6cf4de",
"ami_description": "CI Image of Ubuntu 23.04 x86_64",
"ami_name": "salt-project/ci/ubuntu/23.04/x86_64/20230912.1552",
"arch": "x86_64",
"cloudwatch-agent-available": "true",
"instance_type": "t3a.large",

View file

@ -197,3 +197,12 @@ How to access python binary
The python library is available in the install directory of the onedir package. For example
on linux the default location would be ``/opt/saltstack/salt/bin/python3``.
Testing the packages
====================
If you want to test your built packages, or any other collection of salt packages post 3006.0, follow :ref:`this guide <pkging-testing>`
.. toctree::
testing

View file

@ -0,0 +1,157 @@
.. _pkging-testing:
================
Testing packages
================
The package test suite
======================
The salt repo provides a test suite for testing basic functionality of our
packages at ``<repo-root>/pkg/tests/``. You can run the install, upgrade, and
downgrade tests. These tests run automatically on most PRs that are submitted
against Salt.
.. warning::
These tests make destructive changes to your system because they install the
built packages onto the system. They may also install older versions in the
case of upgrades or downgrades. To prevent destructive changes, run the
tests in an isolated system, preferably a virtual machine.
Setup
=====
In order to run the package tests, the `relenv
<https://github.com/saltstack/relative-environment-for-python>`_ onedir and
built packages need to be placed in the correct locations.
* Place all salt packages for the applicable testing version in
``<repo-root>/pkg/artifacts/``.
* The onedir must be located under ``<repo-root>/artifacts/``.
* Additionally, to ensure complete parity with Salt's CI/CD suite, place the
``nox`` virtual environment in ``<repo-root>/.nox/test-pkgs-onedir``.
The following are a few ways this can be accomplished easily.
You can ensure parity by installing the package test suite through a few
possible methods:
* Using ``tools``
* Downloading individually
Using ``tools``
---------------
Salt has preliminary support for setting up the package test suite in the
``tools`` command suite that is located under ``<repo-root>/tools/testsuite/``.
This method requires the Github CLI tool ``gh`` (https://cli.github.com/) to be properly configured for
interaction with the salt repo.
#. Install the dependencies using this command:
.. code-block:: bash
pip install -r requirements/static/ci/py{python_version}/tools.txt
#. Download and extract the artifacts with this ``tools`` command:
.. code-block:: bash
tools ts setup --platform {linux|darwin|windows} --slug
<operating-system-slug> --pr <pr-number> --pkg
The most common use case is to test the packages built on a CI/CD run for a
given PR. To see the possible options for each argument, and other ways to
utilize this command, use the following:
.. code-block:: bash
tools ts setup -h
.. warning::
You can only download artifacts from finished workflow runs. This is something
imposed by the GitHub API.
To download artifacts from a running workflow run, you either have to wait for
the finish or cancel it.
Downloading individually
------------------------
If the ``tools ts setup`` command doesn't work, you can download, unzip, and
place the artifacts in the correct locations manually. Typically, you want to
test packages built on a CI/CD run for a given PR. This guide explains how to
set up for running the package tests using those artifacts. An analogous process
can be performed for artifacts from nightly builds.
#. Find and download the artifacts:
Under the summary page for the most recent actions run for that PR, there is
a list of available artifacts from that run that can be downloaded. Download
the package artifacts by finding
``salt-<major>.<minor>+<number>.<sha>-<arch>-<pkg-type>``. For example, the
amd64 deb packages might look like:
``salt-3006.2+123.01234567890-x86_64-deb``.
The onedir artifact will look like
``salt-<major>.<minor>+<number>.<sha>-onedir-<platform>-<arch>.tar.xz``. For
instance, the macos x86_64 onedir may have the name
``salt-3006.2+123.01234567890-onedir-darwin-x86_64.tar.xz``.
.. note::
Windows onedir artifacts have ``.zip`` extensions instead of ``tar.xz``
While it is optional, it is recommended to download the ``nox`` session
artifact as well. This will have the form of
``nox-<os-name>-test-pkgs-onedir-<arch>``. The amd64 Ubuntu 20.04 nox
artifact may look like ``nox-ubuntu-20.04-test-pkgs-onedir-x86_64``.
#. Place the artifacts in the correct location:
Unzip the packages and place them in ``<repo-root>/pkg/artifacts/``.
You must unzip and untar the onedir packages and place them in
``<repo-root>/artifacts/``. Windows onedir requires an additional unzip
action. If you set it up correctly, the ``<repo-root>/artifacts/salt``
directory then contains the uncompressed onedir files.
Additionally, decompress the ``nox`` artifact and place it under
``<repo-root>/.nox/``.
Running the tests
=================
You can run the test suite run if all the artifacts are in the correct location.
.. note::
You need root access to run the test artifacts. Run all nox commands at the
root of the salt repo and as the root user.
#. Install ``nox``:
.. code-block:: bash
pip install nox
#. Run the install tests:
.. code-block:: bash
nox -e test-pkgs-onedir -- install
#. Run the upgrade or downgrade tests:
.. code-block:: bash
nox -e test-pkgs-onedir -- upgrade --prev-version <previous-version>
You can run the downgrade tests in the same way, replacing ``upgrade`` with
``downgrade``.
.. note::
If you are testing upgrades or downgrades and classic packages are
available for your system, replace ``upgrade`` or
``downgrade`` with ``upgrade-classic`` or ``downgrade-classic``
respectively to test against those versions.

View file

@ -0,0 +1,19 @@
.. _release-3005-3:
=========================
Salt 3005.3 Release Notes
=========================
Version 3005.3 is a Bug fix release for :ref:`3005 <release-3005>`.
Changed
-------
- Fix __env__ and improve cache cleaning see more info at pull #65017. (#65002)
Security
--------
- Update to `gitpython>=3.1.35` due to https://github.com/advisories/GHSA-wfm5-v35h-vwf4 and https://github.com/advisories/GHSA-cwvm-v4w8-q58c (#65167)

View file

@ -1231,7 +1231,7 @@ def decompress_dependencies(session):
nox_dependencies_tarball_path = REPO_ROOT / nox_dependencies_tarball
if not nox_dependencies_tarball_path.exists():
session.error(
f"The {nox_dependencies_tarball} file"
f"The {nox_dependencies_tarball} file "
"does not exist. Not decompressing anything."
)

View file

@ -53,10 +53,7 @@ def test_salt_downgrade(salt_call_cli, install_salt):
ret.stdout.strip().split()[1]
) < packaging.version.parse(install_salt.artifact_version)
# Windows does not keep the extras directory around in the same state
# TODO: Fix this problem in windows installers
# TODO: Fix this problem in macos installers
if is_downgrade_to_relenv and not (platform.is_windows() or platform.is_darwin()):
if is_downgrade_to_relenv:
new_py_version = install_salt.package_python_version()
if new_py_version == original_py_version:
# test pip install after a downgrade

View file

@ -14,10 +14,6 @@ def test_help(install_salt):
# Singlebin build, unable to get the version
continue
# TODO: Remove this condition once the fixed 3005.x classic packages are released.
if "salt-proxy" in cmd[0] and platform.is_darwin() and install_salt.classic:
continue
if "python" in cmd[0] and len(cmd) == 1:
ret = install_salt.proc.run(
*cmd, "--version", stdout=subprocess.PIPE, stderr=subprocess.PIPE

View file

@ -4,6 +4,7 @@
apache-libcloud>=2.4.0
cherrypy>=17.4.1
gitpython>=3.1.35
cryptography>=41.0.3
gitpython>=3.1.30
idna>=2.8

View file

@ -2,7 +2,7 @@ mock >= 3.0.0
# PyTest
docker
pytest >= 7.2.0
pytest-salt-factories >= 1.0.0rc25
pytest-salt-factories >= 1.0.0rc26
pytest-helpers-namespace >= 2019.1.8
pytest-subtests
pytest-timeout

View file

@ -15,7 +15,7 @@ clustershell
croniter>=0.3.0,!=0.3.22"; sys_platform != 'win32'
dnspython
etcd3-py==0.1.6
gitpython>=3.1.30
gitpython>=3.1.35
jmespath
jsonschema
junos-eznc; sys_platform != 'win32'

View file

@ -20,7 +20,7 @@ charset-normalizer==3.2.0
# via
# -c requirements/static/ci/py3.10/linux.txt
# requests
cryptography==41.0.3
cryptography==41.0.4
# via
# -c requirements/static/ci/py3.10/linux.txt
# pyspnego
@ -67,7 +67,7 @@ smbprotocol==1.10.1
# via
# -r requirements/static/ci/cloud.in
# pypsexec
urllib3==1.26.6
urllib3==1.26.14
# via
# -c requirements/static/ci/py3.10/linux.txt
# requests

View file

@ -93,7 +93,7 @@ contextvars==2.4
# -r requirements/base.txt
croniter==1.3.15 ; sys_platform != "win32"
# via -r requirements/static/ci/common.in
cryptography==41.0.3
cryptography==41.0.4
# via
# -c requirements/static/ci/../pkg/py3.10/darwin.txt
# -r requirements/crypto.txt
@ -120,7 +120,7 @@ etcd3-py==0.1.6
# via -r requirements/static/ci/common.in
exceptiongroup==1.1.1
# via pytest
filelock==3.12.1
filelock==3.12.4
# via virtualenv
flaky==3.7.0
# via -r requirements/pytest.txt
@ -272,7 +272,7 @@ netaddr==0.8.0
# pyeapi
netmiko==4.2.0
# via napalm
netutils==1.4.1
netutils==1.6.0
# via napalm
ntc-templates==3.4.0
# via netmiko
@ -360,7 +360,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.0rc25
pytest-salt-factories==1.0.0rc26
# via -r requirements/pytest.txt
pytest-shell-utilities==1.8.0
# via pytest-salt-factories
@ -485,7 +485,7 @@ sqlparse==0.4.4
# via -r requirements/static/ci/common.in
strict-rfc3339==0.7
# via -r requirements/static/ci/common.in
tempora==5.2.2
tempora==5.3.0
# via
# -c requirements/static/ci/../pkg/py3.10/darwin.txt
# portend
@ -510,20 +510,20 @@ transitions==0.9.0
# via junos-eznc
ttp-templates==0.3.5
# via napalm
ttp==0.9.4
ttp==0.9.5
# via
# napalm
# ttp-templates
types-pyyaml==6.0.1
# via responses
typing-extensions==4.6.2
typing-extensions==4.6.3
# via
# -c requirements/static/ci/../pkg/py3.10/darwin.txt
# napalm
# pydantic
# pytest-shell-utilities
# pytest-system-statistics
urllib3==1.26.6
urllib3==1.26.14
# via
# -c requirements/static/ci/../pkg/py3.10/darwin.txt
# botocore
@ -565,7 +565,7 @@ yamlordereddictloader==0.4.0
# via junos-eznc
yarl==1.9.2
# via aiohttp
zc.lockfile==2.0
zc.lockfile==3.0.post1
# via
# -c requirements/static/ci/../pkg/py3.10/darwin.txt
# cherrypy

View file

@ -142,21 +142,21 @@ sphinxcontrib-serializinghtml==1.1.5
# via sphinx
sphinxcontrib-spelling==8.0.0
# via -r requirements/static/ci/docs.in
tempora==5.2.2
tempora==5.3.0
# via
# -c requirements/static/ci/py3.10/linux.txt
# portend
typing-extensions==4.6.2
typing-extensions==4.6.3
# via
# -c requirements/static/ci/py3.10/linux.txt
# pydantic
uc-micro-py==1.0.2
# via linkify-it-py
urllib3==1.26.6
urllib3==1.26.14
# via
# -c requirements/static/ci/py3.10/linux.txt
# requests
zc.lockfile==1.4
zc.lockfile==3.0.post1
# via
# -c requirements/static/ci/py3.10/linux.txt
# cherrypy

View file

@ -89,7 +89,7 @@ contextvars==2.4
# -r requirements/base.txt
croniter==1.3.15 ; sys_platform != "win32"
# via -r requirements/static/ci/common.in
cryptography==41.0.3
cryptography==41.0.4
# via
# -c requirements/static/ci/../pkg/py3.10/freebsd.txt
# -r requirements/crypto.txt
@ -117,7 +117,7 @@ etcd3-py==0.1.6
# via -r requirements/static/ci/common.in
exceptiongroup==1.1.1
# via pytest
filelock==3.12.1
filelock==3.12.4
# via virtualenv
flaky==3.7.0
# via -r requirements/pytest.txt
@ -267,7 +267,7 @@ netaddr==0.8.0
# pyeapi
netmiko==4.2.0
# via napalm
netutils==1.4.1
netutils==1.6.0
# via napalm
ntc-templates==3.4.0
# via netmiko
@ -354,7 +354,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.0rc25
pytest-salt-factories==1.0.0rc26
# via -r requirements/pytest.txt
pytest-shell-utilities==1.8.0
# via pytest-salt-factories
@ -477,7 +477,7 @@ sqlparse==0.4.4
# via -r requirements/static/ci/common.in
strict-rfc3339==0.7
# via -r requirements/static/ci/common.in
tempora==5.2.2
tempora==5.3.0
# via
# -c requirements/static/ci/../pkg/py3.10/freebsd.txt
# portend
@ -502,20 +502,20 @@ transitions==0.9.0
# via junos-eznc
ttp-templates==0.3.5
# via napalm
ttp==0.9.4
ttp==0.9.5
# via
# napalm
# ttp-templates
types-pyyaml==6.0.1
# via responses
typing-extensions==4.6.2
typing-extensions==4.6.3
# via
# -c requirements/static/ci/../pkg/py3.10/freebsd.txt
# napalm
# pydantic
# pytest-shell-utilities
# pytest-system-statistics
urllib3==1.26.6
urllib3==1.26.14
# via
# -c requirements/static/ci/../pkg/py3.10/freebsd.txt
# botocore
@ -553,7 +553,7 @@ yamlordereddictloader==0.4.0
# via junos-eznc
yarl==1.9.2
# via aiohttp
zc.lockfile==1.4
zc.lockfile==3.0.post1
# via
# -c requirements/static/ci/../pkg/py3.10/freebsd.txt
# cherrypy

View file

@ -103,7 +103,7 @@ contextvars==2.4
# -r requirements/base.txt
croniter==1.3.15 ; sys_platform != "win32"
# via -r requirements/static/ci/common.in
cryptography==41.0.3
cryptography==41.0.4
# via
# -c requirements/static/ci/../pkg/py3.10/linux.txt
# -r requirements/crypto.txt
@ -133,7 +133,7 @@ exceptiongroup==1.1.1
# via
# anyio
# pytest
filelock==3.12.1
filelock==3.12.4
# via virtualenv
flaky==3.7.0
# via -r requirements/pytest.txt
@ -292,7 +292,7 @@ netaddr==0.8.0
# pyeapi
netmiko==4.2.0
# via napalm
netutils==1.4.1
netutils==1.6.0
# via napalm
ntc-templates==3.4.0
# via netmiko
@ -388,7 +388,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.0rc25
pytest-salt-factories==1.0.0rc26
# via -r requirements/pytest.txt
pytest-shell-utilities==1.8.0
# via pytest-salt-factories
@ -539,7 +539,7 @@ sqlparse==0.4.4
# via -r requirements/static/ci/common.in
strict-rfc3339==0.7
# via -r requirements/static/ci/common.in
tempora==5.2.2
tempora==5.3.0
# via
# -c requirements/static/ci/../pkg/py3.10/linux.txt
# portend
@ -548,7 +548,7 @@ textfsm==1.1.3
# napalm
# netmiko
# ntc-templates
timelib==0.2.5
timelib==0.3.0
# via
# -c requirements/static/ci/../pkg/py3.10/linux.txt
# -r requirements/static/pkg/linux.in
@ -564,7 +564,7 @@ transitions==0.9.0
# via junos-eznc
ttp-templates==0.3.5
# via napalm
ttp==0.9.4
ttp==0.9.5
# via
# napalm
# ttp-templates
@ -572,14 +572,14 @@ twilio==8.2.2
# via -r requirements/static/ci/linux.in
types-pyyaml==6.0.1
# via responses
typing-extensions==4.6.2
typing-extensions==4.6.3
# via
# -c requirements/static/ci/../pkg/py3.10/linux.txt
# napalm
# pydantic
# pytest-shell-utilities
# pytest-system-statistics
urllib3==1.26.6
urllib3==1.26.14
# via
# -c requirements/static/ci/../pkg/py3.10/linux.txt
# botocore
@ -617,7 +617,7 @@ yamlordereddictloader==0.4.0
# via junos-eznc
yarl==1.9.2
# via aiohttp
zc.lockfile==1.4
zc.lockfile==3.0.post1
# via
# -c requirements/static/ci/../pkg/py3.10/linux.txt
# cherrypy

View file

@ -18,7 +18,7 @@ cffi==1.15.1
# via
# clr-loader
# cryptography
charset-normalizer==3.1.0
charset-normalizer==3.2.0
# via requests
cheroot==10.0.0
# via cherrypy
@ -30,7 +30,7 @@ colorama==0.4.6
# via pytest
contextvars==2.4
# via -r requirements/base.txt
cryptography==41.0.3
cryptography==41.0.4
# via -r requirements/crypto.txt
distlib==0.3.6
# via virtualenv
@ -40,7 +40,7 @@ distro==1.8.0
# pytest-skip-markers
exceptiongroup==1.1.1
# via pytest
filelock==3.12.1
filelock==3.12.4
# via virtualenv
idna==3.4
# via requests
@ -109,7 +109,7 @@ pytest-helpers-namespace==2021.12.29
# pytest-shell-utilities
pytest-salt-factories==1.0.0rc17
# via -r requirements/static/ci/pkgtests-windows.in
pytest-shell-utilities==1.7.0
pytest-shell-utilities==1.8.0
# via pytest-salt-factories
pytest-skip-markers==1.4.1
# via
@ -155,7 +155,7 @@ typing-extensions==4.6.3
# pydantic
# pytest-shell-utilities
# pytest-system-statistics
urllib3==2.0.3
urllib3==1.26.14
# via requests
virtualenv==20.23.0
# via pytest-salt-factories

View file

@ -16,7 +16,7 @@ certifi==2023.07.22
# via requests
cffi==1.15.1
# via cryptography
charset-normalizer==3.1.0
charset-normalizer==3.2.0
# via requests
cheroot==10.0.0
# via cherrypy
@ -24,7 +24,7 @@ cherrypy==18.8.0
# via -r requirements/static/ci/pkgtests.in
contextvars==2.4
# via -r requirements/base.txt
cryptography==41.0.3
cryptography==41.0.4
# via -r requirements/crypto.txt
distlib==0.3.6
# via virtualenv
@ -36,7 +36,7 @@ docker==6.1.3
# via -r requirements/static/ci/pkgtests.in
exceptiongroup==1.1.1
# via pytest
filelock==3.12.1
filelock==3.12.4
# via virtualenv
idna==3.4
# via requests
@ -106,7 +106,7 @@ pytest-helpers-namespace==2021.12.29
# pytest-shell-utilities
pytest-salt-factories==1.0.0rc17
# via -r requirements/static/ci/pkgtests.in
pytest-shell-utilities==1.7.0
pytest-shell-utilities==1.8.0
# via pytest-salt-factories
pytest-skip-markers==1.4.1
# via
@ -148,13 +148,13 @@ typing-extensions==4.6.3
# pydantic
# pytest-shell-utilities
# pytest-system-statistics
urllib3==2.0.3
urllib3==1.26.14
# via
# docker
# requests
virtualenv==20.23.0
# via pytest-salt-factories
websocket-client==1.5.3
websocket-client==1.6.3
# via docker
zc.lockfile==3.0.post1
# via cherrypy

View file

@ -16,7 +16,7 @@ botocore==1.29.152
# s3transfer
certifi==2023.07.22
# via requests
charset-normalizer==3.1.0
charset-normalizer==3.2.0
# via requests
idna==3.4
# via requests
@ -54,7 +54,7 @@ six==1.16.0
# via python-dateutil
typing-extensions==4.6.3
# via python-tools-scripts
urllib3==1.26.16
urllib3==1.26.14
# via
# botocore
# requests

View file

@ -88,7 +88,7 @@ contextvars==2.4
# via
# -c requirements/static/ci/../pkg/py3.10/windows.txt
# -r requirements/base.txt
cryptography==41.0.3
cryptography==41.0.4
# via
# -c requirements/static/ci/../pkg/py3.10/windows.txt
# -r requirements/crypto.txt
@ -117,7 +117,7 @@ etcd3-py==0.1.6
# via -r requirements/static/ci/common.in
exceptiongroup==1.1.1
# via pytest
filelock==3.12.1
filelock==3.12.4
# via virtualenv
flaky==3.7.0
# via -r requirements/pytest.txt
@ -315,7 +315,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.0rc25
pytest-salt-factories==1.0.0rc26
# via -r requirements/pytest.txt
pytest-shell-utilities==1.8.0
# via pytest-salt-factories
@ -441,7 +441,7 @@ sqlparse==0.4.4
# via -r requirements/static/ci/common.in
strict-rfc3339==0.7
# via -r requirements/static/ci/common.in
tempora==5.2.2
tempora==5.3.0
# via
# -c requirements/static/ci/../pkg/py3.10/windows.txt
# portend
@ -459,13 +459,13 @@ tornado==6.3.2
# -r requirements/base.txt
types-pyyaml==6.0.1
# via responses
typing-extensions==4.6.2
typing-extensions==4.6.3
# via
# -c requirements/static/ci/../pkg/py3.10/windows.txt
# pydantic
# pytest-shell-utilities
# pytest-system-statistics
urllib3==1.26.6
urllib3==1.26.14
# via
# -c requirements/static/ci/../pkg/py3.10/windows.txt
# -r requirements/windows.txt
@ -510,7 +510,7 @@ yamllint==1.32.0
# via -r requirements/static/ci/windows.in
yarl==1.9.2
# via aiohttp
zc.lockfile==2.0
zc.lockfile==3.0.post1
# via
# -c requirements/static/ci/../pkg/py3.10/windows.txt
# cherrypy

View file

@ -20,7 +20,7 @@ charset-normalizer==3.2.0
# via
# -c requirements/static/ci/py3.11/linux.txt
# requests
cryptography==41.0.3
cryptography==41.0.4
# via
# -c requirements/static/ci/py3.11/linux.txt
# pyspnego
@ -67,7 +67,7 @@ smbprotocol==1.10.1
# via
# -r requirements/static/ci/cloud.in
# pypsexec
urllib3==1.26.6
urllib3==1.26.14
# via
# -c requirements/static/ci/py3.11/linux.txt
# requests

View file

@ -67,7 +67,7 @@ cffi==1.15.1
# napalm
# pygit2
# pynacl
charset-normalizer==3.1.0
charset-normalizer==3.2.0
# via
# -c requirements/static/ci/../pkg/py3.11/darwin.txt
# aiohttp
@ -93,7 +93,7 @@ contextvars==2.4
# -r requirements/base.txt
croniter==1.3.15 ; sys_platform != "win32"
# via -r requirements/static/ci/common.in
cryptography==41.0.3
cryptography==41.0.4
# via
# -c requirements/static/ci/../pkg/py3.11/darwin.txt
# -r requirements/crypto.txt
@ -118,7 +118,7 @@ docker==6.1.3
# via -r requirements/pytest.txt
etcd3-py==0.1.6
# via -r requirements/static/ci/common.in
filelock==3.12.1
filelock==3.12.4
# via virtualenv
flaky==3.7.0
# via -r requirements/pytest.txt
@ -270,7 +270,7 @@ netaddr==0.8.0
# pyeapi
netmiko==4.2.0
# via napalm
netutils==1.4.1
netutils==1.6.0
# via napalm
ntc-templates==3.4.0
# via netmiko
@ -358,7 +358,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.0rc25
pytest-salt-factories==1.0.0rc26
# via -r requirements/pytest.txt
pytest-shell-utilities==1.8.0
# via pytest-salt-factories
@ -483,7 +483,7 @@ sqlparse==0.4.4
# via -r requirements/static/ci/common.in
strict-rfc3339==0.7
# via -r requirements/static/ci/common.in
tempora==5.2.2
tempora==5.3.0
# via
# -c requirements/static/ci/../pkg/py3.11/darwin.txt
# portend
@ -506,20 +506,20 @@ transitions==0.9.0
# via junos-eznc
ttp-templates==0.3.5
# via napalm
ttp==0.9.4
ttp==0.9.5
# via
# napalm
# ttp-templates
types-pyyaml==6.0.1
# via responses
typing-extensions==4.6.2
typing-extensions==4.6.3
# via
# -c requirements/static/ci/../pkg/py3.11/darwin.txt
# napalm
# pydantic
# pytest-shell-utilities
# pytest-system-statistics
urllib3==1.26.6
urllib3==1.26.14
# via
# -c requirements/static/ci/../pkg/py3.11/darwin.txt
# botocore
@ -561,7 +561,7 @@ yamlordereddictloader==0.4.0
# via junos-eznc
yarl==1.9.2
# via aiohttp
zc.lockfile==2.0
zc.lockfile==3.0.post1
# via
# -c requirements/static/ci/../pkg/py3.11/darwin.txt
# cherrypy

View file

@ -142,21 +142,21 @@ sphinxcontrib-serializinghtml==1.1.5
# via sphinx
sphinxcontrib-spelling==8.0.0
# via -r requirements/static/ci/docs.in
tempora==5.2.2
tempora==5.3.0
# via
# -c requirements/static/ci/py3.11/linux.txt
# portend
typing-extensions==4.6.2
typing-extensions==4.6.3
# via
# -c requirements/static/ci/py3.11/linux.txt
# pydantic
uc-micro-py==1.0.2
# via linkify-it-py
urllib3==1.26.6
urllib3==1.26.14
# via
# -c requirements/static/ci/py3.11/linux.txt
# requests
zc.lockfile==1.4
zc.lockfile==3.0.post1
# via
# -c requirements/static/ci/py3.11/linux.txt
# cherrypy

View file

@ -89,7 +89,7 @@ contextvars==2.4
# -r requirements/base.txt
croniter==1.3.15 ; sys_platform != "win32"
# via -r requirements/static/ci/common.in
cryptography==41.0.3
cryptography==41.0.4
# via
# -c requirements/static/ci/../pkg/py3.11/freebsd.txt
# -r requirements/crypto.txt
@ -115,7 +115,7 @@ docker==6.1.3
# via -r requirements/pytest.txt
etcd3-py==0.1.6
# via -r requirements/static/ci/common.in
filelock==3.12.1
filelock==3.12.4
# via virtualenv
flaky==3.7.0
# via -r requirements/pytest.txt
@ -265,7 +265,7 @@ netaddr==0.8.0
# pyeapi
netmiko==4.2.0
# via napalm
netutils==1.4.1
netutils==1.6.0
# via napalm
ntc-templates==3.4.0
# via netmiko
@ -352,7 +352,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.0rc25
pytest-salt-factories==1.0.0rc26
# via -r requirements/pytest.txt
pytest-shell-utilities==1.8.0
# via pytest-salt-factories
@ -475,7 +475,7 @@ sqlparse==0.4.4
# via -r requirements/static/ci/common.in
strict-rfc3339==0.7
# via -r requirements/static/ci/common.in
tempora==5.2.2
tempora==5.3.0
# via
# -c requirements/static/ci/../pkg/py3.11/freebsd.txt
# portend
@ -498,20 +498,20 @@ transitions==0.9.0
# via junos-eznc
ttp-templates==0.3.5
# via napalm
ttp==0.9.4
ttp==0.9.5
# via
# napalm
# ttp-templates
types-pyyaml==6.0.1
# via responses
typing-extensions==4.6.2
typing-extensions==4.6.3
# via
# -c requirements/static/ci/../pkg/py3.11/freebsd.txt
# napalm
# pydantic
# pytest-shell-utilities
# pytest-system-statistics
urllib3==1.26.6
urllib3==1.26.14
# via
# -c requirements/static/ci/../pkg/py3.11/freebsd.txt
# botocore
@ -549,7 +549,7 @@ yamlordereddictloader==0.4.0
# via junos-eznc
yarl==1.9.2
# via aiohttp
zc.lockfile==1.4
zc.lockfile==3.0.post1
# via
# -c requirements/static/ci/../pkg/py3.11/freebsd.txt
# cherrypy

View file

@ -103,7 +103,7 @@ contextvars==2.4
# -r requirements/base.txt
croniter==1.3.15 ; sys_platform != "win32"
# via -r requirements/static/ci/common.in
cryptography==41.0.3
cryptography==41.0.4
# via
# -c requirements/static/ci/../pkg/py3.11/linux.txt
# -r requirements/crypto.txt
@ -129,7 +129,7 @@ docker==6.1.3
# via -r requirements/pytest.txt
etcd3-py==0.1.6
# via -r requirements/static/ci/common.in
filelock==3.12.1
filelock==3.12.4
# via virtualenv
flaky==3.7.0
# via -r requirements/pytest.txt
@ -288,7 +288,7 @@ netaddr==0.8.0
# pyeapi
netmiko==4.2.0
# via napalm
netutils==1.4.1
netutils==1.6.0
# via napalm
ntc-templates==3.4.0
# via netmiko
@ -384,7 +384,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.0rc25
pytest-salt-factories==1.0.0rc26
# via -r requirements/pytest.txt
pytest-shell-utilities==1.8.0
# via pytest-salt-factories
@ -535,7 +535,7 @@ sqlparse==0.4.4
# via -r requirements/static/ci/common.in
strict-rfc3339==0.7
# via -r requirements/static/ci/common.in
tempora==5.2.2
tempora==5.3.0
# via
# -c requirements/static/ci/../pkg/py3.11/linux.txt
# portend
@ -558,7 +558,7 @@ transitions==0.9.0
# via junos-eznc
ttp-templates==0.3.5
# via napalm
ttp==0.9.4
ttp==0.9.5
# via
# napalm
# ttp-templates
@ -566,14 +566,14 @@ twilio==8.2.2
# via -r requirements/static/ci/linux.in
types-pyyaml==6.0.1
# via responses
typing-extensions==4.6.2
typing-extensions==4.6.3
# via
# -c requirements/static/ci/../pkg/py3.11/linux.txt
# napalm
# pydantic
# pytest-shell-utilities
# pytest-system-statistics
urllib3==1.26.6
urllib3==1.26.14
# via
# -c requirements/static/ci/../pkg/py3.11/linux.txt
# botocore
@ -611,7 +611,7 @@ yamlordereddictloader==0.4.0
# via junos-eznc
yarl==1.9.2
# via aiohttp
zc.lockfile==1.4
zc.lockfile==3.0.post1
# via
# -c requirements/static/ci/../pkg/py3.11/linux.txt
# cherrypy

View file

@ -18,7 +18,7 @@ cffi==1.15.1
# via
# clr-loader
# cryptography
charset-normalizer==3.1.0
charset-normalizer==3.2.0
# via requests
cheroot==10.0.0
# via cherrypy
@ -30,7 +30,7 @@ colorama==0.4.6
# via pytest
contextvars==2.4
# via -r requirements/base.txt
cryptography==41.0.3
cryptography==41.0.4
# via -r requirements/crypto.txt
distlib==0.3.6
# via virtualenv
@ -38,7 +38,7 @@ distro==1.8.0
# via
# -r requirements/base.txt
# pytest-skip-markers
filelock==3.9.0
filelock==3.12.4
# via virtualenv
idna==3.4
# via requests
@ -83,7 +83,7 @@ packaging==23.1
# via
# -r requirements/base.txt
# pytest
platformdirs==2.6.2
platformdirs==3.5.3
# via virtualenv
pluggy==1.0.0
# via pytest
@ -142,22 +142,22 @@ pyzmq==25.1.0
# pytest-salt-factories
requests==2.31.0
# via -r requirements/base.txt
tempora==5.2.2
tempora==5.3.0
# via portend
tornado==6.3.2
# via -r requirements/base.txt
typing-extensions==4.6.2
typing-extensions==4.6.3
# via
# pydantic
# pytest-shell-utilities
# pytest-system-statistics
urllib3==1.26.14
# via requests
virtualenv==20.18.0
virtualenv==20.23.0
# via pytest-salt-factories
wmi==1.5.1 ; sys_platform == "win32"
# via -r requirements/static/ci/pkgtests-windows.in
zc.lockfile==2.0
zc.lockfile==3.0.post1
# via cherrypy
# The following packages are considered to be unsafe in a requirements file:

View file

@ -16,7 +16,7 @@ certifi==2023.07.22
# via requests
cffi==1.15.1
# via cryptography
charset-normalizer==3.1.0
charset-normalizer==3.2.0
# via requests
cheroot==10.0.0
# via cherrypy
@ -24,7 +24,7 @@ cherrypy==18.8.0
# via -r requirements/static/ci/pkgtests.in
contextvars==2.4
# via -r requirements/base.txt
cryptography==41.0.3
cryptography==41.0.4
# via -r requirements/crypto.txt
distlib==0.3.6
# via virtualenv
@ -34,7 +34,7 @@ distro==1.8.0
# pytest-skip-markers
docker==6.1.3
# via -r requirements/static/ci/pkgtests.in
filelock==3.9.0
filelock==3.12.4
# via virtualenv
idna==3.4
# via requests
@ -80,7 +80,7 @@ packaging==23.1
# -r requirements/base.txt
# docker
# pytest
platformdirs==2.6.2
platformdirs==3.5.3
# via virtualenv
pluggy==1.0.0
# via pytest
@ -135,11 +135,11 @@ requests==2.31.0
# via
# -r requirements/base.txt
# docker
tempora==5.2.2
tempora==5.3.0
# via portend
tornado==6.3.2
# via -r requirements/base.txt
typing-extensions==4.6.2
typing-extensions==4.6.3
# via
# pydantic
# pytest-shell-utilities
@ -148,11 +148,11 @@ urllib3==1.26.14
# via
# docker
# requests
virtualenv==20.17.1
virtualenv==20.23.0
# via pytest-salt-factories
websocket-client==1.5.1
websocket-client==1.6.3
# via docker
zc.lockfile==2.0
zc.lockfile==3.0.post1
# via cherrypy
# The following packages are considered to be unsafe in a requirements file:

View file

@ -16,7 +16,7 @@ botocore==1.29.152
# s3transfer
certifi==2023.07.22
# via requests
charset-normalizer==3.1.0
charset-normalizer==3.2.0
# via requests
idna==3.4
# via requests
@ -52,7 +52,7 @@ s3transfer==0.6.1
# via boto3
six==1.16.0
# via python-dateutil
urllib3==1.26.16
urllib3==1.26.14
# via
# botocore
# requests

View file

@ -88,7 +88,7 @@ contextvars==2.4
# via
# -c requirements/static/ci/../pkg/py3.11/windows.txt
# -r requirements/base.txt
cryptography==41.0.3
cryptography==41.0.4
# via
# -c requirements/static/ci/../pkg/py3.11/windows.txt
# -r requirements/crypto.txt
@ -115,7 +115,7 @@ docker==6.1.3
# via -r requirements/pytest.txt
etcd3-py==0.1.6
# via -r requirements/static/ci/common.in
filelock==3.12.3
filelock==3.12.4
# via virtualenv
flaky==3.7.0
# via -r requirements/pytest.txt
@ -313,7 +313,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.0rc25
pytest-salt-factories==1.0.0rc26
# via -r requirements/pytest.txt
pytest-shell-utilities==1.8.0
# via pytest-salt-factories
@ -439,7 +439,7 @@ sqlparse==0.4.4
# via -r requirements/static/ci/common.in
strict-rfc3339==0.7
# via -r requirements/static/ci/common.in
tempora==5.2.2
tempora==5.3.0
# via
# -c requirements/static/ci/../pkg/py3.11/windows.txt
# portend
@ -455,13 +455,13 @@ tornado==6.3.2
# -r requirements/base.txt
types-pyyaml==6.0.1
# via responses
typing-extensions==4.6.2
typing-extensions==4.6.3
# via
# -c requirements/static/ci/../pkg/py3.11/windows.txt
# pydantic
# pytest-shell-utilities
# pytest-system-statistics
urllib3==1.26.6
urllib3==1.26.14
# via
# -c requirements/static/ci/../pkg/py3.11/windows.txt
# -r requirements/windows.txt
@ -506,7 +506,7 @@ yamllint==1.32.0
# via -r requirements/static/ci/windows.in
yarl==1.9.2
# via aiohttp
zc.lockfile==2.0
zc.lockfile==3.0.post1
# via
# -c requirements/static/ci/../pkg/py3.11/windows.txt
# cherrypy

View file

@ -20,7 +20,7 @@ charset-normalizer==3.2.0
# via
# -c requirements/static/ci/py3.8/linux.txt
# requests
cryptography==41.0.3
cryptography==41.0.4
# via
# -c requirements/static/ci/py3.8/linux.txt
# pyspnego
@ -67,7 +67,7 @@ smbprotocol==1.10.1
# via
# -r requirements/static/ci/cloud.in
# pypsexec
urllib3==1.26.6
urllib3==1.26.14
# via
# -c requirements/static/ci/py3.8/linux.txt
# requests

View file

@ -151,21 +151,21 @@ sphinxcontrib-serializinghtml==1.1.5
# via sphinx
sphinxcontrib-spelling==8.0.0
# via -r requirements/static/ci/docs.in
tempora==5.2.2
tempora==5.3.0
# via
# -c requirements/static/ci/py3.8/linux.txt
# portend
typing-extensions==4.6.2
typing-extensions==4.6.3
# via
# -c requirements/static/ci/py3.8/linux.txt
# pydantic
uc-micro-py==1.0.2
# via linkify-it-py
urllib3==1.26.6
urllib3==1.26.14
# via
# -c requirements/static/ci/py3.8/linux.txt
# requests
zc.lockfile==1.4
zc.lockfile==3.0.post1
# via
# -c requirements/static/ci/py3.8/linux.txt
# cherrypy

View file

@ -89,7 +89,7 @@ contextvars==2.4
# -r requirements/base.txt
croniter==1.3.15 ; sys_platform != "win32"
# via -r requirements/static/ci/common.in
cryptography==41.0.3
cryptography==41.0.4
# via
# -c requirements/static/ci/../pkg/py3.8/freebsd.txt
# -r requirements/crypto.txt
@ -117,7 +117,7 @@ etcd3-py==0.1.6
# via -r requirements/static/ci/common.in
exceptiongroup==1.1.1
# via pytest
filelock==3.12.1
filelock==3.12.4
# via virtualenv
flaky==3.7.0
# via -r requirements/pytest.txt
@ -358,7 +358,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.0rc25
pytest-salt-factories==1.0.0rc26
# via -r requirements/pytest.txt
pytest-shell-utilities==1.8.0
# via pytest-salt-factories
@ -481,7 +481,7 @@ sqlparse==0.4.4
# via -r requirements/static/ci/common.in
strict-rfc3339==0.7
# via -r requirements/static/ci/common.in
tempora==5.2.2
tempora==5.3.0
# via
# -c requirements/static/ci/../pkg/py3.8/freebsd.txt
# portend
@ -512,14 +512,14 @@ ttp==0.9.5
# ttp-templates
types-pyyaml==6.0.1
# via responses
typing-extensions==4.6.2
typing-extensions==4.6.3
# via
# -c requirements/static/ci/../pkg/py3.8/freebsd.txt
# napalm
# pydantic
# pytest-shell-utilities
# pytest-system-statistics
urllib3==1.26.6
urllib3==1.26.14
# via
# -c requirements/static/ci/../pkg/py3.8/freebsd.txt
# botocore
@ -557,7 +557,7 @@ yamlordereddictloader==0.4.0
# via junos-eznc
yarl==1.9.2
# via aiohttp
zc.lockfile==1.4
zc.lockfile==3.0.post1
# via
# -c requirements/static/ci/../pkg/py3.8/freebsd.txt
# cherrypy

View file

@ -103,7 +103,7 @@ contextvars==2.4
# -r requirements/base.txt
croniter==1.3.15 ; sys_platform != "win32"
# via -r requirements/static/ci/common.in
cryptography==41.0.3
cryptography==41.0.4
# via
# -c requirements/static/ci/../pkg/py3.8/linux.txt
# -r requirements/crypto.txt
@ -133,7 +133,7 @@ exceptiongroup==1.1.1
# via
# anyio
# pytest
filelock==3.12.1
filelock==3.12.4
# via virtualenv
flaky==3.7.0
# via -r requirements/pytest.txt
@ -392,7 +392,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.0rc25
pytest-salt-factories==1.0.0rc26
# via -r requirements/pytest.txt
pytest-shell-utilities==1.8.0
# via pytest-salt-factories
@ -543,7 +543,7 @@ sqlparse==0.4.4
# via -r requirements/static/ci/common.in
strict-rfc3339==0.7
# via -r requirements/static/ci/common.in
tempora==5.2.2
tempora==5.3.0
# via
# -c requirements/static/ci/../pkg/py3.8/linux.txt
# portend
@ -576,14 +576,14 @@ twilio==8.2.2
# via -r requirements/static/ci/linux.in
types-pyyaml==6.0.1
# via responses
typing-extensions==4.6.2
typing-extensions==4.6.3
# via
# -c requirements/static/ci/../pkg/py3.8/linux.txt
# napalm
# pydantic
# pytest-shell-utilities
# pytest-system-statistics
urllib3==1.26.6
urllib3==1.26.14
# via
# -c requirements/static/ci/../pkg/py3.8/linux.txt
# botocore
@ -621,7 +621,7 @@ yamlordereddictloader==0.4.0
# via junos-eznc
yarl==1.9.2
# via aiohttp
zc.lockfile==1.4
zc.lockfile==3.0.post1
# via
# -c requirements/static/ci/../pkg/py3.8/linux.txt
# cherrypy

View file

@ -88,7 +88,7 @@ contextvars==2.4
# via
# -c requirements/static/ci/../pkg/py3.8/windows.txt
# -r requirements/base.txt
cryptography==41.0.3
cryptography==41.0.4
# via
# -c requirements/static/ci/../pkg/py3.8/windows.txt
# -r requirements/crypto.txt
@ -117,7 +117,7 @@ etcd3-py==0.1.6
# via -r requirements/static/ci/common.in
exceptiongroup==1.1.1
# via pytest
filelock==3.12.1
filelock==3.12.4
# via virtualenv
flaky==3.7.0
# via -r requirements/pytest.txt
@ -319,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.0rc25
pytest-salt-factories==1.0.0rc26
# via -r requirements/pytest.txt
pytest-shell-utilities==1.8.0
# via pytest-salt-factories
@ -446,7 +446,7 @@ sqlparse==0.4.4
# via -r requirements/static/ci/common.in
strict-rfc3339==0.7
# via -r requirements/static/ci/common.in
tempora==5.2.2
tempora==5.3.0
# via
# -c requirements/static/ci/../pkg/py3.8/windows.txt
# portend
@ -464,13 +464,13 @@ tornado==6.3.2
# -r requirements/base.txt
types-pyyaml==6.0.1
# via responses
typing-extensions==4.6.2
typing-extensions==4.6.3
# via
# -c requirements/static/ci/../pkg/py3.8/windows.txt
# pydantic
# pytest-shell-utilities
# pytest-system-statistics
urllib3==1.26.6
urllib3==1.26.14
# via
# -c requirements/static/ci/../pkg/py3.8/windows.txt
# -r requirements/windows.txt
@ -515,7 +515,7 @@ yamllint==1.32.0
# via -r requirements/static/ci/windows.in
yarl==1.9.2
# via aiohttp
zc.lockfile==2.0
zc.lockfile==3.0.post1
# via
# -c requirements/static/ci/../pkg/py3.8/windows.txt
# cherrypy

View file

@ -20,7 +20,7 @@ charset-normalizer==3.2.0
# via
# -c requirements/static/ci/py3.9/linux.txt
# requests
cryptography==41.0.3
cryptography==41.0.4
# via
# -c requirements/static/ci/py3.9/linux.txt
# pyspnego
@ -67,7 +67,7 @@ smbprotocol==1.10.1
# via
# -r requirements/static/ci/cloud.in
# pypsexec
urllib3==1.26.6
urllib3==1.26.14
# via
# -c requirements/static/ci/py3.9/linux.txt
# requests

View file

@ -93,7 +93,7 @@ contextvars==2.4
# -r requirements/base.txt
croniter==1.3.15 ; sys_platform != "win32"
# via -r requirements/static/ci/common.in
cryptography==41.0.3
cryptography==41.0.4
# via
# -c requirements/static/ci/../pkg/py3.9/darwin.txt
# -r requirements/crypto.txt
@ -120,7 +120,7 @@ etcd3-py==0.1.6
# via -r requirements/static/ci/common.in
exceptiongroup==1.1.1
# via pytest
filelock==3.12.1
filelock==3.12.4
# via virtualenv
flaky==3.7.0
# via -r requirements/pytest.txt
@ -360,7 +360,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.0rc25
pytest-salt-factories==1.0.0rc26
# via -r requirements/pytest.txt
pytest-shell-utilities==1.8.0
# via pytest-salt-factories
@ -485,7 +485,7 @@ sqlparse==0.4.4
# via -r requirements/static/ci/common.in
strict-rfc3339==0.7
# via -r requirements/static/ci/common.in
tempora==5.2.2
tempora==5.3.0
# via
# -c requirements/static/ci/../pkg/py3.9/darwin.txt
# portend
@ -516,14 +516,14 @@ ttp==0.9.5
# ttp-templates
types-pyyaml==6.0.1
# via responses
typing-extensions==4.6.2
typing-extensions==4.6.3
# via
# -c requirements/static/ci/../pkg/py3.9/darwin.txt
# napalm
# pydantic
# pytest-shell-utilities
# pytest-system-statistics
urllib3==1.26.6
urllib3==1.26.14
# via
# -c requirements/static/ci/../pkg/py3.9/darwin.txt
# botocore
@ -565,7 +565,7 @@ yamlordereddictloader==0.4.0
# via junos-eznc
yarl==1.9.2
# via aiohttp
zc.lockfile==2.0
zc.lockfile==3.0.post1
# via
# -c requirements/static/ci/../pkg/py3.9/darwin.txt
# cherrypy

View file

@ -146,21 +146,21 @@ sphinxcontrib-serializinghtml==1.1.5
# via sphinx
sphinxcontrib-spelling==8.0.0
# via -r requirements/static/ci/docs.in
tempora==5.2.2
tempora==5.3.0
# via
# -c requirements/static/ci/py3.9/linux.txt
# portend
typing-extensions==4.6.2
typing-extensions==4.6.3
# via
# -c requirements/static/ci/py3.9/linux.txt
# pydantic
uc-micro-py==1.0.2
# via linkify-it-py
urllib3==1.26.6
urllib3==1.26.14
# via
# -c requirements/static/ci/py3.9/linux.txt
# requests
zc.lockfile==1.4
zc.lockfile==3.0.post1
# via
# -c requirements/static/ci/py3.9/linux.txt
# cherrypy

View file

@ -89,7 +89,7 @@ contextvars==2.4
# -r requirements/base.txt
croniter==1.3.15 ; sys_platform != "win32"
# via -r requirements/static/ci/common.in
cryptography==41.0.3
cryptography==41.0.4
# via
# -c requirements/static/ci/../pkg/py3.9/freebsd.txt
# -r requirements/crypto.txt
@ -117,7 +117,7 @@ etcd3-py==0.1.6
# via -r requirements/static/ci/common.in
exceptiongroup==1.1.1
# via pytest
filelock==3.12.1
filelock==3.12.4
# via virtualenv
flaky==3.7.0
# via -r requirements/pytest.txt
@ -354,7 +354,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.0rc25
pytest-salt-factories==1.0.0rc26
# via -r requirements/pytest.txt
pytest-shell-utilities==1.8.0
# via pytest-salt-factories
@ -477,7 +477,7 @@ sqlparse==0.4.4
# via -r requirements/static/ci/common.in
strict-rfc3339==0.7
# via -r requirements/static/ci/common.in
tempora==5.2.2
tempora==5.3.0
# via
# -c requirements/static/ci/../pkg/py3.9/freebsd.txt
# portend
@ -508,14 +508,14 @@ ttp==0.9.5
# ttp-templates
types-pyyaml==6.0.1
# via responses
typing-extensions==4.6.2
typing-extensions==4.6.3
# via
# -c requirements/static/ci/../pkg/py3.9/freebsd.txt
# napalm
# pydantic
# pytest-shell-utilities
# pytest-system-statistics
urllib3==1.26.6
urllib3==1.26.14
# via
# -c requirements/static/ci/../pkg/py3.9/freebsd.txt
# botocore
@ -553,7 +553,7 @@ yamlordereddictloader==0.4.0
# via junos-eznc
yarl==1.9.2
# via aiohttp
zc.lockfile==1.4
zc.lockfile==3.0.post1
# via
# -c requirements/static/ci/../pkg/py3.9/freebsd.txt
# cherrypy

View file

@ -103,7 +103,7 @@ contextvars==2.4
# -r requirements/base.txt
croniter==1.3.15 ; sys_platform != "win32"
# via -r requirements/static/ci/common.in
cryptography==41.0.3
cryptography==41.0.4
# via
# -c requirements/static/ci/../pkg/py3.9/linux.txt
# -r requirements/crypto.txt
@ -133,7 +133,7 @@ exceptiongroup==1.1.1
# via
# anyio
# pytest
filelock==3.12.1
filelock==3.12.4
# via virtualenv
flaky==3.7.0
# via -r requirements/pytest.txt
@ -390,7 +390,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.0rc25
pytest-salt-factories==1.0.0rc26
# via -r requirements/pytest.txt
pytest-shell-utilities==1.8.0
# via pytest-salt-factories
@ -541,7 +541,7 @@ sqlparse==0.4.4
# via -r requirements/static/ci/common.in
strict-rfc3339==0.7
# via -r requirements/static/ci/common.in
tempora==5.2.2
tempora==5.3.0
# via
# -c requirements/static/ci/../pkg/py3.9/linux.txt
# portend
@ -574,14 +574,14 @@ twilio==8.2.2
# via -r requirements/static/ci/linux.in
types-pyyaml==6.0.1
# via responses
typing-extensions==4.6.2
typing-extensions==4.6.3
# via
# -c requirements/static/ci/../pkg/py3.9/linux.txt
# napalm
# pydantic
# pytest-shell-utilities
# pytest-system-statistics
urllib3==1.26.6
urllib3==1.26.14
# via
# -c requirements/static/ci/../pkg/py3.9/linux.txt
# botocore
@ -619,7 +619,7 @@ yamlordereddictloader==0.4.0
# via junos-eznc
yarl==1.9.2
# via aiohttp
zc.lockfile==1.4
zc.lockfile==3.0.post1
# via
# -c requirements/static/ci/../pkg/py3.9/linux.txt
# cherrypy

View file

@ -16,7 +16,7 @@ botocore==1.29.152
# s3transfer
certifi==2023.07.22
# via requests
charset-normalizer==3.1.0
charset-normalizer==3.2.0
# via requests
idna==3.4
# via requests
@ -54,7 +54,7 @@ six==1.16.0
# via python-dateutil
typing-extensions==4.6.3
# via python-tools-scripts
urllib3==1.26.16
urllib3==1.26.14
# via
# botocore
# requests

View file

@ -88,7 +88,7 @@ contextvars==2.4
# via
# -c requirements/static/ci/../pkg/py3.9/windows.txt
# -r requirements/base.txt
cryptography==41.0.3
cryptography==41.0.4
# via
# -c requirements/static/ci/../pkg/py3.9/windows.txt
# -r requirements/crypto.txt
@ -117,7 +117,7 @@ etcd3-py==0.1.6
# via -r requirements/static/ci/common.in
exceptiongroup==1.1.1
# via pytest
filelock==3.12.1
filelock==3.12.4
# via virtualenv
flaky==3.7.0
# via -r requirements/pytest.txt
@ -315,7 +315,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.0rc25
pytest-salt-factories==1.0.0rc26
# via -r requirements/pytest.txt
pytest-shell-utilities==1.8.0
# via pytest-salt-factories
@ -442,7 +442,7 @@ sqlparse==0.4.4
# via -r requirements/static/ci/common.in
strict-rfc3339==0.7
# via -r requirements/static/ci/common.in
tempora==5.2.2
tempora==5.3.0
# via
# -c requirements/static/ci/../pkg/py3.9/windows.txt
# portend
@ -460,13 +460,13 @@ tornado==6.3.2
# -r requirements/base.txt
types-pyyaml==6.0.1
# via responses
typing-extensions==4.6.2
typing-extensions==4.6.3
# via
# -c requirements/static/ci/../pkg/py3.9/windows.txt
# pydantic
# pytest-shell-utilities
# pytest-system-statistics
urllib3==1.26.6
urllib3==1.26.14
# via
# -c requirements/static/ci/../pkg/py3.9/windows.txt
# -r requirements/windows.txt
@ -511,7 +511,7 @@ yamllint==1.32.0
# via -r requirements/static/ci/windows.in
yarl==1.9.2
# via aiohttp
zc.lockfile==2.0
zc.lockfile==3.0.post1
# via
# -c requirements/static/ci/../pkg/py3.9/windows.txt
# cherrypy

View file

@ -20,7 +20,7 @@ cherrypy==18.8.0
# via -r requirements/darwin.txt
contextvars==2.4
# via -r requirements/base.txt
cryptography==41.0.3
cryptography==41.0.4
# via
# -r requirements/crypto.txt
# -r requirements/darwin.txt
@ -107,19 +107,19 @@ six==1.16.0
# via python-dateutil
smmap==3.0.2
# via gitdb
tempora==5.2.2
tempora==5.3.0
# via portend
timelib==0.3.0
# via -r requirements/darwin.txt
tornado==6.3.2
# via -r requirements/base.txt
typing-extensions==4.6.2
typing-extensions==4.6.3
# via pydantic
urllib3==1.26.6
urllib3==1.26.14
# via requests
vultr==1.0.1
# via -r requirements/darwin.txt
zc.lockfile==2.0
zc.lockfile==3.0.post1
# via cherrypy
# The following packages are considered to be unsafe in a requirements file:

View file

@ -18,7 +18,7 @@ cherrypy==18.8.0
# via -r requirements/static/pkg/freebsd.in
contextvars==2.4
# via -r requirements/base.txt
cryptography==41.0.3
cryptography==41.0.4
# via
# -r requirements/crypto.txt
# -r requirements/static/pkg/freebsd.in
@ -94,17 +94,17 @@ setproctitle==1.3.2
# via -r requirements/static/pkg/freebsd.in
six==1.16.0
# via python-dateutil
tempora==5.2.2
tempora==5.3.0
# via portend
timelib==0.3.0
# via -r requirements/static/pkg/freebsd.in
tornado==6.3.2
# via -r requirements/base.txt
typing-extensions==4.6.2
typing-extensions==4.6.3
# via pydantic
urllib3==1.26.6
urllib3==1.26.14
# via requests
zc.lockfile==1.4
zc.lockfile==3.0.post1
# via cherrypy
zipp==3.15.0
# via importlib-metadata

View file

@ -18,7 +18,7 @@ cherrypy==18.8.0
# via -r requirements/static/pkg/linux.in
contextvars==2.4
# via -r requirements/base.txt
cryptography==41.0.3
cryptography==41.0.4
# via
# -r requirements/crypto.txt
# -r requirements/static/pkg/linux.in
@ -94,17 +94,17 @@ setproctitle==1.3.2
# via -r requirements/static/pkg/linux.in
six==1.16.0
# via python-dateutil
tempora==5.2.2
tempora==5.3.0
# via portend
timelib==0.2.5
timelib==0.3.0
# via -r requirements/static/pkg/linux.in
tornado==6.3.2
# via -r requirements/base.txt
typing-extensions==4.6.2
typing-extensions==4.6.3
# via pydantic
urllib3==1.26.6
urllib3==1.26.14
# via requests
zc.lockfile==1.4
zc.lockfile==3.0.post1
# via cherrypy
zipp==3.15.0
# via importlib-metadata

View file

@ -25,7 +25,7 @@ clr-loader==0.2.4
# via pythonnet
contextvars==2.4
# via -r requirements/base.txt
cryptography==41.0.3
cryptography==41.0.4
# via
# -r requirements/crypto.txt
# -r requirements/windows.txt
@ -121,15 +121,15 @@ six==1.15.0
# via python-dateutil
smmap==4.0.0
# via gitdb
tempora==5.2.2
tempora==5.3.0
# via portend
timelib==0.3.0
# via -r requirements/windows.txt
tornado==6.3.2
# via -r requirements/base.txt
typing-extensions==4.6.2
typing-extensions==4.6.3
# via pydantic
urllib3==1.26.6
urllib3==1.26.14
# via
# -r requirements/windows.txt
# requests
@ -137,7 +137,7 @@ wheel==0.38.4
# via -r requirements/windows.txt
wmi==1.5.1
# via -r requirements/windows.txt
zc.lockfile==2.0
zc.lockfile==3.0.post1
# via cherrypy
zipp==3.15.0
# via importlib-metadata

View file

@ -12,7 +12,7 @@ certifi==2023.07.22
# via requests
cffi==1.15.1
# via cryptography
charset-normalizer==3.1.0
charset-normalizer==3.2.0
# via requests
cheroot==10.0.0
# via cherrypy
@ -20,7 +20,7 @@ cherrypy==18.8.0
# via -r requirements/darwin.txt
contextvars==2.4
# via -r requirements/base.txt
cryptography==41.0.3
cryptography==41.0.4
# via
# -r requirements/crypto.txt
# -r requirements/darwin.txt
@ -107,19 +107,19 @@ six==1.16.0
# via python-dateutil
smmap==3.0.2
# via gitdb
tempora==5.2.2
tempora==5.3.0
# via portend
timelib==0.3.0
# via -r requirements/darwin.txt
tornado==6.3.2
# via -r requirements/base.txt
typing-extensions==4.6.2
typing-extensions==4.6.3
# via pydantic
urllib3==1.26.6
urllib3==1.26.14
# via requests
vultr==1.0.1
# via -r requirements/darwin.txt
zc.lockfile==2.0
zc.lockfile==3.0.post1
# via cherrypy
# The following packages are considered to be unsafe in a requirements file:

View file

@ -18,7 +18,7 @@ cherrypy==18.8.0
# via -r requirements/static/pkg/freebsd.in
contextvars==2.4
# via -r requirements/base.txt
cryptography==41.0.3
cryptography==41.0.4
# via
# -r requirements/crypto.txt
# -r requirements/static/pkg/freebsd.in
@ -94,17 +94,17 @@ setproctitle==1.3.2
# via -r requirements/static/pkg/freebsd.in
six==1.16.0
# via python-dateutil
tempora==5.2.2
tempora==5.3.0
# via portend
timelib==0.3.0
# via -r requirements/static/pkg/freebsd.in
tornado==6.3.2
# via -r requirements/base.txt
typing-extensions==4.6.2
typing-extensions==4.6.3
# via pydantic
urllib3==1.26.6
urllib3==1.26.14
# via requests
zc.lockfile==1.4
zc.lockfile==3.0.post1
# via cherrypy
zipp==3.15.0
# via importlib-metadata

View file

@ -18,7 +18,7 @@ cherrypy==18.8.0
# via -r requirements/static/pkg/linux.in
contextvars==2.4
# via -r requirements/base.txt
cryptography==41.0.3
cryptography==41.0.4
# via
# -r requirements/crypto.txt
# -r requirements/static/pkg/linux.in
@ -94,17 +94,17 @@ setproctitle==1.3.2
# via -r requirements/static/pkg/linux.in
six==1.16.0
# via python-dateutil
tempora==5.2.2
tempora==5.3.0
# via portend
timelib==0.3.0
# via -r requirements/static/pkg/linux.in
tornado==6.3.2
# via -r requirements/base.txt
typing-extensions==4.6.2
typing-extensions==4.6.3
# via pydantic
urllib3==1.26.6
urllib3==1.26.14
# via requests
zc.lockfile==1.4
zc.lockfile==3.0.post1
# via cherrypy
zipp==3.15.0
# via importlib-metadata

View file

@ -25,7 +25,7 @@ clr-loader==0.2.4
# via pythonnet
contextvars==2.4
# via -r requirements/base.txt
cryptography==41.0.3
cryptography==41.0.4
# via
# -r requirements/crypto.txt
# -r requirements/windows.txt
@ -121,15 +121,15 @@ six==1.15.0
# via python-dateutil
smmap==4.0.0
# via gitdb
tempora==5.2.2
tempora==5.3.0
# via portend
timelib==0.3.0
# via -r requirements/windows.txt
tornado==6.3.2
# via -r requirements/base.txt
typing-extensions==4.6.2
typing-extensions==4.6.3
# via pydantic
urllib3==1.26.6
urllib3==1.26.14
# via
# -r requirements/windows.txt
# requests
@ -137,7 +137,7 @@ wheel==0.38.4
# via -r requirements/windows.txt
wmi==1.5.1
# via -r requirements/windows.txt
zc.lockfile==2.0
zc.lockfile==3.0.post1
# via cherrypy
zipp==3.15.0
# via importlib-metadata

View file

@ -18,7 +18,7 @@ cherrypy==18.8.0
# via -r requirements/static/pkg/freebsd.in
contextvars==2.4
# via -r requirements/base.txt
cryptography==41.0.3
cryptography==41.0.4
# via
# -r requirements/crypto.txt
# -r requirements/static/pkg/freebsd.in
@ -96,17 +96,17 @@ setproctitle==1.3.2
# via -r requirements/static/pkg/freebsd.in
six==1.16.0
# via python-dateutil
tempora==5.2.2
tempora==5.3.0
# via portend
timelib==0.3.0
# via -r requirements/static/pkg/freebsd.in
tornado==6.3.2
# via -r requirements/base.txt
typing-extensions==4.6.2
typing-extensions==4.6.3
# via pydantic
urllib3==1.26.6
urllib3==1.26.14
# via requests
zc.lockfile==1.4
zc.lockfile==3.0.post1
# via cherrypy
zipp==3.15.0
# via

View file

@ -18,7 +18,7 @@ cherrypy==18.8.0
# via -r requirements/static/pkg/linux.in
contextvars==2.4
# via -r requirements/base.txt
cryptography==41.0.3
cryptography==41.0.4
# via
# -r requirements/crypto.txt
# -r requirements/static/pkg/linux.in
@ -96,17 +96,17 @@ setproctitle==1.3.2
# via -r requirements/static/pkg/linux.in
six==1.16.0
# via python-dateutil
tempora==5.2.2
tempora==5.3.0
# via portend
timelib==0.3.0
# via -r requirements/static/pkg/linux.in
tornado==6.3.2
# via -r requirements/base.txt
typing-extensions==4.6.2
typing-extensions==4.6.3
# via pydantic
urllib3==1.26.6
urllib3==1.26.14
# via requests
zc.lockfile==1.4
zc.lockfile==3.0.post1
# via cherrypy
zipp==3.15.0
# via

View file

@ -25,7 +25,7 @@ clr-loader==0.2.4
# via pythonnet
contextvars==2.4
# via -r requirements/base.txt
cryptography==41.0.3
cryptography==41.0.4
# via
# -r requirements/crypto.txt
# -r requirements/windows.txt
@ -124,15 +124,15 @@ six==1.15.0
# via python-dateutil
smmap==4.0.0
# via gitdb
tempora==5.2.2
tempora==5.3.0
# via portend
timelib==0.3.0
# via -r requirements/windows.txt
tornado==6.3.2
# via -r requirements/base.txt
typing-extensions==4.6.2
typing-extensions==4.6.3
# via pydantic
urllib3==1.26.6
urllib3==1.26.14
# via
# -r requirements/windows.txt
# requests
@ -140,7 +140,7 @@ wheel==0.38.4
# via -r requirements/windows.txt
wmi==1.5.1
# via -r requirements/windows.txt
zc.lockfile==2.0
zc.lockfile==3.0.post1
# via cherrypy
zipp==3.15.0
# via

View file

@ -20,7 +20,7 @@ cherrypy==18.8.0
# via -r requirements/darwin.txt
contextvars==2.4
# via -r requirements/base.txt
cryptography==41.0.3
cryptography==41.0.4
# via
# -r requirements/crypto.txt
# -r requirements/darwin.txt
@ -107,19 +107,19 @@ six==1.16.0
# via python-dateutil
smmap==3.0.2
# via gitdb
tempora==5.2.2
tempora==5.3.0
# via portend
timelib==0.3.0
# via -r requirements/darwin.txt
tornado==6.3.2
# via -r requirements/base.txt
typing-extensions==4.6.2
typing-extensions==4.6.3
# via pydantic
urllib3==1.26.6
urllib3==1.26.14
# via requests
vultr==1.0.1
# via -r requirements/darwin.txt
zc.lockfile==2.0
zc.lockfile==3.0.post1
# via cherrypy
# The following packages are considered to be unsafe in a requirements file:

View file

@ -18,7 +18,7 @@ cherrypy==18.8.0
# via -r requirements/static/pkg/freebsd.in
contextvars==2.4
# via -r requirements/base.txt
cryptography==41.0.3
cryptography==41.0.4
# via
# -r requirements/crypto.txt
# -r requirements/static/pkg/freebsd.in
@ -94,17 +94,17 @@ setproctitle==1.3.2
# via -r requirements/static/pkg/freebsd.in
six==1.16.0
# via python-dateutil
tempora==5.2.2
tempora==5.3.0
# via portend
timelib==0.3.0
# via -r requirements/static/pkg/freebsd.in
tornado==6.3.2
# via -r requirements/base.txt
typing-extensions==4.6.2
typing-extensions==4.6.3
# via pydantic
urllib3==1.26.6
urllib3==1.26.14
# via requests
zc.lockfile==1.4
zc.lockfile==3.0.post1
# via cherrypy
zipp==3.15.0
# via importlib-metadata

View file

@ -18,7 +18,7 @@ cherrypy==18.8.0
# via -r requirements/static/pkg/linux.in
contextvars==2.4
# via -r requirements/base.txt
cryptography==41.0.3
cryptography==41.0.4
# via
# -r requirements/crypto.txt
# -r requirements/static/pkg/linux.in
@ -94,17 +94,17 @@ setproctitle==1.3.2
# via -r requirements/static/pkg/linux.in
six==1.16.0
# via python-dateutil
tempora==5.2.2
tempora==5.3.0
# via portend
timelib==0.3.0
# via -r requirements/static/pkg/linux.in
tornado==6.3.2
# via -r requirements/base.txt
typing-extensions==4.6.2
typing-extensions==4.6.3
# via pydantic
urllib3==1.26.6
urllib3==1.26.14
# via requests
zc.lockfile==1.4
zc.lockfile==3.0.post1
# via cherrypy
zipp==3.15.0
# via importlib-metadata

View file

@ -25,7 +25,7 @@ clr-loader==0.2.4
# via pythonnet
contextvars==2.4
# via -r requirements/base.txt
cryptography==41.0.3
cryptography==41.0.4
# via
# -r requirements/crypto.txt
# -r requirements/windows.txt
@ -122,15 +122,15 @@ six==1.15.0
# via python-dateutil
smmap==4.0.0
# via gitdb
tempora==5.2.2
tempora==5.3.0
# via portend
timelib==0.3.0
# via -r requirements/windows.txt
tornado==6.3.2
# via -r requirements/base.txt
typing-extensions==4.6.2
typing-extensions==4.6.3
# via pydantic
urllib3==1.26.6
urllib3==1.26.14
# via
# -r requirements/windows.txt
# requests
@ -138,7 +138,7 @@ wheel==0.38.4
# via -r requirements/windows.txt
wmi==1.5.1
# via -r requirements/windows.txt
zc.lockfile==2.0
zc.lockfile==3.0.post1
# via cherrypy
zipp==3.15.0
# via importlib-metadata

View file

@ -9,7 +9,7 @@ pythonnet>=3.0.1
certifi>=2022.12.07
cffi>=1.14.5
cherrypy>=18.6.1
gitpython>=3.1.30
gitpython>=3.1.35
cryptography>=41.0.3
lxml>=4.6.3
pyasn1>=0.4.8

View file

@ -24,15 +24,6 @@ authenticated against. This defaults to `login`
The Python interface to PAM does not support authenticating as ``root``.
.. note:: Using PAM groups with SSSD groups on python2.
To use sssd with the PAM eauth module and groups the `pysss` module is
needed. On RedHat/CentOS this is `python-sss`.
This should not be needed with python >= 3.3, because the `os` modules has the
`getgrouplist` function.
.. note:: This module executes itself in a subprocess in order to user the system python
and pam libraries. We do this to avoid openssl version conflicts when
running under a salt onedir build.
@ -113,7 +104,7 @@ class PamMessage(Structure):
]
def __repr__(self):
return "<PamMessage {} '{}'>".format(self.msg_style, self.msg)
return f"<PamMessage {self.msg_style} '{self.msg}'>"
class PamResponse(Structure):
@ -127,7 +118,7 @@ class PamResponse(Structure):
]
def __repr__(self):
return "<PamResponse {} '{}'>".format(self.resp_retcode, self.resp)
return f"<PamResponse {self.resp_retcode} '{self.resp}'>"
CONV_FUNC = CFUNCTYPE(
@ -245,8 +236,7 @@ def authenticate(username, password):
ret = subprocess.run(
[str(pyexe), str(pyfile)],
env=env,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
capture_output=True,
check=False,
)
if ret.returncode == 0:

View file

@ -380,7 +380,7 @@ class AutoKey:
line = salt.utils.stringutils.to_unicode(line).strip()
if line.startswith("#"):
continue
if autosign_grains[grain] == line:
if str(autosign_grains[grain]) == line:
return True
return False

View file

@ -328,9 +328,12 @@ def load_args_and_kwargs(func, args, data=None, ignore_invalid=False):
invalid_kwargs = []
for arg in args:
if isinstance(arg, dict) and arg.pop("__kwarg__", False) is True:
if isinstance(arg, dict) and arg.get("__kwarg__", False) is True:
# if the arg is a dict with __kwarg__ == True, then its a kwarg
for key, val in arg.items():
# Skip __kwarg__ when checking kwargs
if key == "__kwarg__":
continue
if argspec.keywords or key in argspec.args:
# Function supports **kwargs or is a positional argument to
# the function.

View file

@ -435,7 +435,7 @@ def set_mode(path, mode):
if not mode:
mode = "0"
if not os.path.exists(path):
raise CommandExecutionError("{}: File not found".format(path))
raise CommandExecutionError(f"{path}: File not found")
try:
os.chmod(path, int(mode, 8))
except Exception: # pylint: disable=broad-except
@ -678,14 +678,14 @@ def chattr(*files, **kwargs):
cmd = ["chattr"]
if operator == "add":
attrs = "+{}".format(attributes)
attrs = f"+{attributes}"
elif operator == "remove":
attrs = "-{}".format(attributes)
attrs = f"-{attributes}"
cmd.append(attrs)
if flags is not None:
cmd.append("-{}".format(flags))
cmd.append(f"-{flags}")
if version is not None:
cmd.extend(["-v", version])
@ -828,12 +828,7 @@ def get_source_sum(
"following are supported hash types and lengths: {}.".format(
source_hash,
", ".join(salt.utils.files.VALID_PROTOS),
", ".join(
[
"{} ({})".format(HASHES_REVMAP[x], x)
for x in sorted(HASHES_REVMAP)
]
),
", ".join([f"{HASHES_REVMAP[x]} ({x})" for x in sorted(HASHES_REVMAP)]),
)
)
@ -849,7 +844,7 @@ def get_source_sum(
)
if not hash_fn:
raise CommandExecutionError(
"Source hash file {} not found".format(source_hash)
f"Source hash file {source_hash} not found"
)
else:
if proto != "":
@ -879,7 +874,7 @@ def get_source_sum(
_invalid_source_hash_format()
except ValueError:
# No hash type, try to figure out by hash length
if not re.match("^[{}]+$".format(string.hexdigits), source_hash):
if not re.match(f"^[{string.hexdigits}]+$", source_hash):
_invalid_source_hash_format()
ret["hsum"] = source_hash
source_hash_len = len(source_hash)
@ -964,10 +959,7 @@ def check_hash(path, file_hash):
file_hash,
hash_len,
", ".join(
[
"{} ({})".format(HASHES_REVMAP[x], x)
for x in sorted(HASHES_REVMAP)
]
[f"{HASHES_REVMAP[x]} ({x})" for x in sorted(HASHES_REVMAP)]
),
)
)
@ -1097,7 +1089,7 @@ def find(path, *args, **kwargs):
try:
finder = salt.utils.find.Finder(kwargs)
except ValueError as ex:
return "error: {}".format(ex)
return f"error: {ex}"
ret = [
item
@ -1192,11 +1184,11 @@ def sed(
options = options.replace("-r", "-E")
cmd = ["sed"]
cmd.append("-i{}".format(backup) if backup else "-i")
cmd.append(f"-i{backup}" if backup else "-i")
cmd.extend(salt.utils.args.shlex_split(options))
cmd.append(
r"{limit}{negate_match}s/{before}/{after}/{flags}".format(
limit="/{}/ ".format(limit) if limit else "",
limit=f"/{limit}/ " if limit else "",
negate_match="!" if negate_match else "",
before=before,
after=after,
@ -1240,9 +1232,9 @@ def sed_contains(path, text, limit="", flags="g"):
cmd.extend(salt.utils.args.shlex_split(options))
cmd.append(
r"{limit}s/{before}/$/{flags}".format(
limit="/{}/ ".format(limit) if limit else "",
limit=f"/{limit}/ " if limit else "",
before=before,
flags="p{}".format(flags),
flags=f"p{flags}",
)
)
cmd.append(path)
@ -1323,10 +1315,10 @@ def psed(
# The pattern to replace with does not need to be escaped
limit = _sed_esc(limit, escape_all)
shutil.copy2(path, "{}{}".format(path, backup))
shutil.copy2(path, f"{path}{backup}")
with salt.utils.files.fopen(path, "w") as ofile:
with salt.utils.files.fopen("{}{}".format(path, backup), "r") as ifile:
with salt.utils.files.fopen(f"{path}{backup}", "r") as ifile:
if multi is True:
for line in ifile.readline():
ofile.write(
@ -1509,12 +1501,12 @@ def comment_line(path, regex, char="#", cmnt=True, backup=".bak"):
# Make sure the file exists
if not os.path.isfile(path):
raise SaltInvocationError("File not found: {}".format(path))
raise SaltInvocationError(f"File not found: {path}")
# Make sure it is a text file
if not __utils__["files.is_text"](path):
raise SaltInvocationError(
"Cannot perform string replacements on a binary file: {}".format(path)
f"Cannot perform string replacements on a binary file: {path}"
)
# First check the whole file, determine whether to make the replacement
@ -1536,14 +1528,12 @@ def comment_line(path, regex, char="#", cmnt=True, backup=".bak"):
# Load lines into dictionaries, set found to True
orig_file.append(line)
if cmnt:
new_file.append("{}{}".format(char, line))
new_file.append(f"{char}{line}")
else:
new_file.append(line.lstrip(char))
found = True
except OSError as exc:
raise CommandExecutionError(
"Unable to open file '{}'. Exception: {}".format(path, exc)
)
raise CommandExecutionError(f"Unable to open file '{path}'. Exception: {exc}")
# We've searched the whole file. If we didn't find anything, return False
if not found:
@ -1558,7 +1548,7 @@ def comment_line(path, regex, char="#", cmnt=True, backup=".bak"):
try:
temp_file = _mkstemp_copy(path=path, preserve_inode=False)
except OSError as exc:
raise CommandExecutionError("Exception: {}".format(exc))
raise CommandExecutionError(f"Exception: {exc}")
try:
# Open the file in write mode
@ -1577,7 +1567,7 @@ def comment_line(path, regex, char="#", cmnt=True, backup=".bak"):
if re.match(regex, line):
# Write the new line
if cmnt:
wline = "{}{}".format(char, line)
wline = f"{char}{line}"
else:
wline = line.lstrip(char)
else:
@ -1593,13 +1583,13 @@ def comment_line(path, regex, char="#", cmnt=True, backup=".bak"):
"Exception: {}".format(path, temp_file, exc)
)
except OSError as exc:
raise CommandExecutionError("Exception: {}".format(exc))
raise CommandExecutionError(f"Exception: {exc}")
except OSError as exc:
raise CommandExecutionError("Exception: {}".format(exc))
raise CommandExecutionError(f"Exception: {exc}")
if backup:
# Move the backup file to the original directory
backup_name = "{}{}".format(path, backup)
backup_name = f"{path}{backup}"
try:
shutil.move(temp_file, backup_name)
except OSError as exc:
@ -1686,9 +1676,7 @@ def _mkstemp_copy(path, preserve_inode=True):
try:
temp_file = salt.utils.files.mkstemp(prefix=salt.utils.files.TEMPFILE_PREFIX)
except OSError as exc:
raise CommandExecutionError(
"Unable to create temp file. Exception: {}".format(exc)
)
raise CommandExecutionError(f"Unable to create temp file. Exception: {exc}")
# use `copy` to preserve the inode of the
# original file, and thus preserve hardlinks
# to the inode. otherwise, use `move` to
@ -1727,7 +1715,7 @@ def _regex_to_static(src, regex):
compiled = re.compile(regex, re.DOTALL)
src = [line for line in src if compiled.search(line) or line.count(regex)]
except Exception as ex: # pylint: disable=broad-except
raise CommandExecutionError("{}: '{}'".format(_get_error_message(ex), regex))
raise CommandExecutionError(f"{_get_error_message(ex)}: '{regex}'")
return src
@ -1748,7 +1736,7 @@ def _assert_occurrence(probe, target, amount=1):
if msg:
raise CommandExecutionError(
'Found {} expected occurrences in "{}" expression'.format(msg, target)
f'Found {msg} expected occurrences in "{target}" expression'
)
return occ
@ -1859,7 +1847,7 @@ def _set_line(
"Mode was not defined. How to process the file?"
)
else:
raise CommandExecutionError("Unknown mode: {}".format(mode))
raise CommandExecutionError(f"Unknown mode: {mode}")
if mode != "delete" and content is None:
raise CommandExecutionError("Content can only be empty if mode is delete")
@ -2235,7 +2223,7 @@ def line(
if not os.path.isfile(path):
if not quiet:
raise CommandExecutionError(
'File "{}" does not exists or is not a file.'.format(path)
f'File "{path}" does not exists or is not a file.'
)
return False # No changes had happened
@ -2246,7 +2234,7 @@ def line(
"Mode was not defined. How to process the file?"
)
else:
raise CommandExecutionError('Unknown mode: "{}"'.format(mode))
raise CommandExecutionError(f'Unknown mode: "{mode}"')
# We've set the content to be empty in the function params but we want to make sure
# it gets passed when needed. Feature #37092
@ -2494,11 +2482,11 @@ def replace(
if ignore_if_missing:
return False
else:
raise SaltInvocationError("File not found: {}".format(path))
raise SaltInvocationError(f"File not found: {path}")
if not __utils__["files.is_text"](path):
raise SaltInvocationError(
"Cannot perform string replacements on a binary file: {}".format(path)
f"Cannot perform string replacements on a binary file: {path}"
)
if search_only and (append_if_not_found or prepend_if_not_found):
@ -2577,7 +2565,7 @@ def replace(
# content if it was pre/appended in a previous run.
if re.search(
salt.utils.stringutils.to_bytes(
"^{}($|(?=\r\n))".format(re.escape(content))
f"^{re.escape(content)}($|(?=\r\n))"
),
r_data,
flags=re_flags,
@ -2595,9 +2583,7 @@ def replace(
has_changes = False
except OSError as exc:
raise CommandExecutionError(
"Unable to open file '{}'. Exception: {}".format(path, exc)
)
raise CommandExecutionError(f"Unable to open file '{path}'. Exception: {exc}")
finally:
if r_data and isinstance(r_data, mmap.mmap):
r_data.close()
@ -2608,7 +2594,7 @@ def replace(
# Create a copy to read from and to use as a backup later
temp_file = _mkstemp_copy(path=path, preserve_inode=preserve_inode)
except OSError as exc:
raise CommandExecutionError("Exception: {}".format(exc))
raise CommandExecutionError(f"Exception: {exc}")
r_data = None
try:
@ -2636,12 +2622,12 @@ def replace(
"Exception: {}".format(path, temp_file, exc)
)
except OSError as exc:
raise CommandExecutionError("Exception: {}".format(exc))
raise CommandExecutionError(f"Exception: {exc}")
finally:
if r_data and isinstance(r_data, mmap.mmap):
r_data.close()
except OSError as exc:
raise CommandExecutionError("Exception: {}".format(exc))
raise CommandExecutionError(f"Exception: {exc}")
if not found and (append_if_not_found or prepend_if_not_found):
if not_found_content is None:
@ -2667,7 +2653,7 @@ def replace(
# Create a copy to read from and for later use as a backup
temp_file = _mkstemp_copy(path=path, preserve_inode=preserve_inode)
except OSError as exc:
raise CommandExecutionError("Exception: {}".format(exc))
raise CommandExecutionError(f"Exception: {exc}")
# write new content in the file while avoiding partial reads
try:
fh_ = salt.utils.atomicfile.atomic_open(path, "wb")
@ -2679,7 +2665,7 @@ def replace(
if backup and has_changes and not dry_run:
# keep the backup only if it was requested
# and only if there were any changes
backup_name = "{}{}".format(path, backup)
backup_name = f"{path}{backup}"
try:
shutil.move(temp_file, backup_name)
except OSError as exc:
@ -2689,8 +2675,8 @@ def replace(
"Exception: {}".format(path, temp_file, exc)
)
if symlink:
symlink_backup = "{}{}".format(given_path, backup)
target_backup = "{}{}".format(target_path, backup)
symlink_backup = f"{given_path}{backup}"
target_backup = f"{target_path}{backup}"
# Always clobber any existing symlink backup
# to match the behaviour of the 'backup' option
try:
@ -2709,7 +2695,7 @@ def replace(
os.remove(temp_file)
except OSError as exc:
raise CommandExecutionError(
"Unable to delete temp file '{}'. Exception: {}".format(temp_file, exc)
f"Unable to delete temp file '{temp_file}'. Exception: {exc}"
)
if not dry_run and not salt.utils.platform.is_windows():
@ -2848,7 +2834,7 @@ def blockreplace(
path = os.path.expanduser(path)
if not os.path.exists(path):
raise SaltInvocationError("File not found: {}".format(path))
raise SaltInvocationError(f"File not found: {path}")
try:
file_encoding = __utils__["files.get_encoding"](path)
@ -2858,7 +2844,7 @@ def blockreplace(
if __utils__["files.is_binary"](path):
if not file_encoding:
raise SaltInvocationError(
"Cannot perform string replacements on a binary file: {}".format(path)
f"Cannot perform string replacements on a binary file: {path}"
)
if insert_before_match or insert_after_match:
@ -2970,7 +2956,7 @@ def blockreplace(
new_file.append(line)
except OSError as exc:
raise CommandExecutionError("Failed to read from {}: {}".format(path, exc))
raise CommandExecutionError(f"Failed to read from {path}: {exc}")
finally:
if linesep is None:
# If the file was empty, we will not have set linesep yet. Assume
@ -3035,7 +3021,7 @@ def blockreplace(
# backup old content
if backup is not False:
backup_path = "{}{}".format(path, backup)
backup_path = f"{path}{backup}"
shutil.copy2(path, backup_path)
# copy2 does not preserve ownership
if salt.utils.platform.is_windows():
@ -3070,7 +3056,7 @@ def blockreplace(
# backup old content
if backup is not False:
backup_path = "{}{}".format(path, backup)
backup_path = f"{path}{backup}"
shutil.copy2(path, backup_path)
# copy2 does not preserve ownership
if salt.utils.platform.is_windows():
@ -3403,11 +3389,9 @@ def append(path, *args, **kwargs):
# Append lines in text mode
with salt.utils.files.fopen(path, "a") as ofile:
for new_line in args:
ofile.write(
salt.utils.stringutils.to_str("{}{}".format(new_line, os.linesep))
)
ofile.write(salt.utils.stringutils.to_str(f"{new_line}{os.linesep}"))
return 'Wrote {} lines to "{}"'.format(len(args), path)
return f'Wrote {len(args)} lines to "{path}"'
def prepend(path, *args, **kwargs):
@ -3461,12 +3445,12 @@ def prepend(path, *args, **kwargs):
preface = []
for line in args:
preface.append("{}\n".format(line))
preface.append(f"{line}\n")
with salt.utils.files.fopen(path, "w") as ofile:
contents = preface + contents
ofile.write(salt.utils.stringutils.to_str("".join(contents)))
return 'Prepended {} lines to "{}"'.format(len(args), path)
return f'Prepended {len(args)} lines to "{path}"'
def write(path, *args, **kwargs):
@ -3511,10 +3495,10 @@ def write(path, *args, **kwargs):
contents = []
for line in args:
contents.append("{}\n".format(line))
contents.append(f"{line}\n")
with salt.utils.files.fopen(path, "w") as ofile:
ofile.write(salt.utils.stringutils.to_str("".join(contents)))
return 'Wrote {} lines to "{}"'.format(len(contents), path)
return f'Wrote {len(contents)} lines to "{path}"'
def touch(name, atime=None, mtime=None):
@ -3675,7 +3659,7 @@ def link(src, path):
os.link(src, path)
return True
except OSError as E:
raise CommandExecutionError("Could not create '{}': {}".format(path, E))
raise CommandExecutionError(f"Could not create '{path}': {E}")
return False
@ -3715,7 +3699,7 @@ def is_link(path):
return os.path.islink(os.path.expanduser(path))
def symlink(src, path, force=False, atomic=False):
def symlink(src, path, force=False, atomic=False, follow_symlinks=True):
"""
Create a symbolic link (symlink, soft link) to a file
@ -3733,6 +3717,11 @@ def symlink(src, path, force=False, atomic=False):
Use atomic file operations to create the symlink
.. versionadded:: 3006.0
follow_symlinks (bool):
If set to ``False``, use ``os.path.lexists()`` for existence checks
instead of ``os.path.exists()``.
.. versionadded:: 3007.0
Returns:
bool: ``True`` if successful, otherwise raises ``CommandExecutionError``
@ -3744,8 +3733,13 @@ def symlink(src, path, force=False, atomic=False):
"""
path = os.path.expanduser(path)
if follow_symlinks:
exists = os.path.exists
else:
exists = os.path.lexists
if not os.path.isabs(path):
raise SaltInvocationError("Link path must be absolute: {}".format(path))
raise SaltInvocationError(f"Link path must be absolute: {path}")
if os.path.islink(path):
try:
@ -3758,14 +3752,14 @@ def symlink(src, path, force=False, atomic=False):
pass
if not force and not atomic:
msg = "Found existing symlink: {}".format(path)
msg = f"Found existing symlink: {path}"
raise CommandExecutionError(msg)
if os.path.exists(path) and not force and not atomic:
msg = "Existing path is not a symlink: {}".format(path)
if exists(path) and not force and not atomic:
msg = f"Existing path is not a symlink: {path}"
raise CommandExecutionError(msg)
if (os.path.islink(path) or os.path.exists(path)) and force and not atomic:
if (os.path.islink(path) or exists(path)) and force and not atomic:
os.unlink(path)
elif atomic:
link_dir = os.path.dirname(path)
@ -3782,13 +3776,13 @@ def symlink(src, path, force=False, atomic=False):
return True
except OSError:
os.remove(temp_link)
raise CommandExecutionError("Could not create '{}'".format(path))
raise CommandExecutionError(f"Could not create '{path}'")
try:
os.symlink(src, path)
return True
except OSError:
raise CommandExecutionError("Could not create '{}'".format(path))
raise CommandExecutionError(f"Could not create '{path}'")
def rename(src, dst):
@ -3811,7 +3805,7 @@ def rename(src, dst):
os.rename(src, dst)
return True
except OSError:
raise CommandExecutionError("Could not rename '{}' to '{}'".format(src, dst))
raise CommandExecutionError(f"Could not rename '{src}' to '{dst}'")
return False
@ -3849,7 +3843,7 @@ def copy(src, dst, recurse=False, remove_existing=False):
raise SaltInvocationError("File path must be absolute.")
if not os.path.exists(src):
raise CommandExecutionError("No such file or directory '{}'".format(src))
raise CommandExecutionError(f"No such file or directory '{src}'")
if not salt.utils.platform.is_windows():
pre_user = get_user(src)
@ -3872,7 +3866,7 @@ def copy(src, dst, recurse=False, remove_existing=False):
else:
shutil.copyfile(src, dst)
except OSError:
raise CommandExecutionError("Could not copy '{}' to '{}'".format(src, dst))
raise CommandExecutionError(f"Could not copy '{src}' to '{dst}'")
if not salt.utils.platform.is_windows():
check_perms(dst, None, pre_user, pre_group, pre_mode)
@ -4014,10 +4008,10 @@ def readlink(path, canonicalize=False):
path = os.path.expandvars(path)
if not os.path.isabs(path):
raise SaltInvocationError("Path to link must be absolute: {}".format(path))
raise SaltInvocationError(f"Path to link must be absolute: {path}")
if not os.path.islink(path):
raise SaltInvocationError("A valid link was not specified: {}".format(path))
raise SaltInvocationError(f"A valid link was not specified: {path}")
if canonicalize:
return os.path.realpath(path)
@ -4026,7 +4020,7 @@ def readlink(path, canonicalize=False):
return salt.utils.path.readlink(path)
except OSError as exc:
if exc.errno == errno.EINVAL:
raise CommandExecutionError("Not a symbolic link: {}".format(path))
raise CommandExecutionError(f"Not a symbolic link: {path}")
raise CommandExecutionError(exc.__str__())
@ -4090,7 +4084,7 @@ def statvfs(path):
)
}
except OSError:
raise CommandExecutionError("Could not statvfs '{}'".format(path))
raise CommandExecutionError(f"Could not statvfs '{path}'")
return False
@ -4118,7 +4112,7 @@ def stats(path, hash_type=None, follow_symlinks=True):
# message in this exception. Any changes made to the message for this
# exception will reflect the file.directory state as well, and will
# likely require changes there.
raise CommandExecutionError("Path not found: {}".format(path))
raise CommandExecutionError(f"Path not found: {path}")
else:
if follow_symlinks:
pstat = os.stat(path)
@ -4260,7 +4254,7 @@ def remove(path, **kwargs):
path = os.path.expanduser(path)
if not os.path.isabs(path):
raise SaltInvocationError("File path must be absolute: {}".format(path))
raise SaltInvocationError(f"File path must be absolute: {path}")
try:
if os.path.islink(path) or (os.path.exists(path) and not os.path.isdir(path)):
@ -4270,7 +4264,7 @@ def remove(path, **kwargs):
shutil.rmtree(path)
return True
except OSError as exc:
raise CommandExecutionError("Could not remove '{}': {}".format(path, exc))
raise CommandExecutionError(f"Could not remove '{path}': {exc}")
return False
@ -4352,7 +4346,7 @@ def get_selinux_context(path):
if cmd_ret["retcode"] == 0:
ret = cmd_ret["stdout"]
else:
ret = "No selinux context information is available for {}".format(path)
ret = f"No selinux context information is available for {path}"
return ret
@ -4388,9 +4382,7 @@ def set_selinux_context(
)
if fcontext_result.get("retcode", None) != 0:
# Problem setting fcontext policy
raise CommandExecutionError(
"Problem setting fcontext: {}".format(fcontext_result)
)
raise CommandExecutionError(f"Problem setting fcontext: {fcontext_result}")
cmd = ["chcon"]
if user:
@ -4420,7 +4412,7 @@ def source_list(source, source_hash, saltenv):
salt '*' file.source_list salt://http/httpd.conf '{hash_type: 'md5', 'hsum': <md5sum>}' base
"""
contextkey = "{}_|-{}_|-{}".format(source, source_hash, saltenv)
contextkey = f"{source}_|-{source_hash}_|-{saltenv}"
if contextkey in __context__:
return __context__[contextkey]
@ -4700,12 +4692,12 @@ def get_managed(
if parsed_scheme == "":
parsed_path = sfn = source
if not os.path.exists(sfn):
msg = "Local file source {} does not exist".format(sfn)
msg = f"Local file source {sfn} does not exist"
return "", {}, msg
elif parsed_scheme == "file":
sfn = parsed_path
if not os.path.exists(sfn):
msg = "Local file source {} does not exist".format(sfn)
msg = f"Local file source {sfn} does not exist"
return "", {}, msg
if parsed_scheme and parsed_scheme.lower() in string.ascii_lowercase:
@ -4718,7 +4710,7 @@ def get_managed(
return (
"",
{},
"Source file {} not found in saltenv '{}'".format(source, saltenv),
f"Source file {source} not found in saltenv '{saltenv}'",
)
elif not source_hash and unix_local_source:
source_sum = _get_local_file_source_sum(parsed_path)
@ -4782,13 +4774,13 @@ def get_managed(
# A 404 or other error code may raise an exception, catch it
# and return a comment that will fail the calling state.
_source = salt.utils.url.redact_http_basic_auth(source)
return "", {}, "Failed to cache {}: {}".format(_source, exc)
return "", {}, f"Failed to cache {_source}: {exc}"
# If cache failed, sfn will be False, so do a truth check on sfn first
# as invoking os.path.exists() on a bool raises a TypeError.
if not sfn or not os.path.exists(sfn):
_source = salt.utils.url.redact_http_basic_auth(source)
return sfn, {}, "Source file '{}' not found".format(_source)
return sfn, {}, f"Source file '{_source}' not found"
if sfn == name:
raise SaltInvocationError("Source file cannot be the same as destination")
@ -4817,7 +4809,7 @@ def get_managed(
return (
sfn,
{},
"Specified template format {} is not supported".format(template),
f"Specified template format {template} is not supported",
)
if data["result"]:
@ -4890,7 +4882,7 @@ def extract_hash(
hash_type,
)
hash_type = ""
hash_len_expr = "{},{}".format(min(HASHES_REVMAP), max(HASHES_REVMAP))
hash_len_expr = f"{min(HASHES_REVMAP)},{max(HASHES_REVMAP)}"
else:
hash_len_expr = str(hash_len)
@ -5195,7 +5187,7 @@ def check_perms(
ret["changes"]["user"] = user
else:
ret["result"] = False
ret["comment"].append("Failed to change user to {}".format(user))
ret["comment"].append(f"Failed to change user to {user}")
elif "cuser" in perms:
ret["changes"]["user"] = user
@ -5211,7 +5203,7 @@ def check_perms(
ret["changes"]["group"] = group
else:
ret["result"] = False
ret["comment"].append("Failed to change group to {}".format(group))
ret["comment"].append(f"Failed to change group to {group}")
elif "cgroup" in perms:
ret["changes"]["group"] = group
@ -5224,7 +5216,7 @@ def check_perms(
ret["changes"]["mode"] = mode
else:
ret["result"] = False
ret["comment"].append("Failed to change mode to {}".format(mode))
ret["comment"].append(f"Failed to change mode to {mode}")
elif "cmode" in perms:
ret["changes"]["mode"] = mode
@ -5257,9 +5249,7 @@ def check_perms(
cmp_attrs = _cmp_attrs(name, attrs)
if any(attr for attr in cmp_attrs):
ret["result"] = False
ret["comment"].append(
"Failed to change attributes to {}".format(attrs)
)
ret["comment"].append(f"Failed to change attributes to {attrs}")
changes["new"] = "".join(lsattr(name)[name])
else:
changes["new"] = attrs
@ -5314,17 +5304,17 @@ def check_perms(
selinux_change_new = ""
selinux_change_orig = ""
if requested_seuser:
selinux_change_new += "User: {} ".format(requested_seuser)
selinux_change_orig += "User: {} ".format(current_seuser)
selinux_change_new += f"User: {requested_seuser} "
selinux_change_orig += f"User: {current_seuser} "
if requested_serole:
selinux_change_new += "Role: {} ".format(requested_serole)
selinux_change_orig += "Role: {} ".format(current_serole)
selinux_change_new += f"Role: {requested_serole} "
selinux_change_orig += f"Role: {current_serole} "
if requested_setype:
selinux_change_new += "Type: {} ".format(requested_setype)
selinux_change_orig += "Type: {} ".format(current_setype)
selinux_change_new += f"Type: {requested_setype} "
selinux_change_orig += f"Type: {current_setype} "
if requested_serange:
selinux_change_new += "Range: {} ".format(requested_serange)
selinux_change_orig += "Range: {} ".format(current_serange)
selinux_change_new += f"Range: {requested_serange} "
selinux_change_orig += f"Range: {current_serange} "
if __opts__["test"]:
ret["comment"] = "File {} selinux context to be updated".format(
@ -5364,9 +5354,7 @@ def check_perms(
selinux_error = True
if not selinux_error:
ret["comment"].append(
"The file {} is set to be changed".format(name)
)
ret["comment"].append(f"The file {name} is set to be changed")
if requested_seuser:
if current_seuser != requested_seuser:
@ -5498,9 +5486,9 @@ def check_managed(
if changes:
log.info(changes)
comments = ["The following values are set to be changed:\n"]
comments.extend("{}: {}\n".format(key, val) for key, val in changes.items())
comments.extend(f"{key}: {val}\n" for key, val in changes.items())
return None, "".join(comments)
return True, "The file {} is in the correct state".format(name)
return True, f"The file {name} is in the correct state"
def check_managed_changes(
@ -6148,7 +6136,7 @@ def manage_file(
# File is not present, cache it
sfn = __salt__["cp.cache_file"](source, saltenv, verify_ssl=verify_ssl)
if not sfn:
return _error(ret, "Source file '{}' not found".format(source))
return _error(ret, f"Source file '{source}' not found")
htype = source_sum.get("hash_type", __opts__["hash_type"])
# Recalculate source sum now that file has been cached
source_sum = {"hash_type": htype, "hsum": get_hash(sfn, form=htype)}
@ -6185,7 +6173,7 @@ def manage_file(
source, saltenv, verify_ssl=verify_ssl, use_etag=use_etag
)
if not sfn:
return _error(ret, "Source file '{}' not found".format(source))
return _error(ret, f"Source file '{source}' not found")
# If the downloaded file came from a non salt server or local
# source, and we are not skipping checksum verification, then
# verify that it matches the specified checksum.
@ -6227,7 +6215,7 @@ def manage_file(
)
except OSError as io_error:
__clean_tmp(sfn)
return _error(ret, "Failed to commit change: {}".format(io_error))
return _error(ret, f"Failed to commit change: {io_error}")
if contents is not None:
# Write the static contents to a temporary file
@ -6258,7 +6246,7 @@ def manage_file(
except CommandExecutionError as exc:
ret.setdefault("warnings", []).append(
"Failed to detect changes to file: {}".format(exc.strerror)
f"Failed to detect changes to file: {exc.strerror}"
)
differences = ""
@ -6275,7 +6263,7 @@ def manage_file(
)
except OSError as io_error:
__clean_tmp(tmp)
return _error(ret, "Failed to commit change: {}".format(io_error))
return _error(ret, f"Failed to commit change: {io_error}")
__clean_tmp(tmp)
# Check for changing symlink to regular file here
@ -6283,7 +6271,7 @@ def manage_file(
if not sfn:
sfn = __salt__["cp.cache_file"](source, saltenv, verify_ssl=verify_ssl)
if not sfn:
return _error(ret, "Source file '{}' not found".format(source))
return _error(ret, f"Source file '{source}' not found")
# If the downloaded file came from a non salt server source verify
# that it matches the intended sum value
if check_web_source_hash:
@ -6307,7 +6295,7 @@ def manage_file(
)
except OSError as io_error:
__clean_tmp(sfn)
return _error(ret, "Failed to commit change: {}".format(io_error))
return _error(ret, f"Failed to commit change: {io_error}")
ret["changes"]["diff"] = "Replace symbolic link with regular file"
@ -6341,7 +6329,7 @@ def manage_file(
)
if ret["changes"]:
ret["comment"] = "File {} updated".format(salt.utils.data.decode(name))
ret["comment"] = f"File {salt.utils.data.decode(name)} updated"
elif not ret["changes"] and ret["result"]:
ret["comment"] = "File {} is in the correct state".format(
@ -6359,7 +6347,7 @@ def manage_file(
drive, _ = os.path.splitdrive(name)
if drive and not os.path.exists(drive):
__clean_tmp(sfn)
return _error(ret, "{} drive not present".format(drive))
return _error(ret, f"{drive} drive not present")
if dir_mode is None and mode is not None:
# Add execute bit to each nonzero digit in the mode, if
# dir_mode was not specified. Otherwise, any
@ -6392,7 +6380,7 @@ def manage_file(
if not sfn:
sfn = __salt__["cp.cache_file"](source, saltenv, verify_ssl=verify_ssl)
if not sfn:
return _error(ret, "Source file '{}' not found".format(source))
return _error(ret, f"Source file '{source}' not found")
# If the downloaded file came from a non salt server source verify
# that it matches the intended sum value
if check_web_source_hash:
@ -6433,16 +6421,16 @@ def manage_file(
if contents is None:
if not __opts__["test"]:
if touch(name):
ret["changes"]["new"] = "file {} created".format(name)
ret["changes"]["new"] = f"file {name} created"
ret["comment"] = "Empty file"
else:
return _error(ret, "Empty file {} not created".format(name))
return _error(ret, f"Empty file {name} not created")
else:
if not __opts__["test"]:
if touch(name):
ret["changes"]["diff"] = "New file"
else:
return _error(ret, "File {} not created".format(name))
return _error(ret, f"File {name} not created")
if contents is not None:
# Write the static contents to a temporary file
@ -6575,12 +6563,12 @@ def makedirs_(path, user=None, group=None, mode=None):
if os.path.isdir(dirname):
# There's nothing for us to do
msg = "Directory '{}' already exists".format(dirname)
msg = f"Directory '{dirname}' already exists"
log.debug(msg)
return msg
if os.path.exists(dirname):
msg = "The path '{}' already exists and is not a directory".format(dirname)
msg = f"The path '{dirname}' already exists and is not a directory"
log.debug(msg)
return msg
@ -6634,7 +6622,7 @@ def makedirs_perms(name, user=None, group=None, mode="0755"):
if tail == os.curdir: # xxx/newdir/. exists if xxx/newdir exists
return
os.mkdir(name)
check_perms(name, None, user, group, int("{}".format(mode)) if mode else None)
check_perms(name, None, user, group, int(f"{mode}") if mode else None)
def get_devmm(name):
@ -6704,7 +6692,7 @@ def mknod_chrdev(name, major, minor, user=None, group=None, mode="0660"):
)
try:
if __opts__["test"]:
ret["changes"] = {"new": "Character device {} created.".format(name)}
ret["changes"] = {"new": f"Character device {name} created."}
ret["result"] = None
else:
if (
@ -6715,7 +6703,7 @@ def mknod_chrdev(name, major, minor, user=None, group=None, mode="0660"):
)
is None
):
ret["changes"] = {"new": "Character device {} created.".format(name)}
ret["changes"] = {"new": f"Character device {name} created."}
ret["result"] = True
except OSError as exc:
# be happy it is already there....however, if you are trying to change the
@ -6723,9 +6711,9 @@ def mknod_chrdev(name, major, minor, user=None, group=None, mode="0660"):
if exc.errno != errno.EEXIST:
raise
else:
ret["comment"] = "File {} exists and cannot be overwritten".format(name)
ret["comment"] = f"File {name} exists and cannot be overwritten"
# quick pass at verifying the permissions of the newly created character device
check_perms(name, None, user, group, int("{}".format(mode)) if mode else None)
check_perms(name, None, user, group, int(f"{mode}") if mode else None)
return ret
@ -6777,7 +6765,7 @@ def mknod_blkdev(name, major, minor, user=None, group=None, mode="0660"):
)
try:
if __opts__["test"]:
ret["changes"] = {"new": "Block device {} created.".format(name)}
ret["changes"] = {"new": f"Block device {name} created."}
ret["result"] = None
else:
if (
@ -6788,7 +6776,7 @@ def mknod_blkdev(name, major, minor, user=None, group=None, mode="0660"):
)
is None
):
ret["changes"] = {"new": "Block device {} created.".format(name)}
ret["changes"] = {"new": f"Block device {name} created."}
ret["result"] = True
except OSError as exc:
# be happy it is already there....however, if you are trying to change the
@ -6796,9 +6784,9 @@ def mknod_blkdev(name, major, minor, user=None, group=None, mode="0660"):
if exc.errno != errno.EEXIST:
raise
else:
ret["comment"] = "File {} exists and cannot be overwritten".format(name)
ret["comment"] = f"File {name} exists and cannot be overwritten"
# quick pass at verifying the permissions of the newly created block device
check_perms(name, None, user, group, int("{}".format(mode)) if mode else None)
check_perms(name, None, user, group, int(f"{mode}") if mode else None)
return ret
@ -6844,20 +6832,20 @@ def mknod_fifo(name, user=None, group=None, mode="0660"):
log.debug("Creating FIFO name: %s", name)
try:
if __opts__["test"]:
ret["changes"] = {"new": "Fifo pipe {} created.".format(name)}
ret["changes"] = {"new": f"Fifo pipe {name} created."}
ret["result"] = None
else:
if os.mkfifo(name, int(str(mode).lstrip("0Oo"), 8)) is None:
ret["changes"] = {"new": "Fifo pipe {} created.".format(name)}
ret["changes"] = {"new": f"Fifo pipe {name} created."}
ret["result"] = True
except OSError as exc:
# be happy it is already there
if exc.errno != errno.EEXIST:
raise
else:
ret["comment"] = "File {} exists and cannot be overwritten".format(name)
ret["comment"] = f"File {name} exists and cannot be overwritten"
# quick pass at verifying the permissions of the newly created fifo
check_perms(name, None, user, group, int("{}".format(mode)) if mode else None)
check_perms(name, None, user, group, int(f"{mode}") if mode else None)
return ret
@ -6939,9 +6927,9 @@ def list_backups(path, limit=None):
]:
if salt.utils.platform.is_windows():
# ':' is an illegal filesystem path character on Windows
strpfmt = "{}_%a_%b_%d_%H-%M-%S_%f_%Y".format(basename)
strpfmt = f"{basename}_%a_%b_%d_%H-%M-%S_%f_%Y"
else:
strpfmt = "{}_%a_%b_%d_%H:%M:%S_%f_%Y".format(basename)
strpfmt = f"{basename}_%a_%b_%d_%H:%M:%S_%f_%Y"
try:
timestamp = datetime.datetime.strptime(fname, strpfmt)
except ValueError:
@ -7017,7 +7005,7 @@ def list_backups_dir(path, limit=None):
for x in sorted(ff):
basename = x.split("_")[0]
if i == basename:
strpfmt = "{}_%a_%b_%d_%H:%M:%S_%f_%Y".format(basename)
strpfmt = f"{basename}_%a_%b_%d_%H:%M:%S_%f_%Y"
try:
timestamp = datetime.datetime.strptime(x, strpfmt)
except ValueError:
@ -7067,7 +7055,7 @@ def restore_backup(path, backup_id):
# Note: This only supports minion backups, so this function will need to be
# modified if/when master backups are implemented.
ret = {"result": False, "comment": "Invalid backup_id '{}'".format(backup_id)}
ret = {"result": False, "comment": f"Invalid backup_id '{backup_id}'"}
try:
if len(str(backup_id)) == len(str(int(backup_id))):
backup = list_backups(path)[int(backup_id)]
@ -7076,7 +7064,7 @@ def restore_backup(path, backup_id):
except ValueError:
return ret
except KeyError:
ret["comment"] = "backup_id '{}' does not exist for {}".format(backup_id, path)
ret["comment"] = f"backup_id '{backup_id}' does not exist for {path}"
return ret
salt.utils.files.backup_minion(path, _get_bkroot())
@ -7126,7 +7114,7 @@ def delete_backup(path, backup_id):
"""
path = os.path.expanduser(path)
ret = {"result": False, "comment": "Invalid backup_id '{}'".format(backup_id)}
ret = {"result": False, "comment": f"Invalid backup_id '{backup_id}'"}
try:
if len(str(backup_id)) == len(str(int(backup_id))):
backup = list_backups(path)[int(backup_id)]
@ -7135,7 +7123,7 @@ def delete_backup(path, backup_id):
except ValueError:
return ret
except KeyError:
ret["comment"] = "backup_id '{}' does not exist for {}".format(backup_id, path)
ret["comment"] = f"backup_id '{backup_id}' does not exist for {path}"
return ret
try:
@ -7253,9 +7241,9 @@ def open_files(by_pid=False):
# Then we look at the open files for each PID
files = {}
for pid in pids:
ppath = "/proc/{}".format(pid)
ppath = f"/proc/{pid}"
try:
tids = os.listdir("{}/task".format(ppath))
tids = os.listdir(f"{ppath}/task")
except OSError:
continue
@ -7267,17 +7255,17 @@ def open_files(by_pid=False):
# except Exception: # pylint: disable=broad-except
# pass
for fpath in os.listdir("{}/fd".format(ppath)):
fd_.append("{}/fd/{}".format(ppath, fpath))
for fpath in os.listdir(f"{ppath}/fd"):
fd_.append(f"{ppath}/fd/{fpath}")
for tid in tids:
try:
fd_.append(os.path.realpath("{}/task/{}/exe".format(ppath, tid)))
fd_.append(os.path.realpath(f"{ppath}/task/{tid}/exe"))
except OSError:
continue
for tpath in os.listdir("{}/task/{}/fd".format(ppath, tid)):
fd_.append("{}/task/{}/fd/{}".format(ppath, tid, tpath))
for tpath in os.listdir(f"{ppath}/task/{tid}/fd"):
fd_.append(f"{ppath}/task/{tid}/fd/{tpath}")
fd_ = sorted(set(fd_))
@ -7454,15 +7442,13 @@ def move(src, dst, disallow_copy_and_unlink=False):
ret = {
"result": True,
"comment": "'{}' moved to '{}'".format(src, dst),
"comment": f"'{src}' moved to '{dst}'",
}
try:
shutil.move(src, dst)
except OSError as exc:
raise CommandExecutionError(
"Unable to move '{}' to '{}': {}".format(src, dst, exc)
)
raise CommandExecutionError(f"Unable to move '{src}' to '{dst}': {exc}")
return ret

View file

@ -259,7 +259,7 @@ def gid_to_group(gid):
salt '*' file.gid_to_group S-1-5-21-626487655-2533044672-482107328-1010
"""
func_name = "{}.gid_to_group".format(__virtualname__)
func_name = f"{__virtualname__}.gid_to_group"
if __opts__.get("fun", "") == func_name:
log.info(
"The function %s should not be used on Windows systems; "
@ -294,7 +294,7 @@ def group_to_gid(group):
salt '*' file.group_to_gid administrators
"""
func_name = "{}.group_to_gid".format(__virtualname__)
func_name = f"{__virtualname__}.group_to_gid"
if __opts__.get("fun", "") == func_name:
log.info(
"The function %s should not be used on Windows systems; "
@ -336,7 +336,7 @@ def get_pgid(path, follow_symlinks=True):
salt '*' file.get_pgid c:\\temp\\test.txt
"""
if not os.path.exists(path):
raise CommandExecutionError("Path not found: {}".format(path))
raise CommandExecutionError(f"Path not found: {path}")
# Under Windows, if the path is a symlink, the user that owns the symlink is
# returned, not the user that owns the file/directory the symlink is
@ -420,7 +420,7 @@ def get_gid(path, follow_symlinks=True):
salt '*' file.get_gid c:\\temp\\test.txt
"""
func_name = "{}.get_gid".format(__virtualname__)
func_name = f"{__virtualname__}.get_gid"
if __opts__.get("fun", "") == func_name:
log.info(
"The function %s should not be used on Windows systems; "
@ -467,7 +467,7 @@ def get_group(path, follow_symlinks=True):
salt '*' file.get_group c:\\temp\\test.txt
"""
func_name = "{}.get_group".format(__virtualname__)
func_name = f"{__virtualname__}.get_group"
if __opts__.get("fun", "") == func_name:
log.info(
"The function %s should not be used on Windows systems; "
@ -548,7 +548,7 @@ def get_uid(path, follow_symlinks=True):
salt '*' file.get_uid c:\\temp\\test.txt follow_symlinks=False
"""
if not os.path.exists(path):
raise CommandExecutionError("Path not found: {}".format(path))
raise CommandExecutionError(f"Path not found: {path}")
# Under Windows, if the path is a symlink, the user that owns the symlink is
# returned, not the user that owns the file/directory the symlink is
@ -587,7 +587,7 @@ def get_user(path, follow_symlinks=True):
salt '*' file.get_user c:\\temp\\test.txt follow_symlinks=False
"""
if not os.path.exists(path):
raise CommandExecutionError("Path not found: {}".format(path))
raise CommandExecutionError(f"Path not found: {path}")
# Under Windows, if the path is a symlink, the user that owns the symlink is
# returned, not the user that owns the file/directory the symlink is
@ -620,9 +620,9 @@ def get_mode(path):
salt '*' file.get_mode /etc/passwd
"""
if not os.path.exists(path):
raise CommandExecutionError("Path not found: {}".format(path))
raise CommandExecutionError(f"Path not found: {path}")
func_name = "{}.get_mode".format(__virtualname__)
func_name = f"{__virtualname__}.get_mode"
if __opts__.get("fun", "") == func_name:
log.info(
"The function %s should not be used on Windows systems; "
@ -671,7 +671,7 @@ def lchown(path, user, group=None, pgroup=None):
salt '*' file.lchown c:\\temp\\test.txt myusername "pgroup='None'"
"""
if group:
func_name = "{}.lchown".format(__virtualname__)
func_name = f"{__virtualname__}.lchown"
if __opts__.get("fun", "") == func_name:
log.info(
"The group parameter has no effect when using %s on "
@ -720,7 +720,7 @@ def chown(path, user, group=None, pgroup=None, follow_symlinks=True):
"""
# the group parameter is not used; only provided for API compatibility
if group is not None:
func_name = "{}.chown".format(__virtualname__)
func_name = f"{__virtualname__}.chown"
if __opts__.get("fun", "") == func_name:
log.info(
"The group parameter has no effect when using %s on "
@ -733,7 +733,7 @@ def chown(path, user, group=None, pgroup=None, follow_symlinks=True):
path = _resolve_symlink(path)
if not os.path.exists(path):
raise CommandExecutionError("Path not found: {}".format(path))
raise CommandExecutionError(f"Path not found: {path}")
__utils__["dacl.set_owner"](path, user)
if pgroup:
@ -804,7 +804,7 @@ def chgrp(path, group):
salt '*' file.chpgrp c:\\temp\\test.txt administrators
"""
func_name = "{}.chgrp".format(__virtualname__)
func_name = f"{__virtualname__}.chgrp"
if __opts__.get("fun", "") == func_name:
log.info(
"The function %s should not be used on Windows systems; see "
@ -850,7 +850,7 @@ def stats(path, hash_type="sha256", follow_symlinks=True):
# This is to mirror the behavior of file.py. `check_file_meta` expects an
# empty dictionary when the file does not exist
if not os.path.exists(path):
raise CommandExecutionError("Path not found: {}".format(path))
raise CommandExecutionError(f"Path not found: {path}")
if follow_symlinks and sys.getwindowsversion().major >= 6:
path = _resolve_symlink(path)
@ -953,13 +953,13 @@ def _get_version_type(file_type, file_subtype):
if ret_type == "Driver":
if file_subtype in driver_subtypes:
ret_type = "{} Driver".format(driver_subtypes[file_subtype])
ret_type = f"{driver_subtypes[file_subtype]} Driver"
if ret_type == "Font":
if file_subtype in font_subtypes:
ret_type = "{} Font".format(font_subtypes[file_subtype])
ret_type = f"{font_subtypes[file_subtype]} Font"
if ret_type == "Virtual Device":
# The Virtual Device Identifier
ret_type = "Virtual Device: {}".format(file_subtype)
ret_type = f"Virtual Device: {file_subtype}"
return ret_type
@ -1028,9 +1028,9 @@ def version(path):
"""
# Input validation
if not os.path.exists(path):
raise CommandExecutionError("File not found: {}".format(path))
raise CommandExecutionError(f"File not found: {path}")
if os.path.isdir(path):
raise CommandExecutionError("Not a file: {}".format(path))
raise CommandExecutionError(f"Not a file: {path}")
return _get_version(path)
@ -1068,9 +1068,9 @@ def version_details(path):
"""
# Input validation
if not os.path.exists(path):
raise CommandExecutionError("File not found: {}".format(path))
raise CommandExecutionError(f"File not found: {path}")
if os.path.isdir(path):
raise CommandExecutionError("Not a file: {}".format(path))
raise CommandExecutionError(f"Not a file: {path}")
ret = {}
try:
@ -1146,7 +1146,7 @@ def get_attributes(path):
salt '*' file.get_attributes c:\\temp\\a.txt
"""
if not os.path.exists(path):
raise CommandExecutionError("Path not found: {}".format(path))
raise CommandExecutionError(f"Path not found: {path}")
# set up dictionary for attribute values
attributes = {}
@ -1228,7 +1228,7 @@ def set_attributes(
salt '*' file.set_attributes c:\\temp\\a.txt readonly=True hidden=True
"""
if not os.path.exists(path):
raise CommandExecutionError("Path not found: {}".format(path))
raise CommandExecutionError(f"Path not found: {path}")
if normal:
if archive or hidden or notIndexed or readonly or system or temporary:
@ -1297,7 +1297,7 @@ def set_mode(path, mode):
salt '*' file.set_mode /etc/passwd 0644
"""
func_name = "{}.set_mode".format(__virtualname__)
func_name = f"{__virtualname__}.set_mode"
if __opts__.get("fun", "") == func_name:
log.info(
"The function %s should not be used on Windows systems; "
@ -1333,11 +1333,11 @@ def remove(path, force=False):
path = os.path.expanduser(path)
if not os.path.isabs(path):
raise SaltInvocationError("File path must be absolute: {}".format(path))
raise SaltInvocationError(f"File path must be absolute: {path}")
# Does the file/folder exists
if not os.path.exists(path) and not is_link(path):
raise CommandExecutionError("Path not found: {}".format(path))
raise CommandExecutionError(f"Path not found: {path}")
# Remove ReadOnly Attribute
if force:
@ -1354,7 +1354,7 @@ def remove(path, force=False):
os.rmdir(path)
else:
for name in os.listdir(path):
item = "{}\\{}".format(path, name)
item = f"{path}\\{name}"
# If its a normal directory, recurse to remove it's contents
remove(item, force)
@ -1364,12 +1364,12 @@ def remove(path, force=False):
if force:
# Reset attributes to the original if delete fails.
win32api.SetFileAttributes(path, file_attributes)
raise CommandExecutionError("Could not remove '{}': {}".format(path, exc))
raise CommandExecutionError(f"Could not remove '{path}': {exc}")
return True
def symlink(src, link, force=False, atomic=False):
def symlink(src, link, force=False, atomic=False, follow_symlinks=True):
"""
Create a symbolic link to a file
@ -1394,6 +1394,11 @@ def symlink(src, link, force=False, atomic=False):
Use atomic file operations to create the symlink
.. versionadded:: 3006.0
follow_symlinks (bool):
If set to ``False``, use ``os.path.lexists()`` for existence checks
instead of ``os.path.exists()``.
.. versionadded:: 3007.0
Returns:
bool: ``True`` if successful, otherwise raises ``CommandExecutionError``
@ -1412,7 +1417,12 @@ def symlink(src, link, force=False, atomic=False):
)
if not os.path.isabs(link):
raise SaltInvocationError("Link path must be absolute: {}".format(link))
raise SaltInvocationError(f"Link path must be absolute: {link}")
if follow_symlinks:
exists = os.path.exists
else:
exists = os.path.lexists
if os.path.islink(link):
try:
@ -1425,11 +1435,11 @@ def symlink(src, link, force=False, atomic=False):
pass
if not force and not atomic:
msg = "Found existing symlink: {}".format(link)
msg = f"Found existing symlink: {link}"
raise CommandExecutionError(msg)
if os.path.exists(link) and not force and not atomic:
msg = "Existing path is not a symlink: {}".format(link)
if exists(link) and not force and not atomic:
msg = f"Existing path is not a symlink: {link}"
raise CommandExecutionError(msg)
# ensure paths are using the right slashes
@ -1443,7 +1453,7 @@ def symlink(src, link, force=False, atomic=False):
th = win32security.OpenProcessToken(win32api.GetCurrentProcess(), desired_access)
salt.platform.win.elevate_token(th)
if (os.path.islink(link) or os.path.exists(link)) and force and not atomic:
if (os.path.islink(link) or exists(link)) and force and not atomic:
os.unlink(link)
elif atomic:
link_dir = os.path.dirname(link)
@ -1464,14 +1474,14 @@ def symlink(src, link, force=False, atomic=False):
return True
except win32file.error:
os.remove(temp_link)
raise CommandExecutionError("Could not create '{}'".format(link))
raise CommandExecutionError(f"Could not create '{link}'")
try:
win32file.CreateSymbolicLink(link, src, int(is_dir))
return True
except win32file.error as exc:
raise CommandExecutionError(
"Could not create '{}' - [{}] {}".format(link, exc.winerror, exc.strerror)
f"Could not create '{link}' - [{exc.winerror}] {exc.strerror}"
)
@ -1581,7 +1591,7 @@ def mkdir(
# Make sure the drive is valid
drive = os.path.splitdrive(path)[0]
if not os.path.isdir(drive):
raise CommandExecutionError("Drive {} is not mapped".format(drive))
raise CommandExecutionError(f"Drive {drive} is not mapped")
path = os.path.expanduser(path)
path = os.path.expandvars(path)
@ -1698,12 +1708,12 @@ def makedirs_(
if os.path.isdir(dirname):
# There's nothing for us to do
msg = "Directory '{}' already exists".format(dirname)
msg = f"Directory '{dirname}' already exists"
log.debug(msg)
return msg
if os.path.exists(dirname):
msg = "The path '{}' already exists and is not a directory".format(dirname)
msg = f"The path '{dirname}' already exists and is not a directory"
log.debug(msg)
return msg
@ -1912,7 +1922,7 @@ def check_perms(
salt '*' file.check_perms C:\\Temp\\ {} Administrators "{'jsnuffy': {'perms': ['read_attributes', 'read_ea'], 'applies_to': 'files_only'}}"
"""
if not os.path.exists(path):
raise CommandExecutionError("Path not found: {}".format(path))
raise CommandExecutionError(f"Path not found: {path}")
path = os.path.expanduser(path)

View file

@ -450,145 +450,157 @@ class Compiler:
if not isinstance(high, dict):
errors.append("High data is not a dictionary and is invalid")
reqs = OrderedDict()
for name, body in high.items():
if name.startswith("__"):
continue
if not isinstance(name, str):
errors.append(
"ID '{}' in SLS '{}' is not formed as a string, but is a {}".format(
name, body["__sls__"], type(name).__name__
)
)
if not isinstance(body, dict):
err = "The type {} in {} is not formatted as a dictionary".format(
name, body
)
errors.append(err)
continue
for state in body:
if state.startswith("__"):
continue
if not isinstance(body[state], list):
if not errors:
for name, body in high.items():
try:
if name.startswith("__"):
continue
except (AttributeError, TypeError):
# Do not traceback on non string state ID
# handle the error properly
pass
if not isinstance(name, str):
errors.append(
"State '{}' in SLS '{}' is not formed as a list".format(
name, body["__sls__"]
"ID '{}' in SLS '{}' is not formed as a string, but is a {}. It may need to be quoted".format(
name, body["__sls__"], type(name).__name__
)
)
else:
fun = 0
if "." in state:
fun += 1
for arg in body[state]:
if isinstance(arg, str):
fun += 1
if " " in arg.strip():
errors.append(
'The function "{}" in state '
'"{}" in SLS "{}" has '
"whitespace, a function with whitespace is "
"not supported, perhaps this is an argument "
'that is missing a ":"'.format(
arg, name, body["__sls__"]
)
)
elif isinstance(arg, dict):
# The arg is a dict, if the arg is require or
# watch, it must be a list.
#
# Add the requires to the reqs dict and check them
# all for recursive requisites.
argfirst = next(iter(arg))
if argfirst in ("require", "watch", "prereq", "onchanges"):
if not isinstance(arg[argfirst], list):
errors.append(
"The {} statement in state '{}' in SLS '{}' "
"needs to be formed as a list".format(
argfirst, name, body["__sls__"]
)
)
# It is a list, verify that the members of the
# list are all single key dicts.
else:
reqs[name] = {"state": state}
for req in arg[argfirst]:
if isinstance(req, str):
req = {"id": req}
if not isinstance(req, dict):
errors.append(
"Requisite declaration {} in SLS {} "
"is not formed as a single key "
"dictionary".format(
req, body["__sls__"]
)
)
continue
req_key = next(iter(req))
req_val = req[req_key]
if "." in req_key:
errors.append(
"Invalid requisite type '{}' "
"in state '{}', in SLS "
"'{}'. Requisite types must "
"not contain dots, did you "
"mean '{}'?".format(
req_key,
name,
body["__sls__"],
req_key[: req_key.find(".")],
)
)
if not ishashable(req_val):
errors.append(
'Illegal requisite "{}", is SLS {}\n'.format(
str(req_val),
body["__sls__"],
)
)
continue
# Check for global recursive requisites
reqs[name][req_val] = req_key
# I am going beyond 80 chars on
# purpose, this is just too much
# of a pain to deal with otherwise
if req_val in reqs:
if name in reqs[req_val]:
if reqs[req_val][name] == state:
if (
reqs[req_val]["state"]
== reqs[name][req_val]
):
errors.append(
"A recursive requisite was"
' found, SLS "{}" ID "{}"'
' ID "{}"'.format(
body["__sls__"],
name,
req_val,
)
)
# Make sure that there is only one key in the
# dict
if len(list(arg)) != 1:
errors.append(
"Multiple dictionaries defined in argument "
"of state '{}' in SLS '{}'".format(
name, body["__sls__"]
)
)
if not fun:
if state == "require" or state == "watch":
continue
if not isinstance(body, dict):
err = "The type {} in {} is not formatted as a dictionary".format(
name, body
)
errors.append(err)
continue
for state in body:
if state.startswith("__"):
continue
if not isinstance(body[state], list):
errors.append(
"No function declared in state '{}' in SLS '{}'".format(
state, body["__sls__"]
"State '{}' in SLS '{}' is not formed as a list".format(
name, body["__sls__"]
)
)
elif fun > 1:
errors.append(
"Too many functions declared in state '{}' in "
"SLS '{}'".format(state, body["__sls__"])
)
else:
fun = 0
if "." in state:
fun += 1
for arg in body[state]:
if isinstance(arg, str):
fun += 1
if " " in arg.strip():
errors.append(
'The function "{}" in state '
'"{}" in SLS "{}" has '
"whitespace, a function with whitespace is "
"not supported, perhaps this is an argument "
'that is missing a ":"'.format(
arg, name, body["__sls__"]
)
)
elif isinstance(arg, dict):
# The arg is a dict, if the arg is require or
# watch, it must be a list.
#
# Add the requires to the reqs dict and check them
# all for recursive requisites.
argfirst = next(iter(arg))
if argfirst in (
"require",
"watch",
"prereq",
"onchanges",
):
if not isinstance(arg[argfirst], list):
errors.append(
"The {} statement in state '{}' in SLS '{}' "
"needs to be formed as a list".format(
argfirst, name, body["__sls__"]
)
)
# It is a list, verify that the members of the
# list are all single key dicts.
else:
reqs[name] = {"state": state}
for req in arg[argfirst]:
if isinstance(req, str):
req = {"id": req}
if not isinstance(req, dict):
errors.append(
"Requisite declaration {} in SLS {} "
"is not formed as a single key "
"dictionary".format(
req, body["__sls__"]
)
)
continue
req_key = next(iter(req))
req_val = req[req_key]
if "." in req_key:
errors.append(
"Invalid requisite type '{}' "
"in state '{}', in SLS "
"'{}'. Requisite types must "
"not contain dots, did you "
"mean '{}'?".format(
req_key,
name,
body["__sls__"],
req_key[: req_key.find(".")],
)
)
if not ishashable(req_val):
errors.append(
'Illegal requisite "{}", is SLS {}\n'.format(
str(req_val),
body["__sls__"],
)
)
continue
# Check for global recursive requisites
reqs[name][req_val] = req_key
# I am going beyond 80 chars on
# purpose, this is just too much
# of a pain to deal with otherwise
if req_val in reqs:
if name in reqs[req_val]:
if reqs[req_val][name] == state:
if (
reqs[req_val]["state"]
== reqs[name][req_val]
):
errors.append(
"A recursive requisite was"
' found, SLS "{}" ID "{}"'
' ID "{}"'.format(
body["__sls__"],
name,
req_val,
)
)
# Make sure that there is only one key in the
# dict
if len(list(arg)) != 1:
errors.append(
"Multiple dictionaries defined in argument "
"of state '{}' in SLS '{}'".format(
name, body["__sls__"]
)
)
if not fun:
if state == "require" or state == "watch":
continue
errors.append(
"No function declared in state '{}' in SLS '{}'".format(
state, body["__sls__"]
)
)
elif fun > 1:
errors.append(
"Too many functions declared in state '{}' in "
"SLS '{}'".format(state, body["__sls__"])
)
return errors
def order_chunks(self, chunks):

View file

@ -101,6 +101,9 @@ def present(
docker_image.present:
- tag: mytag
name
The name of the docker image.
tag
Tag name for the image. Required when using ``build``, ``load``, or
``sls`` to create the image, but optional if pulling from a repository.
@ -146,10 +149,14 @@ def present(
.. versionchanged:: 2018.3.0
The ``tag`` must be manually specified using the ``tag`` argument.
force : False
force
Set this parameter to ``True`` to force Salt to pull/build/load the
image even if it is already present.
insecure_registry
If ``True``, the Docker client will permit the use of insecure
(non-HTTPS) registries.
client_timeout
Timeout in seconds for the Docker client. This is not a timeout for
the state, but for receiving a response from the API.
@ -212,6 +219,10 @@ def present(
``pillar_roots`` or an external Pillar source.
.. versionadded:: 2018.3.0
kwargs
Additional keyword arguments to pass to
:py:func:`docker.build <salt.modules.dockermod.build>`
"""
ret = {"name": name, "changes": {}, "result": False, "comment": ""}
@ -375,6 +386,9 @@ def absent(name=None, images=None, force=False):
specified either using ``repo:tag`` notation, or just the repo name (in
which case a tag of ``latest`` is assumed).
name
The name of the docker image.
images
Run this state on more than one image at a time. The following two
examples accomplish the same thing:
@ -401,7 +415,7 @@ def absent(name=None, images=None, force=False):
all the deletions in a single run, rather than executing the state
separately on each image (as it would in the first example).
force : False
force
Salt will fail to remove any images currently in use by a container.
Set this option to true to remove the image even if it is already
present.

View file

@ -1542,6 +1542,7 @@ def symlink(
atomic=False,
disallow_copy_and_unlink=False,
inherit_user_and_group=False,
follow_symlinks=True,
**kwargs,
):
"""
@ -1647,6 +1648,13 @@ def symlink(
override this behavior.
.. versionadded:: 3006.0
follow_symlinks (bool):
If set to ``False``, the underlying ``file.symlink`` execution module
and any checks in this state will use ``os.path.lexists()`` for
existence checks instead of ``os.path.exists()``.
.. versionadded:: 3007.0
"""
name = os.path.expanduser(name)
@ -1654,6 +1662,11 @@ def symlink(
if not name:
return _error(ret, "Must provide name to file.symlink")
if follow_symlinks:
exists = os.path.exists
else:
exists = os.path.lexists
# Make sure that leading zeros stripped by YAML loader are added back
mode = salt.utils.files.normalize_mode(mode)
@ -1834,7 +1847,7 @@ def symlink(
)
return ret
elif os.path.exists(name):
elif exists(name):
# It is not a link, but a file, dir, socket, FIFO etc.
if backupname is not None:
if not os.path.isabs(backupname):
@ -1892,7 +1905,9 @@ def symlink(
)
try:
__salt__["file.symlink"](target, name, force=force, atomic=atomic)
__salt__["file.symlink"](
target, name, force=force, atomic=atomic, follow_symlinks=follow_symlinks
)
except (CommandExecutionError, OSError) as exc:
ret["result"] = False
ret["comment"] = "Unable to create new symlink {} -> {}: {}".format(

View file

@ -141,7 +141,7 @@ class OptionParser(optparse.OptionParser):
_mixin_prio_ = sys.maxsize - 200
def __init__(self, *args, **kwargs):
kwargs.setdefault("version", "%prog {}".format(self.VERSION))
kwargs.setdefault("version", f"%prog {self.VERSION}")
kwargs.setdefault("usage", self.usage)
if self.description:
kwargs.setdefault("description", self.description)
@ -187,7 +187,7 @@ class OptionParser(optparse.OptionParser):
# Gather and run the process_<option> functions in the proper order
process_option_funcs = []
for option_key in options.__dict__:
process_option_func = getattr(self, "process_{}".format(option_key), None)
process_option_func = getattr(self, f"process_{option_key}", None)
if process_option_func is not None:
process_option_funcs.append(process_option_func)
@ -274,7 +274,7 @@ class OptionParser(optparse.OptionParser):
temp_log_handler.flush()
salt._logging.shutdown_temp_handler()
if isinstance(msg, str) and msg and msg[-1] != "\n":
msg = "{}\n".format(msg)
msg = f"{msg}\n"
optparse.OptionParser.exit(self, status, msg)
def error(self, msg):
@ -287,7 +287,7 @@ class OptionParser(optparse.OptionParser):
self.print_usage(sys.stderr)
self.exit(
salt.defaults.exitcodes.EX_USAGE,
"{}: error: {}\n".format(self.get_prog_name(), msg),
f"{self.get_prog_name()}: error: {msg}\n",
)
@ -408,7 +408,7 @@ class SaltfileMixIn(metaclass=MixInMeta):
return
if not os.path.isfile(self.options.saltfile):
self.error("'{}' file does not exist.\n".format(self.options.saltfile))
self.error(f"'{self.options.saltfile}' file does not exist.\n")
# Make sure we have an absolute path
self.options.saltfile = os.path.abspath(self.options.saltfile)
@ -422,7 +422,7 @@ class SaltfileMixIn(metaclass=MixInMeta):
self.error(error.message)
self.exit(
salt.defaults.exitcodes.EX_GENERIC,
"{}: error: {}\n".format(self.get_prog_name(), error.message),
f"{self.get_prog_name()}: error: {error.message}\n",
)
if not saltfile_config:
@ -568,7 +568,7 @@ class ConfigDirMixIn(metaclass=MixInMeta):
try:
self.config.update(self.setup_config())
except OSError as exc:
self.error("Failed to load configuration: {}".format(exc))
self.error(f"Failed to load configuration: {exc}")
def get_config_file_path(self, configfile=None):
if configfile is None:
@ -611,7 +611,7 @@ class LogLevelMixIn(metaclass=MixInMeta):
dest=self._loglevel_config_setting_name_,
choices=list(salt._logging.LOG_LEVELS),
help="Console logging log level. One of {}. Default: '{}'.".format(
", ".join(["'{}'".format(n) for n in salt._logging.SORTED_LEVEL_NAMES]),
", ".join([f"'{n}'" for n in salt._logging.SORTED_LEVEL_NAMES]),
self._default_logging_level_,
),
)
@ -629,7 +629,7 @@ class LogLevelMixIn(metaclass=MixInMeta):
action="callback",
type="string",
callback=_logfile_callback,
help="Log file path. Default: '{}'.".format(self._default_logging_logfile_),
help=f"Log file path. Default: '{self._default_logging_logfile_}'.",
)
group.add_option(
@ -637,7 +637,7 @@ class LogLevelMixIn(metaclass=MixInMeta):
dest=self._logfile_loglevel_config_setting_name_,
choices=list(salt._logging.SORTED_LEVEL_NAMES),
help="Logfile logging log level. One of {}. Default: '{}'.".format(
", ".join(["'{}'".format(n) for n in salt._logging.SORTED_LEVEL_NAMES]),
", ".join([f"'{n}'" for n in salt._logging.SORTED_LEVEL_NAMES]),
self._default_logging_level_,
),
)
@ -858,9 +858,7 @@ class LogLevelMixIn(metaclass=MixInMeta):
str(logfile),
str(logfile_basename),
)
logfile = os.path.join(
user_salt_dir, "{}.log".format(logfile_basename)
)
logfile = os.path.join(user_salt_dir, f"{logfile_basename}.log")
# If we haven't changed the logfile path and it's not writeable,
# salt will fail once we try to setup the logfile logging.
@ -915,7 +913,7 @@ class RunUserMixin(metaclass=MixInMeta):
def _mixin_setup(self):
self.add_option(
"-u", "--user", help="Specify user to run {}.".format(self.get_prog_name())
"-u", "--user", help=f"Specify user to run {self.get_prog_name()}."
)
@ -928,14 +926,12 @@ class DaemonMixIn(metaclass=MixInMeta):
"--daemon",
default=False,
action="store_true",
help="Run the {} as a daemon.".format(self.get_prog_name()),
help=f"Run the {self.get_prog_name()} as a daemon.",
)
self.add_option(
"--pid-file",
dest="pidfile",
default=os.path.join(
syspaths.PIDFILE_DIR, "{}.pid".format(self.get_prog_name())
),
default=os.path.join(syspaths.PIDFILE_DIR, f"{self.get_prog_name()}.pid"),
help="Specify the location of the pidfile. Default: '%default'.",
)
@ -1058,7 +1054,7 @@ class DaemonMixIn(metaclass=MixInMeta):
elif signum == signal.SIGTERM:
msg += " received a SIGTERM."
logging.getLogger(__name__).warning("%s Exiting.", msg)
self.shutdown(exitmsg="{} Exited.".format(msg))
self.shutdown(exitmsg=f"{msg} Exited.")
def shutdown(self, exitcode=0, exitmsg=None):
self.exit(exitcode, exitmsg)
@ -1175,7 +1171,7 @@ class TargetOptionsMixIn(metaclass=MixInMeta):
if getattr(self.options, opt.dest):
self.selected_target_option = opt.dest
funcname = "process_{}".format(option.dest)
funcname = f"process_{option.dest}"
if not hasattr(self, funcname):
setattr(self, funcname, partial(process, option))
@ -1433,7 +1429,7 @@ class OutputOptionsMixIn(metaclass=MixInMeta):
return
self.selected_output_option = opt.dest
funcname = "process_{}".format(option.dest)
funcname = f"process_{option.dest}"
if not hasattr(self, funcname):
setattr(self, funcname, partial(process, option))
@ -1452,9 +1448,7 @@ class OutputOptionsMixIn(metaclass=MixInMeta):
# it. This way we keep the file permissions.
pass
except OSError as exc:
self.error(
"{}: Access denied: {}".format(self.options.output_file, exc)
)
self.error(f"{self.options.output_file}: Access denied: {exc}")
def process_state_verbose(self):
if self.options.state_verbose == "True" or self.options.state_verbose == "true":
@ -1709,7 +1703,7 @@ class CloudQueriesMixIn(metaclass=MixInMeta):
)
self.selected_query_option = query
funcname = "process_{}".format(option.dest)
funcname = f"process_{option.dest}"
if not hasattr(self, funcname):
setattr(self, funcname, partial(process, option))
@ -1909,7 +1903,7 @@ class JIDMixin:
def process_jid(self):
if self.options.jid is not None:
if not salt.utils.jid.is_jid(self.options.jid):
self.error("'{}' is not a valid JID".format(self.options.jid))
self.error(f"'{self.options.jid}' is not a valid JID")
class MasterOptionParser(
@ -2649,7 +2643,7 @@ class SaltKeyOptionParser(
default=".",
help=(
"Set the directory to save the generated keypair, only "
"works with \"gen_keys_dir\" option. Default: '%default'."
"works with \"--gen-keys\" option. Default: '%default'."
),
)
@ -2755,9 +2749,7 @@ class SaltKeyOptionParser(
if not self.options.list:
return
if not self.options.list.startswith(("acc", "pre", "un", "rej", "den", "all")):
self.error(
"'{}' is not a valid argument to '--list'".format(self.options.list)
)
self.error(f"'{self.options.list}' is not a valid argument to '--list'")
def process_keysize(self):
if self.options.keysize < 2048:
@ -2767,10 +2759,11 @@ class SaltKeyOptionParser(
def process_gen_keys_dir(self):
# Schedule __create_keys_dir() to run if there's a value for
# --create-keys-dir
self._mixin_after_parsed_funcs.append(
self.__create_keys_dir
) # pylint: disable=no-member
# --gen-keys-dir
if self.options.gen_keys:
self._mixin_after_parsed_funcs.append(
self.__create_keys_dir
) # pylint: disable=no-member
def __create_keys_dir(self):
if not os.path.isdir(self.config["gen_keys_dir"]):

View file

@ -31,13 +31,6 @@ try:
except ImportError:
HAS_GRP = False
try:
import pysss
HAS_PYSSS = True
except ImportError:
HAS_PYSSS = False
try:
import salt.utils.win_functions
@ -289,30 +282,35 @@ def get_group_list(user, include_default=True):
return []
group_names = None
ugroups = set()
if hasattr(os, "getgrouplist"):
# Try os.getgrouplist, available in python >= 3.3
log.trace("Trying os.getgrouplist for '%s'", user)
try:
user_group_list = os.getgrouplist(user, pwd.getpwnam(user).pw_gid)
group_names = [
_group.gr_name
for _group in grp.getgrall()
if _group.gr_gid in user_group_list
]
except Exception: # pylint: disable=broad-except
pass
elif HAS_PYSSS:
# Try pysss.getgrouplist
log.trace("Trying pysss.getgrouplist for '%s'", user)
try:
group_names = list(pysss.getgrouplist(user))
except Exception: # pylint: disable=broad-except
pass
# Try os.getgrouplist, available in python >= 3.3
log.trace("Trying os.getgrouplist for '%s'", user)
try:
user_group_list = sorted(os.getgrouplist(user, pwd.getpwnam(user).pw_gid))
local_grall = _getgrall()
local_gids = sorted(lgrp.gr_gid for lgrp in local_grall)
max_idx = -1
local_max = local_gids[max_idx]
while local_max >= 65000:
max_idx -= 1
local_max = local_gids[max_idx]
user_group_list_local = [lgrp for lgrp in user_group_list if lgrp <= local_max]
user_group_list_remote = [rgrp for rgrp in user_group_list if rgrp > local_max]
local_group_names = [
_group.gr_name
for _group in local_grall
if _group.gr_gid in user_group_list_local
]
remote_group_names = [
grp.getgrgid(group_id).gr_name for group_id in user_group_list_remote
]
group_names = local_group_names + remote_group_names
except Exception: # pylint: disable=broad-except
pass
if group_names is None:
# Fall back to generic code
# Include the user's default group to match behavior of
# os.getgrouplist() and pysss.getgrouplist()
# os.getgrouplist()
log.trace("Trying generic group list for '%s'", user)
group_names = [g.gr_name for g in grp.getgrall() if user in g.gr_mem]
try:
@ -389,3 +387,24 @@ def get_gid(group=None):
return grp.getgrnam(group).gr_gid
except KeyError:
return None
def _getgrall(root=None):
"""
Alternative implemetantion for getgrall, that uses only /etc/group
"""
ret = []
root = "/" if not root else root
etc_group = os.path.join(root, "etc/group")
with salt.utils.files.fopen(etc_group) as fp_:
for line in fp_:
line = salt.utils.stringutils.to_unicode(line)
comps = line.strip().split(":")
# Generate a getgrall compatible output
comps[2] = int(comps[2])
if comps[3]:
comps[3] = [mem.strip() for mem in comps[3].split(",")]
else:
comps[3] = []
ret.append(grp.struct_group(comps))
return ret

View file

@ -323,6 +323,9 @@ salt/(minion\.py|channel/.+|transport/.+):
tests/support/mock.py:
- unit.test_mock
tests/support/virt.py:
- pytests.integration.modules.test_virt
tests/support/pytest/mysql.py:
- pytests.functional.states.test_mysql
- pytests.functional.modules.test_mysql

View file

@ -44,7 +44,7 @@ class PublishModuleTest(ModuleCase, SaltReturnAssertsMixin):
self.assertTrue(name in ret)
self.assertEqual(ret["cheese"], "spam")
self.assertEqual(ret["__pub_arg"], [{"cheese": "spam"}])
self.assertEqual(ret["__pub_arg"], [{"__kwarg__": True, "cheese": "spam"}])
self.assertEqual(ret["__pub_id"], "minion")
self.assertEqual(ret["__pub_fun"], "test.kwarg")
@ -125,7 +125,7 @@ class PublishModuleTest(ModuleCase, SaltReturnAssertsMixin):
self.assertTrue(name in ret)
self.assertEqual(ret["cheese"], "spam")
self.assertEqual(ret["__pub_arg"], [{"cheese": "spam"}])
self.assertEqual(ret["__pub_arg"], [{"__kwarg__": True, "cheese": "spam"}])
self.assertEqual(ret["__pub_id"], "minion")
self.assertEqual(ret["__pub_fun"], "test.kwarg")

View file

@ -353,3 +353,38 @@ def test_onlyif_req(state, subtests):
assert ret.result is False
assert ret.changes
assert ret.comment == "Failure!"
def test_listen_requisite_not_exist(state, state_tree):
"""
Tests a simple state using the listen requisite
when the state id does not exist
"""
sls_contents = """
successful_changing_state:
cmd.run:
- name: echo "Successful Change"
non_changing_state:
test.succeed_without_changes
test_listening_change_state:
cmd.run:
- name: echo "Listening State"
- listen:
- cmd: successful_changing_state
test_listening_non_changing_state:
cmd.run:
- name: echo "Only run once"
- listen:
- test: non_changing_state_not_exist
"""
with pytest.helpers.temp_file("requisite.sls", sls_contents, state_tree):
ret = state.sls("requisite")
assert (
ret.raw[
"Listen_Error_|-listen_non_changing_state_not_exist_|-listen_test_|-Listen_Error"
]["comment"]
== "Referenced state test: non_changing_state_not_exist does not exist"
)

View file

@ -7,6 +7,37 @@ pytestmark = [
pytest.mark.core_test,
]
import salt.modules.cmdmod as cmd
import salt.modules.config as config
import salt.modules.grains as grains
import salt.modules.saltutil as saltutil
import salt.modules.state as state_mod
@pytest.fixture
def configure_loader_modules(minion_opts):
return {
state_mod: {
"__opts__": minion_opts,
"__salt__": {
"config.option": config.option,
"config.get": config.get,
"saltutil.is_running": saltutil.is_running,
"grains.get": grains.get,
"cmd.run": cmd.run,
},
},
config: {
"__opts__": minion_opts,
},
saltutil: {
"__opts__": minion_opts,
},
grains: {
"__opts__": minion_opts,
},
}
def test_requisites_mixed_require_prereq_use_1(state, state_tree):
"""
@ -401,3 +432,23 @@ def test_issue_30161_unless_and_onlyif_together(state, state_tree, tmp_path):
}
for slsid in _expected:
assert ret[slsid].comment == _expected[slsid]["comment"]
def test_requisites_mixed_illegal_req(state_tree):
"""
Call sls file containing several requisites.
When one of the requisites is illegal.
"""
sls_contents = """
A:
cmd.run:
- name: echo A
B:
cmd.run:
- name: echo B
- require:
- cmd: ["A"]
"""
with pytest.helpers.temp_file("requisite.sls", sls_contents, state_tree):
ret = state_mod.sls("requisite")
assert ret == ["Illegal requisite \"['A']\", please check your syntax.\n"]

Some files were not shown because too many files have changed in this diff Show more